Rozpocznij proces w tle od skryptu i zarządzaj nim po zakończeniu skryptu

15

Chciałbym uruchomić i skonfigurować proces podobnie do demona ze skryptu.
Moja powłoka jest emulowana zsh pod Cygwin, a demonem jest SFK , podstawowy serwer FTP.

Dla tego, co jest ważne, skrypt startserv.shmożna napisać w następujący sposób:

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
$cmd &

Po uruchomieniu skryptu startserv.shzatrzymuje się (kończy?) Bez wyświetlania monitu, a następnie:

  • CTRL+ Ckończy zarówno proces skryptu, jak i proces zadania w tle;

  • Naciśnięcie Enterskryptu kończy proces pozostaje w tle.

W każdym razie widzę to tylko przez, psa nie jobs, więc kiedy chcę zakończyć proces, muszę wysłać brutalny kill -9sygnał, czego chciałbym uniknąć na korzyść CTRL+ C.

Alternatywą byłoby uruchomienie całego skryptu w tle. „Byłoby”, ale readpolecenie nie może uzyskać danych wejściowych użytkownika, jeśli skrypt jest uruchamiany jako startserv.sh &.

Zauważ, że potrzebuję efemerycznego serwera, a nie prawdziwego demona : chcę, aby proces serwera działał w tle, po zakończeniu skryptu, aby wykonywać proste zadania powłoki interaktywnej (z gościem maszyny wirtualnej), ale nie „ potrzebuje procesu, aby przetrwać pocisk; dlatego nohupwydaje się niewłaściwe.

Antonio
źródło
pobierz identyfikator procesu uruchomionego w tle, bgproc="$!"a następnie command "$bgproc" wykonaj odpowiednie działanie. Zobacz także stackoverflow.com/questions/1908610/…
Valentin Bajrami
możesz także utworzyć plik PID. Następnie przeczytaj ten plik, aby zobaczyć, jaki jest numer procesu i stamtąd.
jgr208

Odpowiedzi:

18

Naciśnięcie Enterskryptu kończy proces pozostaje w tle.

Prawie! W rzeczywistości skrypt został już zakończony do momentu naciśnięcia Enter. Jednak w ten sposób możesz odzyskać swój monit (ponieważ twoja powłoka drukuje $PS1go od nowa).

Powodem, dla którego wciśnięcie Ctrl+ Ckończy oba z nich, jest to, że oba są ze sobą powiązane. Podczas wykonywania skryptu powłoka inicjuje podpowłokę, w której ma zostać uruchomiony. Po zakończeniu tej podpowłoki proces w tle umiera, prawdopodobnie z powodu SIGHUPsygnału.

Oddziel skrypt, proces w tle i podpowłokę

Używając nohup, możesz pozbyć się tej małej niedogodności.

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

disownalternatywa

Jeśli możesz przełączyć się z /bin/shna /bin/bash, możesz spróbować disownrównież. Aby dowiedzieć się więcej, wystarczy wpisać help disownw bashinstancji.

disown -h $cmd &

„Ładne” zabicie procesu w tle

Teraz, jeśli chodzi o zabicie twojego procesu, możesz doskonale zrobić „ Ctrl+ C” używając kill. Tylko nie wysyłaj brutalnego SIGKILL. Zamiast tego możesz użyć:

$ kill -2 [PID]
$ kill -15 [PID]

Który wyśle ​​miły SIGINT(2) lub SIGTERM(15) do twojego procesu. Możesz także wydrukować wartość PID po rozpoczęciu procesu:

...
nohup $cmd &
echo $!

... lub jeszcze lepiej, poczekaj na skrypt SIGINTi odeślij go z powrotem do procesu w tle (spowoduje to, że skrypt będzie na pierwszym planie) :

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

# Storing the background process' PID.
bg_pid=$!

# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2

# In the meantime, wait for $bg_pid to end.
wait $bg_pid

Jeśli SIGINTto nie wystarczy, użyj SIGTERMzamiast tego (15):

trap "kill -15 $bg_pid" 2 15

W ten sposób, gdy twój skrypt odbierze SIGINT( Ctrl+ C, kill -2) lub jakiś SIGTERMczas waitna proces w tle, po prostu przekaże mu sygnały. Jeśli te sygnały zabiją sfkinstancję, wówczas waitwywołanie zostanie zwrócone, co spowoduje zakończenie również skryptu :)

John WH Smith
źródło
1
+1 Bardzo pouczające. Skoro skrypt działa w podpowłoce, czy jest jakaś możliwość dostępu ze skryptu do tabeli zadań macierzystej powłoki skryptu? To jest lista zadań wystawianych jobsw terminalu po zakończeniu skryptu (zamiast ps).
Antonio
1
Zadania są powiązane z bieżącą powłoką, nie są przesyłane z jednej powłoki do drugiej. Kiedy twoja podpowłoka umiera, jej zadania nie są odzyskiwane. Drukując PID procesu w tle, upewniasz się, że możesz łatwo uzyskać o nim informacje, nawet po zakończeniu podpowłoki ( pid -p).
John WH Smith
miłe wyjaśnienie, jednak jeśli twój skrypt zawiera więcej poleceń, nigdy nie zostaną one wykonane (z powodu wait). Jeśli usuniesz oczekiwanie, obsługa sygnału zostanie zerwana: /
chefarov