Linux / Comando tail: ultime righe e log in tempo reale
tail mostra la parte finale di un file: senza opzioni stampa le ultime 10 righe. Con -n scegliete quante righe leggere; con -f o -F continuate a vedere i dati aggiunti al file.
È utile per leggere gli ultimi messaggi prima di un problema o osservare i log di un servizio in esecuzione. Gli esempi seguenti distinguono lettura statica, inseguimento di un file, rotazione dei log, filtri e più file contemporaneamente.
Che cosa fa tail?
Tail legge la parte finale di un input testuale. Se omettete il file o indicate - al suo posto, legge lo standard input, cioè i dati ricevuti dal terminale o da una pipe. L’unità predefinita è la riga e la quantità predefinita è 10 righe.
Non dovete aprire l’intero file in un editor per consultarne la fine. Tail legge e segue i dati: per analisi, conservazione e ricerca centralizzata dei log servono altri strumenti.
Sintassi e primi esempi
La sintassi generale è questa. Le parentesi quadre indicano elementi facoltativi: sostituite options con le opzioni e file... con uno o più percorsi, senza digitare le parentesi.
tail [options] [file...]
Per leggere le ultime 10 righe del file di esempio /var/log/app.log:
tail /var/log/app.log
Usate un percorso che esiste realmente e per cui avete accesso in lettura. Per le ultime 20 righe:
tail -n 20 /var/log/app.log
La forma abbreviata -20 è disponibile in GNU tail, ma -n 20 esprime meglio l’intenzione negli script e nella documentazione. I nomi come app.log senza percorso si riferiscono alla directory corrente.
Selezionare righe o byte
Le ultime N righe
-n N stampa le ultime N righe, oppure tutte quelle disponibili se il file ne contiene meno. Per esempio:
tail -n 50 access.log
Per leggere una porzione più ampia una schermata alla volta, inviate l’output a less, descritto nella guida in inglese:
tail -n 500 access.log | less
In less potete scorrere il testo e uscire con q. Questo esempio consulta le ultime 500 righe già lette da tail; non aggiunge da solo il monitoraggio continuo.
Dalla riga N fino alla fine
Con un segno più davanti al numero, -n +N cambia significato: parte dalla riga N, contando da 1, anziché selezionare le ultime N righe.
tail -n +2 data.csv
L’esempio salta la prima riga fisica di un CSV (valori separati da virgole). È adatto a un’intestazione su una riga; tail non interpreta il formato CSV e non riconosce i record che contengono ritorni a capo tra virgolette.
Usare i byte anziché le righe
-c N stampa gli ultimi N byte. GNU tail accetta anche suffissi come K e M:
tail -c 1K output.bin
1K equivale a 1.024 byte; 1kB equivale a 1.000 byte. Con -c +N la lettura inizia dal byte N. Un taglio per byte può spezzare un carattere UTF-8, comprese le lettere accentate e i caratteri di altre lingue: per un testo normale preferite le righe.
Seguire i nuovi messaggi di un log
Seguire il file aperto con -f
-f mostra prima la fine del file, poi continua a stampare i dati aggiunti. In GNU tail segue per impostazione predefinita il descrittore, cioè il riferimento al file già aperto.
tail -f /var/log/app.log
È adatto quando lo stesso file continua a crescere. Per interrompere la lettura e tornare alla shell, premete Ctrl+C: il log non viene cancellato né modificato.
Seguire il nome con -F dopo la rotazione
La rotazione dei log può rinominare il vecchio file e crearne uno nuovo con il nome originale. GNU -F equivale a --follow=name --retry: segue quel nome e riprova ad aprirlo se il file non è accessibile.
tail -F /var/log/app.log
Per i servizi che sostituiscono i file durante la rotazione, -F è spesso la scelta più pratica. Il codice e l’aiuto ufficiale di GNU tail specificano la differenza tra nome e descrittore. Se il file viene troncato, tail può rilevarlo e riprendere dall’inizio; non è però un sistema che garantisce l’acquisizione di ogni messaggio durante rotazioni o scritture molto rapide.
Mostrare solo ciò che viene aggiunto
Aggiungete -n 0 se non volete le ultime 10 righe già presenti quando tail apre il file:
tail -n 0 -f /var/log/app.log
Vedrete i dati aggiunti dopo il posizionamento iniziale alla fine del file. Se non appare nulla, il programma potrebbe non aver ancora scritto o svuotato il proprio buffer, oppure potreste osservare il percorso sbagliato.
Le opzioni più usate
| Opzione | Funzione | Esempio o impiego |
|---|---|---|
-n N |
Ultime N righe | tail -n 100 app.log |
-n +N |
Dalla riga N | tail -n +2 data.csv |
-c N |
Ultimi N byte | tail -c 2K data.bin |
-f |
Segue il file aperto | Un file che cresce senza essere sostituito |
-F |
Segue il nome e riprova | Log soggetti a rotazione |
-s N |
Intervallo di attesa approssimativo in secondi | tail -f -s 2 app.log |
--pid=PID |
Termina l’inseguimento dopo la fine del processo indicato | Osservare il log di un processo batch |
-q |
Nasconde le intestazioni con il nome del file | Unire l’output di più file senza intestazioni |
-v |
Mostra sempre il nome del file | Rendere esplicita l’origine dell’output |
Verificate le opzioni con tail --help sul sistema di destinazione: GNU, BSD e altre implementazioni possono differire. Con il meccanismo Linux inotify, le modifiche possono essere notificate direttamente; -s non va quindi interpretato come un ritardo obbligatorio per ogni aggiornamento.
Esempi pratici per i log
Filtrare gli errori recenti
Per cercare la stringa ERROR solo nelle ultime 200 righe:
tail -n 200 app.log | grep 'ERROR'
grep -i ignora la distinzione tra maiuscole e minuscole. grep -n aggiunge numeri di riga, ma in questa pipe li conta dall’inizio dell’input ricevuto da tail: non sono i numeri originali nel file completo.
Filtrare mentre il log cresce
Per seguire il file per nome e mostrare le righe che contengono ERROR:
tail -F app.log | grep --line-buffered 'ERROR'
GNU grep --line-buffered svuota il buffer di output dopo ogni riga e può ridurre i ritardi nelle pipe. Il manuale di GNU grep descrive sia questa opzione sia i numeri di riga. Il filtro non cambia il log; il comando mostra anche eventuali ERROR tra le righe iniziali già presenti. Per soli dati nuovi potete aggiungere -n 0 a tail.
Terminate la pipe con Ctrl+C. Il filtro non può mostrare un messaggio che l’applicazione non ha ancora scritto: --line-buffered riguarda l’output di grep, non il buffer del servizio.
Seguire più file
Indicate più percorsi per osservarli insieme:
tail -F access.log error.log
Le intestazioni indicano da quale file provengono i dati. -v le rende esplicite anche con un solo file; -q le elimina. Non interpretate l’ordine di arrivo da file diversi come un ordinamento globale garantito per data.
Terminare quando finisce il processo che scrive
In GNU tail, --pid permette di uscire quando il processo osservato non esiste più. PID significa identificatore del processo; $! è quello dell’ultimo processo avviato in background dalla shell.
some_command > build.log 2>&1 &
tail --pid=$! -f build.log
some_command è un segnaposto: sostituitelo con il comando reale da eseguire, nella stessa shell. L’operatore > crea o sovrascrive build.log; scegliete un file di lavoro che potete scrivere e il cui contenuto precedente non serve. 2>&1 invia anche lo standard error nel log, e & avvia il comando in background.
Il controllo del PID funziona insieme all’inseguimento e può rilevare la fine con un ritardo. Il processo che scrive e tail devono essere nello stesso ambiente di processi; un PID di un’altra macchina o di un namespace diverso non è un riferimento valido. Tail non restituisce automaticamente il codice di uscita del comando osservato: negli script conservate il PID e controllate separatamente il risultato con wait.
Differenza tra -f e -F
| Aspetto | -f |
-F |
|---|---|---|
| Riferimento | Descrittore del file aperto, per impostazione predefinita | Nome indicato |
| Sostituzione del file | Può continuare a leggere il vecchio file | Riapre il nuovo file con lo stesso nome |
| Percorso temporaneamente assente | Il descrittore già aperto può restare leggibile, ma non riapre il nuovo file | Riprova finché il file torna accessibile |
| Uso tipico | Osservare un file non sostituito, o il vecchio file ancora scritto | Osservare il nome di un log soggetto a rotazione |
La scelta dipende da come il servizio scrive e ruota i log. Se il processo continua a scrivere nel vecchio file dopo averlo rinominato, seguire il descrittore con -f può essere proprio ciò che vi serve. Nessuna delle due opzioni sostituisce una raccolta affidabile e persistente dei log.
Quando usare un altro strumento
- Journal di systemd: per i log nel journal, usate
journalctl -f; conjournalctl -f -u nome-serviziolimitate il risultato al servizio, sostituendo il segnaposto con l’unità reale. - Inizio del file: head è più diretto per leggere le prime righe.
- Lettura e inseguimento:
less +F nomefileconsente di seguire le aggiunte. Interrompete l’inseguimento con Ctrl+C, scorrete il testo e riprendetelo con F; uscite da less con q. - Ripetere un comando: se volete aggiornare il risultato di un comando anziché seguire le aggiunte a un file, consultate la guida a watch, in inglese.
- Log centralizzati: per ricerca, aggregazione e avvisi su più server, usate un sistema di raccolta e osservazione dei log.
Permessi e uso in produzione
Errore Permission denied
Controllate il percorso, il proprietario e i permessi con ls -l nomefile. Può essere necessario verificare anche l’accesso alle directory del percorso. Richiedete i permessi appropriati all’amministratore; evitate di ampliare indiscriminatamente i permessi o aggiungere sudo a ogni comando.
Dati sensibili nei log
I log possono contenere token, identificatori di sessione e dati personali. Prima di condividere lo schermo o inviare un messaggio di errore, estraete solo la parte necessaria e oscurate i valori sensibili, comprese eventuali copie salvate dal terminale.
Domande frequenti
Quante righe stampa tail senza opzioni?
Le ultime 10. Per una quantità diversa usate, per esempio, tail -n 30 nomefile.
Come si interrompe tail -f?
Premete Ctrl+C per fermare la lettura e tornare alla shell. Questo non cancella né modifica il file seguito.
Perché non vedo nuovi messaggi dopo la rotazione?
-f potrebbe seguire ancora il vecchio descrittore. Provate GNU tail -F nomefile per seguire il nome e riaprire il file sostitutivo. Se non cambia nulla, verificate percorso reale, permessi e destinazione dell’output del servizio.
Tail legge automaticamente i log compressi?
No. Potete decomprimere il flusso e inviarlo a tail, per esempio zcat archive.log.gz | tail -n 50 per gzip. Leggere e decomprimere tutto un grande archivio può essere costoso; tail da solo non consente di saltare direttamente alle sue ultime righe testuali.
Riepilogo
Usate tail per le ultime righe, -n per la quantità, -f per seguire il file aperto e GNU -F per seguire un nome durante la sostituzione del log. Aggiungete grep quando volete selezionare messaggi specifici.
Controllate sempre percorsi, permessi e dati sensibili. La raccolta dei comandi Linux più usati, in inglese descrive altri strumenti utili nelle stesse attività.




