Inicie un proceso en segundo plano desde un script y adminístrelo cuando finalice el script


15

Me gustaría ejecutar y configurar un proceso similar a un demonio de un script.
Mi shell está emulado zsh bajo Cygwin y el demonio es SFK , un servidor FTP básico.

Para lo que importa aquí, el script startserv.shse puede redactar de la siguiente manera:

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

Después de ejecutar el script startserv.sh, se detiene (¿finaliza?) Sin mostrar ningún mensaje, luego:

  • CTRL+ Cfinaliza tanto el script como el proceso de trabajo en segundo plano;

  • Al presionar Enterel script, el proceso permanece en segundo plano.

De todos modos, puedo verlo solo a través psy no jobs, así que, cuando quiero cerrar el proceso, tengo que enviar una kill -9señal brutal , que es algo que me gustaría evitar a favor de CTRL+ C.

Una alternativa sería ejecutar todo el script en segundo plano. 'Sería', pero el readcomando no puede obtener la entrada del usuario si el script se ejecuta como startserv.sh &.

Tenga en cuenta que necesito un servidor efímero, no un verdadero demonio : es decir, quiero que el proceso del servidor se ejecute en segundo plano, después de que finalice el script, para realizar tareas de shell interactivas simples (con un invitado de máquina virtual), pero no lo hago ' No necesita el proceso para sobrevivir al caparazón; Por lo tanto, nohupno parece apropiado.


obtenga la identificación del proceso que se está ejecutando en segundo plano utilizando bgproc="$!"y luego command "$bgproc" para tomar la acción adecuada. Ver también stackoverflow.com/questions/1908610/…
Valentin Bajrami

También puede hacer un archivo PID. Luego lea ese archivo para ver qué número de proceso es y vaya desde allí.
jgr208

Respuestas:


18

Al presionar Enterel script, el proceso permanece en segundo plano.

¡Casi! En realidad, el guión ya ha salido cuando presionas Enter. Sin embargo, así es como puede recuperar su solicitud (porque su shell imprime $PS1todo de nuevo).

La razón por la cual presionar Ctrl+ Ctermina a ambos es porque los dos están vinculados. Cuando ejecuta su script, su shell inicia un subshell en el que ejecutarlo. Cuando termina esta subshell, su proceso en segundo plano muere, probablemente por una SIGHUPseñal.

Separe el script, el proceso en segundo plano y la subshell

Con el uso nohup, puede deshacerse de este pequeño 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 &

La disownalternativa

Si puede cambiar de /bin/sha /bin/bash, también puede intentarlo disown. Para saber más, simplemente escriba help disownuna bashinstancia.

disown -h $cmd &

Matar el proceso de fondo "muy bien"

Ahora, cuando se trata de matar su proceso, puede hacer un " Ctrl+ C" perfectamente kill. Simplemente no envíes un brutal SIGKILL. En cambio, podría usar:

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

Lo que enviará un agradable SIGINT(2) o SIGTERM(15) a su proceso. También es posible que desee imprimir el valor PID después de comenzar el proceso:

...
nohup $cmd &
echo $!

... o incluso mejor, haga que la secuencia de comandos espere a SIGINT, y envíela de nuevo al proceso en segundo plano (esto mantendrá su secuencia de comandos en primer 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

Si a SIGINTno es suficiente, solo use a SIGTERMen su lugar (15):

trap "kill -15 $bg_pid" 2 15

De esta manera, cuando su script recibe un SIGINT( Ctrl+ C, kill -2) o un SIGTERMtiempo waitpara el proceso en segundo plano, solo le transmitirá las señales. Si estas señales matan la sfkinstancia, entonces la waitllamada volverá, por lo que también terminará su secuencia de comandos :)


1
+1 Muy informativo. Dado que el script se ejecuta en una subshell, ¿hay alguna posibilidad de acceder desde el script a la tabla de trabajo del shell principal del script? Es decir, lista de trabajos que se emiten jobsen el terminal después de que finaliza el script (en lugar de ps).
antonio

1
Los trabajos están asociados a su shell actual, no se transmiten de un shell a otro. Cuando su subshell muere, sus trabajos no se recuperan. Al imprimir el PID de su proceso en segundo plano, se asegura de que puede obtener información fácilmente incluso después de que la subshell haya finalizado ( pid -p).
John WH Smith

buena explicación, sin embargo, si su script contiene más comandos, nunca se ejecutarán (debido a wait). Si elimina la espera, se interrumpe el manejo de la señal: /
chefarov
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.