2012-07-13 12 views
5

Sto provando a impostare uno script in cui viene generato un avviso quando una determinata stringa viene visualizzata in un file di registro.Come pipe tail -f in awk

La soluzione già presente esegue l'inceppamento dell'intero file di registro una volta al minuto e conta la frequenza con cui viene visualizzata la stringa, utilizzando il timestamp della riga di registro per contare solo le occorrenze nel minuto precedente.

ho pensato che sarebbe stato molto più efficiente di fare questo con una coda, così ho provato quanto segue, come un test:

FILENAME="/var/log/file.log" 

tail -f $FILENAME | awk -F , -v var="$HOSTNAME" ' 
       BEGIN { 
         failed_count=0; 
       } 
       /account failure reason/ { 
         failed_count++; 
       } 
       END { 
         printf("%saccount failure reason (Errors per Interval)=%d\n", var, failed_count); 
       } 
' 

, ma questo solo si blocca e non fa nulla in uscita. Qualcuno ha suggerito questo piccolo cambiamento:

FILENAME="/var/log/file.log" 

awk -F , -v var="$HOSTNAME" ' 
       BEGIN { 
         failed_count=0; 
       } 
       /account failure reason/ { 
         failed_count++; 
       } 
       END { 
         printf("%saccount failure reason (Errors per Interval)=%d\n", var, failed_count); 
       } 
' <(tail -f $FILENAME) 

ma che fa la stessa cosa.

L'awk che sto utilizzando (ho semplificato nel codice sopra) funziona, come è utilizzato nello script esistente in cui i risultati di grep "^ $ TIMESTAMP" vengono reindirizzati.

La mia domanda è: come si può far funzionare la coda -f con awk?

+4

Quando si 'tail -f', lo script awk non giunge mai a una FINE. Quindi continui a contare gli errori, ma non stampi mai nulla. È necessaria un'altra condizione (ad esempio, rilevare che si tratta di un nuovo giorno) che esegue la stampa e reimposta il contatore.Mostraci un esempio del tuo registro e possiamo suggerire una soluzione. – ghoti

risposta

4

Assumendo che il registro sembra qualcosa di simile:

Jul 13 06:43:18 foo account failure reason: unknown 
│ │  
│ └── $2 in awk 
└────── $1 in awk 

si potrebbe fare qualcosa di simile:

FILENAME="/var/log/file.log" 

tail -F $FILENAME | awk -v hostname="$HOSTNAME" ' 
    NR == 1 { 
     last=$1 " " $2; 
    } 
    $1 " " $2 != last { 
     printf("%s account failure reason (Errors on %s)=%d\n", hostname, last, failed); 
     last=$1 " " $2; 
     failed=0; 
    } 
    /account failure reason/ { 
     failed++; 
    } 
' 

Nota che ho cambiato questo per tail -F (capitale F) perché gestisce registro invecchiamento. Questo non è supportato in tutti i sistemi operativi, ma dovrebbe funzionare nei moderni BSD e Linuces.

Come funziona?

Gli script di awk sono costituiti da serie di test { commands; } valutate rispetto a ciascuna riga di input. (Ci sono due prove speciali, BEGIN e END cui comandi vengono eseguiti quando awk inizia e quando awk estremità, rispettivamente. Nella sua interrogazione, awk non finiva mai, in modo che il codice di END non è mai stato eseguito.)

Lo script ha tre di cui sopra sezioni test/comando:

  • Nel primo, NR == 1 è un test che valuta true solo sulla prima riga di input. Il comando eseguito crea il valore iniziale per la variabile last, utilizzata nella sezione successiva.
  • Nella seconda sezione, viene verificato se la variabile "last" è stata modificata dall'ultima riga valutata. Se questo è vero, indica che stiamo valutando i dati di un nuovo giorno. Ora è il momento di stampare un riepilogo (log) del mese scorso, ripristinare le nostre variabili e andare avanti.
  • Nella terza, se la linea che stiamo valutando corrisponde all'espressione regolare /account failure reason/, incrementiamo il nostro contatore.

Chiaro come fango? :-)

+0

+1 - Per fare errori/giorno, è necessario tenere un conteggio dei giorni e fare la divisione. Oppure puoi cambiare il tuo testo in "Errori ieri" e resettare "failed_count'. –

+0

Ooh, perfetto! Non ho idea di cosa stia facendo, ma bello, grazie! – mazz0

+0

@DennisWilliamson - giusto, grazie per averlo indicato. Ho aggiornato la risposta in modo che il codice fornisca risultati più chiari. – ghoti