Enregistrement de la sortie d'un démon avec Upstart

34

J'ai un démon personnalisé qui est géré par upstart sur mon serveur Ubuntu. Cela fonctionne parfaitement sauf que je dois capturer (consigner) la sortie du démon. La page des strophes officielles indique que je peux utiliser console loggedcette méthode, mais dans quel fichier se connecte-t-elle?

J'ai aussi lu que console loggedest plus une strophe valide . J'utilise actuellement la version 0.3.9 (Hardy), mais je passerai à la version 0.6.x (Lucid) dans quelques mois. Si, console loggeden fait, ne fonctionne pas avec les versions ultérieures, que dois-je utiliser à la place?

Alex Reisner
la source
1
Pouvez-vous simplement mettre à jour votre démon personnalisé pour qu'il envoie la sortie à syslog ou à un fichier journal spécifié dans le fichier de configuration du démon?
Zoredache

Réponses:

35

Cet extrait dirigera la sortie de votre service dans le consignateur, tout en vous permettant d'exécuter le processus de service (remplaçant ainsi le processus shell), de manière à éviter toute confusion. Il s'assure également que le processus de journalisation est reparented to init, de sorte qu'il ne s'agit pas d'un enfant de votre service et qu'il évite de rester inactif dans le système de fichiers, même s'il doit créer un fifo temporairement.

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

Voici comment cela fonctionne:

  1. mkfifo /tmp/myservice-log-fifofait simplement le fichier spécial fifo (aka pipe). Tapez man 7 fifopour plus d'informations.
  2. ( logger ... </tmp/myservice-log-fifo & ) commence la lecture de l'enregistreur à partir du fifo, en arrière-plan. Les parens font en sorte que le processus de journalisation soit reparented to init, plutôt que de rester un enfant du processus shell en cours.
  3. exec >/tmp/myservice-log-fiforedirige la sortie standard du shell actuel vers le fifo. Nous avons maintenant un descripteur de fichier ouvert pour ce fifo, et nous n’avons plus besoin de l’entrée du système de fichiers ...
  4. rm /tmp/myservice-log-fifo alors on va l'enlever.
  5. exec myservice 2>/dev/nullexécute simplement le service de la manière habituelle. Stdout va déjà au fifo et cela ne changera pas quand le nouveau programme sera exécuté.

UPDATE: set -e n'est pas nécessaire car Upstart exécute les scripts avec cette option par défaut (voir http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )

Keith Rarick
la source
excellente réponse, et ne laisse pas les fichiers fifo traîner partout.
Ash Berlin-Taylor
Quel est le set -e?
Peter Mounce le
1
Cela set -eprovoque la fermeture immédiate du script en cas d'échec d'une commande. Sans cette ligne, le script continuerait à exécuter les commandes suivantes inutilement (et peut-être dangereusement).
Keith Rarick
1
Pour consigner stderr et stdout, ajoutez la ligne exec 2>&1au-dessus de la rmligne et supprimez-le 2>/dev/nullde la dernière ligne.
itsadok
31

Pour les versions récentes d’Ubuntu (12.04+), utilisez simplement

console log

Et la sortie du démon (STDOUT & STDERR) sera ajoutée à /var/log/upstart/<service>.log

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

Willem
la source
2
Ce serait propre et agréable, mais malheureusement cela ne fonctionne pas sur CentOS 6.x, qui contient toujours une version ancienne d’upstart qui ne le supporte pas.
Cristian Măgherușan-Stanciu
11

Si vous utilisez la console output strophe , puis dirigez la sortie de votre script vers logger(l'interface de commande shell vers le module de journal système syslog (3)), cela fonctionnera.

Par exemple

console output
exec /my/script | logger

se connecter à /var/log/messages

Par exemple

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

se connecter à /var/log/messageset marquer chaque message avecmy-script

logger --help pour les options d'utilisation de l'enregistreur.

(Je suis sur l'AMI Amazon Linux, basée sur Centos 5.x; YMMV)

Peter Mounce
la source
4
Il s'avère que ce n'est pas une bonne solution. Upstart se verrouille sur le PID de logger, pas sur le processus que vous souhaitez réellement gérer.
Peter Mounce
10

Je n'ai pas eu l' mkfifoastuce pour travailler de manière satisfaisante; il n'a pas semblé capturer stderr et les tentatives de redirection ont amené Upstart à se libérer sans erreur.

Cela a également un effet secondaire malheureux: le loggerprocessus est suspendu en tant qu'enfant init. Ainsi, les informations sur le propriétaire de l'enregistreur sont perdues, et quiconque n'est pas déjà au courant mkfifopeut supposer qu'il peut s'agir d'un processus en suspens.

Au lieu de cela, je me suis retrouvé avec la solution suivante, qui résout tous ces problèmes. Il en résulte logger un processus enfant tout en préservant le service en tant que processus racine. Malheureusement, il faut exécuter bash, mais ça a l' air sale.

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

Cela utilise une astuce qui redirige stdout et stderr vers une commande. Comme nous exécutons le service dans la bashcommande, cela a pour effet secondaire de remplacer le shell et de faire de bash, comme par magie, un processus enfant du service, comme indiqué par ps aufxw:

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

Pour une raison quelconque, la commande ci-dessus doit être encapsulée dans un bash -c. Je suppose que c'est parce qu'Uststart prétend seulement exécuter votre script via Bash, mais ce n'est pas le cas. Si quelqu'un pouvait suggérer un moyen d'éviter le shell extra bash, ce serait génial.

Alexander Staubo
la source
1
Oui! Je suis tellement contente d'avoir trouvé ça. Ça a l'air mieux que la variante mkfifo et dans mon cas, je n'avais pas besoin de exec bash -l << EOFperdre là-bas.
thom_nic
6

C'est moche mais jusqu'à présent le meilleur que j'ai trouvé

exec / path / to / server >> /tmp/upstart.log 2> & 1

Jorge Vargas
la source
2
La solution n’est pas bonne en ce qui concerne la rotation des journaux, car l’application se connecte directement au fichier. La journalisation via syslog évite les problèmes liés.
Mark Stosberg le
3

Vous pouvez également rediriger la sortie vers syslog, par exemple

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

Cependant, le pipeline peut amener Upstart à confondre le PID du processus de journalisation avec le PID du démon.

Nikratio
la source
Le démon qui confond le PID est en fait un démon inutile, car il est censé surveiller le processus, puis le réactiver. Vous avez une idée sur la façon de vous assurer que le bon PID est surveillé?
Johann Philipp Strathausen
Je pense (mais je n'ai pas essayé) que vous voudrez la expect forkou la expect daemonstrophe. Ou vous pouvez catinsérer le fichier pid dans le message du journal sinon, je suppose.
Peter Mounce
1

Une autre alternative est d'utiliser un tee comme:

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

obtenir à la fois le fichier upstart et la sortie syslog

perl
la source