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.

użytkownik2328113
źródło
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" &
Marc
źródło
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
11

Dla mnie to działa idealnie z disown

command & disown
ManuelSchneid3r
źródło
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.

użytkownik2328113
źródło
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.

Olivier Dulac
źródło
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