ssh et shell via ssh: comment sortir?

22

Je lance un script distant via SSH comme ceci:

ssh user@ipaddress '~/my_script.sh'

Tout va bien mais une fois le script terminé, la connexion n'est pas fermée. Je dois appuyer sur CTRL-C pour rompre la connexion actuelle.

J'ai essayé la commande "exit" dans '~ / my_script.sh' et c'est inutile. J'ai essayé la commande "logout" dans '~ / my_script.sh' et je reçois un message:

logout: not login shell: use exit

...

Une idée de comment je pourrais fermer automatiquement et correctement le SSH une fois le script terminé?

(Modification pour clarification :) Voici ce qu'il y a dans mon 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

Lorsque je le lance via SSH, il s'exécute et à la fin, je lis "Tout est fait". cela signifie donc qu'il atteint les 2 dernières lignes .

Toute idée que je pourrais faire pour fermer automatiquement et pr

Olivier Pons
la source
1
Que contient le script?
Ignacio Vazquez-Abrams
@Olivier: Transférez-vous des ports (y compris l'agent et X)? La connexion ssh est fermée lorsque la commande se termine et que toutes les connexions TCP ont été fermées.
Gilles 'SO- arrête d'être méchant'
@ Gilles: non je fais juste une connexion shell pour exécuter un script, rien n'est transmis.
Olivier Pons
1
@Olivier: Si vous en avez un ~/.ssh/config, essayez sans et passez les options -a -x(et non -o) sshpour vous assurer qu'il n'y a pas de transfert en cours. Si cela ne fonctionne toujours pas, affichez le contenu du script.
Gilles 'SO- arrête d'être méchant'
@Olivier: le script démarre-t-il un travail d'arrière-plan qu'il attend peut-être? Malheureusement, les travaux ne semblent rien renvoyer lorsqu'ils sont dans un script ssh. Exemple: ssh <yourusername>@localhost '(ls; sleep 10 &); echo Done; jobs'listera les fichiers, affichera terminé et attendra 10 secondes avant de revenir.
asoundmove

Réponses:

19

La sortie dans le script shell ne fonctionne pas car elle quitte le script, pas le shell. Pour quitter le shell une fois le script terminé, faites

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

Cela exécutera le script puis quittera le shell.

Wuffers
la source
3
Il devrait sortir. Le script est le shell.
pause jusqu'à nouvel ordre.
@Dennis: Cela ne fonctionne pas pour lui, donc cela peut fonctionner à la place.
Wuffers
2
@Monsieur. Man: Votre commande est équivalente à l'original, sauf qu'elle force un shell à exister entre sshdle shell et son exécution myscript.sh. Celui que exitvous avez écrit agira à la fin du script, ce qui n'aide pas. La seule façon dont votre solution pourrait fonctionner est si le script fait quelque chose de bizarre lorsque son parent est sshdet ne fait pas cette chose bizarre lorsque son parent est un shell.
Gilles 'SO- arrête d'être méchant'
Comment ça n'aide pas? Quitter fermera le shell et mettra fin à la connexion, n'est-ce pas? Et n'est-ce pas ce que l'affiche veut faire?
Wuffers
3
@MrMan: ~/my_script.sh && exitquitte dès que se termine ~/my_script.sh. Si le script shell ne se terminait pas, votre commande ne parviendrait jamais au exitbit de toute façon. Donc c'est juste inutile.
Gilles 'SO- arrête d'être méchant'
12

La connexion ssh reste ouverte lorsque le processus démarré par ssh (ici, un shell) se termine, si d'autres processus l'utilisent encore. Je ne connais pas les règles exactes que le démon ssh suit, mais une connexion est en cours d'utilisation, au moins, si la sortie standard de tout processus enfant est toujours connectée au canal d'origine fourni par ssh. Comparer:

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

Lorsque vous démarrez un démon, vous devez le mettre en arrière-plan et fermer ses descripteurs de fichiers. Utilisez au moins ceci:

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

Vous voudrez peut-être ajouter nohupà l'avant; cela ne fera aucune différence ici mais serait utile si le script était exécuté à partir d'un terminal. De nombreux programmes conçus pour agir en tant que démon ont des options de ligne de commande pour les amener à bifurquer, fermer les descripteurs de fichiers, ignorer les signaux et autres subtilités. Vérifiez dans la qaswvddocumentation si elle en a un. Vous pouvez également enquêter sur les utilitaires «daemonizer».

Gilles 'SO- arrête d'être méchant'
la source
Eu le même problème, et cela fonctionne. La réponse acceptée ne fonctionne pas.
Andy
5

J'ai vu ce message lorsque j'ai recherché la solution de la même situation sur Google. Bien qu'il soit un peu tard pour résoudre le problème de @ Oliver, puisque la réponse acceptée ne fonctionnait clairement ni pour OP ni pour moi (je ne sais pas pourquoi elle est acceptée), je voudrais quand même publier ma propre solution pour le futur googleur. C'est simple: ajoutez une -foption dans la sshcommande:

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

ÉDITER

L'effet de l' -foption est de mettre sshen arrière-plan, donc sans autre option ajoutée, il est possible que la connexion soit toujours en vie même si elle semble rompue. On peut se référer à la réponse donnée dans un autre post sur ce site si vous êtes intéressé.

Leo Fang
la source
Attention: Ce (-f) ne fonctionnera pas si le script d'origine a des invites pour la saisie utilisateur.
madD7
3

Comme Ignacio, je suis curieux de savoir ce qu'il y a dans votre script.

Peut-être pourriez-vous essayer de réduire votre script au plus petit exemple possible qui génère la condition d'erreur.

Ou commencez à partir d'un script vide et ajoutez une commande à la fois jusqu'à ce que vous voyiez le problème, puis vous saurez quelle commande provoque le verrouillage de votre script.

Si le script vide vous pose un problème, vous voudrez peut-être examiner votre configuration ssh, par exemple, est .bash_logout ou un tel appelé à la sortie qui peut provoquer un problème?

asoundmove
la source
Merci pour votre suggestion, j'ai maintenant ajouté l'exemple de mon script dans ma question.
Olivier Pons
@Olivier: Vous n'avez ajouté que des parties non pertinentes de votre script. Publiez un script (et des instructions d'utilisation si nécessaire) qui permettrait aux lecteurs de reproduire votre problème . Simplifiez le script autant que possible, mais pas plus loin.
Gilles 'SO- arrête d'être méchant'
@Gilles Merci. J'ai modifié ma question et ajouté tout le script. J'espère que cela t'aides. Il semble que le problème soit au fait que je lance un processus en arrière-plan ( la ligne "./qaswvd &" ). Serait-ce l'origine du problème?
Olivier Pons
1
@Olivier: Oui, votre processus principal attendra que le processus d'arrière-plan s'arrête avant de quitter. Si vous voulez que quelque chose continue de fonctionner après votre sortie, vous pouvez essayer nohup. Je ne suis pas sûr que cela fonctionne avec ssh, mais essayez-le, cela ne fera pas de mal.
asoundmove
2

Vous pouvez probablement utiliser des travaux dans votre script. Si tel est le cas, le shell attend que vos travaux soient terminés et ne souhaite pas se détacher.

Je ne vais pas republier, je vous ferai simplement parvenir http://en.wikipedia.org/wiki/Nohup#Existing_jobs

Oleksiy Khilkevich
la source
J'ai modifié ma question et ajouté tout le script. J'espère que cela t'aides. Il semble que le problème soit dû au fait que je lance un processus en arrière-plan (la ligne "./qaswvd &"). Si vous avez raison, cela pourrait être à l'origine du problème?
Olivier Pons
Le processus en arrière-plan est le problème, mais ce nohupn'est pas directement le problème ici car il n'y a pas de terminal côté serveur: je pense que le coupable est spécifiquement le descripteur de fichier ouvert.
Gilles 'SO- arrête d'être méchant'
Oui, je pense que c'est le problème, vous pouvez essayer de le commenter ou d'appliquer le hack à partir du lien ci
Oleksiy Khilkevich
1

Vous devrez tuer votre processus parent depuis votre script.

kill -SIGHUP $PPID

OmnipotentEntity
la source
0

Le problème est probablement la ligne suivante.

./qaswvd &

Cette commande est probablement toujours en cours d'exécution et gardera le tuyau ssh ouvert jusqu'à ce que stdin et stdout & stderr soient fermés.

Utilisez-le à la place:

./qaswvd </dev/null >/dev/null 2>&1 &
edirks
la source