Microsoft's Internet Explorer browser has no built-in vector graphics machinery required for "loss-free" gradient background themes.
Please upgrade to a better browser such as Firefox, Opera, Safari or others with built-in vector graphics machinery and much more. (Learn more or post questions or comments at the Slide Show (S9) project site. Thanks!)
In termini generali una shell è un software fornisce una interfaccia di interazione ad un utente.
Le shell si dividono in due grandi tipologie:
Nell’ambito dell’amministrazione di sistema, la shell è l’applicazione che interpreta i comandi dell’amministratore attraverso un interfaccia testuale.
La shell è uno strumento molto potente e insostituibile per l’amministratore di sistema. Tramite la shell è possibile gestire il le componenti più interne del sistema in modo molto più potente ed efficace rispetto alle interfacce grafiche:
NOTA: Il termine shell (guscio) sta ad indicare la proprietà di una shell di porsi come intermediario tra l’utente e i meccanismi interni del sistema, facilitandone la gestione.
Nel mondo Unix esistono diverse implementazioni di shell. Le più usate sono:
Ogni shell si distingue per il tipo di funzionalità, per la sintassi utilizzata, per le risorse richieste.
Nel seguito del nostro corso faremo riferimento alla più utilizzata in
assoluto: Bourne Again shell ( bash
)
La shell bash
è una shell compatibile con sh
con la quale
condivide molte funzionalità.
La shell bash
può essere controllata attraverso l’interazione
diretta con un terminale o attraverso dei veri e propri programmi
( script ) in grado di eseguire compiti complessi.
L’interazione con una shell avviene attraverso la linea di comando di un terminale.
Il terminale è un software all’interno del quale è in esecuzione una shell.
Generalmente, la linea di comando di un terminale corrisponde con l’ultima riga attiva dello schermo (o della finestra) all’interno del quale è in esecuzione il terminale.
andrea@ganimoide:~$
Nel riquadro sopra viene mostrato il prompt della linea di comando di una shell bash. Il prompt è un testo che segnala all’utente che la shell è pronta a ricevere i suoi comandi. Nel caso specifico, il prompt della shell bash indica di solito (se non è stato personalizzato):
Come abbiamo visto, una shell è un’interprete di comandi.
Un comando è un’operazione richiesta al sistema.
Tecnicamente, un comando è di solito costituito da un programma eseguibile che viene richiamato direttamente dall’utente della shell oppure da un altro comando/processo.
L’utente interagisce con il sistema attraverso i comandi. La shell funge da intermediario di questa interazione.
Per inviare un comando ad una shell bash occorre:
andrea@ganimoide:~$ ls Documenti Immagini Modelli Musica Pubblici Scrivania Video
Il riquadro mostra il risultato (o output) prodotto dall’invio del
comando ls
.
Due funzionalità molto utili delle shell moderne sono la cosidetta TAB completion e la history.
La funzione di TAB completion consente all’utente di completare il
comando senza bisogno di scriverlo per intero ma semplicemente
premendo il tasto TAB
.
La history permette invece di richiamare in maniera veloce gli ultimi comandi inseriti.
Nella slide precedente abbiamo eseguito il comando ls
nel modo più
semplice possibile: chiamandolo per nome.
Generalmente, le funzionalità di un comando possono essere estese invocandolo con argomenti e opzioni.
ls [OPTION]... [FILE]...
Nel riquadro è riportata la sintassi del comando ls
.
Al posto di [OPTION]
si indicano le opzioni da passare al comando.
Al posto di [FILE]
si indicano gli argomenti da passare al comando.
andrea@ganimoide:~/Documenti/books$ ls -l *.gz -rw-r--r-- 1 andrea andrea 299419 2009-01-12 12:11 bash-intro.pdf.gz
Nel riquadro sopra si vede l’output di ls
ottenuto passando al
comando l’opzione -l
e l’argomento *.gz
.
Gli argomenti rendono un comando flessibile e ne ampliano le funzionalità.
Ad esempio, l’argomento *.gz
passato al comando ls
specifica
l’estensione dei file che devono essere elencati (cioè tutti i file
con estensione gz
):
andrea@ganimoide:~/Documenti/books$ ls -l *.gz -rw-r--r-- 1 andrea andrea 299419 2009-01-12 12:11 bash-intro.pdf.gz
Il comando mv
nel riquadro sotto rinomina il file con nome
vecchio_nome
in un file con nome nuovo_nome
.
andrea@ganimoide:~$ mv vecchio_nome nuovo_nome
vecchio_nome
e nuovo_nome
sono i gli argomenti passati al comando
mv
.
Il comando cp
nel riquadro sotto copia tutti i file della cartella
Documenti
nella cartella backup
:
andrea@ganimoide:~$ cp Documenti/* backup/
Documenti/*
e backup/
sono gli argomenti passati al comando
cp
.
Come si intuisce, molti comandi necessitano di uno o più argomenti per funzionare correttamente.
Questi argomenti si dicono obbligatori.
Esistono almeno due convenzioni per individuare gli argomenti obbligatori all’interno della sintassi di un comando:
<
e >
Ad esempio, la sintassi del comando cp
è:
cp [OPTION]... SOURCE... DIRECTORY
Come si vede gli argomenti SOURCE
e DIRECTORY
sono obbligatori in
quanto non compaiono tra parentesi quadre.
A differenza degli argomenti, le opzioni passate ad un comando non sono (generalmente) indispensabili al funzionamento dello stesso.
Come gli argomenti, anche le opzioni amplificano o modificano le funzionalità di un comando.
Ad esempio l’opzione -l
passata al comando ls
modifica la
formattazione del risultato (i file vengono elencati sotto forma di
elenco).
Le opzioni possono essere anche combinate tra loro.
Ad esempio, per visualizzare i file di una cartella sotto forma di
elenco e ottenere le dimensioni degli stessi in byte e multipli di
byte occorre utilizzare contemporaneamente le opzioni -l
e -h
:
andrea@ganimoide:~/src/wordchallenger/spec$ ls -lh totale 8,0K -rwx------ 1 andrea andrea 25 2008-12-09 20:32 spec.opts -rwx------ 1 andrea andrea 1,4K 2008-12-11 11:50 wordchallenger_spec.rb
Nota che lo stesso comando può essere inviato anche tenendo le opzioni separate:
andrea@ganimoide:~/src/wordchallenger/spec$ ls -l -h
Come si nota dagli esempi presentati finora, l’interprete dei comandi
è in grado di discernere un argomento da un’opzione in base alla
presenza del carattere -
(trattino) preposto prima del nome di
quest’ultima.
Inoltre, esistono due diversi formati per i nomi delle opzioni:
Il formato corto è quello utilizzato finora nei nostri esempi.
Il formato lungo, dove supportato, rende il comando più
“leggibile”. Il formato lungo è denotato dai caratteri --
(due
trattini) preposti al nome dell’opzione.
Molte opzioni supportano entrambi i formati.
Riproponiamo l’esempio del comando ls
utilizzando, per le opzioni, i
formati lunghi (dove supportati):
andrea@ganimoide:~/src/wordchallenger/spec$ ls -l --human-readable totale 8,0K -rwx------ 1 andrea andrea 25 2008-12-09 20:32 spec.opts -rwx------ 1 andrea andrea 1,4K 2008-12-11 11:50 wordchallenger_spec.rb
Ci sono delle opzioni la cui funzione è nota per convenzione.
Ad esempio, se vogliamo conoscere la sintassi di utilizzo di un
comando, passeremo allo stesso l’opzione --help
(oppure -h
):
andrea@ganimoide:~$ ls --help Uso: ls [OPZIONE]... [FILE]... Elenca informazioni sui FILE (predefinito: la directory corrente). Ordina alfabeticamente le voci se non è usato uno di -cftuvSUX oppure --sort. Gli argomenti obbligatori per le opzioni lunghe lo sono anche per quelle brevi. -a, --all non nasconde le voci che iniziano con . ...
Altre opzioni comuni sono:
-a
, --all
-f
, --force
-v
, --verbose
Altre ancora si possono trovare qui
Oltre agli esempi di comando mostrati nelle precedenti slide, ne proponiamo degli altri:
Copia ricorsiva di una cartella in un’altra
cp -r cartella_sorgente/* cartella_destinazione/
Visualizzazione del contenuto di un file sul terminale
cat file
Visualizzazione del contenuto di un file sul terminale con impaginazione
less file
Decompressione di un archivio compresso (tarball) con algoritmo gzip
tar -xvzf archivio.tar.gz
Per conoscere la posizione all’interno del filesystem di un comando la shell mette a disposizione una serie di strumenti.
Il comando which
localizza i percorsi in cui si trovano i file
binari relativi ad un comando (o ad una lista di comandi).
andrea@ganimoide:~$ which gcc ruby java /usr/bin/gcc /usr/bin/ruby /usr/bin/java
Il comando whereis
localizza i percorsi dei file binari, della
documentazione e del codice sorgente relativi ad un comando (o ad una
lista di comandi).
andrea@ganimoide:~$ whereis gcc ruby java gcc: /usr/bin/gcc /usr/lib/gcc /usr/share/man/man1/gcc.1.gz ruby: /usr/bin/ruby /usr/bin/ruby1.8 /usr/lib/ruby /usr/share/man/man1/ruby.1.gz java: /usr/bin/java /etc/java /usr/share/java /usr/share/man/man1/java.1.gz
Per uno uso proficuo del terminale è fondamentale saper reperire la documentazione relativa ai comandi.
La shell mette a disposizione una serie di comandi orientati alla visualizzazione e alla navigazione della documentazione.
Il comando man
visualizza le pagine di manuale relative ad una
particolare voce (comando, funzione o programma) e permettere di
navigarle attraverso un’interfaccia di testo.
Ad esempio, se si prova a digitare
andrea@ganimoide:~$ man ls
il comando visualizzerà le pagine di manuale del comando ls
all’interno della finestra del terminale.
Il comando info
è un lettore di manuali scritti in formato Texinfo.
Il formato Texinfo permette la stesura articolata di documentazione.
andrea@ganimoide:~$ info ls
Generalmente, la documentazione redatta in formato Texinfo è più
completa rispetto a quella accessibile tramite il comando man
.
Per visualizzare le pagine di documentazione di un comando è
sufficiente invocare info
seguito dal nome del comando:
andrea@ganimoide:~$ info ls
Un altro comando utile nella ricerca di documentazione è apropos
.
apropos
effettua una ricerca per parola chiave all’interno di tutti
i manuali presenti nel sistema.
andrea@ganimoide:~$ apropos ruby erb (1) - an embedded Ruby language interpreter erb1.8 (1) - an embedded Ruby language interpreter irb1.8 (1) - interactive ruby ...
Infine, un’altra fonte di informazioni presente nel sistema è la
cartella /usr/share/doc
. Generalmente, in questa cartella le
applicazioni installano la propria documentazione.
Per gestire opportunamente il sistema è necessario poter accedere alle informazioni riguardanti le componenti hardware dello stesso. La shell offre una serie di comandi utili a questo scopo.
Il comando lsusb
, ad esempio, visualizza l’elenco di tutte le
periferiche usb connesse al sistema.
Analogamente, il comando lspci
visualizza i dettagli hardware delle
schede con slot PCI installate nel sistema.
Inoltre, una preziosa fonte di informazione è costituita dalla
cartella /proc/
che contiene, sotto forma di file, una serie di
informazioni utili relative alla componentistica elettronica del
sistema.
Ad esempio il comando
andrea@ganimoide:~$ cat /proc/cpuinfo
visualizza informazioni dettagliate circa il processore (o i processori) presenti nel sistema.
Infine, il comando fdisk
(eseguito con i permessi di amministratore)
riporta le informazioni riguardanti i supporti di memorizzazione
presenti.
andrea@ganimoide:~$ sudo fdisk -l
Naturalmente, la shell offre un insieme di comandi che permettono un’agevole navigazione all’interno del filesystem (fs).
Come vedremo in seguito, il fs rappresenta la struttura con la quale i dati vengono rappresentati nel sistema.
In un tipico fs GNU/Linux non esiste differenza tra file e cartelle: ogni elemento del fs è un file:
Tuttavia, nel seguito della lezione, per semplicità di esposizione, faremo distinzione tra file e cartelle.
La struttura delle cartelle all’interno del fs
è una struttura
gerarchica. Per avere un’idea della struttura di un tipico fs
GNU/Linux digitate:
ls -l /
Il risultato ottenuto rappresenta il contenuto della cartella
principale (/
).
Il comando che si utilizza per spostarsi da una cartella ad un’altra è
cd
.
andrea@ganimoide:~$ cd Documenti andrea@ganimoide:~/Documenti$
Ad esempio, nel riquadro sopra si sta invocando il comando cd
insieme all’argomento Documenti
. Il risultato dell’esecuzione del
comando si vede al prompt della linea successiva che indica la
cartella in cui ci si trova dopo lo spostamento.
Il simbolo di ~
(tilde) è una forma contratta che sta ad indicare la
cartella home
dell’utente che sta operando sul terminale
(/home/andrea/
).
Il comando pwd
segnala la posizione attuale all’interno del fs:
andrea@ganimoide:~/Documenti$ pwd /home/andrea/Documenti
Come si vede il comando pwd
ha espanso la forma contratta
~/Documenti
La struttura delle cartelle all’interno del fs
è una struttura
gerarchica per cui:
e di conseguenza:
Ad esempio, la cartella Documenti
degli esempi precedenti è
contenuta nella cartella andrea
la quale è a sua volta contenuta
nella cartella home
. Infine, la cartella home
è contenuta nella
cartella principale del fs, la cartella /
( root ).
Per rappresentare questa situazione si utilizza la seguente scrittura
sintetica: /home/andrea/Documenti
All’interno di ogni cartella (ad eccezione di /
) esiste una cartella
speciale: ..
La cartella ..
rappresenta un collegamento alla cartella di ordine
superiore e permette di spostarsi su di essa.
andrea@ganimoide:~/Documenti$ cd .. andrea@ganimoide:~$ pwd /home/andrea
Il comando cp
copia file e cartelle in una cartella di destinazione:
andrea@ganimoide:~$ cp Documenti/relazione Documenti/relazioni/relazione
L’opzione -r
copia ricorsivamente anche le sottocartelle contenute
nella cartella di origine. In questo modo è possibile riprodurre nella
cartella di destinazione l’intera struttura della cartella di partenza.
andrea@ganimoide:~$ cp -r Documenti/ backups/
Il comando mv
ha una duplice funzione:
andrea@ganimoide:~$ mv Documenti/relazione Documenti/relazioni/ andrea@ganimoide:~$ mv Documenti/relazione Documenti/relazione_con_nuovo_nome
Esercizio
Utilizzando il terminale, consulta le pagine di manuale dei comandi
cp
e mv
.
Il comando rm
permette di rimuovere file e cartelle.
andrea@ganimoide:~$ rm Documenti/relazione
L’opzione -r
permette di rimuovere ricorsivamente anche le
sottocartelle e il loro contenuto.
L’opzione -f
(--force
) disabilita la richiesta di conferma di
eliminazione da parte dell’utente.
andrea@ganimoide:~$ rm -rf Documenti/relazioni
Il comando sopra rimuove la cartella relazioni
e tutte le
sottocartelle eventualmente contenute in essa.
Esercizio
Utilizzando il terminale, consulta le pagine di manuale del comando
rm
.
Per cercare file all’interno del fs la shell mette a disposizione il
comando find
.
Il comando find
è in grado di effettuare ricerche di file seguendo
svariati criteri.
Il caso più semplice consiste nel ricercare file in base al nome:
andrea@ganimoide:~$ find -name '*.png'
L’esempio precedente ricerca ricorsivamente a partire dalla cartella
in uso tutti i file con estensione png
.
find
può effettuare ricerche anche in base alla data di modifica dei
file:
andrea@ganimoide:~$ find Documenti -mtime 0
L’esempio mostra come ricercare nella cartella Documenti
tutti i
file che sono stati modificati nelle ultime 24 ore.
find
può eseguire dei comandi sui file identificati
andrea@ganimoide:~$ find -iname *.png -exec ls -l '{}' \;
La shell offre un potente strumento di archiviazione e compressione:
tar
.
Il comando tar
permette di archiviare in un unico file il contenuto
di più file.
Il comando tar
è in grado di utilizzare diversi algoritmi di
compressione tra cui i più efficaci sono:
Per estrarre i file da un archivio compresso in formato gzip:
andrea@ganimoide:~$ tar xvzf archivio.tar.gz
Vediamo il significato delle opzioni:
x
: estrae i dati da un archivioz
: indica il tipo di compressione (gzip)f
: specifica il nome file di archiviov
: visualizza sullo schermo lel informazioni relative
all’operazione in corsoPer estrarre i file da un archivio compresso in formato bzip2:
andrea@ganimoide:~$ tar xvjf archivio.tar.bz2
Il significato delle opzioni è lo stesso dell’esempio precedente con
la differenza dell’opzione j
che indica il tipo di compressione
bzip2.
Vediamo ora come creare un archivio compresso della cartella
Documenti/
utilizzando i due algoritmi di compressione (gzip e
bzip2).
andrea@ganimoide:~$ tar cvzf documenti.tar.gz Documenti/
andrea@ganimoide:~$ tar cvjf documenti.tar.bz2 Documenti/
Come si vede il comando tar
necessita in questo caso di due
argomenti: il nome del file di archivio e il nome della cartella da
archiviare.
Si noti pure l’utilizzo dell’opzione c
di creazione dell’archivio al
posto dell’opzione di estrazione x
.
I processi sono le attività in esecuzione in un sistema GNU/Linux.
Ad esempio, quando si invia un comando da shell, si attiva un processo che termina con la fine dell’esecuzione del comando.
I processi possono essere eseguiti in foreground o in background.
Il più delle volte i processi eseguiti in background sono applicazioni che non richiedono l’intervento dell’utente. Esse svolgono il proprio lavoro in modo silente, rimanendo “nascoste” all’utilizzatore.
Altre volte l’utente ha la necessità di lanciare un processo in background in modo da scorrelarne l’esecuzione dal terminale da cui è stato inviato il comando.
I processi eseguiti in foreground rimangono in uno stato di dipendenza dal terminale da cui sono stati eseguiti.
Per eseguire un processo in background si utilizza il simbolo &
dopo
il nome del comando:
andrea@ganimoide:~$ xman & [1] 17308
Il valore tra parentesi quadre indica il numero progressivo di processi eseguiti dal terminale in uso. Il secondo valore è detto PID ed è un codice che identifica univocamente il processo lanciato.
Il PID di un processo è di fondamentale importanza poichè una volta lanciato il comando in background esso viene sganciato dalla shell in uso. Tramite il PID possiamo continuare a tracciare e a controllare l’esecuzione di un processo.
Ad esempio, per terminare l’esecuzione del processo appena lanciato
( xman
) si utilizza il comando kill
seguito dal PID del processo:
andrea@ganimoide:~$ kill 17308 [1]+ Terminato xman
Per visualizzare le informazioni sui processi attualmente in
esecuzione nel sistema la shell mette a disposizione il comando ps
:
andrea@ganimoide:~$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 3056 1844 ? Ss Jan11 0:01 /sbin/init root 2 0.0 0.0 0 0 ? S< Jan11 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? S< Jan11 0:00 [migration/0] root 4 0.0 0.0 0 0 ? S< Jan11 0:16 [ksoftirqd/0] root 5 0.0 0.0 0 0 ? S< Jan11 0:00 [watchdog/0] root 9 0.0 0.0 0 0 ? S< Jan11 0:02 [events/0] root 11 0.0 0.0 0 0 ? S< Jan11 0:00 [khelper] andrea 5767 0.0 0.1 15064 2552 ? S 22:29 0:00 /usr/bin/gnome... andrea 5778 0.0 0.2 25272 6012 ? Ssl 22:29 0:00 x-session-manager ...
L’esempio nel riquadro mostra un estratto dell’output del comando ps
invocato con le seguenti opzioni:
a
e x
: visualizza tutti i processi in esecuzione sul sistema,
quelli lanciati dal terminale in uso e tutti gli altriu
: visualizza informazioni orientate alla lettura da parte
dell’utente (ad esempio visualizza i campi %MEM e %CPU)Vediamo il significato di alcune delle colonne nel riquadro di output dell’esempio precedente:
Un altro importante caratteristica del sistema a cui avremo direttamente accesso da una shell Unix sono le VARIABILI D’AMBIENTE (ENVIRONMENT VARIABLES).
Le variabili d’ambiente sono delle variabili associate ad ogni processo sul sistema, le quali sono accessibili (indipendentemente dal linguaggio di programmazione utilizzato) attraverso un API di sistema e vengono tramandate di processo padre in processo figlio.
Attraverso la definizione di variabili d’ambiente è possibile manipolare alcuni comportamenti della shell e dei comandi di shell Unix.
Per visualizzare le variabili d’ambiente definite nella shell in utilizzo è sufficiente eseguire il comando env :
$ env SSH_AGENT_PID=2147 TERM=rxvt SHELL=/bin/bash DESKTOP_STARTUP_ID=awesome/rxvt/2293-12-ubik_TIME0 XDG_SESSION_COOKIE=fc45766d472a9ef3a469d82849f26d2e-1240842893.978998-96478676 WINDOWID=88080386 GTK_MODULES=canberra-gtk-module USER=rpl ...
Per visualizzare e settare una singola variabile d’ambiente si utilizzano i comandi echo ed export
$ echo $USER rpl $ export TERM=xterm
La shell mette a disposizione una serie di strumenti orientati alla manipolazione dei flussi di dati.
Un flusso di dati si può definire come una quantità di informazione che viene trasferita da un punto all’altro del sistema.
Consideriamo, ad esempio, le informazioni contenute all’interno di un file. Nel momento in cui visualizziamo sullo schermo queste informazioni, abbiamo stabilito un flusso di dati dal file verso lo schermo del terminale.
Un flusso di dati può attraversare il sistema anche dall’esterno verso l’interno. Ad esempio, quando l’utente digita un carattere sulla tastiera, stabilisce un flusso di dati che dalla periferica hardware raggiunge il sistema.
Anche due o più processi possono scambiare tra loro flussi di dati. Ad esempio, il flusso di dati generato dalla lettura di un file può confluire in un comando che lo filtra o lo modifica.
I flussi di dati percorrono il sistema e costituiscono la sua linfa vitale. Controllare la circolazione dei flussi di dati significa controllare totalmente le informazioni elaborate dal sistema.
Lo schermo del terminale è generalmente il punto di arrivo predefinito
di ogni flusso di dati in uscita dall’elaboratore e diretto verso
l’utente. Per questo motivo, esso viene definito standard output
(stdout
).
Allo stesso modo, il flusso di dati generato dalla tastiera
dell’elaboratore e diretto verso il sistema è definito standard
input (stdin
).
Il binomio standard input/standard output si abbrevia in standard I/O.
Molti comandi della shell consentono di elaborare questi flussi di informazione in entrata e in uscita.
Ad esempio, il comando cat
legge il contenuto di un file e
visualizza il contenuto sullo stdout
.
andrea@ganimoide:~$ cat /proc/meminfo MemTotal: 2041400 kB MemFree: 88388 kB Buffers: 40864 kB ...
Nel riquadro sopra si vede il risultato prodotto dal comando cat
quando gli si passa come argomento il percorso di un file
(/proc/meminfo
) contenente le informazioni sulla memoria RAM del
sistema.
La shell permette di direzionare i flussi di dati su file.
Come abbiamo visto, il comando cat
produce un risultato sullo
stdout
(lo schermo del terminale). Nel riquadro sotto si vede come è
possibile ridirezionare il risultato di cat
in un file di nome
meminfo
.
andrea@ganimoide:~$ cat /proc/meminfo > meminfo
Questo tipo di sintassi consente di creare al volo file di testo:
andrea@ganimoide:~$ echo "Flusso di dati verso un file" > file_di_testo
Il comando echo
invia sullo stdout
la stringa passata come
argomento. L’operatore >
intercetta il flusso prodotto da echo
e
lo ridireziona verso un file di nome file_di_testo
.
L’operatore >>
svolge la stessa funzione di ridirezionamento
dell’operatore >
con la differenza che il flusso di dati viene
accodato al contenuto del file.
andrea@ganimoide:~$ echo "In coda a file_di_testo" >> file_di_testo
Due o più comandi (processi) possono scambiarsi flussi di dati
attraverso i pipes
(tubi).
Si può pensare ai pipes
come a dei raccordi di un sistema idraulico:
essi regolano il flusso delle informazioni da un punto all’altro del
sistema.
L’operatore pipe
è denotato dal simbolo |
.
In pratica, l’operatore |
collega l’output di un comando con l’input
di un altro.
andrea@ganimoide:~$ man ls | grep human -h, --human-readable with -l, print sizes in human readable format (e.g., 1K 234M 2G)
Nell’esempio riportato sopra, l’output del comando man
viene fatto
confluire nell’input del comando grep
.
Il comando grep
filtra le informazioni in ingresso alla ricerca
della parola “human”.
Il risultato finale è l’estrapolazione di una parte del manuale di
ls
riguardante l’opzione --human-readable
che consente di
visualizzare le dimensioni dei file in un formato facilmente
leggibile.
La shell offre la possibilità di utilizzare il risultato di un comando nell’invocazione di un altro. Questa operazione si dice sostituzione di comando.
Ad esempio, supponiamo di aver creato un file di nome da_rimuovere
contenente un elenco di file da rimuovere.
Il comando che segue visualizza su stdout
il contenuto del file.
andrea@ganimoide:~$ cat da_rimuovere *~ *.tmp
Per effettuare l’operazione di eliminazione dei file in modo automatico possiamo utilizzare la sostituzione di comando:
andrea@ganimoide:~$ rm $(cat da_rimuovere)
In questo modo, l’output del comando cat
(cioè l’elenco dei file da
rimuovere) viene passato come input al comando rm
che rimuove i
file.
Il comando cut
permette di visualizzare sullo stdout
parti del
contenuto di un file.
Il comando cut
risulta particolarmente utile per selezionare parti
di file delimitate da particolari caratteri.
Nel riquadro sotto viene mostrato un esempio di utilizzo del comando
cut
. In particolare, interrogando il file /etc/passwd
, si vuole
ricavare l’elenco degli utenti accreditati nel sistema.
andrea@ganimoide:~$ cut -d: -f1 /etc/passwd root daemon ...
L’opzione -d
consente di stabilire il carattere delimitatore in base
al quale suddividere il contenuto del file in colonne.
L’opzione -f
stabilisce quale colonna visualizzare.
L’argomento /etc/passwd
corrisponde al nome del file da processare.
L’utilizzo del comando cut
consente di estrapolare dalla grande
quantità di informazioni contenute nel file /etc/passwd
, solo i
contenuti di interesse.
Il comando paste
permette di unire due o più flussi di dati in
colonne verticali.
Supponiamo di poter visualizzare il contenuto di due file:
andrea@ganimoide:~$ cat file_1 A B C andrea@ganimoide:~$ cat file_2 1 2 3
Il comando paste permette di fondere il contenuto di file_1
e
file_2
separando ogni elemento con il carattere ‘:’
andrea@ganimoide:~$ paste -d':' file_1 file_2 A:1 B:2 C:3
Per esercizio, provate a ridirezionare l’output del comando precedente in un nuovo file.
Il comando tr
sostituisce o rimuove un particolare carattere (o una
classe di caratteri) dal flusso di dati in ingresso.
Nell’esempio che segue si sostituiscono tutti i caratteri maiuscoli con i corrispondenti caratteri minuscoli:
andrea@ganimoide:~$ cat file_1 | tr A-Z a-z
Il comando tr
può ricevere come argomento una classe di caratteri:
andrea@ganimoide:~$ cat file_1 | tr -d [:digit:]
Il comando precedente rimuove (opzione -d
) dal flusso di dati in
ingresso tutti i caratteri numerici. In questo caso la classe dei
numeri è indicata dall’argomento [:digit:]
Infine, per rimuovere tutti gli spazi ripetuti (squeeze-repeats) all’interno di un flusso:
andrea@ganimoide:~$ cat file_1 | tr -s [:blank:]
Il comando sort
permette di ordinare i dati contenuti in un flusso.
Supponiamo di voler disporre in ordine alfabetico i nomi degli utenti
del sistema. Ridirezionando l’output del comando cut
attraverso
l’operatore |
possiamo scrivere:
andrea@ganimoide:~$ cut -d: -f1 /etc/passwd | sort andrea avahi avahi-autoipd ...
Il comando sort
può essere utile per ottenere rapidamente alcune
statistiche relative all’utilizzo delle risorse di sistema:
andrea@ganimoide:~$ ps -eo pmem,cmd | sort -k 1 -n -r 33.7 /usr/lib/firefox-3.0.5/firefox 5.2 /usr/X11R6/bin/X :0 -br -audit 0 -dpi 96 -auth /var/lib/gdm/:0.Xauth -nolisten tcp vt7 ...
L’esempio sopra mostra la percentuale di memoria di sistema utilizzata
da ogni singolo programma in esecuzione. I dati sono ordinati in modo
decrescente (opzione -r
).
Un comando molto utile per la consultazione dei registri di sistema è
tail
.
Il comando tail
visualizza sullo stdout
le ultime linee di un
file.
andrea@ganimoide:~$ tail /var/log/messages Jan 18 16:33:36 ganimoide kernel: [148883.736086] usb 1-1: new low speed USB device... ...
L’esempio precedente mostra un utilizzo tipico del comando tail
,
cioè la lettura delle ultime linee del file /var/log/messages
che
registra molte importanti informazioni circa lo stato del sistema.
Un’opzione molto utile del comando tail
è -f
.
Quest’opzione consente di visualizzare in tempo reale i cambiamenti all’interno di un file permettendo all’utente di ottenere un feedback immediato sullo stato del sistema.
Al comando tail
si contrappone il comando head
che visualizza la
parte iniziale di un file.
I comandi less
e more
permettono di impaginare flussi di dati che
non possono essere visualizzati interamente sul terminale.
Ad esempio, se si provasse a visualizzare il contenuto del file
/var/log/messages
all’interno di un terminale di dimensioni
standard, probabilmente non si riuscirebbe a contenere tutto il flusso
di dati prodotto.
Il comando less
produce una versione impaginata del contenuto del
file.
andrea@ganimoide:~$ less /var/log/messages
Sfruttando l’operatore |
il comando less
è in grado di impaginare
un flusso di dati qualsiasi.
andrea@ganimoide:~$ cat /var/log/messages | less
Lavorando su sistemi particolarmente limitati, il comando less
potrebbe non essere disponibile. In tal caso, il comando more
,
seppur più primitivo, presenta le medesime funzionalità base di
less
.
In un ambiente potente come la shell di sistema non possono mancare strumenti in grado di effettuare ricerche all’interno dei flussi di dati.
Ricercare all’interno di un flusso di dati ha un duplice scopo:
L’ambiente bash contiene numerosi strumenti per la ricerca e il filtraggio delle informazioni.
Molti di questi strumenti si basano sul concetto di espressioni regolari.
Le espressioni regolari sono dei particolari costrutti attraverso i quali è possibile descrivere i criteri di ricerca di determinati schemi ripetuti.
Nel seguito, dove necessario, utilizzeremo espressioni regolari molto semplici.
Alle espressioni regolari verra dedicata una lezione apposita.
Il comando grep
consente di ricercare/filtrare informazioni
all’interno di un flusso di dati.
andrea@ganimoide:~$ cat frutta.txt mele pere pompelmi arance andrea@ganimoide:~$ cat frutta.txt | grep pompelmi pompelmi
L’esempio precedente mostra il risultato prodotto da grep
nell’elaborare il flusso di dati alla ricerca della parola ‘pompelmi’.
L’esempio che segue mostra il filtraggio dell’output di ls
alla
ricerca di tutti i file con la prima lettera del nome maiuscola.
andrea@ganimoide:~$ ls | grep ^[A-Z] Documenti Examples Immagini Modelli
sed
sta per stream editor ovvero un programma in grado di
effettuare ricerche e sostituzioni all’interno di un flusso di dati.
sed
è un software molto potente che offre svariate
funzionalità.
Tuttavia, la funzione più utilizzata è quella di sostituzione.
andrea@ganimoide:~$ echo "prendere fischi per fiaschi" | sed 's/fischi/fiaschi/' prendere fiaschi per fiaschi
Il comando echo
nell’esempio sopra produce un flusso di dati che
viene elaborato da sed
.
L’elaborazione consiste nella ricerca della parola ‘fischi’ e nella sostituzione della stessa con la parola ‘fiaschi’.
Oltre al comando sed
, la shell mette a disposizione gawk
un vero e
proprio linguaggio di programmazione orientato all’elaborazione di
file di testo (o flussi di dati).
La funzione basilare di gawk
è quella di cercare degli schemi
ripetuti (patterns) all’interno di flussi di dati. Quando uno schema viene
identificato, gawk
è in grado di eseguire una determinata azione
programmata dall’utente.
La sintassi base di gawk è la seguente:
awk ‘pattern {action}’ input_file
dove pattern è in generale una espressione regolare.
Una discussione approfondita su linguaggio gawk
esula dagli
obiettivi di questa lezione, tuttavia, si vogliono dare alcuni esempi di utilizzo di
questo potente linguaggio.
andrea@ganimoide:~$ ls -l | awk '/Immagini/ { print }' drwxr-xr-x 3 andrea andrea 4096 2009-01-16 12:51 Immagini
L’esempio precedente va interpretato in questo modo:
ls
visualizza l’elenco delle cartelle in /home/andrea
|
collega l’output di ls
all’input di awk
awk
cerca all’interno del flusso di dati in ingresso la
parola Immagini
; se la trova stampa la linea che la contiene.In questa slide vediamo alcuni esempi che combinano le conoscenze sulla linea di comando che abbiamo acquisito:
Crea un file contenente il nome degli utenti del sistema.
andrea@ganimoide:~$ awk -F":" '{ print $1 }' /etc/passwd > utenti
Visualizza la history della linea di comando e la impagina tramite less.
andrea@ganimoide:~$ history | less
Visualizza gli ultimi quattro comandi inviati:
andrea@ganimoide:~$ history | tail -4
Rimuove dalla cartella documenti tutti i file di backup:
andrea@ganimoide:~$ find -name '*~' | xargs rm