Aggiornato Giugno 2008
Aggiornato Maggio 2009


________________________________________________________________________________________

Linux script e Asterisk (by GF 2008)

_________________________________________________________________________________________________

Questo documento mira ad insegnare a chi ha una conoscenza di base del sistema operativo Linux una serie di comandi di shell di elaborazione del testo.

 

Dati in input

Sia assegnato il file di nome "prova"

1 2 3 4 5 6
bianco giallo verde blu
bianco arancione rosso
1 2 10 11 12 13
Tabella 1


 

Grep

Problema: Ritornare tutte le righe che fanno match con una espressione regolare.
Note:  ".*"  indica una sequenza di un qualsiasi numero di qualsiasi tipo di carattere
          

grep  "bianco.*blu" prova

bianco giallo verde blu

Problema: Ritornare tutte le righe che NON fanno match con una espressione regolare.
Note:  "-v" e' un NOT ovvero fa il reverse del risultato
           

grep -v "bianco.*blu" prova

1 2 3 4 5 6
bianco arancione rosso
1 2 10 11 12 13

Problema: Ritornare il numero di righe che fanno match con una espressione regolare
Note:  "-c" indica di ritornare il numero di righe che fanno match, o non fanno match (-cv) con una espressione regolare
           

grep -c "bianco" prova
2

grep -cv "10" prova
3

Problema: Ritornare il nome dei file che contengono/non contengono match con una espressione regolare
Note:  "-l" indica di ritornare il nome dei file che fanno match con una regex. "-L" ne e' la negazione.
           

grep -l "bianco" *
bianco

grep -L "bianco" *
file1
file2
file3

 

Problema: Ritornare la riga contenente il match e un certo numero di righe antecedenti o successive
Note:  "-A" indica di ritornare la riga che fa match e la successiva, "-B" l'antecedente
           

grep -A1 "bianco.*rosso" prova
bianco arancione rosso
1 2 10 11 12 13

grep -B1 "bianco.*rosso" prova
bianco giallo verde blu
bianco arancione rosso

Problema: Ritornare la riga contenente il match e la posizione della riga nel file
Note:  "-n" ritorna in numero di riga dove e' stato trovato il match
           

grep -n "bianco" prova
2:bianco giallo verde blu
3:bianco arancione rosso
 

Grep avanzato

 Enhanced regular expression

   L'opzione "-E" permette di utilizzare le enhanced regular expression.  Il carattere speciale "\" (backslash) assume ruolo differente nel caso di enhanced regexp dove si presuppone che un carattere speciale sia un metacarattere piuttosto che un carattere letterale.

    I metacaratteri "(, ), {, }" vanno preceduti da "'\"  nelle basic regular expression.
 

1 2 3 4 5 6
bianco giallo verde blu
bianco (arancione 2) rosso
1 2 10 11 12 13
Tabella 2

 

grep "(arancione)" prova

 

 

Le parentesi vengono interpretate come elementi di testo pertanto si cerca una match con "(arancione)" che non esiste
grep -E "(arancione)" prova
bianco (arancione 2) rosso

 
In questo caso le parentesi vengono interpretate come metacaratteri, in quanto con il "\" sarebbero interpretate come elementi di testo. Quindi le parentesi indicano una subregexp che rappresenta una riga contenente "arancione"
grep -E "\(arancione 2\)" prova
bianco (arancione 2) rosso
In questo caso si usa il "\" per indicare che le parentesi non sono metacaratteri ma caratteri regolari.
grep "\(arancione\)" prova
bianco (arancione 2) rosso
 
Si vede come l'interpretazione del backslash nel caso di regular regexp e' invertito rispetto che nelle extended regexp.

 

    Come si evince da questo esempio metacaratteri "(, ), {, }" vanno preceduti da "'\"  nelle basic regular expression.
 

grep -E ".*2[[:space:]][0-9]{1,2}[[:space]]11.*" prova
1 2 10 11 12 13

grep ".*2[[:space:]][0-9]{1,2}[[:space]]11.*" prova

grep ".*2[[:space:]][0-9]\{1,2\}[[:space]]11.*" prova
1 2 10 11 12 13

    Cerchiamo una riga contenente "2 " quindi un numero di una o due cifre e quindi un " 11"

 Backreference

    In una regexp un backreference e' un riferimento ad un match gia' ottenuto, gia' segnato con le parentesi tonde. I backreference si indicano con "\n" dove "n" e' un numero indicante il backreference.

Ad esempio  "<h1>titolo</h1>"  e' un elemento html indicante un titolo. Per fare match potremmo utilizzare "<h[1-9]>titolo</h[1-9]>". Tuttavia questo fa match anche con "<h1>titolo</h3>". Abbiamo bisogno di un riferimento all'indietro, ovvero di un backreference. Allora scrivendo "<h\([1-9]\)>titolo</h\1>" abbiamo il risultato voluto. Il riferimento all'indietro della posizione numero 1 indica la prima coppia di parentesi tonde che racchiudono il numero che ci interessa.

Un uso possibile del backreference e' anche quello di tirare fuori, dalle righe restituite dal grep, le parole che hanno fatto match. Per questo possiamo usare il comando "sed" insieme a cron. Questa e' una procedura valida per estrarre da file di testo dei dati variabili restituiti ad esempio, da comandi inviati a software amministrabili da remoto. Ad esempio si pensi ad un'analisi dell'output di un comando "show interfaces" di un router Cisco o di un comando "show channels" di una centrale Asterisk:

cat prova  |  grep -E "1.*3"  |   sed "s/1[[:space:]]\([0-9]\)[[:space:]]3.*/\1/"

2

Il cat manda a grep uno o piu' file di testo. Il grep tira fuori solo le righe che interessano, in questo caso quelle contenenti i numeri 1 e 3. Successivamente sed tira fuori il valore numerico tra il numero 1 e il numero 3. Per far cio' utilizza un backreference "\1" al valore numerico. Si noti che sed sostanzialmente cambia una riga sostituendola con la stringa di cui abbiamo fatto il backreference, che e' quella che interessa.

Sed

Consideriamo sempre il file di input in tabella 1, che ripresentiamo per comodita':

1 2 3 4 5 6
bianco giallo verde blu
bianco arancione rosso
1 2 10 11 12 13

Il comando "sed" effettua trasformazioni sui testi, quali ad esempio ricerche e sostituzioni.

Problema: Sostituire la parola 'bianco' con 'blu' in tutto il file
Note:  la sintassi del comando sed utilizza lo slash ('/') per delimitare le varie sezioni. "s" indica la sostituzione mentre 'g' indica che vogliamo sostituite tutte le occorrenze in una riga e non solo la prima (questo e' opzionale).
          

sed  's/bianco/blu/g' prova

1 2 3 4 5 6
blu giallo verde blu
blu arancione rosso
1 2 10 11 12 13

Problema: Cancellare la parola "bianco" da tutto il file
Note:  una cancellazione di una parola non e' altro che un caso particolare di sostituzione
          

sed  's/bianco//g' prova

1 2 3 4 5 6
 giallo verde blu
 arancione rosso
1 2 10 11 12 13

 

Problema: Sostituire la parola 'bianco' con 'blu' in righe specifiche del file
Note:  aggiungiamo una nuova condizione al comando sed, indicante su quali righe la sostituzione va effettuata. Questa condizione va a inizio riga e indica il numero di riga. Se indicata tra "/", allora e' una espressione regolare, che risolta indica su quali righe la sostituzione va effettuata.
          

sed  '2  s/bianco/blu/g' prova

1 2 3 4 5 6
blu giallo verde blu
bianco arancione rosso
1 2 10 11 12 13

sed  '2,4  s/bianco/blu/g' prova     <-- dalla 2a alla 4a riga
                                    <-- il '$' indica l'ultima riga
1 2 3 4 5 6
blu giallo verde blu
blu arancione rosso
1 2 10 11 12 13

sed  '/.*ver.*/  s/bianco/blu/g' prova

1 2 3 4 5 6
blu giallo verde blu
bianco arancione rosso
1 2 10 11 12 13

Problema: Estrarre parti da un file cancellando intere righe
Note:  la lettera 'd' indica la cancellazione. Cancellando l'intero file tranne alcune righe, si ottiene il risultato di visualizzare le righe volute. Con il secondo esempio si utilizza "-e" che consente di specificare piu' comandi sed in sequenza, in questo caso due. Il primo toglie tutte le righe che iniziano con "1" e il secondo toglie le righe vuote, che sono quelle che iniziavano con "1". Si noti che la cancellazione ha la negazione che si ottiene con "!d".
          

sed  '2,$ d' prova

1 2 3 4 5 6

sed -e 's/1.*//' -e '/^$/ d' prova

blu giallo verde blu
bianco arancione rosso
 

Problema: Aggiungere linee e cambiare linee
Note:  Con il comando "a" si aggiunge una riga a quella successiva di un  match. Con "i" si aggiunge una riga a quella precedente il "match". Con "c" si sostituisce una linea.
          

sed  '/bianco/ a\la riga precedente contiene bianco' prova

1 2 3 4 5 6
bianco giallo verde blu
la riga precedente contiene bianco
bianco arancione rosso
la riga precedente contiene bianco
1 2 10 11 12 13

sed  '/bianco/ i\la riga successiva contiene bianco' prova

1 2 3 4 5 6
la riga successiva contiene bianco
bianco giallo verde blu
la riga successiva contiene bianco
bianco arancione rosso
1 2 10 11 12 13

sed  '/bianco/ c\questa riga conteneva bianco' prova

1 2 3 4 5 6
questa riga conteneva bianco
questa riga conteneva bianco
1 2 10 11 12 13
 

 

 

Problema: Estrazione di una espressione regolare da un file
Note:  con il backreference (vedi grep) possiamo estrarre una espressione regolare da un file. Questo e' utile nel caso in cui ci siano parti di un file variabili, ad esempio, perche' output di sistemi di visualizzazione dati. Supponiamo di voler visualizzare cosa c'e' tra il numero 10 e il numero 12, immaginando che cio' che si trova tra questi due numeri non e' un dato fisso. Ricordiamoci che le espressioni regolari oggetto di backreference devono essere tra parentesi tonda. Per capire meglio il principo modifichiamo il file 'prova' file di input e proponiamoci di estrarre il valore numerico di traffico in input:
 

Traffico in input: 244245 bytes
Traffico in output: 37444 bytes

Tabella 3


          

sed  -e 's/.*input: \([0-9]*\).*/\1/' -e '/output/ d' prova

244245

 

 

Awk

  Abbiamo visto come con grep sia possibile estrarre righe ben precise da un file, con sed sia possibile effettuare modifiche in un file. Con awk e' possibile elaborare i dati in un file interpretandolo come una tabella. Consideriamo questo file di esempio:

 

nome cognome citta' nascita
marco privitera catania 1972
salvo giuffrida palermo 1980
daniele nauta messina 1985
santo micale catania 1960
Tabella 4

Osservate il seguente comando:

awk '/catania/ {if ($4>1960) print $1"-"$2" anno: "$4}' prova

marco-privitera anno: 1972

Con awk il file in tabella 4 viene interpretato come una tabella di database con spazio come separatore. Le varie colonne sono richiamabili tramite il comando '$'. La prima parte del comando, in rosso, e' un filtro sulla riga, opzionale. La parte in verde, anch'essa opzionale, rappresenta una condizione. In questo esempio cerchiamo in tabella i nomi di chi e' nato successivamente del 1972 a Catania. Come si vede ci sono delle similitudini con operazioni fatte con SQL in tabelle di database. In casi semplici, awk e' un ottimo strumento di analisi.

 

 

 

 

________________________________________________________________________________________

Applicazione ad Asterisk

_________________________________________________________________________________________________

 

 

Problema: Vogliamo filtrare l'output del comando "show channels" per interpretare lo stato delle linee (Zaptel)

Soluzione:

Interpretando l'output del comando "show channels" si deduce:

-
Le chiamate entranti dall'esterno possiamo estrapolarle considerandon le righe con Channel SIP e Application del tipo "bridged call Zap/NN"
- Le chiamate uscenti possiamo estrapolarle considerando le righe con Channel SIP e Application del tipo Dial(Zap/g1...
 

asterisk -rx "show channels"  |  grep -E "SIP.*Zap/[0-9]{1,2}.*"  |  sed 's/.*SIP\/\([0-9]\{2,3\}\).*Zap\/\([0-9]\{1,2\}\).*/\1 \2/'



Analisi:

Il comando "show channels" restituisce un elenco delle conversazioni in corso e dei canali ad essi associati.

1. Consideriamo (grep) solo le righe contenenti un canale sip (ad es. SIP/200) ed uno zaptel (ad es. Zap/24)
2. Preleviamo (sed) le espressioni regolari relative alla coppia data dal canale sip (ad es.200) e quello zaptel (ad es. 24)

Note:

1. "sed" fa sostituzioni. Se in una riga di un file non trova match lascia la riga inalterata. Per questo motivo e' necessario che grep faccia trovare a sed solo righe che contengono entrambe le espressioni regolari volute.
2. In questo esempio si presuppone che si adotti una numerazione SIP a 2 o 3 cifre e i canali zap siano ad 1 o 2 cifre.
3. Si ricorda che le parentesi graffe in una espressione regolare rappresentano il numero di ripetizioni che puo' avere un pattern indicato in precedenza. In questo esempio [0-9]{1,2} indica una o due cifre;
4. Si ricorda che \1 e \2 rappresentano il richiamo di una parte di espressione regolare delimitata dalle parentesi tonde. Ad esempio ".*([0-9]{2}).*" permette di tenere traccia di una coppia di numeri all'interno di una espressione piu' complessa e di richiamarla successivamente utilizzando "\1";
5. L'espressione regolare va modificata per chiamate che non utilizzano Zaptel (chiamate SIP<->SIP o SIP<->IAX per esempio)

6. Parentesi tonde e graffe vogliono il backslash. Anche il carattere slash vuole il backslash

 

 

Esempio:

[root]# asterisk -rx "show channels"
Channel             Location             State     Application(Data)
SIP/504-08e89250    1018@agentsliv1:1     Up         Bridged Call(Zap/61-1)
Zap/61-1            s@macro-coda:12       Up         Queue(codalivello1|t)
Zap/2-1                (None)             Up         Bridged Call(SIP/500-b7411ab0)
SIP/500-b7411ab0    06016605@ingresso:    Up         Dial(Zap/g1/6806685)
SIP/511-08e4e290    1019@agentsliv1:1     Up         Bridged Call(Zap/55-1)
Zap/1-1             (None)                Up         Bridged Call(SIP/501-b740fd48)
SIP/501-b740fd48    01788198@ingresso:    Up         Dial(Zap/g1/1786898)
Zap/55-1            s@macro-coda:12       Up         Queue(codalivello1|t)
8 active channels
4 active calls
[root@ ~]# cat showchannels | grep -E "SIP.*Zap/[0-9]{1,2}.*" | sed 's/.*SIP\/\([0-9]\{2,3\}\).*Zap\/\([0-9]\{1,2\}\).*/\1 \2/'

504 61
511 55

 

Altro:
Nel caso in cui utilizziate il gruppo g1 per le chiamate uscenti potete identificarle con questo comando:

grep -E "SIP.*Zap/g1.*" | sed 's/.*SIP\/\([0-9]\{2,3\}\).*Zap\/g1\/\([0-9]\{3,13\}\).*/\1 \2/'

 

Per vedere semplicemente quali canali di tipo SIP sono in uso:

[root@ ~]# cat showchannels | grep "SIP" | sed 's/.*\(SIP\/[0-9]\{2,3\}\).*/\1/' | uniq
SIP/504
SIP/500
SIP/511
SIP/501

 

Notate il comando "uniq" che elimina eventuali righe duplicate

 

 

________________________________________________________________________________________

Script di trasferimento file tramite ftp previa verifica raggiungibilita' ICMP

_________________________________________________________________________________________________

    Questo script bash e' stato utilizzato per automatizzare il trasferimento file da un server linux a un sito ftp remoto (sotto IIS 6.0 nel lab test). Particolarita' dello script e' la verifica della raggiungibilita' IP del destinatario prima di procedere al trasferimento.
    Lo script preleva un file di log (di asterisk nell'esempio), lo rinomina includendone la data, e lo copia in un server remoto. E' un esempio per fini didattici, va personalizzato se usato in esercizio.

 

#!/bin/sh
#by GF 2008
### VERIFICA RAGGIUNGIBILITA' ###
myHost="192.168.30.10"
count=$(ping -c 4 $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
if [ $count -eq 0 ]; then
# 100% failed connettivita' assente
exit 0;
fi
### TRASFERIMENTO DATI ###
suffix=$(eval stat --printf=%z   /var/log/asterisk/queue_log | awk '{print $1}')    #si prende la data dell'ultima modifica del file
nomeremoto=queue_log.$suffix                                                                        #genera un nuovo nome per il file queue, con la data inclusa
cp  /var/log/asterisk/queue_log   /var/log/asterisk/temp/$nomeremoto             
# TRASFERIMENTO DATI SU SERVER
ftp -i -v -n 192.168.30.10 <<End-of-Session
user FTPUSERNAME  FTPPASSWORD
lcd  /var/log/asterisk/temp/
cd  myfolder
cd  mysubfolder
put  $nomeremoto
bye
End-of-Session
exit 0
 

Copyright 2008 – Gianrico Fichera –

Questa pagina e' protetta dalla legge sul Diritto d'Autore. L’autore di questa pagina non si assume nessuna responsabilita’ e non da nessuna garanzia riguardante l’accuratezza e la completezza delle informazioni presenti nonche’ da conseguenze sull’uso delle informazioni presenti in questa pagina.

 

Pagina aggiornata il 15 Aprile 2009