Jak rozpocząć proces w stanie zawieszenia w systemie Linux?


19

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:


7

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.


1
Zmodyfikowałem go, aby kontynuować na końcu: [enter] #!/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
— java.is.for.desktop

7
Właśnie dlatego wiesz, że podproces może zakończyć się, zanim zdążysz wysłać do niego sygnał STOP.
— MikeyB,

16
Kolejny dzień na wyścigach.
— ctrl-alt-delor

23

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:

  • 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 :)


Miałem nadzieję to zrobić ze skryptu powłoki ...
— java.is.for.desktop

Świetnie, więc ponieważ chcesz to zrobić ze skryptu powłoki, użyj programu pośredniczącego.
— MikeyB,

20

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:

  1. Nawiasy (...)rozpoczynają podpowłokę: kolejne wystąpienie BASH.
  2. killKomenda wysyła sygnał STOP, aby ten proces, co stawia go w stanie zawieszenia.
  3. 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.
  4. Możesz użyć tej $!zmiennej, aby uzyskać PID procesu.

2
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).
— Hibou57

1
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.
— Hibou57

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.
— rasty.g

Aby zobaczyć opcje zamiany $BASHPIDna pociski inne niż bash, zobacz tutaj
— Jakob
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.