Fabric: Init-Skripte können ihre Daemons häufig nicht starten

Erstellt am 19. Aug. 2011  ·  19Kommentare  ·  Quelle: fabric/fabric

Beschreibung

Ich habe mehrere Berichte darüber im IRC sowie einen Kommentar zu # 350 und jetzt einen Mailinglisten-Thread erhalten .

Noch keine klare Ursache, und obwohl mehrfach darüber berichtet wurde, erwarte ich nicht, dass es sich um ein ständiges Problem handelt, oder wir würden viel mehr darüber hören. In einigen bisher nur sehr begrenzten Tests kann ich das Problem in 30-50% der Fälle neu erstellen - aber es ist reproduzierbar.

Das Symptom ist einfach, dass Skripte im Init-Stil, die für das Starten von Dämonen und die sofortige Rückgabe verantwortlich sind, OK zurückgeben, den Code 0 zurückgeben und die Statusmeldung "Erfolg" auf stdout gedruckt werden - aber den betreffenden Dämon nicht tatsächlich starten.

Mein persönlicher Test wurde über den neuesten Master durchgeführt, der auf eine Ubuntu 10.04 (Lucid) VM und das Init-Skript des Standard-Apache2-Pakets abzielte.


Ursprünglich eingereicht von Jeff Forcier ( Bitprophet ) am 23.07.2011 um 19:25 Uhr EDT

Beziehungen

  • Im Zusammenhang mit # 350: Fabric legt einen Remote-Befehl auf (für Daemon-Programm)
Bug Docs Wart

Hilfreichster Kommentar

Ich bin gerade mit diesem Problem konfrontiert.
Ich hatte eine Situation, in der ich tty = False nicht verwenden kann, weil ich den Befehl mit sudo ausführe.
Das Hinzufügen von >& /dev/null < /dev/null & funktioniert gut, aber der Prozess wurde nicht gestartet.

Ich habe das Problem mit dem Hinzufügen eines Ruhezustands nach der Befehlsausführungszeile gelöst: nohup java -jar text.jar & sleep 5; exit 0

Alle 19 Kommentare

Jeff Forcier ( Bitprophet ) gepostet:


Instrumentiert das Init-Skript, das ich teste, und alles scheint in beiden Richtungen gleich zu laufen (dh echte Erfolgsszenarien oder falsche Erfolgsszenarien), was bedeutet, dass das Problem innerhalb des Aufrufs von apachectl , den das Skript selbst ausführt.

Beginnen Sie darüber nachzudenken, was die Ursache für uns sein könnte:

  • Da es halb zufällig ist, denke ich an die vergangenen Probleme mit dem von Rennbedingungen geplagten E / A-Subsystem. Ich kann mir jedoch nicht wirklich vorstellen, wie sich dies möglicherweise auf diese Weise auf etwas am entfernten Ende auswirken könnte, und die Rennbedingungen waren sowieso alle lokal.

    • Eine Möglichkeit, dies zu testen, könnte darin bestehen, festzustellen, ob dieses Problem mit Fab 0.9.x und pty = True auftritt (um dem aktuellen Standard in 1.x zu entsprechen).

  • Es könnte auch nur pty-bezogen sein - ich erinnere mich nicht, dass dies ein Problem vor 1.0 war und das Setzen von pty auf True eine der wichtigsten Änderungen im Standardverhalten war. Auch hier kann ich nicht verstehen, warum die Verwendung des SSH-Subsystems request-a-pty dazu führen würde, dass sich Init-Skripte so verhalten.

    • Ein Test hier wäre, ssh -t <hostname> <command> und zu sehen, ob dies auch das Problem reproduziert.


am 23.07.2011 um Uhr EDT

Jeff Forcier ( Bitprophet ) gepostet:


apache2ctl selbst ist auch einfach ein Wrapper-Bash-Skript, das /usr/sbin/apache2 aufruft und ein Symlink zu einer tatsächlichen ausführbaren Binärdatei im Installationsverzeichnis von Apache mpm-worker ist. Insbesondere bei normaler Verwendung von start wird /usr/sbin/apache2 -k start . Nach wie vor scheint sich apache2ctl in den beiden verschiedenen Szenarien, dem Rückgabewert oder den ausgeführten Abschnitten, nicht anders zu verhalten.

/usr/sbin/apache2 Dokumente von apache2 alleine ausführen, ist dies ziemlich schwierig offensichtlich mit Fehlern darüber, dass diese Variablen nicht gesetzt sind.)

Wenn Sie die Ausgabe von env kurz vor dem Aufruf von apache2ctl von apache2 nur wenige Elemente: Benutzer, Gruppe, Speicherort der PID-Datei und Sprache. Diese ändern sich nicht zwischen Erfolgs- und Misserfolgssituationen. Ich hatte gehofft, dass es etwas in den verschiedenen Quellen- und Umgebungseinstellungen in den Wrappern geben würde, das sich manchmal ändern würde, aber nein.


Bisher ist dies nirgendwo sinnvoll. Zeit, die oben genannten Ideen (pty, ssh) zu testen, um zu sehen, was sich dort ändert.


am 23.07.2011 um 20:46 Uhr EDT

Jeff Forcier ( Bitprophet ) gepostet:


Mit pty=False scheint es viel besser zu funktionieren (wie aus Max 'Kommentar in # 350 hervorgeht). Mit der Standardeinstellung True habe ich ungefähr 5/10 Mal Fehler gesehen, manchmal ein paar mehr oder weniger. Mit False habe ich es gerade ungefähr 15 Mal hintereinander ohne Fehler ausgeführt. Kein Statistiker, aber das scheint mir ziemlich gut zu sein.

Das manuelle Ausführen von ssh ähnlichen Ergebnissen: ssh -t <host> sudo /etc/init.d/apache2 start kann Apache in etwa 50% der Fälle stillschweigend nicht starten. Das gleiche gilt für -T (keine Pty erzwingen) und es startet 100% der Zeit.

Das ist also nicht Fabric's Schuld; Es ist etwas Tieferes, wo sich diese Init-Skripte schlecht verhalten, wenn eine Pseudo-Tty im SSH-Stil im Spiel ist.


Aus Neugier ein bisschen tiefer gehen, aber es sieht so aus, als ob die "Lösung" hier eine neue FAQ ist, die besagt, dass pty=False wenn dieses Problem auftritt.


am 23.07.2011 um 20:59 Uhr EDT

Jeff Forcier ( Bitprophet ) gepostet:


Ja, ich finde leider nichts, was dieses Verhalten erklärt. Angesichts der obigen Ergebnisse denke ich, dass eine FAQ definitiv der richtige Weg ist.


am 23.07.2011 um Uhr EDT

Hugo Garza (hiro2k) gepostet:


Ughh, ich bin gestern gerade darauf gestoßen, ich wünschte, ich hätte diesen Fehler gesehen, zum Glück habe ich versucht, pty = False zu setzen, und es hat auch funktioniert. Danke für die Erklärung, zumindest ist es kein Stofffehler. Jetzt frage ich mich wirklich, warum dies fehlschlägt.


am 02.08.2011 um 13:27 Uhr EDT

Sind Sie sicher, dass dies nicht nur ein Bash-Skript-Problem ist? Ich meine mit meinem Mailinglisten-Thread. Es waren nur Bash-Skripte, mit denen Java und Weblogic gestartet wurden.

FWIW, ich bekomme dieses schreckliche Verhalten auf so ziemlich jeder Ubuntu-Maschine, die ich auf EC2 hochfahre.

Es ist auch reproduzierbar mit Aufgaben, die über einen abgetrennten Bildschirm screen -d -m someBackgroundTask gestartet werden.

Ich sollte erwähnen, dass normalerweise pty=False das Problem löst, aber ich habe Fälle gesehen, in denen dies nicht der Fall war.

@yuvadm - Kann das Problem in den Fällen, in denen pty = False das Problem nicht löst, immer noch mithilfe eines regulären ssh-Befehls (wie oben erwähnt) neu erstellt werden? Soweit ich gesehen habe, handelt es sich um ein SSH-Problem und nicht um ein Fabric-Problem, aber es wäre gut zu wissen, ob es Situationen gibt, in denen es nicht übereinstimmt.

Das ist ein interessanter Winkel, den ich überprüfen werde. Ich werde mich in diesem Fall bei Ihnen melden ...

Ich habe dieses Problem reproduziert. Client ist Ubuntu 10.04.3 LTS, Server ist "Ubuntu 8.04.4 LTS (Server)".
Der SSH-Client ist "OpenSSH_5.3p1 Debian-3ubuntu7, OpenSSL 0.9.8k, 25. März 2009", der SSH-Server ist "OpenSSH_4.7p1 Debian-8ubuntu1, OpenSSL 0.9.8g, 19. Oktober 2007". Stoff ist "1.3.3 endgültig".

Das Problem besteht zu 100% bei pty = True und verschwindet mit pty = False.

Bei der Verbindung mit anderen Servern tritt das Problem nicht immer auf, wenn pty = True ist.

In meinem Fall führe ich zum Testen einen sehr einfachen Befehl aus: "nohup sleep 100> / tmp / xxx 2> & 1

Ich bin davon gebissen worden, nur auf EC2, wie es scheint (ich habe es auf meinem Linode nicht gesehen, bin mir aber nicht 100% sicher). Das Setzen von pty = False scheint das Problem zu beheben.

Ich bin gerade mit diesem Problem konfrontiert.
Ich hatte eine Situation, in der ich tty = False nicht verwenden kann, weil ich den Befehl mit sudo ausführe.
Das Hinzufügen von >& /dev/null < /dev/null & funktioniert gut, aber der Prozess wurde nicht gestartet.

Ich habe das Problem mit dem Hinzufügen eines Ruhezustands nach der Befehlsausführungszeile gelöst: nohup java -jar text.jar & sleep 5; exit 0

Danke spodgruskiy,

Ihre Tipps funktionieren bei mir.
Ich hatte versucht, fabelhaft zu schreiben, um einen Strom-Cluster mit folgenden Befehlen zu starten.

  1. run ('nohup ./bin/storm nimbus> & / dev / null </ dev / null &', pty = False)
  2. run ('nohup ./bin/storm nimbus> & / dev / null </ dev / null &')
  3. run ("screen -d -m './bin/storm nimbus'", pty = False)
  4. run ("|| screen -d -m './bin/storm nimbus'")

Aber keiner von ihnen funktioniert, Nimbus hat überhaupt nicht gestartet. Ich verstehe nicht, was passiert ist.
Trotzdem danke.

+1 für den Schlaftrick

benötigt, um an Systemen mit Anforderungen zu arbeiten

sudo ('Service starten; Schlaf .5') und alles ist gut!

Wenn Sie 'sudo ()' verwenden und auf dem Remote-System RequireTty für den sudo-Zugriff aktiviert ist, können Sie 'set -m' verwenden. Bedienungstart ', um zu verhindern, dass das SIGHUP an den vom Init-Skript gestarteten Prozess gesendet wird.

Unter http://stackoverflow.com/a/14866774 finden Sie eine ausführlichere Erläuterung zu Bash Interactive und Non-Interactive sowie zu den Auswirkungen auf die Jobsteuerung.

Ich bin neugierig, was ist das SSH-Problem hier?

pty = false funktioniert bei mir

Es ist nicht wirklich ein SSH-Problem, sondern eher das subtile Verhalten in Bezug auf nicht interaktive / interaktive BASH-Modi und die Signalausbreitung an Prozessgruppen.

Das Folgende basiert auf http://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774 und http: //www.itp.uzh.ch/~dpotter/howto/daemonize , wobei einige Annahmen nicht vollständig validiert sind, aber Tests darüber, wie dies funktioniert, scheinen dies zu bestätigen.

pty / tty = false

Die gestartete Bash-Shell stellt eine Verbindung zu stdout / stderr / stdin des gestarteten Prozesses her und wird so lange ausgeführt, bis nichts mehr an den Sockets angebracht ist und die untergeordneten Elemente beendet wurden. Ein guter Deamon-Prozess stellt sicher, dass er nicht darauf wartet, dass seine Kinder beendet werden, einen untergeordneten Prozess gabelt und dann beendet. In diesem Modus wird von SSH kein SIGHUP an den untergeordneten Prozess gesendet. Ich glaube, dass dies für die meisten Skripte, die einen Prozess ausführen, der die Desamonisierung selbst handhabt und nicht im Hintergrund ausgeführt werden muss, korrekt funktioniert. Wenn Init-Skripte '&' verwenden, um einen Prozess als Hintergrund zu verwenden, besteht das Hauptproblem wahrscheinlich darin, ob der Hintergrundprozess jemals versucht, aus stdin zu lesen, da dies ein SIGHUP auslöst, wenn die Sitzung beendet wurde.

pty / tty = true *

Wenn das Init-Skript den Prozess gestartet hat, gibt die übergeordnete BASH-Shell einen Exit-Code an die SSH-Verbindung zurück, der sofort beendet werden soll, da er nicht darauf wartet, dass ein untergeordneter Prozess beendet wird, und nicht auf stdout blockiert wird / stderr / stdin. Dies führt dazu, dass ein SIGHUP an die übergeordnete Bash-Shell-Prozessgruppe gesendet wird. Da die Jobsteuerung in Bash im nicht interaktiven Modus deaktiviert ist, werden die gerade gestarteten untergeordneten Prozesse eingeschlossen. Wenn ein Daemon-Prozess beim Forking oder im Forked-Prozess explizit eine neue Prozesssitzung startet, erhalten er oder seine untergeordneten Elemente das SIGHUP nicht vom BASH-übergeordneten Prozess, der beendet wird. Beachten Sie, dass sich dies von angehaltenen Jobs unterscheidet, bei denen ein SIGTERM angezeigt wird.

Ich vermute, dass die Probleme damit nur manchmal mit einer leichten Rennbedingung zu tun haben. Wenn Sie sich den Standardansatz für die Deseamonisierung ansehen - http://www.itp.uzh.ch/~dpotter/howto/daemonize - werden Sie sehen, dass die neue Sitzung im Code durch den gegabelten Prozess erstellt wird, der möglicherweise nicht vorhanden ist Laufen Sie, bevor das übergeordnete Element beendet wird, was zu dem oben erwähnten zufälligen Erfolgs- / Fehlerverhalten führt. Eine Schlafanweisung lässt genügend Zeit, damit der gegabelte Prozess eine neue Sitzung erstellt hat, weshalb dies in einigen Fällen funktioniert.

pty / tty = true und die Jobsteuerung ist in bash explizit aktiviert

SSH stellt keine Verbindung zum stdout / stderr / stdin der Bash-Shell oder zu gestarteten untergeordneten Prozessen her. Dies bedeutet, dass es beendet wird, sobald die übergeordnete Bash-Shell die Ausführung der angeforderten Befehle beendet hat. In diesem Fall werden bei explizit aktivierter Jobsteuerung alle Prozesse, die von der Bash-Shell mit '&' als Hintergrund gestartet wurden, sofort in eine separate Sitzung gestellt und erhalten kein SIGHUP-Signal, wenn der übergeordnete Prozess zur BASH-Sitzung beendet wird ( SSH-Verbindung in diesem Fall).

Was muss repariert werden?

Ich denke, die Lösungen müssen nur explizit in der run / sudo-Betriebsdokumentation als Sonderfall bei der Arbeit mit Hintergrundprozessen / -diensten erwähnt werden. Verwenden Sie grundsätzlich entweder 'pty = false' oder aktivieren Sie die Jobsteuerung explizit als ersten Befehl, wenn dies nicht möglich ist, und das Verhalten ist korrekt.

Wie ich hier erwähnt habe fabrickit (eine Hülle aus Stoffbibliotheken) https://github.com/HyukjinKwon/fabrickit/commit/cceb8bfb8f960a3ac41b24c64b8358bd6e7a0366

Sie können ein Programm ganz einfach als Daemon ohne bestimmte Konfigurationen oder Einstellungen starten.
Dies ist sowieso eine Art Shell-Ausführung, und daher sollte es eine Möglichkeit geben, das zu tun, was Shell kann.

Versuche dies:

run("sh -c '((nohup %s > /dev/null 2> /dev/null) & )'" % cmd, pty=False)

Ich habe es versucht und es funktioniert einwandfrei, auch wenn es keine zusätzliche Programmierung implementiert, um als Daemon ausgeführt zu werden (selbst ein Programm, das 'Hallo' innerhalb einer while-Schleife schreibt, funktioniert einwandfrei).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen