2009-03-09 8 views
2

Ich habe einen Dienst, sagen foo, in C++ geschrieben, der als root läuft. Es gibt den üblichen Scrip, /etc/init.d/foo start | stop | restart.Wie bekomme ich einen Prozess, um sich in Linux neu zu laden?

Zu bestimmten Zeiten muss foo sich neu laden. Normalerweise, nachdem ein Upgrade beendet wurde. Aber Dinge zu tun, wie:

system("/etc/init.d/foo restart") 

funktioniert nicht, da, sobald Neustart tötet foo, wobei das System() -Aufruf wird offensichtlich auch getötet, und der Neustart Skript führt nie zum Abschluss.

Gibt es einen anderen Aufruf, den ich anstelle von system() verwenden kann, das asynchron als ein Geschwister zum aufrufenden Prozess ausgeführt wird, anstatt ein synchrones Kind zu erstellen?

Danke!

Antwort

9

Haben Sie schon die exec[*] Familie in Betracht gezogen? Hier ist eine - execve.

+2

Danke. Der andere Trick, den ich recherchieren musste, war fcntl() aufzurufen, um FD_CLOEXEC auf dem Server Listening Port zu setzen. Andernfalls würde die exec'd-App den ursprünglichen Socket erben und mir Kummer bereiten. –

5

Wie wäre es mit fork() gefolgt von exec()?

+1

Keine Gabel in diesem Fall, nur exec(). – Juliano

1

Kombinieren Sie die beiden Antworten bisher mit fork-exec.

9

Sie könnten es in inittab setzen und init sorgen über den Neustart des Prozesses, wenn es aus irgendeinem Grund beendet. Das würde auch für automatische Neustarts sorgen, wenn Ihr Prozess abstürzt oder assert() oder unerwartet unerwartet beendet wird.

Dann, um Ihren Anwendungsfall zu behandeln, würde der Prozess einfach sich selbst beenden.

1

Um hinzuzufügen, was Ori bereits gesagt hat, verwenden einige Linux-Distributionen immer noch initab, aber Ubuntu und möglicherweise andere sind zu /etc/event.d gewechselt. Du legst dort eine Datei ein (kopiere und bearbeite eine der vorhandenen) und starte dann den Daemon mit "sudo start ssh_tunnel" oder wie auch immer deine Datei aufgerufen wird.

Dann, wenn Sie es neu starten müssen, können Sie es einfach mit einem Signal beenden, und das System wird es neu starten. Oder es könnte selbst entscheiden, dass es Zeit für einen Neustart ist, indem "exit (0)" aufgerufen wird. oder Wasauchimmer.

0

Schauen Sie sich die Manpage für inittab an.

Es beschreibt, wie das System Ihre Prozesse automatisch neu startet, wenn es stirbt (Respawn).

Mit dieser Einrichtung ist alles, was Sie tun müssen, zu beenden und das System kümmert sich automatisch um den Neustart (respawn) für Sie.

1

exec*() selbst auf der ursprünglichen Befehlszeile sollte den Trick tun. Sie können den Fork wahrscheinlich weglassen, weil dann zwei Kopien laufen, die Sie nicht benötigen, und die ursprüngliche Kopie muss dann beendet werden.

Aber schauen Sie auch inittab und event.d je nach Distro, um zu sehen, ob es das tun wird, was Sie besser brauchen.

2

Betrachten

/etc/init.d/foo reload 

für Ihren Daemon (ziemlich Standard Beurteilung durch einen grep meiner Debian-Box) zu implementieren.

Dies wird typischerweise durch Senden eines SIGHUP-Signals an den Prozess erreicht; Der Daemon sollte einen Signalhandler haben, der diese fängt und jede Konfiguration neu lädt.

Wenn der Prozess weiß, dass er neu geladen werden muss, kann er sich selbst signalisieren.

Wenn Sie wirklich neue Bibliotheken müssen neu starten, dann mit exec*()

1

Eine dritte Möglichkeit, was Ori und Paul vorgeschlagen gehen zu holen haben wäre daemontools zu verwenden. Es ist tragbarer, jedoch weniger wahrscheinlich verfügbar. Sie erstellen ein Skript mit dem Namen/service/foo/run, und daemontools wird Ihren Dienst bei jedem Beenden neu starten.

http://cr.yp.to/daemontools.html