Die Ausgabe eines Daemons mit Upstart protokollieren

34

Ich habe einen benutzerdefinierten Daemon, der von Upstart auf meinem Ubuntu-Server verwaltet wird. Es funktioniert einwandfrei, außer dass ich die Ausgabe des Daemons erfassen (protokollieren) muss. Auf der offiziellen Strophenseite heißt es, dass ich das console loggedtun kann, aber in welche Datei wird das Protokoll geschrieben?

Ich habe auch gelesen , dass console loggedist nicht mehr eine gültige Strophe . Ich verwende derzeit 0.3.9 (Hardy), werde aber in ein paar Monaten auf 0.6.x (Lucid) upgraden. console loggedWas verwende ich stattdessen, wenn es in späteren Versionen nicht funktioniert?

Alex Reisner
quelle
1
Können Sie Ihren benutzerdefinierten Dämon einfach aktualisieren, um die Ausgabe an syslog oder an eine in der Konfigurationsdatei des Dämons angegebene Protokolldatei zu senden?
Zoredache

Antworten:

35

Dieses Snippet leitet die Ausgabe Ihres Dienstes an Logger weiter, während Sie weiterhin den Dienstprozess ausführen können (wodurch der Shell-Prozess ersetzt wird), damit der Start nicht verwirrt wird. Es stellt auch sicher, dass der Logger-Prozess auf init zurückgesetzt wird, damit er nicht zu Ihren Diensten gehört, und verhindert, dass cruft im Dateisystem herumsteht, obwohl es vorübergehend erforderlich ist, ein FIFO zu erstellen.

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

So funktioniert das:

  1. mkfifo /tmp/myservice-log-fifomacht einfach die fifo spezial datei (aka named pipe). Geben Sie man 7 fifofür weitere Informationen.
  2. ( logger ... </tmp/myservice-log-fifo & ) Startet den Logger-Lesevorgang vom FIFO im Hintergrund. Die Parens bewirken, dass der Logger-Prozess erneut an init gesendet wird, anstatt ein Kind des aktuellen Shell-Prozesses zu bleiben.
  3. exec >/tmp/myservice-log-fifoLeitet die Standardausgabe der aktuellen Shell an das FIFO um. Jetzt haben wir einen offenen Dateideskriptor für dieses FIFO und brauchen den Dateisystemeintrag nicht mehr ...
  4. rm /tmp/myservice-log-fifo Also werden wir es entfernen.
  5. exec myservice 2>/dev/nullführt den Dienst einfach auf die übliche Weise aus. Stdout geht bereits zum FIFA, und das wird sich nicht ändern, wenn das neue Programm ausgeführt wird.

UPDATE: set -e wird nicht benötigt, da Upstart standardmäßig Skripte mit dieser Option ausführt (siehe http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )

Keith Rarick
quelle
Tolle Antwort und lässt keine FIFO-Dateien irgendwo herumliegen.
Ash Berlin-Taylor
Was ist das set -e?
Peter Mounce
1
Das set -ebewirkt , dass das Skript sofort beenden , wenn ein Befehl fehlschlägt. Ohne diese Zeile würde das Skript nachfolgende Befehle weiterhin nutzlos (und möglicherweise gefährlich) ausführen.
Keith Rarick
1
Um sowohl stderr als auch stdout zu protokollieren, fügen Sie die Zeile exec 2>&1über der rmZeile hinzu und entfernen Sie die 2>/dev/nullvon der letzten Zeile.
itsadok
31

Für aktuelle Ubuntu-Versionen (12.04+) verwenden Sie einfach

console log

Die Daemon-Ausgabe (STDOUT & STDERR) wird angehängt /var/log/upstart/<service>.log

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

Willem
quelle
2
Das wäre sauber und nett, aber leider funktioniert es nicht auf CentOS 6.x, das immer noch eine alte Version von Upstart enthält, die dies nicht unterstützt.
Cristian Măgherușan-Stanciu
11

Wenn Sie die console output Zeilengruppe verwenden und die Ausgabe Ihres Skripts an logger(die Shell-Befehlsschnittstelle zum Systemprotokollmodul syslog (3)) weiterleiten, funktioniert dies.

Beispielsweise

console output
exec /my/script | logger

wird sich anmelden bei /var/log/messages

Beispielsweise

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

loggt sich in /var/log/messagesjede Nachricht ein und markiert sie mitmy-script

logger --help für Logger-Nutzungsoptionen.

(Ich verwende Amazon Linux AMI, das auf Centos 5.x basiert; YMMV)

Peter Mounce
quelle
4
Es stellt sich heraus, dass dies keine gute Lösung ist. upstart speichert die PID von loggerund nicht von dem Prozess, den Sie tatsächlich verwalten möchten.
Peter Mounce
10

Ich habe den mkfifoTrick nicht bekommen , um zufriedenstellend zu arbeiten; Es schien kein stderr zu erfassen, und Versuche, es umzuleiten, führten dazu, dass Upstart ohne Fehler ausfiel.

Es hat auch den unglücklichen Nebeneffekt, dass der loggerProzess als Kind herumlungert init, sodass die Informationen darüber, wem der Logger "gehört", verloren gehen und jeder, der sich dessen noch nicht bewusst ist, mkfifodavon ausgehen kann, dass es sich um einen baumelnden Prozess handelt, der getötet werden kann.

Stattdessen habe ich die folgende Lösung gefunden, die all diese Probleme behebt. Es wird logger zu einem untergeordneten Prozess, während der Dienst als Stammprozess beibehalten wird. Leider muss es ausgeführt werden bash, aber es sieht nur schmutzig aus.

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

Dies verwendet einen Trick, der stdout und stderr zu einem Befehl umleitet. Da wir den Service innerhalb des exec - bashBefehl hat dies den Effekt , dass der Schale zu ersetzen und auf magische Weise machen bash ein Kind - Prozess des Dienstes werden, wie durch ps aufxw:

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

Aus irgendeinem Grund muss der obige Befehl in a eingeschlossen werden bash -c. Ich nehme an, dies liegt daran, dass Upstart nur vorgibt, Ihr Skript über Bash auszuführen, dies jedoch nicht wirklich ist. Wenn jemand einen Weg vorschlagen kann, um die zusätzliche Bash-Shell zu umgehen, wäre das großartig.

Alexander Staubo
quelle
1
Ja! Ich bin so froh, dass ich das gefunden habe. Sieht besser aus als die mkfifo Variante und in meinem Fall brauchte ich exec bash -l << EOFdamit keinen Verlust.
thom_nic
6

Das ist hässlich aber bisher das beste was ich gefunden habe

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

Jorge Vargas
quelle
2
Die Lösung ist nicht gut, wenn es um die Protokollrotation geht, da die Anwendung direkt in der Datei protokolliert. Durch die Protokollierung über Syslog werden verwandte Probleme vermieden.
Mark Stosberg
3

Sie können die Ausgabe auch an syslog umleiten, z

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

Die Pipeline kann jedoch dazu führen, dass der Start die PID des Protokollierungsprozesses mit der PID des Dämons verwechselt.

Nikratio
quelle
Der Dämon, der die PID verwirrt, ist eigentlich ein nutzloser Dämon, da er den Prozess beobachten und ihn dann erneut erzeugen soll. Haben Sie eine Idee, wie Sie sicherstellen können, dass die richtige PID überwacht wird?
Johann Philipp Strathausen
Ich denke (aber ich habe es nicht versucht), dass Sie die Strophe expect forkoder wollen expect daemon. Oder du könntest catdie PID-Datei in die Log-Nachricht sonst, denke ich.
Peter Mounce
1

Eine andere Alternative ist die Verwendung von Tee wie:

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

um sowohl die Upstart-Datei als auch die Syslog-Ausgabe zu erhalten

perl
quelle