Jak mogę odłączyć proces od skryptu bash?


18

Usiłuję odłączyć proces od skryptu bash, aby SIGINT nie był przekazywany do procesu po zamknięciu skryptu.

Użyłem disownpolecenia bezpośrednio w terminalu, jednak w bash disownnie powstrzymuje SIGINT od przekazania. Celem tego skryptu jest uruchomienie openocd, a następnie gdb za pomocą pojedynczego wywołania. Ponieważ skrypt nigdy się nie kończy (działa z gdb), SIGINT jest nadal przekazywany z gdb do openocd, co stanowi problem, ponieważ SIGINT jest używany jako polecenie zatrzymania w gdb.

W terminalu wyglądałoby to mniej więcej tak:

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

wywołany na terminalu w tej kolejności, SIGINT nie jest przekazywany z gdb do openocd. Jednak jeśli to samo wywołanie było w skrypcie bash, SIGINT jest przekazywany.

Każda pomoc byłaby bardzo mile widziana.

ps ten problem występuje w OS X, ale próbuję użyć narzędzi, które są również przenośne dla wszystkich narzędzi Uniksa.


nohupnie jest właściwą odpowiedzią. Powinieneś dodać pseudokod lub przykładowy kod, aby dokładniej pokazać, czego chcesz.
Bruce Ediger,

1
Czy jesteś otwarty na korzystanie z takiego narzędzia screen?
Eric Renouf,

Odpowiedzi:


16

Aby odłączyć proces od skryptu bash:

nohup ./process &

Jeśli zatrzymasz skrypt bash za pomocą SIGINT(ctrl + c) lub powłoka zakończy wysyłanie, SIGHUPna przykład, proces nie będzie przeszkadzał i będzie kontynuował normalne działanie. stdoutI stderrzostanie przekierowany do pliku dziennika: nohup.out.

Jeśli chcesz wykonać odłączoną komendę, jednocześnie widząc dane wyjściowe w terminalu, użyj tail:

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

Dlaczego jest to nohupkonieczne? Jaka jest różnica między, nohup COMMAND &a COMMAND &jeśli Twoim celem jest uruchomienie polecenia w tle i zwolnienie terminala?
James Wierzba

@JamesWierzba Jedną z różnic jest to, że jeśli potrzebujesz komendy, aby kontynuować działanie nawet po wyjściu z powłoki, to nic nie jest dobrym rozwiązaniem. Istnieje tysiące obszernych wyjaśnień w sieci. Np stackoverflow.com/questions/15595374/...
MARC


4

Znalezione przeze mnie rozwiązanie obejmuje program o nazwie „odłącz” napisany przez Annona Ingloriona i dostępny do pobrania z jego strony internetowej

Po skompilowaniu można go użyć w skrypcie w następujący sposób:

$ ./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

Ten pierwszy wiersz tworzy nowy proces (z uruchomionym openocd) i przechowuje identyfikator procesu w pliku (debug.pid) do późniejszego wykorzystania. Zapobiega to problemom z grepowaniem dla pid zgodnie z odpowiedzią Olivera. Po wyjściu z następnego programu blokującego (gdb) plik przechowujący pid służy do bezpośredniego zabicia odłączonego procesu.


Potwierdza, detachczyni cuda.
AS

2

proste i przenośne rozwiązanie:

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

Niektóre zastrzeżenia dotyczące przenośności: psopcje zależą od systemu operacyjnego! można zamiast tego użyć wariant: { ps -ef || ps aux ;} | grep '[o]penocd | cut -f 1. atnie może być dostępny (dziwne, ale tak się dzieje ...). $(...)potrzebuje naprawdę starej powłoki, w przeciwnym razie użyj backicks.


Wydaje się to niebezpieczne, przechwytywanie pid może robić nieoczekiwane rzeczy, jeśli więcej niż jeden proces działa z tą samą nazwą, a nawet, jeśli inny proces zawiera słowo openocd.
orion

1
@orion: daję prosty przykład, aby przekazać pomysły, o których wspomnieniach można łatwo się pozbyć: aturuchom skrypt, który uruchamia program i zamiast tego podaje swój pid w pliku, a skrypt główny czeka na to pojawi się plik, a następnie przeczytaj z niego pid.
Olivier Dulac,

oczywiście powinieneś zastąpić w moim (zbyt prostym) przykładzie grep testem wewnątrz awk, w prawej kolumnie (zwykle 8 $) (kolumny zależą od twojego systemu operacyjnego i wersji / opcji ps)
Olivier Dulac
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.