Wie kann ich die Standardausgabe eines Prozesses protokollieren, der vom Start-Stopp-Dämon gestartet wurde?

120

Ich verwende ein Init-Skript, um einen einfachen Prozess auszuführen, der gestartet wird mit:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS

Der Prozess mit dem Namen $ DAEMON druckt normalerweise Protokollinformationen in die Standardausgabe. Soweit ich das beurteilen kann, werden diese Daten nirgendwo gespeichert.

Ich möchte den Standard von $ DAEMON irgendwo an eine Datei schreiben oder anhängen.

Die einzige Lösung, die ich kenne, besteht darin, start-stop-daemon anzuweisen, ein Shellscript anstelle von $ DAEMON direkt aufzurufen. Das Skript ruft dann $ DAEMON auf und schreibt in die Protokolldatei. Dies erfordert jedoch ein zusätzliches Skript, das wie das Ändern des Dämons selbst der falsche Weg ist, um eine solche häufige Aufgabe zu lösen.

joeytwiddle
quelle

Antworten:

127

Um die Antwort von ypocat zu erweitern, da ich dadurch keinen Kommentar abgeben kann:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
 --make-pidfile --pidfile $PIDFILE --background       \
 --startas /bin/bash -- -c "exec $DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Wenn Sie execden Daemon verwenden, kann stop den untergeordneten Prozess korrekt stoppen, anstatt nur den übergeordneten Bash.

Die Verwendung von --startasanstelle von --execstellt sicher, dass der Prozess von seiner PID korrekt erkannt wird und nicht fälschlicherweise mehrere Instanzen des Dämons startet, wenn start mehrmals aufgerufen wird. Andernfalls sucht der Start-Stopp-Dämon nach einem / bin / bash-Prozess und ignoriert den tatsächlichen untergeordneten Prozess, auf dem der Dämon ausgeführt wird.

Stormbeta
quelle
2
Dies ist eine weitaus bessere Lösung als die von @ypocat, vor allem, weil das Herunterfahren des Dämons durch Ersetzen --startdurch --stoptatsächlich funktioniert.
Aef
Ich habe versucht, diesen Befehl von rc.local anstelle von init.d auszuführen. Ich scheine nicht die gleichen Ergebnisse zu erzielen. Wenn Sie es jedoch von einer Shell über SSH ausführen, funktioniert es wie ein Zauber!
Nemo
1
Wie würde die Begleitung start-stop-daemon --test (...)aussehen?
Abdull
2
@MattClimbs Es überschreibt die Datei nach jedem Start. Verwenden Sie >>statt >zum Anhängen.
Miau
2
Bevor Sie (wie ich) ausflippen, weil Ihr Protokoll leer war, beachten Sie, dass dies gepuffert ist! Sie können "exec stdbuf -oL -eL $ DAEMON $ DAEMONARGS> $ LOGFILE 2> & 1" verwenden, um die Ausgabe zu zwingen, jede Zeile zu leeren (von blog.lanyonm.org/articles/2015/01/11/… )
piers7
47

Sie müssen tun:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec /bin/bash -- -c "$DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Auch wenn Sie --chuidoder verwenden --user, stellen Sie sicher, dass der Benutzer auf /var/logoder das vorhandene schreiben kann /var/log/some.log. Der beste Weg ist, dass dieser Benutzer ein /var/log/subdir/obwohl besitzt.

youurayy
quelle
1
Fantastisch, danke ypocat. Heute musste ich nicht nur das Protokoll speichern, sondern auch ein nicht-binäres Skript ausführen, das --exec nicht zulässt, aber Ihr Trick funktioniert!
Joeytwiddle
8
Die Kehrseite ... das Stoppen des Dienstes beendet die Bash, aber nicht die untergeordnete Prozess-Bash wurde gestartet! (In meinem Fall DAEMON = Kaffee).
Joeytwiddle
1
Ich habe das umgangen, indem ich alle untergeordneten Prozesse des Bash-Prozesses oben in do_stop beendet habe. bashPID=$(cat $PIDFILE); [ -n "$bashPID" ] && pkill -P "$bashPID"
Joeytwiddle
5
Gut zu wissen und die pkillLösung auch. Ich ... -c "exec $DAEMON..."frage mich, was ich tun würde (Hinzufügen des "exec"). Habe das jetzt noch nicht auf dem Teller, also kann ich es nicht probieren.
Youurayy
12
@ypocat Ich habe gerade überprüft, ob es mit -c "exec $ DAEMON ..." funktioniert. Dies bedeutet, dass keine Pkill-Hacks erforderlich sind.
Überdenken Sie den
40

Es scheint, dass Sie jetzt in der Lage sein sollten, den --no-closeParameter zu verwenden, wenn Sie start-stop-daemonmit der Erfassung der Daemon-Ausgabe beginnen. Diese neue Funktion ist im dpkgPaket seit Version 1.16.5 unter Debian verfügbar :

Fügen Sie die neue Option --no-close hinzu, um das Schließen von fds auf --background zu deaktivieren.

Auf diese Weise konnte der Aufrufer Prozessmeldungen zu Debugging-Zwecken anzeigen oder Dateideskriptoren in Protokolldateien, Syslog oder ähnliches umleiten.

Stéphane
quelle
8
Es ist eine Schande, dass es in Ubuntu 12.04 nicht verfügbar ist :(
Leon Radley
Ich kann nicht scheinen, dass - nicht in der Nähe der Arbeit ... die Ausgabe geht immer noch an die Shell, die ich das init.d-Skript ausführe :(
stantonk
+1 Funktioniert perfekt bei Debian Squeeze mit einem daemonisierten node.js-Dienst.
Speakr
2
@stantonk Hast du auch stdout / stderr in eine Datei geleitet? Die vollständige Befehlszeile sieht wie folgt aus. Und stellen Sie sicher, dass die Protokolldatei vom Benutzer $ USER geschrieben werden kann: start-stop-daemon --start --chuid $ USER --pidfile $ PIDFILE --background --no-close --make-pidfile --exec $ DAEMON - $ DAEMONARGS >> /var/log/xxxxx.log 2> & 1
nharrer
1
Dies ist mit dem openrc nicht verfügbar start-stop-daemon. Die openrc-Version verfügt jedoch über die Optionen -1und -2, um stdout bzw. stderr umzuleiten.
kleiner Kerl
14

Mit openrc (das ist die Standardeinstellung unter Gentoo oder Alpin Linux) stehen start-stop-daemondie Optionen -1und -2zur Verfügung:

-1, --stdout Stdout in Datei umleiten

-2, --stderr Leitet stderr in die Datei um

Sie können also einfach schreiben:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS -1 $LOGFILE -2 $LOGFILE
kleine Kerl
quelle
9

Es ist nicht allzu schwer, die Ausgabe des Dämons zu erfassen und in einer Datei zu speichern:

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas $DAEMON --no-close \
  -- $DAEMON_ARGS >> $LOGFILE 2>&1

Diese Lösung kann jedoch für nicht optimal sein logrotate.

Es ist möglicherweise besser, die Ausgabe in Syslog zu erfassen. Unter Debian würde dies dem Verhalten von systemd-Diensten entsprechen. Der folgende einfache Versuch, das obige Beispiel neu zu schreiben, ist falsch, da nach dem Stoppen des Daemons zwei übergeordnete Prozesse ("Zombie") (Logger und Daemon) zurückbleiben, da start-stop-daemonnur sein untergeordnetes Element, aber nicht alle Nachkommen beendet werden:

## Do not use this!
start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /bin/sh \
  -- -c """exec $DAEMON $DAEMON_ARGS | /usr/bin/logger --tag $NAME"""

Damit es funktioniert, benötigen wir einen Wrapper, der seine untergeordneten Elemente beim Empfang SIGTERMvon beendet start-stop-daemon. Dort sind einige:

duende :
start-stop-daemon --start --background \
  --pidfile $PIDFILE \
  --startas /usr/sbin/duende \
  -- --pid $PIDFILE --chroot=/ --uid 65534 --ident $NAME \
  /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec ${DAEMON} $DAEMON_ARGS"""

Hinweis: uid=65534ist ein Benutzer nobody.

Vorteile : Es funktioniert und es ist relativ einfach.
Nachteile : 4 Prozesse (Supervisor duende, Fork mit verworfenen Berechtigungen (Logger) suund Daemon selbst); obligatorisch --chroot; Wenn der Dämon sofort beendet wird (z. B. ungültiger Befehl), status_of_proc -p $PIDFILE "$DAEMON" "$NAME"melden Sie ihn als erfolgreich gestartet.

Daemon :
start-stop-daemon --start --pidfile $PIDFILE \
  --startas /usr/bin/daemon \
  -- --noconfig --name $NAME --stderr=syslog.info --stdout=syslog.info \
  -- /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec $DAEMON $DAEMON_ARGS"""

Pros : 3 - Prozesse (Supervisor daemon, suund Dämon selbst).
Nachteile : $PIDFILEAufgrund der verwirrenden Befehlszeilenoptionen des Dämons schwierig zu verwalten . Wenn der Dämon sofort beendet wird (z. B. ungültiger Befehl), status_of_proc -p $PIDFILE "$DAEMON" "$NAME"melden Sie ihn als erfolgreich gestartet.

pipexec ( der Gewinner ):

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /usr/bin/pipexec -- -k \
   -- [ D $DAEMON $DAEMON_ARGS ] [ L /usr/bin/logger --tag $NAME ] '{D:2>D:1}' '{D:1>L:0}'

Pros : 3 - Prozesse (Supervisor pipexec, loggerund Daemon selbst); Wenn der Daemon sofort beendet wird (z. B. ungültiger Befehl) status_of_proc -p $PIDFILE "$DAEMON" "$NAME", melden Sie den Fehler korrekt.
Nachteile : keine.

Dies ist der Gewinner - die einfachste und ordentlichste Lösung, die anscheinend gut funktioniert.

Onlyjob
quelle
7

start-stop-daemonSchließt normalerweise die Standard-Dateideskriptoren, wenn sie im Hintergrund ausgeführt werden. Aus der Manpage von start-stop-daemon:

-C, --no-close
Schließen Sie keinen Dateideskriptor, wenn Sie den Daemon in den Hintergrund stellen. Wird zum Debuggen verwendet, um die Prozessausgabe anzuzeigen oder um Dateideskriptoren umzuleiten, um die Prozessausgabe zu protokollieren. Nur relevant bei Verwendung von --background.

Dieser hat für mich gearbeitet:

    start-stop-daemon -b -C -o -c \ 
         $DAEMON_USER -S -x $DAEMON > $DAEMON_LOG 2>&1
Raashid Muhammed
quelle
4

Zitieren einer alten Mailingliste:

https://lists.ubuntu.com/archives/ubuntu-uk/2005-June/000037.html

Ein einfacher - und wenn Sie Start-Stop-Daemon verwenden möchten, vielleicht der einzige - Weg, dies zu umgehen, besteht darin, ein kleines Skript zu erstellen, das Folgendes enthält:

#!/bin/sh
exec /home/boinc/boinc/boinc > /home/boinc/log/boinc.log

und verwenden Sie dieses Skript dann als Argument für den Start-Stopp-Dämon.

Vielleicht ist die eigentliche Frage jedoch, ob es wirklich notwendig ist, Start-Stop-Daemon überhaupt zu verwenden?

joeytwiddle
quelle
3

Ich bin nicht sicher, ob "$ DAEMON $ DAEMON_ARGS> /var/log/some.log 2> & 1" jemals den Dateideskriptor für die Protokolldatei schließen wird. Wenn Ihr Daemon also für immer ausgeführt wird, bin ich mir nicht sicher Diese Protokollierung oder andere Mechanismen zum Bereinigen des Speicherplatzes würden funktionieren. Da es> statt >> ist, würde der vorgeschlagene Befehl beim Neustart auch vorhandene Protokolle abschneiden. Wenn Sie sehen möchten, warum der Dämon abgestürzt ist und automatisch neu gestartet wird, ist dies möglicherweise nicht sehr hilfreich.

Eine andere Option könnte "$ DAEMON | logger" sein. logger ist ein Befehl, der in syslog (/ var / log / messages) protokolliert wird. Wenn Sie auch stderr benötigen, können Sie "$ DAEMON 1> & 2 | logger" verwenden.

nairbv
quelle
Sie haben Recht, die Verwendung >>ist im Allgemeinen besser für Dämonen geeignet, obwohl dies impliziert, dass Sie jetzt eine Logrotate-Regel erstellen sollten!
Joeytwiddle
Was den Speicherplatz betrifft, erhalten Methoden, die die Datei abschneiden , den Speicherplatz sofort zurück (zumindest unter ext-Dateisystemen). Achten Sie jedoch auf Methoden, mit denen eine Datei, in die noch geschrieben wird, einfach gelöscht wird: Der Speicherplatz wird erst wieder freigegeben, wenn das Handle freigegeben wurde, und Sie können den Dateiknoten zum manuellen Abschneiden nicht mehr finden!
Joeytwiddle
@joeytwiddle Ein Teil meines Punktes hier ist, dass es Situationen gibt, in denen logrotate Protokolle nicht drehen kann, wenn das Dateihandle nie geschlossen wird.
Nairbv
--no-close ... | loggerfunktioniert bei mir nicht (Debian 7.3, Start-Stop-Daemon 1.16.12). Das Start-Stopp-Daemon-Skript wird nicht zurückgegeben, obwohl / var / log / messages gefüllt ist :-). Ich habe es mit und ohne versucht 1>&2.
Hgoebl
hgoebl Sie müssen den Ausdruck "cmd | logger" in Anführungszeichen setzen, damit der Interpreter weiß, dass es sich um "cmd" handelt, das Sie an logger weiterleiten, nicht um den Ausdruck "start-stop-daemon".
Wexxor
2

Angenommen, es ist Bash (obwohl einige andere Shells dies ebenfalls zulassen), lautet die Zeile:

exec >>/tmp/myDaemon.log

sendet alle zukünftigen Standardausgaben an diese Datei. Das liegt daran, dass execohne Programmnamen nur Umleitungszauber ausgeführt wird. Von der bashManpage:

Wenn kein Befehl angegeben wird, werden alle Umleitungen in der aktuellen Shell wirksam.

Die Verwaltung dieser Datei ist natürlich ein weiteres Problem.

paxdiablo
quelle
Können Sie klarstellen, wo diese Zeile platziert werden soll? Gleich nach der start-stop-daemonZeile, die in der ersten Frage erwähnt wurde?
Abdull
1

Wie wäre es mit:

sudo -u myuser -i start-stop-daemon ...
jakub.piasecki
quelle