Praktycznie potrzebuję procesu, który zachowuje się tak, jakbym naciskał Ctrl+Zzaraz po jego rozpoczęciu.
Mamy nadzieję, że można to zrobić za pomocą skryptu powłoki.
(Wiedząc, że wynikowy PID byłby świetny, żebym mógł kontynuować proces później).
Praktycznie potrzebuję procesu, który zachowuje się tak, jakbym naciskał Ctrl+Zzaraz po jego rozpoczęciu.
Mamy nadzieję, że można to zrobić za pomocą skryptu powłoki.
(Wiedząc, że wynikowy PID byłby świetny, żebym mógł kontynuować proces później).
Odpowiedzi:
Po rozpoczęciu procesu możesz wysłać go do SIGSTOP, aby go zawiesić. Aby wznowić, wyślij SIGCONT. Myślę, że ten mały skrypt może ci pomóc
#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID
Uruchamia proces (polecenie wyślij jako parametr), zawiesza go, drukuje identyfikator procesu i czeka na zakończenie.
Z jakiego środowiska tworzysz proces?
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:
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:
(...)rozpoczynają podpowłokę: kolejne wystąpienie BASH.killKomenda wysyła sygnał STOP, aby ten proces, co stawia go w stanie zawieszenia.CONTsygnał), execpolecenie powoduje, że zamienia się ono na żądany program. my_commandzachowuje oryginalny PID podpowłoki.$!zmiennej, aby uzyskać PID procesu.-s STOPzamiast -SIGSTOP). Wciąż zastanawiam się, dlaczego to musi być $BASHPIDzamiast $$? (Może naprawdę nie rozumiem różnicy).
$$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.
#!/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