Wie kann ich einen Prozess von einem Bash-Skript trennen?


18

Ich versuche, einen Prozess von einem Bash-Skript zu trennen, damit SIGINT nicht an den Prozess weitergeleitet wird, wenn ich das Skript beende.

Ich habe den disownBefehl im Terminal direkt verwendet, aber in der Bash wird disowndie Weiterleitung von SIGINT nicht gestoppt. Der Zweck dieses Skripts besteht darin, openocd und dann gdb mit einem einzigen Aufruf zu starten. Da das Skript nie beendet wird (es läuft mit gdb), wird SIGINT immer noch von gdb an openocd weitergeleitet, was ein Problem darstellt, da SIGINT als Befehl zum Anhalten in gdb verwendet wird.

Im Terminal würde es ungefähr so ​​aussehen:

$ openocd &    # run openocd demonized
$ disown $!    # disown last pid
$ gdb          # invoke GDB

Wenn SIGINT in dieser Reihenfolge auf dem Terminal aufgerufen wird, wird es nicht von gdb an openocd übergeben. Wenn sich derselbe Aufruf jedoch in einem Bash-Skript befand, wird der SIGINT übergeben.

Jede Hilfe wäre sehr dankbar.

PS: Dieses Problem ist in OS X, aber ich versuche, Tools zu verwenden, die auch auf alle Unix-Tools portierbar sind.


nohupist nicht ganz die richtige Antwort. Sie sollten einen Pseudocode oder Beispielcode hinzufügen, um genauer zu zeigen, was Sie wollen.
Bruce Ediger

1
Sind Sie offen für ein Tool wie screen?
Eric Renouf

Antworten:


17

So trennen Sie einen Prozess von einem Bash-Skript:

nohup ./process &

Wenn Sie Ihr Bash-Skript mit SIGINT(Strg + C) stoppen oder die Shell SIGHUPbeispielsweise das Senden beendet , wird der Prozess nicht gestört und normal weiter ausgeführt. stdout& stderrWird in einer Protokolldatei umgeleitet werden: nohup.out.

Wenn Sie einen getrennten Befehl ausführen möchten, während die Ausgabe im Terminal angezeigt wird, verwenden Sie tail:

TEMP_LOG_FILE=tmp.log
> "$TEMP_LOG_FILE"
nohup ./process &> "$TEMP_LOG_FILE" & tail -f "$TEMP_LOG_FILE" &

Warum ist das nohupnotwendig? Was ist der Unterschied zwischen nohup COMMAND &und COMMAND &ob es Ihr Ziel ist, den Befehl nur im Hintergrund auszuführen und das Terminal freizugeben?
James Wierzba

@JamesWierzba Einer der Unterschiede besteht darin, dass nohup der richtige Weg ist, wenn Sie den Befehl auch nach dem Beenden der Shell ausführen müssen. Es gibt tausende ausführliche Erklärungen im Web. ZB stackoverflow.com/questions/15595374/…
Marc


3

Die Lösung, die ich gefunden habe, ist ein Programm namens "detach", das von Annon Inglorion geschrieben und von seiner Website heruntergeladen werden kann

Einmal kompiliert, kann es wie folgt in einem Skript verwendet werden:

$ ./detach -p debug.pid openocd <args> # detach openocd
$ gdb <args>                           # run gdb
$ kill -9 $(cat debug.pid)             # end openocd process
$ rm debug.pid                         # remove file containing process id

In dieser ersten Zeile wird ein neuer Prozess erstellt (openocd wird ausgeführt) und die Prozess-ID zur späteren Verwendung in der Datei (debug.pid) gespeichert. Dies verhindert die Probleme mit dem Greifen nach der PID, wie in Olivers Antwort angegeben. Beim Beenden des nächsten Sperrprogramms (gdb) wird die Datei, in der die pid gespeichert ist, verwendet, um den getrennten Prozess direkt abzubrechen.


2

eine einfache und tragbare Lösung:

echo "openocd" | at now #openocd starts now, but via the at daemon, not the current shell!
pid=$(ps -ef | grep "[o]penocd" | awk '{print $1}')  
echo "openocd is running with pid: $pid"
gdb

Einige Portabilitätseinschränkungen: Die psOptionen hängen vom Betriebssystem ab! Sie könnten stattdessen eine Variante benutzen { ps -ef || ps aux ;} | grep '[o]penocd | cut -f 1. atkonnte nicht verfügbar sein (seltsam, aber das passiert ...). $(...)benötigt eine nicht wirklich alte Shell, ansonsten Backticks verwenden.


Dies scheint gefährlich zu sein. Das Greifen nach pid kann unerwartete Dinge bewirken, wenn mehr als ein Prozess mit demselben Namen ausgeführt wird oder sogar, wenn ein anderer Prozess das Wort openocd enthält.
Orion

1
@orion: Ich gebe ein einfaches Beispiel, um die Ideen zu nennen. Diese Bedenken, die Sie erwähnen, sind leicht zu beseitigen: atStarten Sie ein Skript, das das Programm startet und stattdessen seine PID in einer Datei ausgibt, und lassen Sie das Hauptskript darauf warten Datei zu erscheinen und dann die PID daraus zu lesen.
Olivier Dulac

Natürlich sollten Sie in meinem (zu einfachen) Beispiel das grep durch einen Test in awk in der rechten Spalte ersetzen (normalerweise $ 8) (die Spalten hängen von Ihrem Betriebssystem und der Version / den Optionen von ps ab)
Olivier Dulac
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.