Como posso limitar o tamanho de um arquivo de log gravado com >>
200 MB?
$ run_program >> myprogram.log
Como posso limitar o tamanho de um arquivo de log gravado com >>
200 MB?
$ run_program >> myprogram.log
Respostas:
Se o seu aplicativo (ou seja, run_program
) não suportar a limitação do tamanho do arquivo de log, você poderá verificar o tamanho do arquivo periodicamente em um loop com um aplicativo ou script externo.
Você também pode usar logrotate(8)
para girar seus logs, ele possui um size
parâmetro que você pode usar para sua finalidade:
Com isso, o arquivo de log é girado quando o tamanho especificado é atingido. O tamanho pode ser especificado em bytes (padrão), kilobytes (sizek) ou megabytes (tamanho).
postscript
opção para fazer com que a configuração do logrotate seja enviada SIGHUP
ao programa.
Se o seu programa não precisar gravar OUTROS arquivos maiores que esse limite, você poderá informar o kernel desse limite usando ulimit
. Antes de executar seu comando, execute isso para configurar um limite de tamanho de arquivo de 200 MB para todo o processo executado na sua sessão atual do shell:
ulimit -f $((200*1024))
Isso protegerá o seu sistema, mas pode estar causando problemas para o programa que está gravando o arquivo. Como eyazici sugere , considere configurar logrotate
para remover arquivos de log assim que atingirem um determinado tamanho ou idade. Você pode descartar dados antigos ou arquivá-los por um período de tempo em uma série de arquivos compactados.
Você pode criar uma nova imagem do sistema de arquivos, montá-la usando o dispositivo de loop e colocar o arquivo de log nesse sistema de arquivos:
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
Você também pode usar em tmpfs
vez de um arquivo, se tiver memória suficiente.
Você pode truncar a saída com head
:
size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log
SIGPIPE
) assim que atingir o limite de tamanho, em vez de descartar os dados.
dd
mágica, mas sim, a Random832 está certa, você receberá um SIGPIPE
as head
/ dd
/ whatever
drops.
trap '' SIGPIPE
?
{ head -c "$size" >> log; cat > /dev/null; }
.
No pacote apache2-utils
está presente o utilitário chamado rotatelogs
, pode ser útil para você.
Sinopse:
rotatelogs [-l] [-L linkname ] [-p program ] [-f] [-t] [-v] [-e] [-c] [-n número de arquivos ] tempo de rotação do arquivo de log | tamanho do arquivo (B | K | M | G) [ deslocamento ]
Exemplo:
your_program | rotatelogs -n 5 /var/log/logfile 1M
Manual completo que você pode ler neste link .
Estou certo de que o pôster original encontrou uma solução. Aqui está outro para outros que podem ler este tópico ...
O corte reduz o tamanho da saída de um programa e preserva os últimos 200 MB de saída com o seguinte comando:
$ run_program | curtail -s 200M myprogram.log
NOTA: Sou o mantenedor do repositório acima. Apenas compartilhando a solução ...
Como é um texto, eu escreveria um script no seu idioma favorito e o direcionaria para isso. Faça com que ele lide com a E / S do arquivo (ou mantenha tudo na memória e depois despeje-o SIGHUP
ou similar). Por isso, em vez de 200 MB, eu pensaria em um número 'razoável' de linhas para acompanhar.
syslog
e logrotate
.
O script a seguir deve fazer o trabalho.
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
Ele tem alguns atalhos óbvios, mas no geral ele faz o que você pediu. Ele dividirá o log em pedaços de tamanho limitado e a quantidade de pedaços também é limitada. Tudo pode ser especificado através dos argumentos da linha de comando. O arquivo de log também é especificado através da linha de comando.
Observe uma pequena pegadinha se você a usar com o daemon que se bifurca em segundo plano. O uso de um pipe impedirá que o daemon vá para o segundo plano. Nesse caso, há uma sintaxe (provavelmente específica do bash) para evitar o problema:
my_daemon | ( logger.sh /var/log/my_log.log <&0 & )
Observe que <&0
, embora pareça redundante, não funcionará sem isso.