Va detto che le due cose dipendono una dall'altra. Una pipe è un meccanismo messo a disposizione dal sistema che permette di mettere in comunicazione due processi. Senza la capacità di redirigere i flussi però non si avrebbe la necessaria flessibilità per permettere di arrivare alla filosofia del "poco ma ben fatto".
Mi spiego meglio: una delle caratteristiche dei tool di Unix, a differenza di quelli di Multix, è assere realizzati per svolgere una sola semplice funzione nel miglior modo possibile.
Un esempio pratico è il comando cat, che a prima vista non fà nulla di utile; provate ad aprire una Shell e a dare il comando cat:
:~$ catA cosa serve un programma del genere? Se non esistesse modo di redirigere i flussi e creare pipe praticamente a nulla! Ma, con i dovuti supporti del sistema operativo, cat mi può servire a mille scopi.
questo ripete tutto quello che scrivo
questo ripete tutto quello che scrivo
quando batto invio lui ripete la riga pari-pari
quando batto invio lui ripete la riga pari-pari
a prima vista sembrerebbe una cosa assurda
a prima vista sembrerebbe una cosa assurda
ma chi usa Unix non potrebbe farne a meno
ma chi usa Unix non potrebbe farne a meno
per uscire da questa situazione premo ctrl+d
per uscire da questa situazione premo ctrl+d
:~$
I flussi e la redirezione:
Partiamo dal concetto base, forse un poco spartano a dire il vero, per il quale: per Unix tutto è un file! Con tutto intendo anche tastiera e monitor/video. Questo può sembrare una masochistica complicazione ma, in realtà, ci facilita la vita in una maniera impressionate (sia a livello di realizzazione che utilizzo di un software)! Vediamo il perchè:
- Ho un programma che legge i dati da tastiera e li scrive a video.
- La tastiera è un file.
- Il video è un file.
- Il mio programma può leggere da un file.
- Il mio programma può scrivere su un file.
- Un processo può aprire (avere accesso a, se preferite) file durante l'esecuzione del suo programma
- Un file aperto, da un processo, lo chiameremo flusso
- I file si possono aprire nelle due modalità (in realtà sono di più di due, ma per ora va benone così) lettura o scrittura.
- stdin: lo standard input, normalmente la tastiera (lettura)
- stdout: lo standard output, normalmente lo schermo (scrittura)
- stderr: lo standard error, normalmente lo schermo (scrittura)
:~/esempi$ lsLa directory esempi era vuota, lo si vede dall'output del primo ls. Dopo l'esecuzione di cat invece è comparso il file pippo.txt. Cosa è successo?
:~/esempi$ cat > pippo.txt
Ora scrivo ma cat non ripete
le mie righe a video...
Come mai?
Semplice, le stà scrivendo dentro al file pippo.txt
... provare per credere!
:~/esempi$ ls
pippo.txt
:~$
Abbiamo "imbrogliato" cat sostituendogli il flusso verso lo schermo con quello verso il file pippo.txt, che è stato appositamte creato. Tutto stà nel simbolo di redirezione dell'output >. Ora se aprissimo pippo.txt con il nostro editor di testo preferito vedremmo che contiene le righe da noi scritte. Ma, visto che vogliamo redirigere, possiamo anche usare cat per verificare. L'output di $cat < pippo.txt sarà:
Ora scrivo ma cat non ripeteQuindi, per redirigere l'input usiamo il simbolo <. La faccenda non è difficile da ricordare, basta considerare i simboli di redirezione come frecce:
le mie righe a video...
Come mai?
Semplice, le stà scrivendo dentro al file pippo.txt
... provare per credere!
- Redirezione input - freccia da file al programma: $nomeprog < file_input
- Redirezione output - freccia da programma al file: $nomeprog > file_output
- Redirezione input e output: $nomeprog > file_output < file_input
- Redirezione stdout in modalità append: $nomeprog >> file_output
Pipes:
Tubi è il nome che meglio si addice a queste particolari strutture messe a disposizione da Unix. Abbiamo visto come sia facile sostituire lo stdin di un processo con un file. Abbiamo visto come sia facile farlo anche con lo stdout.
Sarebbe bello, a questo punto, vedere se si può sostituire lo stdin di un processo con lo stdout di un'altro. Secondo voi?
Dobbiamo pensare la pipe esattamante come un tubo. Un tubo attraverso il quale non scorre acqua ma caratteri. Mettere in pipe due processi significa collegarli.
Uno sguardo veloce a grep:
:~/esempi$ grep pippoQuindi dare un comando come $grep pippo vuol dire cercare nello stdin tutte le righe che contengono la parola "pippo". E se volessimo controllare quali righe contengono la parola "video" nel file pippo.txt?
grep non è come cat
lui non ripete tutte le righe
ma solamente quelle che gli ho detto di cercare
in questo caso particolare solo quelle che
contengono la parola pippo
contengono la parola pippo
Mario và al mare
pippo và in montagna
pippo và in montagna
per uscire uso ctrl+d
:~/esempi$
:~/esempi$ cat pippo.txt | grep videoE così abbiamo scoperto come si possono mettere in comunicazione due processi tramite pipe: $nomeprog1 | nomeprog2. Il simbolo che usiamo per creare le pipe è |. Mi rendo conto che l'esempio è stupido, infondo possiamo ottenere lo stesso risultato con: $grep video < pippo.txt. Ma è un caso dovuto alla semplicità dell'esempio. Mettiamo invece di voler controllare se sul nostro sistema gira apache:
le mie righe a video...
:~/esempi$
:~/esempi$ ps ax | grep apacheComodo no? Senza pipe non avremo potuto dire a grep di cercare per noi nell'output di ps. Se volete avere un'idea di come la faccenda semplifichi estremamente la vita provate a dare un $ps ax e a cercare voi stessi quello che vi interessa.
2958 ? Ss 0:00 /usr/sbin/apache2 -k start
2996 ? S 0:00 /usr/sbin/apache2 -k start
2997 ? S 0:00 /usr/sbin/apache2 -k start
2998 ? S 0:00 /usr/sbin/apache2 -k start
2999 ? S 0:00 /usr/sbin/apache2 -k start
3000 ? S 0:00 /usr/sbin/apache2 -k start
3386 pts/0 R+ 0:00 grep apache
In fine dei conti una pipe è un speciale file, temporaneo, che viene sostiuito allo stdout del primo programma, della linea di comando, e, contemporanemamte, allo stdin del secondo. Ci permette quindi di redirigere l'output di un processo nell'input di un'altro.
Anche le pipes possono essere multiple:
$prog1 | prog2 | prog3 | prog4
Un riassuntino grafico può aiutare a fissare le idee?
Redirezione stdout: $ prog > file
Redirezione stdin: $ prog < file
Pipe: $ prog1 | prog2
Immagini realizzate con Dia: http://live.gnome.org/Dia
Nessun commento:
Posta un commento