Tengo un script bash que inicia un script python3 (llamémoslo startup.sh), con la línea clave:
nohup python3 -u <script> &
Cuando entro sshdirectamente y llamo a este script, el script de Python continúa ejecutándose en segundo plano después de salir. Sin embargo, cuando ejecuto esto:
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
El proceso termina tan pronto como sshhaya terminado de ejecutarse y cierra la sesión.
¿Cuál es la diferencia entre los dos?
EDIT: El script en Python, se está ejecutando un servicio web a través de la botella.
EDIT2: también intenté crear un script de inicio que startup.shejecuta y ejecuta ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>", pero obtuve el mismo comportamiento.
EDITAR3: Tal vez sea algo más en el guión. Aquí está la mayor parte del guión:
chmod 700 ${key_loc}
echo "INFO: Syncing files."
rsync -azP -e "ssh -i ${key_loc} -o StrictHostKeyChecking=no" ${source_client_loc} ${remote_user}@${remote_hostname}:${destination_client_loc}
echo "INFO: Running startup script."
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart"
EDIT4: Cuando ejecuto la última línea con un sueño al final:
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart; sleep 1"
echo "Finished"
Nunca llega echo "Finished", y veo el mensaje del servidor Botella, que nunca vi antes:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
Veo "Terminado" si manualmente SSH y matar el proceso mismo.
EDIT5: Utilizando EDIT4, si hago una solicitud a cualquier punto final, obtengo una página de regreso, pero los errores de la botella se eliminan:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
----------------------------------------
Exception happened during processing of request from ('<IP>', 55104)
fuente

stracesi está utilizando Linux otrusssi está ejecutando Solaris y ver cómo / por qué termina. Como por ejemplossh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> strace -fo /tmp/debug ./startup.sh.&al final del script de inicio? Agregar el le&quita la dependencia de su sesión ssh de ser la identificación principal (cuando los identificadores principales mueren, también lo hacen sus hijos). También creo que esta es una pregunta duplicada basada en esta publicación anterior. La publicación que le envié en la oración anterior es un duplicado de esta publicación que podría proporcionar mejores detalles.nohup ./startup.sh &antes, pero tuvo el mismo comportamiento.startup.shya contiene un tenedor (nohup python3 -u <script> &), así que estoy bastante seguro de que no necesito bifurcar nuevamente.Respuestas:
Desconectaría el comando de su entrada / salida estándar y flujos de error:
sshnecesita un indicador que no tenga más salida y que no requiera más entrada. Tener otra cosa que sea la entrada y redirigir los medios de salidasshpuede salir de forma segura, ya que la entrada / salida no viene ni va al terminal. Esto significa que la entrada debe provenir de otro lugar y la salida (tanto STDOUT como STDERR) debe ir a otro lugar.La
</dev/nullparte se especifica/dev/nullcomo entrada para<script>. Por qué eso es útil aquí:Alternativamente, la redirección desde otra fuente de entrada debería ser relativamente segura siempre que
sshno sea necesario mantener abierta la sesión actual .Con el
>/dev/nullparte, el shell redirige la salida estándar a / dev / null esencialmente descartándola.>/path/to/fileTambién funcionará.La ultima parte
2>&1es redirigir STDERR a STDOUT.fuente
nohup python3 -u <script> >/dev/null 2>&1 &ynohup python3 -u <script> > nohup.out 2>&1 &trabajado Sin embargo, pensé que nohup redirige automáticamente toda la salida: ¿cuál es la diferencia?nohuptiene en su host remoto?nohupNo se requiere un POSIX para redirigirstdin, lo cual me perdí, pero aún así debería redirigirstdoutystderr.nohup (GNU coreutils) 8.21.nohupimprimir los mensajes, comonohup: ignoring input and appending output to ‘nohup.out’?Mira
man ssh:Cuando corres
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh", está ejecutando el script de shell startup.sh como un comando ssh.De la descripción:
En base a esto, debería ejecutar el script de forma remota.
La diferencia entre eso y correr
nohup python3 -u <script> &en su terminal local es que esto se ejecuta como un proceso de fondo local mientras el comando ssh intenta ejecutarlo como un proceso de fondo remoto.Si tiene la intención de ejecutar el script localmente, no ejecute startup.sh como parte del comando ssh. Puedes intentar algo como
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"Si su intención es ejecutar el script de forma remota y desea que este proceso continúe después de que finalice su sesión ssh, primero deberá iniciar una
screensesión en el host remoto. Luego, debe ejecutar el script de Python dentro de la pantalla y continuará ejecutándose después de que finalice su sesión ssh.Consulte el Manual del usuario de la pantalla
Si bien creo que la pantalla es su mejor opción, si debe usar nohup, considere configurar
shopt -s huponexiten el host remoto antes de ejecutar el comando nohup. Alternativamente, puede usardisown -h [jobID]para marcar el proceso para que SIGHUP no se le envíe. 1Además, vea este resumen de cómo
huponexitfunciona cuando se sale de una concha, mató o se ha caído. Supongo que su problema actual está relacionado con cómo termina la sesión de shell. 2Por último, he aquí algunos ejemplos de cómo utilizar huponexit shopt. 3
fuente
bashpágina del manual,huponexitsolo debería afectar a los shells interactivos y no a los scripts: "Si la opción de shell huponexit se ha configurado con shopt, bash envía un SIGHUP a todos los trabajos cuando sale un shell de inicio de sesión interactivo".Tal vez vale la pena probar la
-nopción al comenzar unssh? Se evitará la dependencia proceso remoto a nivel localstdin, que por supuesto se cierra en cuantossh sessionextremos. Y esto hará que los precios de terminación remotos cada vez que intenta acceder a sustdin.fuente
Sospecho que tienes una condición de carrera. Sería algo parecido a esto:
Si ssh no hubiera acortado las cosas, habría sucedido lo siguiente (no estoy seguro sobre el orden de estos dos):
Así que los dos últimos pasos críticos no suceden, porque startup.sh y ssh meta antes nohup tiene tiempo para hacer su cosa.
Espero que su problema desaparezca si coloca unos segundos de suspensión al final de startup.sh. No estoy seguro de cuánto tiempo necesitas exactamente. Si es importante mantenerlo al mínimo, entonces tal vez pueda mirar algo en proceso para ver cuándo es seguro.
fuente
/proc/$!/commno esnohupmás portátilps -o comm= $!.Esto suena más como un problema con lo que está haciendo el
pythonscript o enpythonsí mismo. Todo lo quenohuprealmente hace (barras que simplifican los redireccionamientos) es simplemente configurar el controlador para que laHUPseñalSIG_IGN(ignorar) antes de ejecutar el programa. No hay nada que impida que el programa lo vuelva a configurarSIG_DFLo que instale su propio controlador una vez que comience a ejecutarse.Una cosa que quizás desee probar es encerrar su comando entre paréntesis para que obtenga un efecto de doble tenedor y su
pythonscript ya no sea un elemento secundario del proceso de shell. P.ej:Otra cosa que también puede valer la pena intentar (si está usando
bashy no otro shell) es usar eldisownincorporado en lugar denohup. Si todo funciona según lo documentado, esto no debería hacer ninguna diferencia, pero en un shell interactivo esto evitaría que laHUPseñal se propague a supythonscript. Puede agregar el disown en la siguiente línea o la misma que se muestra a continuación (tenga en cuenta que agregar un;after a&es un errorbash):Si lo anterior o alguna combinación no funciona, entonces seguramente el único lugar para abordar el problema es en el
pythonscript mismo.fuente
huponexitcosas, ejecutarse en una subshell debería tener el mismo efecto yadisownque el proceso no se agregará a la lista de trabajos.disown. Sin embargo, no esperes que haga mucha diferencia. Creo que lo mejor es alterar elpythonguión para que te diga por qué está saliendo.nohuphacerlo.Creo que es porque el trabajo está vinculado a la sesión. Una vez que finaliza, también se finalizan los trabajos de los usuarios.
fuente
Si
nohuppuede abrir su archivo de salida, puede tener una pistanohup.out. Es posiblepythonque no esté en el camino cuando ejecuta el script víassh.Intentaría crear un archivo de registro para el comando. Intenta usar:
fuente
sshpara ejecutar el script manualmente, por lo que estoy asumiendo python3 está en el camino.