Registrar la salida de un demonio con Upstart

34

Tengo un demonio personalizado que es administrado por advenedizo en mi servidor Ubuntu. Funciona perfectamente, excepto que necesito capturar (registrar) la salida del daemon. La página oficial de estrofas dice que puedo usar console loggedpara hacer esto, pero ¿en qué archivo se registra?

También he leído que console loggedes ya no es válida una estrofa . Actualmente estoy usando 0.3.9 (Hardy) pero actualizaré a 0.6.x (Lucid) en unos pocos meses. Si console loggedde hecho no funciona con versiones posteriores, ¿qué uso en su lugar?

Alex Reisner
fuente
1
¿Puede simplemente actualizar su daemon personalizado para enviar la salida a syslog o a un archivo de registro especificado en el archivo de configuración del daemon?
Zoredache

Respuestas:

35

Este fragmento canalizará la salida de su servicio en el registrador, mientras le permite ejecutar el proceso de servicio (reemplazando así el proceso de shell) para que el arranque no se confunda. También se asegura de que el proceso del registrador se reparented a init, por lo que no es un elemento secundario de su servicio, y evita dejar cruft en el sistema de archivos, a pesar de que necesita crear un Fifo temporalmente.

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

Así es como funciona:

  1. mkfifo /tmp/myservice-log-fifosimplemente crea el archivo especial fifo (también conocido como tubería). Escriba man 7 fifopara más información.
  2. ( logger ... </tmp/myservice-log-fifo & ) comienza la lectura del registrador desde el fifo, en segundo plano. Los parens hacen que el proceso del registrador se reparented a init, en lugar de seguir siendo un hijo del proceso de shell actual.
  3. exec >/tmp/myservice-log-fiforedirige el stdout del shell actual al fifo. Ahora tenemos un descriptor de archivo abierto para esa quincena, y ya no necesitamos la entrada del sistema de archivos ...
  4. rm /tmp/myservice-log-fifo así que lo eliminaremos
  5. exec myservice 2>/dev/nullsimplemente ejecuta el servicio de la forma habitual. Stdout ya está yendo al Fifo, y eso no cambiará cuando se ejecute el nuevo programa.

ACTUALIZACIÓN: set -e no es necesario ya que Upstart ejecuta scripts con esta opción de forma predeterminada (consulte http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )

Keith Rarick
fuente
gran respuesta, y no deja quince archivos por todas partes.
Ash Berlin-Taylor
¿Cuál es el set -e?
Peter Mounce
1
Esto set -ehace que el script salga inmediatamente si falla algún comando. Sin esa línea, el script continuaría ejecutando comandos posteriores de manera inútil (y posiblemente peligrosa).
Keith Rarick el
1
Para registrar stderr y stdout, agregue la línea exec 2>&1sobre la rmlínea y elimine 2>/dev/nullla última línea.
itsadok
31

Para versiones recientes de Ubuntu (12.04+), simplemente use

console log

Y la salida del demonio (STDOUT & STDERR) se agregará a /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log

Willem
fuente
2
Eso sería limpio y agradable, pero desafortunadamente no funciona en CentOS 6.x, que todavía incluye una versión antigua de advenedizo que no admite esto.
Cristian Măgherușan-Stanciu
11

Si usa la console output estrofa y luego canaliza la salida de su script a logger(la interfaz de comando de shell al módulo de registro del sistema syslog (3)), entonces eso funcionará.

Por ejemplo

console output
exec /my/script | logger

iniciará sesión en /var/log/messages

Por ejemplo

console output
exec /my/script | logger -t my-script

iniciará sesión /var/log/messagesy etiquetará cada mensaje conmy-script

logger --help para las opciones de uso del registrador.

(Estoy en Amazon Linux AMI, que está basado en Centos 5.x; YMMV)

Peter Mounce
fuente
44
Resulta que esta no es una buena solución. El arranque inicial se engancha en el PID logger, no en el proceso que realmente desea que gestione.
Peter Mounce
10

No conseguí el mkfifotruco para funcionar satisfactoriamente; no parecía capturar stderr, y los intentos de redirigir causaron que Upstart salga sin ningún error.

También tiene un efecto secundario desafortunado de hacer que el loggerproceso se quede como un niño init, por lo que la información sobre quién "posee" el registrador se pierde, y cualquiera que no esté al tanto de esto mkfifopodría suponer que es un proceso pendiente que se puede matar.

En cambio, terminé con la siguiente solución, que resuelve todos estos problemas. Hace logger que se convierta en un proceso hijo, al tiempo que conserva el servicio como el proceso raíz. Desafortunadamente, requiere ejecución bash, pero se ve sucio.

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

Esto utiliza un truco que redirige stdout y stderr a un comando. Como ejecutamos el servicio dentro del bashcomando, esto tiene el efecto secundario de reemplazar el shell y hacer que bash se convierta mágicamente en un proceso secundario del servicio, como se muestra en ps aufxw:

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

Por alguna razón, el comando anterior tiene que estar envuelto en a bash -c. Supongo que esto se debe a que Upstart solo pretende ejecutar su script a través de Bash, pero en realidad no lo es. Si alguien puede sugerir una forma de evitar el shell de bash extra, sería genial.

Alexander Staubo
fuente
1
¡Sí! Estoy tan contento de haber encontrado esto. Se ve mejor que la variante mkfifo y en mi caso lo necesitaba para exec bash -l << EOFque no perdiera allí.
thom_nic
6

Esto es feo pero hasta ahora lo mejor que he encontrado

exec / ruta / al / servidor >> /tmp/upstart.log 2> & 1

Jorge Vargas
fuente
2
La solución no es buena cuando se trata de rotación de registros, porque la aplicación está registrando directamente en el archivo. Iniciar sesión a través de syslog evita problemas relacionados.
Mark Stosberg
3

También puede redirigir la salida a syslog, p. Ej.

exec $SERVER 2>&1 | logger -t myservice -p local0.info

Sin embargo, la canalización puede causar que el arranque confunda el PID del proceso de registro con el PID del demonio.

Nikratio
fuente
El demonio que confunde al PID es en realidad un demonio inútil, ya que se supone que debe observar el proceso, reaparecer en ese momento. ¿Alguna idea sobre cómo asegurarse de que se está viendo el PID correcto?
Johann Philipp Strathausen
Creo (pero no lo he probado) que usted desea que el expect forko expect daemonestrofa. O, de lo catcontrario, podría incluir el archivo pid en el mensaje de registro.
Peter Mounce
1

Otra alternativa es usar tee como:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

para obtener tanto el archivo de inicio como la salida de syslog

perl
fuente