ssh y shell a través de ssh: ¿cómo salir?

22

Estoy lanzando un script distante a través de SSH como este:

ssh user@ipaddress '~/my_script.sh'

Todo va bien, pero una vez que finaliza el script, la conexión no se cierra. Tengo que presionar CTRL-C para romper la conexión actual.

He intentado el comando "salir" en '~ / my_script.sh' y es inútil. He probado el comando "cerrar sesión" en '~ / my_script.sh' y recibo un mensaje:

logout: not login shell: use exit

...

¿Alguna idea de cómo podría hacer para cerrar automáticamente y correctamente el SSH una vez que se haya completado el script?

(Modificación para aclarar :) Esto es lo que hay dentro de mi script:

#!/bin/sh
path_sources_qas=/sources/QuickAddress/
path_qas_bin=/usr/bin/qas

umount_disque_qas()
{
  # Umount du disque 'qas' s'il n'avait pas été 'umount' :
  nom_disque_monte=`cat /etc/mtab | grep qas | awk '{ print $2}'`
  if [ "$nom_disque_monte" != "" ]
  then
    echo "For safety, umount : $nom_disque_monte"
    umount $nom_disque_monte
  fi

}

# Umount twice (we never know if a st***d guy mounted it twice) :
umount_disque_qas
umount_disque_qas

echo "--------------------------------"
echo "Install ISO quick address..."
nom_fichier_iso=`ls -t $path_sources_qas | awk '{if (NR==1) {print $1}}'`
echo "Mount disk $nom_fichier_iso..."
mount -o loop -t iso9660 $path_sources_qas/$nom_fichier_iso /mnt/qas
echo "Done."

# All the folders are like this :
# /usr/bin/qas/Data.old.10
# /usr/bin/qas/Data.old.11
# /usr/bin/qas/Data.old.12
# ...

echo "--------------------------------"
echo "Stopping QuickAdress server..."
cd $path_qas_bin/apps/
./wvmgmtd shutdown qaserver:2021
sleep 3
echo "Done."

# Get last number of the folder:
num_dernier_dossier_backup=`ls -Atd $path_qas_bin/Data.old* | awk '{if (NR==1) {print $1}}' | awk -F . '{print $NF}'`
# Add 1 :
let "num_dernier_dossier_backup += 1"
# Full name :
nom_dossier_backup=Data.old.$num_dernier_dossier_backup
echo "--------------------------------"
echo "Saving Data to $nom_dossier_backup..."
cd $path_qas_bin
mv Data $nom_dossier_backup
echo "Done."


echo "--------------------------------"
echo "Copying new folder Data..."
cd $path_qas_bin
cp -r /mnt/qas/Data .
echo "Done."

echo "--------------------------------"
echo "Deleting unused datas..."
cd $path_qas_bin/apps/
rm -f $path_qas_bin/Data/frxmos.dap
echo "Done."

echo "--------------------------------"
echo "Restart server..."
cd $path_qas_bin/apps/
./qaswvd &
sleep 3
echo "Done."
sleep 3

echo "--------------------------------"
echo "Check: server state: you should read 'OK':"
./wvmgmtd srvlist
echo "Done."

echo "--------------------------------"
echo "Check: active licences (only one here):"
./wvmgmtd licencelistread qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: counters: number of addresses left:"
./wvmgmtd counterinforead qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: Datasets avalaibles:"
./wvmgmtd datalistread current qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: "meters" for "licence by click":"
./wvmgmtd meterslistread current qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Removing virtual disk..."
umount_disque_qas
echo "Done."

echo "All done"
echo "Click 'Ctrl-C' to quit."

exit

Cuando lo ejecuto a través de SSH, se ejecuta y, al final, leo "Todo listo". Esto significa que llega a las últimas 2 líneas .

Alguna idea de cómo podría hacer para cerrar automáticamente y pr

Olivier Pons
fuente
1
¿Qué hay en el guión?
Ignacio Vazquez-Abrams
@ Olivier: ¿Reenvía algún puerto (incluido el agente y X)? La conexión ssh se cierra cuando finaliza el comando y todas las conexiones TCP se han cerrado.
Gilles
@Gilles: no, acabo de hacer una conexión de shell para ejecutar un script, no se reenvía nada.
Olivier Pons
1
@Olivier: si tiene un ~/.ssh/config, intente sin él y pase las opciones -a -x(y no -o) sshpara asegurarse de que no haya reenvío. Si aún no funciona, muestre el contenido del guión.
Gilles
@Olivier: ¿el script inicia algún trabajo en segundo plano que pueda estar esperando? Desafortunadamente, los trabajos no parecen devolver nada cuando están en un script ssh. Ejemplo: ssh <yourusername>@localhost '(ls; sleep 10 &); echo Done; jobs'mostrará una lista de archivos, la pantalla estará lista y esperará 10 segundos antes de regresar.
asoundmove

Respuestas:

19

La salida en el script de shell no funciona porque está saliendo del script, no del shell. Para salir del shell después de que se complete el script, haga

ssh user@ipaddress '~/my_script.sh && exit'

Esto ejecutará el script y luego saldrá del shell.

Wuffers
fuente
3
Debería ser emocionante. El guión es el caparazón.
Dennis Williamson el
@ Dennis: No está funcionando para él, por lo que esto puede funcionar en su lugar.
Wuffers
2
@Señor. Hombre: Su comando es equivalente al original, excepto que obliga a que exista un shell entre sshdy el shell en ejecución myscript.sh. Lo exitque escribiste actuará cuando salga el guión, lo que no ayuda. La única forma en que su solución podría funcionar es si el script hace algo extraño cuando su padre es sshdy no hace algo extraño cuando su padre es un shell.
Gilles
¿Cómo no ayuda? Salir cerrará el shell y finalizará la conexión, ¿correcto? ¿Y no es esto lo que quiere hacer el cartel?
Wuffers
3
@MrMan: ~/my_script.sh && exitsale tan pronto como ~/my_script.shsale. Si el script de shell no se cierra, su comando nunca llegará al exitbit de todos modos. Entonces es inútil.
Gilles
12

La conexión ssh permanece abierta cuando sale el proceso iniciado por ssh (aquí, un shell), si hay otros procesos que todavía lo están utilizando. No sé las reglas exactas que sigue el demonio ssh, pero se está utilizando una conexión, al menos, si la salida estándar de cualquier proceso secundario todavía está conectada a la tubería original proporcionada por ssh. Comparar:

ssh somehost 'sleep 5 &'  # exits after 5 seconds
ssh somehost 'sleep 5 >/dev/null &'  # exits immediately seconds

Cuando comienzas un demonio, debes ponerlo en segundo plano y cerrar sus descriptores de archivo. Al menos, usa esto:

./qaswvd </dev/null >/dev/null 2>/dev/null &

Es posible que desee agregar nohupal frente; aquí no hará la diferencia, pero sería útil si el script se ejecutara desde un terminal. Muchos programas que están diseñados para actuar como daemon tienen opciones de línea de comandos para hacer que se bifurquen, cierren los descriptores de archivos, ignoren las señales y otros detalles. Consulte en la qaswvddocumentación si tiene uno. También puede investigar las utilidades de "daemonizer".

Gilles
fuente
Tuve el mismo problema, y ​​esto funciona. La respuesta aceptada no funciona.
Andy
5

Vi esta publicación cuando busqué en Google la solución de la misma situación. Aunque es un poco tarde para resolver el problema de @ Oliver, ya que la respuesta aceptada claramente no funcionó ni para OP ni para mí (no sé por qué se acepta), todavía me gustaría publicar mi propia solución para el futuro buscador de Google. Es simple: agregue una -fopción al sshcomando:

ssh -f user@ipaddress '~/my_script.sh'

EDITAR

El efecto de la -fopción es ponerlo sshen segundo plano, por lo que sin agregar ninguna otra opción, es posible que la conexión siga viva incluso si parece que está rota. Uno puede referirse a la respuesta dada en otra publicación en este sitio si está interesado.

Leo Fang
fuente
Precaución: Este (-f) no funcionará si el script original tiene solicitudes para la entrada del usuario.
madD7
3

Como Ignacio, tengo curiosidad por saber qué hay en tu guión.

Quizás podría intentar reducir su script al ejemplo más pequeño posible que produzca la condición de error.

O comience desde un script vacío y agregue un comando a la vez hasta que vea el problema, entonces sabrá qué comando hace que su script se bloquee.

Si la secuencia de comandos vacía le causa un problema, es posible que desee investigar su configuración de ssh, por ejemplo, ¿es .bash_logout o alguno de los llamados a la salida que puede causar un problema?

asoundmove
fuente
Gracias por su sugerencia, ahora he agregado la muestra de mi script en mi pregunta.
Olivier Pons
@ Olivier: ha agregado solo partes irrelevantes de su secuencia de comandos. Publique un script (e instrucciones de uso si es necesario) que permitiría a los lectores reproducir su problema . Simplifique la secuencia de comandos tanto como sea posible, pero no más.
Gilles
@Gilles Gracias. Modifiqué mi pregunta y agregué todo el script. Espero que esto ayude. Parece que el problema puede ser el hecho de que estoy iniciando un proceso en segundo plano ( la línea "./qaswvd &" ). ¿Podría ser este el origen del problema?
Olivier Pons
1
@ Olivier: Sí, su proceso principal esperará a que se detenga el proceso en segundo plano antes de salir. Si desea que algo siga funcionando después de salir, es posible que desee probar nohup. Sin embargo, no estoy seguro de que funcione con ssh, pero pruébalo para que no duela.
asoundmove
2

Probablemente pueda usar trabajos en su script. Si ese es el caso, Shell solo espera a que finalicen sus trabajos y no quiere separarse.

No voy a volver a publicar, solo te reenviaré http://en.wikipedia.org/wiki/Nohup#Existing_jobs

Oleksiy Khilkevich
fuente
Modifiqué mi pregunta y agregué todo el script. Espero que esto ayude. Parece que el problema puede ser el hecho de que estoy iniciando un proceso en segundo plano (la línea "./qaswvd &"). Si tiene razón, ¿este podría ser el origen del problema?
Olivier Pons
El proceso de fondo es el problema, pero nohupno es directamente el problema aquí, ya que no hay terminal en el lado del servidor: creo que el culpable es específicamente el descriptor de archivo abierto.
Gilles
Sí, creo que ese es el problema, puedes intentar comentar eso o aplicar el truco desde el enlace de arriba
Oleksiy Khilkevich
1

Necesitarás eliminar tu proceso padre desde tu script.

kill -SIGHUP $PPID

Entidad omnipotente
fuente
0

El problema es probablemente la siguiente línea.

./qaswvd &

Este comando probablemente todavía se esté ejecutando y mantendrá la tubería ssh abierta hasta que stdin y stdout & stderr estén cerrados.

Use esto en su lugar:

./qaswvd </dev/null >/dev/null 2>&1 &
edirks
fuente