¿Cómo continuar redireccionando stdout a un archivo después de que logrotate lo mueva?

22

Tengo un script simple que genera un montón de registros en la pantalla y canalicé el STDOUT a un archivo para almacenar los registros. Dado que este script se ejecuta durante mucho tiempo, necesitaba rotar los archivos de registro para que se coloquen en otros más pequeños y manejables.

El problema que enfrenté fue que una vez que logrotatemueve el archivo de registro actual a uno nuevo, el archivo de registro recién creado ya no se rellena con los registros. Parece que una vez que se elimina el archivo de registro original, se pierde su controlador de archivos y la redirección ya no funcionará.

También encontré esta publicación que tenía el mismo problema que yo y afirma que se puede solucionar usando en >>lugar de >redirigir la salida. Probé su solución pero no funcionó para mí. ¿Alguien tiene alguna idea de cómo mantener el trabajo de redirección?

Mehran
fuente
44
Todavía recomiendo, en su caso, usar ">>" en lugar de ">" si tiene la intención de escribir en un archivo truncado: como ">>" se abre en modo agregar, buscará hasta el final del archivo cada vez que escribe. De esa forma, cuando trunca el archivo (haciéndolo pasar de XXXX bytes a 0 bytes), "buscará hasta el final", entonces sabrá que ahora tiene que escribir después del byte 0. De lo contrario, puede escribir después del byte XXXX, y así cree un archivo disperso con XXXX bytes nulos antes (es decir, cuando ">", el fd puede recordar dónde estaba en ese archivo y escribir desde allí, ¡sin darse cuenta de que el tamaño del archivo se redujo!)
Olivier Dulac

Respuestas:

25

Debe usar la directiva copytruncate en su configuración logrotate para este archivo de registro.

copytruncate Trunca el archivo de registro original en su lugar después de crear una copia, en lugar de mover el archivo de registro anterior y, opcionalmente, crear uno nuevo. Se puede usar cuando no se le puede decir a algún programa que cierre su archivo de registro y, por lo tanto, puede continuar escribiendo (anexando) en el archivo de registro anterior para siempre. 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. Cuando se utiliza esta opción, la opción de creación no tendrá efecto, ya que el archivo de registro anterior permanece en su lugar

user9517 es compatible con GoFundMonica
fuente
2
Vale la pena mencionar: por un corto tiempo, antes de la compressoperación, los datos se duplican. Eso nos causó un problema una vez, pero fue nuestro mal ya que no deberíamos haber estado tan cerca del lvlímite de espacio. Además, como se indica en el manfragmento, puede perder algunos datos de registro entre las operaciones de copia y truncamiento.
Belmin Fernández el
6

Como alternativa, también puede:

  • use la utilidad de registro en su secuencia de comandos en lugar de tuberías, con una instalación dedicada (por ejemplo, local5), por ejemplo:

    logger -p local5.info -t myscriptname "this is some log data"

  • configure syslog para escribir esta función en el archivo de registro deseado, ejemplo (rsyslog.conf):

    local5.* /var/log/mylogfile

  • configurar la regla de rotación de registros para este registro.

tonioc
fuente
Esto solo funciona si tiene comandos de salida explícitos como echo. El resultado de las herramientas de terceros que se llaman desde el script y que también generan algo no se pueden redirigir al registrador de esta manera
Daniel Alder
4

Otra alternativa a la solución de Iain es usar un postrotatescript para relanzar su script una vez que la rotación ha tenido lugar. Esto se hace para muchos demonios (reiniciar o volver a cargar el demonio), pero sin conocer su script, no sé si esta solución le conviene o no (¿su script depende de algún estado generado hace un tiempo?).

Contenido de /etc/logrotate.d/your-script-name:

/var/log/your-script-name.log {
    # your current logrotate options
    ...
    postrotate
        # this supposing you have the current pid stored
        cat /run/your-script-name.pid | xargs -r kill
        #relaunch it again
        /usr/local/bin/your-script-name
    endscript
}
Carlos Campderrós
fuente
0

Puede canalizar stdout a "split" (parte de coreutils en linux). Le permite dividir el archivo / stdin en fragmentos según el tamaño, el número de líneas, etc. Una vez que lo haya fragmentado, puede administrarlo con logrotate si es necesario.

Nazar
fuente