Inicie um processo em segundo plano a partir de um script e gerencie-o quando o script terminar

13

Gostaria de executar e configurar um processo de forma semelhante a um daemon de um script.
Meu shell é emulado em zsh sob o Cygwin e o daemon é SFK , um servidor FTP básico.

Para o que importa aqui, o script startserv.sh pode ser redigido da seguinte forma:

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

Depois de executar o script startserv.sh , ele pára (termina?) sem mostrar nenhum prompt, então:

  • CTRL + C encerra o script e o processo de trabalho em segundo plano;

  • Acertando Enter o script termina o processo permanece em segundo plano.

De qualquer forma, só consigo ver via ps e não jobs , por isso, quando quero fechar o processo, tenho de enviar um sinal kill -9 brutal, que é algo que gostaria de evitar em favor de CTRL + C .

Uma alternativa seria executando o script inteiro em segundo plano. 'Would be', mas o comando read não pode obter a entrada do usuário se o script for executado como startserv.sh & .

Note que preciso de um servidor efêmero, não um daemon verdadeiro: quero que o processo do servidor seja executado em segundo plano, depois que o script terminar, para executar tarefas simples de shell interativo (com uma máquina virtual guest), mas eu não preciso do processo para sobreviver ao shell; portanto, nohup parece não ser apropriado.

    
por antonio 23.10.2014 / 15:36

1 resposta

16

Hitting Enter the script ends the process remains in the background.

Quase! Na verdade, o script já saiu quando você pressionou Enter . No entanto, é assim que você pode obter seu prompt de volta (porque seu shell imprime seu $PS1 novamente).

O motivo pelo qual pressionar Ctrl + C termina os dois é porque os dois estão vinculados. Quando você executa seu script, seu shell inicia um subshell para executá-lo. Quando você termina este subshell, seu processo em background morre, provavelmente de um sinal SIGHUP .

Separe o script, o processo em segundo plano e a subshell

Usando nohup , talvez você consiga se livrar desse pequeno 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 &

A alternativa disown

Se você puder alternar de /bin/sh para /bin/bash , experimente também disown . Para saber mais, basta digitar help disown em uma instância bash .

disown -h $cmd &

Matando o processo em segundo plano "bem"

Agora, quando se trata de matar seu processo, você pode perfeitamente fazer um " Ctrl + C " usando kill . Apenas não envie um brutal SIGKILL . Em vez disso, você poderia usar:

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

O qual enviará% niceSIGINT (2) ou SIGTERM (15) ao seu processo. Você também pode querer imprimir o valor PID depois de iniciar o processo:

...
nohup $cmd &
echo $!

... ou melhor ainda, faça o script esperar por um SIGINT e envie-o de volta para o processo em segundo plano (isso manterá seu script em primeiro plano) :

#!/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 um SIGINT não for suficiente, use apenas SIGTERM (15):

trap "kill -15 $bg_pid" 2 15

Dessa forma, quando seu script recebe um SIGINT ( Ctrl + C , kill -2 ) ou um SIGTERM enquanto wait ing para o plano de fundo processo, apenas transmitirá os sinais para ele. Se esses sinais matarem a instância de sfk , a chamada wait retornará, encerrando seu script também:)

    
por 23.10.2014 / 17:52