Dla każdego, kto boryka się z tym samym problemem: pamiętaj, że nawet jeśli piszesz, yourExecutable &a wyniki wciąż pojawiają się na ekranie i Ctrl+Cnie wydają się niczego zatrzymywać, po prostu ślepo wpisz disown;i naciśnij, Enternawet jeśli ekran przewija się z wyjściami i nie możesz zobaczyć, co piszesz. Proces zostanie odrzucony, a ty będziesz mógł zamknąć terminal bez śmierci procesu.
Nav
Odpowiedzi:
1367
Korzystanie z kontroli zadań bash, aby wysłać proces w tle:
Ctrl+, Zaby zatrzymać (wstrzymać) program i wrócić do powłoki.
bg aby uruchomić go w tle.
disown -h [job-spec]gdzie [specyfikacja zadania] to numer zadania (jak %1dla pierwszego uruchomionego zadania; znajdź swój numer za pomocą jobspolecenia), aby zadanie nie zostało zabite, gdy terminal zostanie zamknięty.
Ponieważ pytanie brzmiało, jak „umieścić to pod nohup”, disown -hbyć może jest bardziej dokładna odpowiedź: „spraw, aby disown zachowywał się bardziej jak nohup (tzn. Zadania pozostaną w drzewie procesów bieżącej powłoki, dopóki nie opuścisz powłoki) To pozwala ci zobaczyć wszystkie zadania uruchomione przez tę powłokę. ” (z [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
Dr Jan-Philip Gehrcke
8
Jak mogę później odzyskać pracę? Widzę, że działa przy użyciu ps -e.
Paulo Casaretto,
26
Nie widać wyniku zadania po disown, disown czyni proces demonem, co oznacza, że standardowe wejścia / wyjścia są przekierowywane do / dev / null. Jeśli więc planujesz odrzucić zadanie, lepiej zacząć od zalogowania się do pliku, np.my_job_command | tee my_job.log
rustyx
8
czy można w jakiś sposób zrobić coś takiego jak „my_job_command | tee my_job.log ' po uruchomieniu polecenia?
arod
23
disownoddziela wszelkie rury od procesu. Aby ponownie przymocować rury, użyj gdbzgodnie z opisem w tym wątku . Mówiąc dokładniej, ten post .
mbrownnyc
185
Załóżmy, że z jakiegoś powodu Ctrl+ Zrównież nie działa, przejdź do innego terminala, znajdź identyfikator procesu (za pomocą ps) i uruchom:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOPzawiesi proces i SIGCONTwznowi proces w tle. Więc teraz zamknięcie obu terminali nie zatrzyma twojego procesu.
Tak, to problem z systemem operacyjnym, kill nie działa z Cygwin w systemie Windows.
Pungs 11.11.13
6
Jest to również bardzo przydatne, jeśli zadanie jest uruchamiane z innej sesji ssh.
Amir Ali Akbari
5
Pamiętaj tylko, aby zrobić to disown %1w pierwszym terminalu przed jego zamknięciem.
fred
1
Jest to przydatne, ponieważ uruchomiłem interfejs graficzny z konsolą (w moim przypadku zacząłem od konsoli kwinpo awarii bez myślenia o konsekwencjach). Więc gdybym przestał kwin, wszystko by się zawiesiło i nie miałem możliwości biegać bg!
Michele,
@fred Nie zrobiłem tego i wydawało się, że nadal działa. Możliwe czy trafiłem w zły PID?
Nikt
91
Polecenie oddzielenia uruchomionego zadania od powłoki (= powoduje, że nie jest to żadna czynność) jest disownpodstawowym poleceniem powłoki.
Z bash-manpage (man bash):
disown [-ar] [-h] [jobspec ...]
Bez opcji każdy rodzaj zadania jest usuwany z tabeli aktywnych zadań. Jeśli podano opcję -h, każdy parametr zadania nie jest usuwany z tabeli, ale jest oznaczony tak, że SIGHUP nie jest wysyłany do zadania, jeśli powłoka otrzyma SIGHUP. Jeśli nie podano specyfikacji zadania i nie podano opcji -a ani -r, używane jest bieżące zadanie. Jeśli nie podano specyfikacji zadania, opcja -a oznacza usunięcie lub zaznaczenie wszystkich zadań; opcja -r bez argumentu spec zadania ogranicza operację do uruchamiania zadań. Zwracana wartość wynosi 0, chyba że specyfikacja zadania nie określa poprawnego zadania.
To znaczy, że to proste
disown -a
usunie wszystkie zadania z tabeli zadań i sprawi, że nie będą działać
Tylko dla AIXi Solaris. „Wersje nohup w systemach AIX i Solaris mają opcję -p, która modyfikuje uruchomiony proces w celu zignorowania przyszłych sygnałów SIGHUP. W przeciwieństwie do opisanego powyżej wbudowanego bash, nohup -p akceptuje identyfikatory procesów.”. Źródło
AlikElzin-kilaka
27
Odpowiedź węzła jest naprawdę świetna, ale pozostawiło otwarte pytanie, w jaki sposób można przekierować stdout i stderr. Znalazłem rozwiązanie w systemach Unix i Linux , ale nie jest ono również kompletne. Chciałbym połączyć te dwa rozwiązania. Oto on:
Dla mojego testu stworzyłem mały skrypt bash o nazwie loop.sh, który drukuje swój pid z chwilą snu w nieskończonej pętli.
$./loop.sh
Teraz jakoś uzyskaj PID tego procesu. Zwykle ps -C loop.shjest wystarczająco dobry, ale jest wydrukowany w moim przypadku.
Teraz możemy przełączyć się na inny terminal (lub nacisnąć ^ Z i w tym samym terminalu). Teraz gdbnależy dołączyć do tego procesu.
$ gdb -p <PID>
To zatrzymuje skrypt (jeśli jest uruchomiony). Jego stan można sprawdzić ps -f <PID>, gdzie STATpole to „T +” (lub w przypadku ^ Z „T”), co oznacza (man ps (1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 =0
Close (1) zwraca zero po sukcesie.
(gdb) call open("loop.out",01102,0600)
$6 =1
Open (1) zwraca nowy deskryptor pliku, jeśli się powiedzie.
To otwarcie jest równe open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). Zamiast O_RDWRO_WRONLYmożna zastosować, ale /usr/sbin/lsofmówi „u” dla wszystkich procedur obsługi plików std * ( FDkolumna), co oznacza O_RDWR.
Sprawdziłem wartości w pliku nagłówkowym /usr/include/bits/fcntl.h.
Plik wyjściowy można otworzyć za pomocą O_APPEND, podobnie jak w nohupprzypadku, ale nie jest to sugerowane przez man open(2), ze względu na możliwe problemy z NFS.
Jeśli otrzymamy -1 jako wartość zwracaną, to call perror("")drukuje komunikat o błędzie. Jeśli potrzebujemy errno, użyj polecenia p errnogdb.
Teraz możemy sprawdzić nowo przekierowany plik. /usr/sbin/lsof -p <PID>drukuje:
Jeśli chcemy, możemy przekierować stderr do innego pliku, jeśli chcemy użyć call close(2)i call open(...)ponownie używając innej nazwy pliku.
Teraz załączony bashmusi zostać zwolniony i możemy wyjść gdb:
(gdb) detach
Detaching from program:/bin/bash, process <PID>(gdb) q
Jeśli skrypt został zatrzymany przez gdbinny terminal, kontynuuje działanie. Możemy wrócić do terminalu loop.sh. Teraz nic nie zapisuje na ekranie, ale działa i zapisuje do pliku. Musimy to umieścić w tle. Więc naciśnij ^Z.
^Z
[1]+Stopped./loop.sh
(Teraz jesteśmy w takim samym stanie, jak ^Zna początku naciśnięto).
Teraz możemy sprawdzić stan zadania:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID><PID><PPID>011:16 pts/36 S 0:00/bin/bash ./loop.sh
$ jobs
[1]+Stopped./loop.sh
Tak więc proces powinien być uruchomiony w tle i odłączony od terminala. Liczba w jobswynikach polecenia w nawiasach kwadratowych oznacza zadanie wewnątrz bash. Możemy użyć następujących wbudowanych bashpoleceń, stosując znak „%” przed numerem zadania:
$ bg %1[1]+./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID><PID><PPID>011:16 pts/36 S 0:00/bin/bash ./loop.sh
A teraz możemy wyjść z bashu wywołującego. Proces jest kontynuowany w tle. Jeśli wyjdziemy, jego PPID zmieni się na 1 (proces init (1)), a terminal kontrolny stanie się nieznany.
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID><PID>1011:16? S 0:00/bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>...
loop.sh <PID> truey 0u CHR 136,3638/dev/pts/36(deleted)
loop.sh <PID> truey 1u REG 0,26112715008411/home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,3638/dev/pts/36(deleted)
KOMENTARZ
Pliki gdb można zautomatyzować, tworząc plik (np. Loop.gdb) zawierający polecenia i uruchamiany gdb -q -x loop.gdb -p <PID>. Mój loop.gdb wygląda następująco:
Rzeczywiście bardzo pouczające i może działać dobrze w prostych przypadkach. Ale uwaga, bardziej złożone przypadki mogą zawieść nieszczęśliwie. Miałem jeden z nich dzisiaj: mój proces zrodził inny proces, który wykonał wynik (przypuszczalnie do stderr), ale stdout podłączył się do komunikacji ze swoim panem. Przekierowywanie FD-ów masterów było bezskuteczne, ponieważ dziecko odziedziczyło stderr, a zamknięcie standardowego potomka nie powiodło się dla mistrza, który czekał na drugim końcu rury. X- | Zanim spróbujesz tego, lepiej poznaj swoje procesy.
cmaster
@cmaster Możesz sprawdzić, czy uchwyt jest przekierowany za pomocą lsof(nazwa uchwytu pliku jest inna pipeniż /dev/pts/1) lub przez ls -l /proc/<PID>/fd/<fd>(pokazuje to dowiązanie symboliczne uchwytu). Również podprocesy nadal nie mogą przekierowywać danych wyjściowych, które powinny zostać przekierowane do pliku.
Następnie wypróbowałem następujące polecenia i zadziałało bardzo dobrze
Powiedzmy, że uruchomcie SOMECOMMAND /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.
Ctrl+, Zaby zatrzymać (wstrzymać) program i wrócić do powłoki.
bg aby uruchomić go w tle.
disown -h aby proces nie został zabity, gdy terminal zostanie zamknięty.
Wpisz, exitaby wyjść z powłoki, ponieważ teraz możesz zacząć, ponieważ operacja będzie działać w tle w swoim własnym procesie, więc nie jest związana z powłoką.
Ten proces jest równoważny z uruchomieniem nohup SOMECOMMAND.
Myślę, że zachowanie disown -a polega na odcięciu przywiązania do wszystkich zadań. Jednak nie wyłącza potoków stdin / stdout, co oznacza, że proces nadal będzie próbował pisać (/ czytać) z terminala
yourExecutable &
a wyniki wciąż pojawiają się na ekranie iCtrl+C
nie wydają się niczego zatrzymywać, po prostu ślepo wpiszdisown;
i naciśnij,Enter
nawet jeśli ekran przewija się z wyjściami i nie możesz zobaczyć, co piszesz. Proces zostanie odrzucony, a ty będziesz mógł zamknąć terminal bez śmierci procesu.Odpowiedzi:
Korzystanie z kontroli zadań bash, aby wysłać proces w tle:
bg
aby uruchomić go w tle.disown -h [job-spec]
gdzie [specyfikacja zadania] to numer zadania (jak%1
dla pierwszego uruchomionego zadania; znajdź swój numer za pomocąjobs
polecenia), aby zadanie nie zostało zabite, gdy terminal zostanie zamknięty.źródło
disown -h
być może jest bardziej dokładna odpowiedź: „spraw, aby disown zachowywał się bardziej jak nohup (tzn. Zadania pozostaną w drzewie procesów bieżącej powłoki, dopóki nie opuścisz powłoki) To pozwala ci zobaczyć wszystkie zadania uruchomione przez tę powłokę. ” (z [ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )disown
, disown czyni proces demonem, co oznacza, że standardowe wejścia / wyjścia są przekierowywane do / dev / null. Jeśli więc planujesz odrzucić zadanie, lepiej zacząć od zalogowania się do pliku, np.my_job_command | tee my_job.log
disown
oddziela wszelkie rury od procesu. Aby ponownie przymocować rury, użyjgdb
zgodnie z opisem w tym wątku . Mówiąc dokładniej, ten post .Załóżmy, że z jakiegoś powodu Ctrl+ Zrównież nie działa, przejdź do innego terminala, znajdź identyfikator procesu (za pomocą
ps
) i uruchom:SIGSTOP
zawiesi proces iSIGCONT
wznowi proces w tle. Więc teraz zamknięcie obu terminali nie zatrzyma twojego procesu.źródło
disown %1
w pierwszym terminalu przed jego zamknięciem.kwin
po awarii bez myślenia o konsekwencjach). Więc gdybym przestał kwin, wszystko by się zawiesiło i nie miałem możliwości biegaćbg
!Polecenie oddzielenia uruchomionego zadania od powłoki (= powoduje, że nie jest to żadna czynność) jest
disown
podstawowym poleceniem powłoki.Z bash-manpage (man bash):
To znaczy, że to proste
usunie wszystkie zadania z tabeli zadań i sprawi, że nie będą działać
źródło
disown -a
usuwa wszystkie zadania. Prostydisown
usuwa tylko bieżące zadanie. Jak mówi strona podręcznika w odpowiedzi.Oto dobre odpowiedzi powyżej, chciałem tylko dodać wyjaśnienie:
Nie możesz
disown
płacić ani przetwarzać, jesteśdisown
pracą, a to ważne rozróżnienie.Zadanie jest czymś, co jest pojęciem związanym z powłoką, dlatego musisz rzucić zadanie w tło (nie zawieszać go), a następnie odrzucić.
Kwestia:
Zobacz http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/, aby uzyskać bardziej szczegółowe omówienie Unix Job Control.
źródło
Niestety
disown
jest specyficzny dla bash i nie jest dostępny we wszystkich powłokach.Niektóre warianty Uniksa (np. AIX i Solaris) mają opcję w
nohup
samej komendzie, którą można zastosować do uruchomionego procesu:Zobacz http://en.wikipedia.org/wiki/Nohup
źródło
AIX
iSolaris
. „Wersje nohup w systemach AIX i Solaris mają opcję -p, która modyfikuje uruchomiony proces w celu zignorowania przyszłych sygnałów SIGHUP. W przeciwieństwie do opisanego powyżej wbudowanego bash, nohup -p akceptuje identyfikatory procesów.”. ŹródłoOdpowiedź węzła jest naprawdę świetna, ale pozostawiło otwarte pytanie, w jaki sposób można przekierować stdout i stderr. Znalazłem rozwiązanie w systemach Unix i Linux , ale nie jest ono również kompletne. Chciałbym połączyć te dwa rozwiązania. Oto on:
Dla mojego testu stworzyłem mały skrypt bash o nazwie loop.sh, który drukuje swój pid z chwilą snu w nieskończonej pętli.
Teraz jakoś uzyskaj PID tego procesu. Zwykle
ps -C loop.sh
jest wystarczająco dobry, ale jest wydrukowany w moim przypadku.Teraz możemy przełączyć się na inny terminal (lub nacisnąć ^ Z i w tym samym terminalu). Teraz
gdb
należy dołączyć do tego procesu.To zatrzymuje skrypt (jeśli jest uruchomiony). Jego stan można sprawdzić
ps -f <PID>
, gdzieSTAT
pole to „T +” (lub w przypadku ^ Z „T”), co oznacza (man ps (1))Close (1) zwraca zero po sukcesie.
Open (1) zwraca nowy deskryptor pliku, jeśli się powiedzie.
To otwarcie jest równe
open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
. ZamiastO_RDWR
O_WRONLY
można zastosować, ale/usr/sbin/lsof
mówi „u” dla wszystkich procedur obsługi plików std * (FD
kolumna), co oznaczaO_RDWR
.Sprawdziłem wartości w pliku nagłówkowym /usr/include/bits/fcntl.h.
Plik wyjściowy można otworzyć za pomocą
O_APPEND
, podobnie jak wnohup
przypadku, ale nie jest to sugerowane przezman open(2)
, ze względu na możliwe problemy z NFS.Jeśli otrzymamy -1 jako wartość zwracaną, to
call perror("")
drukuje komunikat o błędzie. Jeśli potrzebujemy errno, użyj poleceniap errno
gdb.Teraz możemy sprawdzić nowo przekierowany plik.
/usr/sbin/lsof -p <PID>
drukuje:Jeśli chcemy, możemy przekierować stderr do innego pliku, jeśli chcemy użyć
call close(2)
icall open(...)
ponownie używając innej nazwy pliku.Teraz załączony
bash
musi zostać zwolniony i możemy wyjśćgdb
:Jeśli skrypt został zatrzymany przez
gdb
inny terminal, kontynuuje działanie. Możemy wrócić do terminalu loop.sh. Teraz nic nie zapisuje na ekranie, ale działa i zapisuje do pliku. Musimy to umieścić w tle. Więc naciśnij^Z
.(Teraz jesteśmy w takim samym stanie, jak
^Z
na początku naciśnięto).Teraz możemy sprawdzić stan zadania:
Tak więc proces powinien być uruchomiony w tle i odłączony od terminala. Liczba w
jobs
wynikach polecenia w nawiasach kwadratowych oznacza zadanie wewnątrzbash
. Możemy użyć następujących wbudowanychbash
poleceń, stosując znak „%” przed numerem zadania:A teraz możemy wyjść z bashu wywołującego. Proces jest kontynuowany w tle. Jeśli wyjdziemy, jego PPID zmieni się na 1 (proces init (1)), a terminal kontrolny stanie się nieznany.
KOMENTARZ
Pliki gdb można zautomatyzować, tworząc plik (np. Loop.gdb) zawierający polecenia i uruchamiany
gdb -q -x loop.gdb -p <PID>
. Mój loop.gdb wygląda następująco:Lub zamiast tego można użyć jednej wkładki:
Mam nadzieję, że jest to dość kompletny opis rozwiązania.
źródło
lsof
(nazwa uchwytu pliku jest innapipe
niż/dev/pts/1
) lub przezls -l /proc/<PID>/fd/<fd>
(pokazuje to dowiązanie symboliczne uchwytu). Również podprocesy nadal nie mogą przekierowywać danych wyjściowych, które powinny zostać przekierowane do pliku.Aby wysłać uruchomiony proces do nohup ( http://en.wikipedia.org/wiki/Nohup )
nohup -p pid
, to nie zadziałało dla mnieNastępnie wypróbowałem następujące polecenia i zadziałało bardzo dobrze
Powiedzmy, że uruchomcie SOMECOMMAND
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.Ctrl+, Zaby zatrzymać (wstrzymać) program i wrócić do powłoki.
bg
aby uruchomić go w tle.disown -h
aby proces nie został zabity, gdy terminal zostanie zamknięty.Wpisz,
exit
aby wyjść z powłoki, ponieważ teraz możesz zacząć, ponieważ operacja będzie działać w tle w swoim własnym procesie, więc nie jest związana z powłoką.Ten proces jest równoważny z uruchomieniem
nohup SOMECOMMAND
.źródło
W moim systemie AIX próbowałem
To działało dobrze. Kontynuował mój proces nawet po zamknięciu okien terminala. Mamy domyślną powłokę ksh, więc polecenia
bg
idisown
nie działały.źródło
bg
- spowoduje to umieszczenie zadania w tle i powrót do uruchomionego procesudisown -a
- spowoduje to odcięcie całego załącznika z zadaniem (abyś mógł zamknąć terminal i nadal działać)Te proste kroki pozwolą ci zamknąć terminal przy jednoczesnym zachowaniu procesu.
Nie
nohup
da się go założyć (w oparciu o moje rozumienie twojego pytania, nie potrzebujesz go tutaj).źródło
To działało dla mnie na Ubuntu Linux w tcshell.
CtrlZ wstrzymać to
bg
działać w tlejobs
aby uzyskać numer zadanianohup %n
gdzie n jest numerem zadaniaźródło
nohup: failed to run command '%1': No such file or directory