Jeśli robisz to ze środowiska takiego jak kod C, możesz rozwidlić (), a następnie w dziecku wysłać do siebie SIGSTOP przed exec (), uniemożliwiając dalsze wykonanie.
Bardziej ogólnym rozwiązaniem (prawdopodobnie najlepszym) byłoby utworzenie kodu pośredniczącego, który to robi. Zatem program pośredniczący:
Weź argumenty składające się z prawdziwej nazwy programu i argumentów
wyślij do siebie SIGSTOP
exec () prawdziwy program z odpowiednimi argumentami
Zapewni to, że unikniesz jakichkolwiek warunków wyścigowych związanych z zbyt dużym wyprzedzeniem nowego przetwarzania, zanim będziesz mógł wysłać do niego sygnał.
Przykład dla powłoki:
#!/bin/bash
kill -STOP $$
exec "$@"
I używając powyższego kodu:
michael@challenger:~$ ./stopcall.sh ls -al stopcall.sh
[1]+ Stopped ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ jobs -l
[1]+ 23143 Stopped (signal) ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ kill -CONT 23143; sleep 1
-rwxr-xr-x 1 michael users 36 2011-07-24 22:48 stopcall.sh
[1]+ Done ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$
jobs -lPokazuje PID. Ale jeśli robisz to z powłoki, nie potrzebujesz bezpośrednio PID. Możesz po prostu: kill -CONT %1(zakładając, że masz tylko jedną pracę).
Robisz to z więcej niż jedną pracą? Pozostawiono jako ćwiczenie dla czytelnika :)
Odpowiedź MikeyB jest poprawna. Od tego pytania na temat superużytkownika, oto bardziej zwięzła wersja:
( kill -SIGSTOP $BASHPID; exec my_command ) &
Aby to zrozumieć, należy zrozumieć, w jaki sposób procesy są uruchamiane w execsystemie uniksowym: wywołanie systemowe zastępuje aktualnie działający program nowym , zachowując istniejący PID. Więc drodze niezależny proces jest tworzony jest pierwszy fork, a następnie exec, zastępując program uruchomiony w procesie potomnym z żądanego programu.
Składniki tego polecenia powłoki to:
Nawiasy (...)rozpoczynają podpowłokę: kolejne wystąpienie BASH.
killKomenda wysyła sygnał STOP, aby ten proces, co stawia go w stanie zawieszenia.
Gdy tylko zezwolisz na kontynuowanie procesu (wysyłając mu CONTsygnał), execpolecenie powoduje, że zamienia się ono na żądany program. my_commandzachowuje oryginalny PID podpowłoki.
Możesz użyć tej $!zmiennej, aby uzyskać PID procesu.
Podoba mi się ten, ponieważ jest zasadniczo poprawny (tyle, że musiałem go użyć -s STOPzamiast -SIGSTOP). Wciąż zastanawiam się, dlaczego to musi być $BASHPIDzamiast $$? (Może naprawdę nie rozumiem różnicy).
Dla $$vs $BASHPIDsprawdzam, że ten ostatni to PID podpowłoki, a nie ten pierwszy. Jest zabawny problem: zastosowanie końcówki w skrypcie bash najczęściej kończy się niepowodzeniem, a ja muszę zrobić coś takiego: PID=$!; ps -p $PID; kill -s CONT $PID;… kończy się niepowodzeniem, jeśli usunę ps -p $PIDczęść: proces wydaje się zniknąć (zabity?) Bez nigdzie komunikatu o błędzie . Z interaktywnej powłoki jest OK, problem pochodzi tylko ze skryptu. To zbyt tajemnicze.
Próbowałem użyć tego rozwiązania do wyświetlenia listy deskryptorów plików mojej komendy. ( goo.gl/cNbUE8 ), ale deskryptory są nadal takie same, bez względu na to, co to moja komenda.
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.
#!/bin/bash
[enter]$@ &
[enter]PID=$!
[enter]kill -STOP $PID
[enter]echo "Suspended: $PID, press ENTER to continue it"
[enter]read
[enter]kill -CONT $PID
[enter]wait $PID
[enter]echo