AWK e Linea di Comand

La shell di Linux è uno strumento potentissimo che permette di velocizzare ed automatizzare le più svariate operazione. Dato che in Linux ogni cosa è un file, sono di fondamentale importanza quegli strumenti che permettono di analizzare e gestire i file.

Spessissimo i file con cui si ha a che fare nelle attività sistemistiche sono dei rudimentali database strutturati con i record in righe e i campi in colonne. In questa categoria rientrano ad esempio i file passwd e moltissimi file di log.

Per poter automatizzare operazioni su questo tipo di file è necessario uno strumento che dia accesso a specifici campi nei vari record. Come sempre in ambiente UNIX/Linux è possibile procedere in diversi modi ma uno strumento di sicuoro interesse è awk. Si tratta di uno di quei tool la cui conoscenza non dovrebbe mancare a nessun sistemista.

Nella sua forma più semplice awk accetta in stdin un file, e permette di estrarre dei campi da ogni riga.

Ed esempio se volessi estrarre gli utenti che hanno script schedulati nel seguente file crontab:

17 * * * * root cd / && run-parts –report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts –report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts –report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts –report /etc/cron.monthly )
potrei utilizzare la seguente righa di comando:

cat /etc/crontab | awk ‘{print $6}’
all’interno di awk ogni campo, infatti, è contenuto in una variabile $n, dove n è il numero del campo ed i campi sono separati de default da spazi. L’intera riga è contenuta nella variabile $0. Ci sono molte altre variabili predefinite in awk e la lista completa è riportata nel suo manuale (man awk). Una menzione la merita $NR che contiene il numero della riga che si sta elaborando.

Non in tutti i file il separatore è lo spazio; l’opzione -F permette di scegliere un separatore differente.

awk può essere utilizzato come filtro sfruttando il costrutto if al suo interno:

Ad esempio se voglio sapere quali utenti non hanno una shell reale posso utilizzare:

cat /etc/passwd|awk -F: ‘{if ($7==”/bin/false”) print $1}’
Di grande interesse anche i costrutti BEGIN ed END che permettono di definire blocchi di operazioni da eseguire prima o dopo l’esame del file. Posso ad esempio riscrivere lo stesso esempio di prima come:

cat /etc/passwd|awk ‘BEGIN{FS=”:”}{if ($7==”/bin/false”) print $1}’
awk è un vero e proprio linguaggio di programmazione anche se abbastanza semplice, e le possibilità che offre sono molto ampie; nondimeno la sua utilità è soprattutto nelle sue forme più semplici dove, con molta semplicità, permette di improvvisare filtri o operazioni anche molto sofisticati.

Concludo con un esempio dove mostro come awk può essere utilizzato per calcolare la durata media delle slow query a partire da un file di log di mysql:

cat mysql-slow.log |grep Query_time|awk ‘{cont++;totale+=$3}END{media=totale/cont; pr