Ricerca tra la vecchia roba

I segreti della linea di comando

Posted: Gennaio 30th, 2009 | Author: | Filed under: Bash, Hack, Life, Programmazione | 3 Comments »

A furia di lavorare al computer ho imparato un paio di cosette veramente cool… prima di tutto però una introduzione su cosa è la shell: l’oggetto che ci permette l’interazione su un sistema *nix, chiamato solitamente terminale, benché abbia un’aria così anni 70 permette un macello di azioni simpatiche e performanti.

Prima di tutto la linea di comando di solito è preceduta da un cosidetto prompt, cioè l’indicatore dello stato del terminale (ne esistono 4 diversi) utile per avere informazioni riguardanti la directory in cui ci troviamo, il computer in cui ci troviamo (il cosidetto host) e che utente siamo (cose non date per scontate in un sistema multiutente). Quando viene eseguito un comando all’interno succede una cosa carina:viene eseguita una chiamata di sistema che sostituisce il processo con quello eseguito (la execv e famiglia) con una piccola accortezza dovuta al fatto che ci sono due tipi di programmi, gli eseguibili e gli script; i secondi hanno la particolarità di necessitare di un interprete per funzionare (può essere la stessa shell, può essere l’interprete python, awk etc…). Proprio a questo scopo esiste il cosidetto numero magico del file: siccome il computer non può fidarsi della estensione del file per riconoscerne la natura, visto che l’estensione non è neanche una specifica di nessun tipo se non per winzoz, legge i primi 3/4 byte di un file per riconoscerlo attraverso una segnatura, chiamata appunto numero magico; provate a eseguire su un file PNG il comando head -c 4 e vedrete che uscirà una stringa contenente proprio il formato. Nel caso di un file di script, la sequenza magica è #!, seguita dal percorso dell’interprete. Se quindi viene chiesto di eseguire un file ‘mioscriptpaura.sh‘ che ha al suo interno come prima riga la sequenza #!/bin/sh, il sistema eseguirà invece /bin/sh mioscriptpaura.sh.

Ogni programma *nix può essere immaginato come una scatola nera, di cui non conosciamo l’implementazione, impegnata in un’azione particolare sul suo input per restituire un output diverso, tenendo conto anche di eventuali messaggi di errore o di log relativi all’azione particolare; ad ognuno di questi flussi di dati (detti stream)  è associato un file descriptor, chiamati rispettivamente standard input, standard output e standard error. La cosa carina è che è possibile concatenare comandi per ottenere una cosidetta pipeline e generare tramite sequenza di comandi semplici, azioni complesse; il modo attraverso cui questo è possibile è la pipe, ottenuta attraverso il carattere |. Per fare un esempio, se necessitiamo di controllare se è stata montata la partizione di swap del sistema al boot, dovremmo spulciare le righe di dmesg una ad una, ma usando grep, comando che cerca l’occorrenza di una data stringa in un file, possiamo facilitarci la vita nella seguente maniera

$ dmesg | grep swap
[   28.276971] Adding 2931852k swap on /dev/sda2.  Priority:-1 extents:1 across:2931852k

Ovviamente il carattere | non può essere utilizzato normalmente, ma deve essere trattato con cura (provate a creare una file che lo contenga ;-)). Altre ficate della shell *nix sono la redirezione degli stream descritti sopra: magari noi vogliamo salvare il risultato della elaborazione su un  file oppure prendere un file come standard input per un comando e proprio per questo ecco la magia

COMANDO < INPUT_FILE
COMANDO > OUTPUT_FILE
COMANDO >> OUTPUT_FILE
COMANDO < INPUT_FILE > OUTPUT_FILE
COMANDO < INPUT_FILE >> OUTPUT_FILE

Nel primo caso usiamo le righe di INPUT_FILE come se fossero scritte direttamente sul terminale dopo aver avviato COMANDO (equivalente peraltro a cat INPUT_FILE | COMANDO), nel secondo caso in OUTPUT_FILE viene scritto il risultato dell’esecuzione di COMANDO; il terzo caso è l’unione dei due precedenti. Particolare attenzione riveste l’operatore >> che apre il file in questione e aggiunge alla fine il risultato del comando (l’operatore > nel caso esista già il file e non sia vuoto, lo riscrive da zero).

Esiste anche l’operatore << che permette di ottenere i cosiddetti Here document; eseguendo

cat <<EOF > porcatroia.txt
sei solo una troia, pensi solo ai $soldi
EOF

ottieni nel file porcatroia la riga "sei solo una troia, pensi solo ai ", la mancanza di $soldi è dovuto al fatto che la shell cerca di sostituirlo con una variabile, per essere riprodotto testualmente, bisogna quotare EOF, ma quello del quoting nella prossima puntata.

Per finire mostro solo la presenza di ulteriori operatori logici presenti nella shell: un programma può nella sua esecuzione incontrare dei problemi/errori dovuti a situazioni particolari (disco pieno, file inesistente, digos) e quindi può comunicarlo alla shell tramite il suo valore di ritorno: nel caso questo sia diverso da zero allora c’è stato un problema altrimenti è tutto ok. La variabile che contiene il valore di ritorno è $?.

Bene, questo può essere usato per concatenare comandi; nel caso vogliamo eseguire un dato comando dopo il successo di un altro dobbiamo porre l’operatore && tra di essi. Nel caso in cui vogliamo eseguire un comando nel caso il primo fallisca, si usa l’operatore ||. Ovviamente non potrete utilizzare normalmente questi comandi in nomi di file.


3 Comments on “I segreti della linea di comando”

  1. 1 cretox said at 10:29 pm on Febbraio 3rd, 2009:

    nun zapevo, interessante la storia del numero magico.. ๐Ÿ˜€

  2. 2 packz said at 11:28 pm on Febbraio 3rd, 2009:

    Oh yeah, altrimenti come potrebbe funzionare il comando file(1)?

    http://www.darwinsys.com/file/

    (Esiste anche una libreria…)

  3. 3 abidibo said at 7:52 pm on Febbraio 7th, 2009:

    Sempre interessanti i tuoi post Packz ;), aspetto nuove puntate (e di mettermi seriamente su un sistema *nix). chips