Registro de rotación de stdout?

53

Tengo un programa de Linux que puede escribir información en stdout y stderr.

Tengo un script de shell que redirige esa salida a un archivo /var/log. (Vía >>y 2>&1.)

¿Hay alguna manera de hacer que ese archivo de registro gire? (tamaño máximo, luego cambie a un archivo diferente, mantenga solo un número limitado de archivos)

He visto algunas respuestas que hablan sobre el logrotateprograma, que suena bien, pero también parecen centrarse en programas que generan archivos de registro internamente y manejan señales HUP. ¿Hay alguna manera de hacer que esto funcione con un script de redirección de salida básico?

Miral
fuente
1
¿Por qué no puede simplemente modificar el script que redirige la salida para contener la lógica para la rotación?
MaQleod 01 de
Podría, si alguien pudiera decirme cómo detectar el tamaño de un archivo de registro y rotarlo debajo de la salida estándar de un proceso sin perturbar ese proceso. No tengo que usar logrotatesi hay una mejor opción, que sonaba como un punto de partida conveniente para la discusión.
Miral
2
No tiene que usar logrotate, pero usar logrotate solo ahorra tiempo ... Por lo general, no tiene mucho sentido reinventar la rueda.
bubu
Exactamente mi punto. Entonces, ¿hay alguna manera de hacer que logrotate funcione con un stdout redirigido de un proceso en curso?
Miral

Respuestas:

44

Como alternativa, puede canalizar la salida a través de herramientas diseñadas con el objetivo principal de mantener conjuntos de archivos de registro con límite de tamaño y rotación automática, como:

Las herramientas para luego procesar multilogconjuntos de archivos de registro de formato incluyen, entre otros:

Otras lecturas

JdeBP
fuente
1
Gracias, multilogparece justo lo que necesitaba.
Miral
multilog parece ser la única solución plug-and-play en debian (daemontools tiene un paquete oficial). Pero en mi caso particular, donde quería almacenar los registros en una partición fat32, la rotación no funciona, ya que multilog quiere usar un enlace simbólico. No plug and play para mí :)
Arnout
Eso no puede ser cierto, ya que en multilogninguna parte crea o exige vínculos simbólicos. Es completamente neutral con respecto a ellos.
JdeBP
La URL de "No utilizar logrotate o newsyslog en este siglo" tiene punto extra
duyue
15

la rotatelogsherramienta enviada con apache (en el bindirectorio) (ver documentos ) toma la entrada de stdin y gira el registro después de un período de tiempo específico

BertNase
fuente
14

Si puede hacer que vaya a una de las secuencias de registro estándar (syslog, daemon, cron, usuario, seguridad, correo, etc.), puede usar el loggercomando y canalizarlo.

echo "Hello." | logger -p daemon.info

De lo contrario, es mejor que canalice su contenido registrado a un programa o script personalizado para manejarlo, o busque configurar la logrotateconfiguración.

EDITAR: la respuesta de JdeBP parece tener lo que puede estar buscando.

Lara Dougan
fuente
2
+1 por simplicidad. Por cierto, también puede configurar una instalación personalizada (local0) en lugar de las estándar (daemon en su ejemplo)
Roger Keays
14

Tuve un problema similar e inicialmente descarté logrotate pero resultó que logrotate realmente puede hacerlo bien, la directiva clave es " copytruncate ". Por alguna razón, ese término no apareció en ninguno de los google que hice, por lo que estoy agregando esta respuesta para aclarar exactamente cómo usarlo para este caso.

El truco es que esto solo funciona si la redirección se realiza con " >> " (agregar) en lugar de " > " (crear).

Archivo de configuración (truncate.cfg):

/tmp/temp.log {
    size 10M
    copytruncate
    rotate 4
    maxage 100
}

Programa de prueba (nunca abandona el archivo). Puede verlo llenando el disco y aunque eliminar el archivo de registro parece funcionar, en realidad no liberará espacio en el disco:

cat /dev/urandom >> /tmp/temp.log

Ejecutar registro rotar:

logrotate truncate.cfg
Sam Hendley
fuente
Es una buena teoría, pero en realidad no funciona en ningún sistema que lo haya probado. El archivo en realidad no se trunca y el programa continúa agregándolo como antes. (Y sí, eso es incluso con la redirección realizada a través de >>.) ((Por cierto, esta respuesta ya se dio anteriormente.))
Miral
1
... como se discutió en logrotate no truncará el archivo original (en nuestro sitio Unix y Linux). Además, echo /dev/urandom >> /tmp/temp.logescribirá 13 caracteres deterministas /tmp/temp.logy luego saldrá inmediatamente. Quiso decir cat /dev/urandom?
G-Man dice 'reinstalar a Monica' el
2
Acabo de probar aquí, y parece funcionar. El contenido del archivo se copia en un nuevo archivo de registro. El archivo original se mantiene abierto por el proceso y se trunca (el tamaño ahora muestra 0).
Philipp
1
Tenga cuidado con la posible pérdida de datos con copytruncate.
wanghq
1
+1 aunque "Tenga en cuenta que hay un intervalo de tiempo muy pequeño entre copiar el archivo y truncarlo, por lo que podrían perderse algunos datos de registro".
Tagar
3

Entonces, ¿hay alguna manera de hacer que logrotate funcione con un stdout redirigido de un proceso en curso?

¡Si! Consulte la directiva "copytruncate" que ofrece logrotate. Especificar que instruye a logrotate para manejar esta misma situación: un programa simple que mantiene su archivo de registro abierto indefinidamente.

Una advertencia puede o no ser un problema en su situación:

Tenga en cuenta que hay un intervalo de tiempo muy pequeño entre copiar el archivo y truncarlo, por lo que podrían perderse algunos datos de registro.

Como anécdota, he visto algunas fuentes de registro del "mundo real" que alientan a los usuarios a aplicar esta directiva. Hay un poco de discusión de esta opción aquí .

natevw
fuente
3

Use split, es parte de coreutils. Puede tomar stdin y dividirlo en fragmentos (según el tamaño del fragmento o el número de líneas, etc.).

Ejemplo:

app | split --bytes 1G - /var/logs/put-prefix-here

Nota guión (-) indica a "split" que use stdin en lugar de archivo.

Nazar
fuente
¿Puedes ampliar tu respuesta para describir cómo hacer eso? Gracias.
fijador1234
Acabo de actualizar mi respuesta con un ejemplo.
Nazar
El 1G tiene un tamaño arbitrario, ¿después del cual comienza un nuevo archivo?
fixer1234
1
Esta no es una solución particularmente buena para el problema porque significa que puede terminar con medio mensaje en un archivo y la mitad en el siguiente. También existe el riesgo de pérdida de datos si la máquina falla mientras splittiene datos en lo que podría ser un gran búfer. Dado que hay varias herramientas que resuelven este problema correctamente, no creo que este tipo de solución de rodar su propia cuenta pueda ser recomendada.
David Richerby
1
@David Richerby- ¿qué tal si agregamos -u para unbuffer?
Nick
3

Me gusta multilogpara mi caso de uso, pero mi caso de uso es tan trivial / simple que no se presenta de manera muy simple en los documentos / ejemplos que encontré. Aquí hay un ejemplo simple de rotación multilog:

mkdir /tmp/myapp
./myapp | multilog t s10000 n5 '!tai64nlocal' /tmp/myapp 2>&1

Algunas notas:

  • esto voltea los registros en ese directorio / tmp / myapp /
  • el s10000 representa 10,000 bytes *
  • el n5 representa 5 archivos. * El registro 'actual' cuenta como uno de los archivos, por lo que incluye 4 registros más antiguos + 'actual'
  • esto se basa en, adaptado de los ejemplos proporcionados por François Beausoleil en: http://blog.teksol.info/pages/daemontools/best-practices
  • No entiendo muchas de las opciones, lo remito a la documentación para ampliar esto ...
  • Los documentos advierten que: "Note that running processor may block any program feeding input to multilog."donde 'procesador' es la '!tai64nlocal'parte del comando

* Para muchas aplicaciones, estas son malas elecciones para uso a largo plazo. Permiten observar el comportamiento de llenar y rotar los registros más rápidamente que los registros grandes.

Finalmente, ¡no olvides nohup si es necesario! Con nohup, no necesita el 2>&1(s = 10e6 yn = 30 aquí):

mkdir -p /tmp/myapp
nohup ./myapp | multilog t s10000000 n30 '!tai64nlocal' /tmp/myapp &

Ese comando debería ayudarte a comenzar.

sabio
fuente
1

Solo quería agregar al comentario de Sam Hendley arriba:

El truco es que esto solo funciona si la redirección se realiza con >>(agregar) en lugar de >(crear).

Me encontré con el mismo problema en el que el archivo original sigue creciendo si usa >(crear) pero si usa >>(agregar) Logrotate copytruncate funciona de maravilla y como se esperaba. El archivo original vuelve a cero bytes y el programa continúa escribiendo.

Redireccionar STDOUT y STDERR a un archivo de registro giratorio:

  1. some-program.sh >> /tmp/output.txt 2>&1 &
  2. Crear un archivo de configuración logrotate bajo /etc/logrotate.dllamado whatever, output_roll en mi caso.

    Configuración de muestra para mi caso:

    /tmp/output.txt {
        notifempty
        missingok
        size 1G
        copytruncate
        start 0
        rotate 15
        compress
    }
    
  3. Configura tu trabajo cron dentro del /etc/crontabarchivo

    *  *  *  *  * root /usr/sbin/logrotate /etc/logrotate.d/output_roll
    

    Esto verificará el archivo cada minuto. Puede ajustarse a sus necesidades.

  4. Ponlo en marcha:

    $> service crond restart
    
  5. Eso es

Nota: También tuve un problema con SELinux configurado, SELINUX=enforcingasí que lo configuré SELINUX=disabled.

usuario578558
fuente
1

Escribí un logrotee este fin de semana. Probablemente no lo haría si hubiera leído la gran respuesta de @ JdeBP y multilog.

Me centré en que fuera ligero y capaz de bzip2 sus fragmentos de salida como:

verbosecommand | logrotee \
  --compress "bzip2 {}" --compress-suffix .bz2 \
  /var/log/verbosecommand.log

Sin embargo, todavía hay mucho por hacer y probar.

Victor Sergienko
fuente