Come posso limitare la dimensione di un file di registro scritto con >>
200 MB?
$ run_program >> myprogram.log
Come posso limitare la dimensione di un file di registro scritto con >>
200 MB?
$ run_program >> myprogram.log
Risposte:
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 size
parametro 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).
postscript
opzione per fare in modo che la configurazione di logrotate venga inviata SIGHUP
al programma.
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 logrotate
eseguire 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.
È 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 tmpfs
invece di un file, se si dispone di memoria sufficiente.
È possibile troncare l'output con head
:
size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log
SIGPIPE
) una volta che ha raggiunto il limite di dimensioni, anziché eliminare i dati.
dd
magia, ma sì @ Random832 è giusto, si otterrà una SIGPIPE
come head
/ dd
/ whatever
gocce di esso.
trap '' SIGPIPE
?
{ head -c "$size" >> log; cat > /dev/null; }
.
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 .
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
NOTA: sono il manutentore del repository sopra riportato. Sto solo condividendo la soluzione ...
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 SIGHUP
o simile). Per questo, invece di 200 MB, penserei a un numero "ragionevole" di linee da tenere traccia.
syslog
e logrotate
.
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.