Avviare un processo in background da uno script e gestirlo al termine dello script


15

Vorrei eseguire e configurare un processo in modo simile a un demone da uno script.
La mia shell è emulata da zsh sotto Cygwin e il demone è SFK , un server FTP di base.

Per ciò che conta qui, lo script startserv.shpuò essere redatto come segue:

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

Dopo aver eseguito lo script startserv.sh, si interrompe (termina?) Senza mostrare alcun prompt, quindi:

  • CTRL+ Ctermina sia lo script che il processo in background;

  • Colpire Enterlo script termina il processo rimane in background.

In ogni caso posso vederlo solo tramite pse non jobs, quindi, quando voglio chiudere il processo, devo inviare un kill -9segnale brutale , che è qualcosa che vorrei evitare a favore di CTRL+ C.

Un'alternativa sarebbe eseguire l'intero script in background. 'Sarebbe', ma il readcomando non è in grado di ottenere l'input dell'utente se lo script viene eseguito come startserv.sh &.

Nota che ho bisogno di un server effimero, non di un vero demone : ovvero, voglio che il processo del server venga eseguito in background, al termine dello script, per eseguire semplici attività di shell interattive (con un guest di macchina virtuale), ma non t ha bisogno del processo per sopravvivere al guscio; quindi nohupnon sembra appropriato.


ottenere l'id del processo in esecuzione in background utilizzando bgproc="$!"e quindi command "$bgproc" eseguire l'azione appropriata. Vedi anche stackoverflow.com/questions/1908610/…
Valentin Bajrami,

puoi anche creare un file PID. Quindi leggi quel file per vedere che numero di processo è e vai da lì.
jgr208,

Risposte:


18

Colpire Enterlo script termina il processo rimane in background.

Quasi! In realtà, lo script è già uscito quando si preme Enter. Tuttavia, è così che puoi riavere il tuo prompt (perché la tua shell stampa di $PS1nuovo tutto da capo).

Il motivo per cui colpire Ctrl+ Ctermina entrambi è perché i due sono collegati. Quando esegui il tuo script, la tua shell avvia una subshell in cui eseguirlo. Quando si termina questa subshell, il processo in background termina, probabilmente a causa di un SIGHUPsegnale.

Separare lo script, il processo in background e la subshell

Utilizzando nohup, potresti riuscire a sbarazzarti di questo piccolo inconveniente.

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

L' disownalternativa

Se puoi passare da /bin/sha /bin/bash, puoi provare disownanche a. Per saperne di più, basta digitare help disownin un bashcaso.

disown -h $cmd &

Uccidere il processo in background "bene"

Ora, quando si tratta di uccidere il tuo processo, puoi perfettamente fare un " Ctrl+ C" usando kill. Basta non inviare un brutale SIGKILL. Invece, potresti usare:

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

Che invierà un bel SIGINT(2) o SIGTERM(15) al tuo processo. È inoltre possibile stampare il valore PID dopo aver avviato il processo:

...
nohup $cmd &
echo $!

... o meglio, fai attendere lo script a SIGINT, e rispediscilo al processo in background (questo manterrà comunque lo script in primo piano) :

#!/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

Se a SIGINTnon è abbastanza, basta usare a SIGTERMinvece (15):

trap "kill -15 $bg_pid" 2 15

In questo modo, quando lo script riceve un SIGINT( Ctrl+ C, kill -2) o un SIGTERMpo 'di tempo waitper il processo in background, trasmetterà semplicemente i segnali ad esso. Se questi segnali uccidono l' sfkistanza, allora la waitchiamata tornerà, terminando quindi anche il tuo script :)


1
+1 Molto informativo. Poiché lo script viene eseguito in una subshell, esiste la possibilità di accedere dallo script alla tabella dei lavori della shell padre dello script? Ossia elenca i lavori che vengono emessi jobsnel terminale al termine dello script (anziché ps).
antonio,

1
I lavori sono associati alla shell corrente, non vengono trasmessi da una shell a un'altra. Quando la subshell muore, i suoi lavori non vengono recuperati. Stampando il PID del tuo processo in background, ti assicuri di poter ottenere facilmente informazioni a riguardo anche dopo che la subshell è terminata ( pid -p).
John WH Smith,

bella spiegazione, tuttavia se lo script contiene più comandi, non vengono mai eseguiti (a causa del wait). Se rimuovi l'attesa, la gestione del segnale viene interrotta: /
chefarov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.