In un precedente pezzo ho scritto qualche parola su tee e vi raccontavo che la sua principale limitazione era l’impossibilità di registrare quanto stava accadendo sullo standard error. Vista la natura introduttiva del pezzo ho preferito non tediarvi con le giocolerie possibili con i file descriptor e restare concentrato sul comando.
Ora è venuto il momento, nel frattempo ho studiato, di affrontare il problema e fare qualche gioco di prestigio con stderr e stdout. Tutto questo senza l’ausilio di altro che le nostre dita, una tastiera e la nostra amata, odiata,mai indifferente, bash. La carne al fuoco è tanta e quindi ho deciso di dividere il tutto in più parti.
Partiamo con un minuscolo script d’esempio per introdurre i file descriptor ed i comandi di redirezione.
#!/bin/bash
echo "Questo è un messaggio indirizzato allo standard error" 1>&2
echo "Questo è un messaggio indirizzato allo standard output" 1>&1
Non penso ci sia davvero bisogno di spiegare quello che fa 🙂 . Mi preme solamente illustrare la sintassi >&d, ma, prima, parliamo dei file descriptor, che non sono altro che delle astrazioni, dei segnaposto, di file aperti in lettura o scrittura.
Ad ogni programma, anche agli script bash, a voler essere precisi alla shell che esegue lo script, sono associati almeno tre file descriptor: uno per l’input, stdin, uno per l’output, stdout, ed uno, stderr, per la segnalazione degli errori. Hanno, nell’ordine, indice 0, 1 e 2.
Bash mette a disposizione due operatori, il man li chiama metacaratteri, per la redirezione: < e >.
Il loro uso è semplice e lo conoscerete già, ad esempio
echo 'hello file!' > nome di un file
fa in modo che la shell invii ‘hello file!’ ad un file piuttosto che al mondo intero. Abbiamo appena rediretto l’output su file. Analogamente l’operatore < permette di redirigere l’input e quindi possiamo restituire al mondo il saluto che gli dobbiamo con cat < file.
Se pensate che sia sconveniente salutare il mondo apostrofandolo file provate con
sed “s/file/world/” file | cat 🙂
Utilizzando >& al posto del semplice > è possibile redirigere i file descriptor tra di loro piuttosto che su file presenti sul filesystem (non ho scritto disco perché sarebbe inesatto).
A questo punto possiamo interpretare il comando
echo "Questo è un messaggio indirizzato allo standard error" 1>&2
come invia allo standard outpu (è quello che fa echo) la stringa “Questo è un messaggio indirizzato allo standard error” e subito dopo aggiungiamo: a proposito, invia i dati che passano per standard output (1) dove vanno a finire i dati destinati allo standard error (2). Solitamente si usa la versione >&2 che sottintende 1 (stdout) come file descriptor di partenza. Il secondo comando presente nello script poteva tranquillamente limitarsi a
echo "Questo è un messaggio indirizzato allo standard output"
ma se non sono prolisso non mi diverto.
La redirezione finisce qui, per ora, abbiamo tutti i concetti base per proseguire con i nostri esperimenti ma ho ormai scritto troppo e vi rimando ad un prossimo approfondimento.