web-dev-qa-db-fra.com

Démarrez un processus d'arrière-plan à partir d'un script et gérez-le lorsque le script se termine

Je voudrais exécuter et configurer un processus de la même manière vers un démon d'un script.
[.____] Mon shell est émulé de ZSH sous Cygwin et le démon est SFK , un serveur FTP de base.

Pour ce qui compte ici, le script startserv.sh peut être rédigé comme suit:

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

Après avoir exécuté le script startserv.sh, ça arrête (se termine?) Sans montrer aucune invite, alors:

  • CTRL+C termine à la fois le script et le processus d'emploi de fond;

  • Frappe Enter Le script met fin au processus reste en arrière-plan.

Quoi qu'il en soit, je ne peux le voir que via ps _ et pas jobs, donc, lorsque je veux fermer le processus, je dois envoyer une brutale kill -9 signal, qui est quelque chose que j'aimerais éviter en faveur de CTRL+C.

Une alternative serait exécuter l'ensemble du script en arrière-plan. "Serait", mais la commande read est impossible d'obtenir l'entrée de l'utilisateur si le script est exécuté comme startserv.sh &.

Notez que j'ai besoin d'un serveur éphémère, pas d'un true Daemon : c'est-à-dire que je souhaite que le processus serveur fonctionne en arrière-plan, après la fin du script, Pour effectuer de simples tâches de shell interactifs (avec une machine à machine virtuelle), mais je n'ai pas besoin du processus pour survivre à la coquille; Par conséquent, Nohup semble ne pas approprié.

15
antonio

Frappe Enter Le script met fin au processus reste en arrière-plan.

Presque! En fait, le script est déjà sorti au moment où vous appuyez sur Enter. Cependant, c'est ainsi que vous pouvez récupérer votre retour (car votre shell imprime son $PS1 encore une fois).

La raison pour laquelle frapper CtrlC se termine les deux, c'est parce que les deux d'entre eux sont liés. Lorsque vous exécutez votre script, votre shell initie un sous-vase dans lequel l'exécuter. Lorsque vous terminez ce sous-groupe, votre processus de référence décède, probablement à partir d'un signal SIGHUP.

Séparez le script, le processus d'arrière-plan et le sous-vase

Utilisation Nohup, vous pourrez peut-être vous débarrasser de ce petit inconvénient.

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

Le disown alternative

Si vous pouvez passer de /bin/sh à /bin/bash, vous pouvez essayer d'essayer de disown aussi. Pour en savoir plus, il suffit de taper help disown Dans une instance bash.

disown -h $cmd &

Tuer le processus de fond "bien"

Maintenant, quand il s'agit de tuer votre processus, vous pouvez parfaitement faire un "CtrlC"Utiliser kill. N'envoyez pas un brutal SIGKILL. Au lieu de cela, vous pouvez utiliser:

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

Qui enverra une belle SIGINT (2) ou SIGTERM (15) à votre processus. Vous pouvez également vouloir imprimer la valeur PID après le démarrage du processus:

...
Nohup $cmd &
echo $!

... ou même mieux, faites attendre le script pour un SIGINT et le renvoyer au processus d'arrière-plan (((((((((cela conservera votre script au premier plan) := := :=:

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

Si un SIGINT ne suffit pas, utilisez simplement un SIGTERM à la place (15):

trap "kill -15 $bg_pid" 2 15

De cette façon, lorsque votre script reçoit un SIGINT (CtrlC, kill -2) ou un SIGTERM _ _ _ waiting pour le processus d'arrière-plan, cela relâchera simplement les signaux. Si ces signaux tuent l'instance sfk, alors l'appel wait _ sera renvoyé, terminant ainsi votre script aussi :)

18
John WH Smith