Come mantenere le ultime 50 righe nel file di registro


22

Cerco di mantenere le ultime 50 righe nel mio file dove risparmio la temperatura ogni minuto. Ho usato questo comando:

tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test

Ma il risultato è un file di test vuoto. Ho pensato, elencherà le ultime 50 righe del file di test e lo inserirà nel file di test. Quando uso questo comando:

tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2

funziona benissimo. Sono presenti 50 righe nel file test2.

Qualcuno può spiegarmi dov'è il problema?


2
Qualcosa come rrdtool potrebbe essere più appropriato per conservare N record (tra le altre statistiche) nel tempo.
thrig


2
problema di troncamento classico
haylem,

Se stai usando Python per generare i tuoi log, dovresti esaminare il loggingmodulo
Wayne Werner,

Risposte:


30

Il problema è che la shell sta configurando la pipeline di comandi prima di eseguire i comandi. Non si tratta di "input e output", è che il contenuto del file è già sparito prima ancora che la coda venga eseguita. Va qualcosa come:

  1. La shell apre il >file di output per la scrittura, troncandolo
  2. La shell è configurata per utilizzare il descrittore di file 1 (per stdout) per quell'output
  3. La shell viene eseguita tail.
  4. tailcorre, si apre /home/pi/Documents/teste non trova nulla lì

Esistono varie soluzioni, ma la chiave è capire il problema, cosa sta realmente andando storto e perché.

Questo produrrà quello che stai cercando,

echo "$(tail -n 50 /home/pi/Documents/test)" > /home/pi/Documents/test

Spiegazione :

  • $() si chiama sostituzione dei comandi che viene eseguita tail -n 50 /home/pi/Documents/test
  • le virgolette preservano le interruzioni di riga nell'output.
  • > /home/pi/Documents/testreindirizza l'output echo "$(tail -n 50 /home/pi/Documents/test)"sullo stesso file.

Grazie funziona bene! Ho un'altra domanda. Potresti spiegare come funziona la tua procedura passo dopo passo?
Dorinand,

1
Ma perché nel tuo caso bash non eseguire> prima? Non capisco come bash esegua il comando. Qualcuno può spiegare?
Dorinand,

1
> È sul comando echo, quindi viene eseguito quando il comando echo inizia l'esecuzione. Non può iniziare l'esecuzione prima che sia scritta. La sostituzione delle variabili è ciò che scrive il comando. Esegue il comando nidificato e crea il comando echo sostituendo il valore.
jobermark,

Quando ho provato a utilizzare lo stesso per il file di registro da 44 GB utilizzando 5000 righe anziché 50, viene visualizzato l'errorebash: xrealloc: cannot allocate 18446744071562067968 bytes
Carmageddon

8

Un'altra soluzione al reindirizzamento dei file che cancella prima il file è quella di utilizzare spongedal moreutilspacchetto in questo modo:

tail -n 50 /home/pi/Documents/test | sponge /home/pi/Documents/test

6

Questo perché bash elabora il reindirizzamento con il >primo, eliminando il contenuto del file. Quindi esegue il comando. Se dovessi usare >>, le ultime 50 righe verrebbero aggiunte alla fine di ciò che è attualmente nel file. In questo caso, avresti ripetuto due volte le stesse 50 righe.

Il comando funziona come previsto quando si reindirizza a un altro file. Ecco un modo per scrivere le ultime 50 righe di un file in un file con lo stesso nome:

tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 && mv /home/pi/Documents/test2 /home/pi/Documents/test

Questo prima scrive le ultime 50 righe in un file temporaneo, che viene quindi spostato usando mvper sostituire il file originale.

Come notato nei commenti, questo non funzionerà se il file è ancora aperto. Lo spostamento del file crea anche un nuovo inode e può modificare la proprietà e le autorizzazioni. Un modo migliore per farlo utilizzando un file temporaneo sarebbe:

tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 ; cat /home/pi/Documents/test2 > /home/pi/Documents/test

Il file temporaneo può anche essere rimosso, sebbene ogni volta che ciò accada il suo contenuto verrà sovrascritto.


grazie. Potresti spiegarmi passo dopo passo cosa eseguire bash? Non riesco a immaginare come funzioni.
Dorinand,

tail -50 /home/pi/Documents/test >/tmp/foo && cat /tmp/foo >/home/pi/Documents/test
steve

1
si noti che questo non funzionerà se il file di registro è ancora aperto dal processo di registrazione (che continuerà a registrare nel file originale eliminato). tempfile + move genera un nuovo inode (interrompendo qualsiasi collegamento reale) e possibilmente diversi proprietari o permanenti. tail ... > temp ; cat temp > orig ; rm -f templavori.
Cas

4

Poiché hai riscontrato il problema principale con il reindirizzamento della shell, ecco un modo alternativo per eliminare un file dalle ultime 50 righe:

file=/path/to/the/file
n=$(( $(wc -l < "$file") - 50 ))
[[ $n -gt 0 ]] && sed -i 1,${n}d "$file"

Il duro lavoro è svolto da (GNU) sed con la -ifunzione "editing sul posto", che funziona sotto le copertine creando l'output in un file temporaneo. Il resto delle linee ha impostato la matematica per l'operazione di sed, vale a dire:

  1. contare le righe nel file ( wc), quindi sottrarre 50; assegnalo a n.
  2. se n è positivo, eseguire il comando sed per eliminare le righe da 1 a n.

4
printf '%s\n' '1,$-50d'   w | ed -s /home/pi/Documents/tes

printfviene utilizzato per reindirizzare i comandi (uno per riga) in ed. I edcomandi sono:

  • 1,$-50d - elimina tutto tranne le ultime 50 righe
  • w - riscrive il file modificato su disco

Non sono coinvolti reindirizzamenti, quindi la shell non può sovrascrivere il file di output prima che sia stato letto.

Inoltre, a differenza della maggior parte delle forme di modifica "sul posto" (che in genere simula solo la modifica "sul posto" creando un file temporaneo e quindi rinominandolo sull'originale), edmodifica effettivamente il file originale, quindi mantiene lo stesso inode ( e proprietario, gruppo e permessi - tempfile + mv cambierà sempre l'inode e potrebbe cambiare gli altri a seconda delle circostanze).


4

Su una traccia leggermente diversa, è possibile utilizzare logrotate(8)per eseguire regolarmente il backup dei file di registro su file con nome incrementale, quindi eliminare quelli vecchi.

Ecco come vengono gestiti i file di registro di sistema principali per evitare che diventino troppo lunghi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.