Cómo limitar el tamaño del archivo de registro usando >>

24

¿Cómo puedo limitar el tamaño de un archivo de registro escrito >>a 200 MB?

$ run_program >> myprogram.log
david
fuente
1
¿Quieres que el programa sea eliminado después de 200MB? ¿O quieres los últimos 200 MB con todo lo anterior en el cubo de bits?
Aaron D. Marasco
No, el proceso no puede parar hasta que murieron de forma manual
David
decidimos ir a la logrotate, gracias a todos por las valiosas aportaciones
David

Respuestas:

9

Si su aplicación (es decir, run_program) no admite limitar el tamaño del archivo de registro, puede verificar el tamaño del archivo periódicamente en un bucle con una aplicación o script externo.

También puede usar logrotate(8)para rotar sus registros, tiene un sizeparámetro que puede usar para su propósito:

Con esto, el archivo de registro se gira cuando se alcanza el tamaño especificado. El tamaño puede especificarse en bytes (predeterminado), kilobytes (sizek) o megabytes (sizem).

Emre Yazici
fuente
1
Los archivos de registro +1 con información repetida a menudo se pueden comprimir en órdenes de magnitud.
usuario desconocido
¿Logrota truncar archivos, o simplemente copiarlos o moverlos? Porque esto solo funcionará si el archivo asociado con el fd está truncado. Si está movido, el archivo continuará creciendo, si no está enlazado, se mantendrá abierto y continuará creciendo hasta que el proceso finalice ... IIRC registra copias, desvincula y crea un nuevo archivo, Es por eso que a menudo hay que enviar SIGHUP a demonios cuando se han rotado sus registros.
Michael Trausch
Tenga en cuenta que incluso si se trunca, hay un problema si el archivo no se abre en modo de adición (archivos de registro deben siempre pueden abrir en modalidad de apertura, pero en mi experiencia no son a menudo)
Random832
Logrotate puede rotar una vez que el archivo haya alcanzado un cierto tamaño, diariamente, semanalmente, etc. También puede comprimirse, y puede usar la postscriptopción para que la configuración logrotate se envíe SIGHUPal programa.
laebshade
12

Si su programa no necesita escribir OTROS archivos que sean mayores que este límite, puede informar al núcleo de este límite utilizando ulimit. Antes de ejecutar su comando, ejecútelo para configurar un límite de tamaño de archivo de 200 MB para todos los procesos ejecutados en su sesión de shell actual:

ulimit -f $((200*1024))

Esto protegerá su sistema, pero podría ser complicado para el programa que escribe el archivo. Como sugiere eyazici , considere configurar logrotatepara podar los archivos de registro una vez que alcancen cierto tamaño o edad. Puede descartar datos antiguos o archivarlos durante un período de tiempo en una serie de archivos comprimidos.

Caleb
fuente
esto limita el tamaño de cualquier archivo escrito por el programa
Kim
Cierto. Si el programa tuviera una necesidad legítima de escribir otros archivos grandes, necesitaría una solución diferente.
Caleb
6

Puede crear una nueva imagen del sistema de archivos, montarla con un dispositivo de bucle y colocar el archivo de registro en ese sistema de archivos:

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

También puede usar en tmpfslugar de un archivo, si tiene suficiente memoria.

alex
fuente
Idea creativa ... que deja en manos del programa qué hacer cuando se agota.
Aaron D. Marasco el
6

Puede truncar la salida con head:

size=$((200*1024*1024-$(stat -c %s myprogram.log)))
run_program | head -c ${size} >> myprogram.log
esmoquin
fuente
Muy creativo. Solo una nota de que esto solo funcionaría para limitar NUEVOS datos que se escriben en el archivo, no tomaría en cuenta cuán grande o pequeño ya era el archivo.
Caleb
2
Tenga en cuenta que es probable que esto elimine el programa (con SIGPIPE) una vez que haya alcanzado el límite de tamaño, en lugar de descartar los datos.
Random832
1
Estaba pensando similar con un poco de ddmagia, pero sí @ Random832 es correcto, obtendrá una SIGPIPEcomo head/ dd/ whateverdeja caer.
Aaron D. Marasco el
¿Qué hay de ignorarlo con un trap '' SIGPIPE?
tuxce
O tubo en su lugar a { head -c "$size" >> log; cat > /dev/null; }.
Stéphane Chazelas
5

En el paquete apache2-utilsse llama utilidad actual rotatelogs, puede ser útil para usted.

Sinopsis:

rotatelogs [-l] [-L nombreenlace ] [-p programa ] [-f] [-t] [-v] [-e] [-c] [-n número de archivos ] tiempo de rotación del archivo de registro | tamaño de archivo (B | K | M | G) [ desplazamiento ]

Ejemplo:

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

Puede leer el manual completo en este enlace .

PRIHLOP
fuente
El enlace no existe.
Alexander Gonchiy
1

Estoy seguro de que el póster original ha encontrado una solución. Aquí hay otro para otros que pueden leer este hilo ...

La reducción limita el tamaño de la salida de un programa y conserva los últimos 200 MB de salida con el siguiente comando:

$ run_program | curtail -s 200M myprogram.log

Referencias

NOTA: Soy el mantenedor del repositorio anterior. Simplemente compartiendo la solución ...

Dave Wolaver
fuente
Me encanta la idea de la reducción. No estoy tan familiarizado con C, entonces ¿existe la posibilidad de proporcionarle un binario? o al menos instrucciones detalladas sobre cómo instalarlo?
Felipe
0

Como es texto, escribiría un guión en su idioma favorito y lo canalizaría a eso. Haga que maneje la E / S del archivo (o manténgalo todo en la memoria y luego vuélvalo a descargar SIGHUPo similar). Para eso, en lugar de 200 MB, pensaría en un número 'razonable' de líneas para realizar un seguimiento.

Aaron D. Marasco
fuente
Mantener 200 MB de datos de registro en la memoria por el único motivo de truncarlo no es un muy buen uso de los recursos del sistema. Tampoco está haciendo un recuento de líneas en un archivo de registro grande. Recomendaría usar herramientas creadas para esto como syslogy logrotate.
Caleb
0

El siguiente script debería hacer el trabajo.

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

Tiene un par de atajos obvios, pero en general hace lo que pediste. Dividirá el registro en trozos de un tamaño limitado, y la cantidad de trozos también es limitada. Todo se puede especificar a través de los argumentos de la línea de comandos. El archivo de registro también se especifica a través de la línea de comando.

Tenga en cuenta un pequeño problema si lo usa con el demonio que se bifurca en segundo plano. Usar una tubería evitará que el demonio pase al fondo. En este caso, hay una sintaxis (probablemente específica de bash) para evitar el problema:

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

Tenga en cuenta que <&0, aunque parece redundante, no funcionará sin esto.

stsp
fuente