Come limitare la dimensione del file di registro utilizzando >>


24

Come posso limitare la dimensione di un file di registro scritto con >>200 MB?

$ run_program >> myprogram.log

1
Vuoi che il programma venga ucciso dopo 200 MB? O vuoi gli ultimi 200 MB con tutto ciò che è più vecchio nel bucket?
Aaron D. Marasco,

no, il processo non può fermarsi fino a quando non viene ucciso manualmente
David,

ha deciso di optare per Logrotate, grazie a tutti per i preziosi input
David

Risposte:


9

Se l'applicazione (ad es. run_program) Non supporta la limitazione della dimensione del file di registro, è possibile controllare periodicamente la dimensione del file in un ciclo con un'applicazione o uno script esterno.

Puoi anche usare logrotate(8)per ruotare i tuoi log, ha un sizeparametro che puoi usare per il tuo scopo:

Con ciò, il file di registro viene ruotato quando viene raggiunta la dimensione specificata. La dimensione può essere specificata in byte (impostazione predefinita), kilobyte (dimensionek) o megabyte (dimensione).


1
+1 I file di registro con informazioni ripetute possono spesso essere compressi in ordine di grandezza.
utente sconosciuto

Logrotate tronca i file o semplicemente li copia o sposta? Perché questo funzionerà solo se il file associato a fd viene troncato. Se è mv'd, il file continuerà a crescere, se non è collegato, sarà tenuto aperto e continuerà a crescere fino a quando il processo non termina ... IIRC esegue il logrotate di copie, scollegamenti e crea un nuovo file, motivo per cui spesso si deve inviare SIGHUP ai demoni quando i loro registri sono stati ruotati.
Michael Trausch,

Si noti che anche se viene troncato, c'è un problema se il file non è stato aperto in modalità append (i file di registro devono sempre essere aperti in modalità append, ma nella mia esperienza spesso non lo sono)
Random832

Logrotate può ruotare una volta che il file ha raggiunto una determinata dimensione, giornaliera, settimanale, ecc. Può anche comprimere ed è possibile utilizzare l' postscriptopzione per fare in modo che la configurazione di logrotate venga inviata SIGHUPal programma.
laebshade,

12

Se il tuo programma non ha bisogno di scrivere altri file che siano più grandi di questo limite, puoi informare il kernel di questo limite usando ulimit. Prima di eseguire il comando, eseguirlo per impostare un limite di dimensioni del file di 200 MB per tutto il processo eseguito nella sessione di shell corrente:

ulimit -f $((200*1024))

Questo proteggerà il tuo sistema, ma potrebbe essere in difficoltà per il programma che scrive il file. Come suggerisce eyazici , prendere in considerazione la possibilità di logrotateeseguire la potatura dei file di registro quando raggiungono una determinata dimensione o età. Puoi eliminare i vecchi dati o archiviarli per un certo periodo di tempo in una serie di file compressi.


questo limita la dimensione di qualsiasi file scritto dal programma
Kim

Vero. Se il programma avesse un legittimo bisogno di scrivere altri file di grandi dimensioni, avresti bisogno di una soluzione diversa.
Caleb,

6

È possibile creare una nuova immagine del filesystem, montarla utilizzando il dispositivo loop e inserire il file di registro su quel filesystem:

dd if=/dev/zero of=./200mb.img bs=1024 count=200000 # create new empty 200MB file
mkfs.ext2 200mb.img # or ext3, or whatever fits your needs
mkdir logs
sudo mount -t ext2 -o loop 200mb.img logs # only root can do '-o loop' by default
run_program >>logs/myprogram.log

È inoltre possibile utilizzare tmpfsinvece di un file, se si dispone di memoria sufficiente.


Idea creativa ... che lascia al programma cosa fare quando si esaurisce.
Aaron D. Marasco,

6

È possibile troncare l'output con head:

size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log

Molto creativo. Solo una nota che questo avrebbe funzionato solo per limitare i NUOVI dati scritti nel file, non avrebbe preso in considerazione quanto grande o piccolo fosse già il file.
Caleb,

2
Si noti che è probabile che questo uccida il programma (con SIGPIPE) una volta che ha raggiunto il limite di dimensioni, anziché eliminare i dati.
Casuale 832,

1
Stavo pensando simile con un po 'di ddmagia, ma sì @ Random832 è giusto, si otterrà una SIGPIPEcome head/ dd/ whatevergocce di esso.
Aaron D. Marasco,

Che ne dici di ignorarlo con un trap '' SIGPIPE?
smoking il

O pipa invece a { head -c "$size" >> log; cat > /dev/null; }.
Stéphane Chazelas,

5

Nel pacchetto apache2-utilsè presente l'utilità chiamata rotatelogs, può essere utile per te.

Sinossi:

rotatelogs [-l] [-L linkname ] [-p program ] [-f] [-t] [-v] [-e] [-c] [-n numero di file ] tempo di rotazione del file di log | dimensione file (B | K | M | G) [ offset ]

Esempio:

your_program | rotatelogs -n 5 /var/log/logfile 1M

Manuale completo che puoi leggere su questo link .


Il collegamento è inesistente.
Alexander Gonchiy,

1

Sono certo che il poster originale abbia trovato una soluzione. Eccone un altro per gli altri che potrebbero leggere questa discussione ...

Curtail limita le dimensioni dell'output di un programma e conserva gli ultimi 200 MB di output con il seguente comando:

$ run_program | curtail -s 200M myprogram.log

Riferimenti

NOTA: sono il manutentore del repository sopra riportato. Sto solo condividendo la soluzione ...


Adoro l'idea della riduzione. Non ho familiarità con C, quindi c'è la possibilità di fornire un binario per esso? o almeno istruzioni dettagliate su come installarlo?
Felipe

0

Dal momento che è un testo, scriverei una sceneggiatura nella tua lingua preferita e la porterei a quella. Fai in modo che gestisca l'I / O dei file (o tieni tutto in memoria e poi scaricalo SIGHUPo simile). Per questo, invece di 200 MB, penserei a un numero "ragionevole" di linee da tenere traccia.


Mantenere 200 MB di dati di registro in memoria per nessun altro motivo se non quello di essere in grado di troncarli non è un ottimo uso delle risorse di sistema. Né sta facendo un conteggio di riga su un file di registro di grandi dimensioni. Consiglierei l'uso di strumenti creati per questo tipo sysloge logrotate.
Caleb,

0

Il seguente script dovrebbe fare il lavoro.

LOG_SIZE=500000
NUM_SEGM=2
while getopts "s:n:" opt; do
  case "$opt" in
    s)
      LOG_SIZE=$OPTARG
      ;;
    n)
      NUM_SEGM=$OPTARG
      ;;
  esac
done
shift $((OPTIND-1))
if [ $# == 0 -o -z "$1" ]; then
    echo "missing output file argument"
    exit 1
fi
OUT_FILE=$1
shift
NUM=1
while :; do
    dd bs=10 count=$(($LOG_SIZE/10)) >> $OUT_FILE 2>/dev/null
    SZ=`stat -c%s $OUT_FILE`
    if [ $SZ -eq 0 ]; then
        rm $OUT_FILE
        break
    fi
    echo -e "\nLog portion finished" >> $OUT_FILE
    mv $OUT_FILE $OUT_FILE.n$NUM
    NUM=$(($NUM + 1))
    [ $NUM -gt $NUM_SEGM ] && NUM=1
done

Ha un paio di scorciatoie ovvie, ma nel complesso fa quello che hai chiesto. Suddividerà il registro in blocchi di dimensioni limitate e anche la quantità di blocchi sarà limitata. Tutto può essere specificato tramite gli argomenti della riga di comando. Il file di registro viene inoltre specificato tramite la riga di comando.

Nota un piccolo gotcha se lo usi con il demone che si biforca in background. L'uso di una pipe impedirà al demone di andare in background. In questo caso esiste una sintassi (probabilmente specifica per bash) per evitare il problema:

my_daemon | ( logger.sh /var/log/my_log.log <&0 & )

Nota che <&0, sebbene apparentemente ridondante, non funzionerà senza questo.

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.