SSH und Shell durch SSH: wie man beendet?


22

Ich starte ein entferntes Skript über SSH wie folgt:

ssh user@ipaddress '~/my_script.sh'

Alles läuft gut, aber sobald das Skript beendet ist, wird die Verbindung nicht geschlossen. Ich muss STRG-C drücken, um die aktuelle Verbindung zu trennen.

Ich habe den Befehl "exit" in "~ / my_script.sh" ausprobiert und er ist unbrauchbar. Ich habe den Befehl "logout" in "~ / my_script.sh" ausprobiert und erhalte folgende Meldung:

logout: not login shell: use exit

...

Irgendeine Idee, wie ich das SSH automatisch und richtig schließen könnte, wenn das Skript fertig ist?

(Änderung zur Verdeutlichung :) Folgendes ist in meinem Skript enthalten:

#!/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

Wenn ich es über SSH starte, läuft es und am Ende lese ich "Alles erledigt". Das bedeutet also, dass es die letzten 2 Zeilen erreicht .

Irgendeine Idee, wie ich es machen könnte, automatisch zu schließen und pr


1
Was steht im Drehbuch?
Ignacio Vazquez-Abrams

@Olivier: Leiten Sie irgendwelche Ports weiter (einschließlich des Agenten und X)? Die ssh-Verbindung wird geschlossen, wenn der Befehl beendet wird und alle TCP-Verbindungen geschlossen wurden.
Gilles 'SO- hör auf böse zu sein'

@ Gilles: Nein, ich mache nur eine Shell-Verbindung, um ein Skript auszuführen, nichts wird weitergeleitet.
Olivier Pons

1
@Olivier: Wenn Sie eine haben ~/.ssh/config, versuchen Sie es ohne diese und übergeben Sie die Optionen -a -x(und nein -o) an ssh, um sicherzustellen, dass keine Weiterleitung stattfindet. Wenn es immer noch nicht funktioniert, zeigen Sie den Inhalt des Skripts an.
Gilles 'SO- hör auf böse zu sein'

@Olivier: Startet das Skript einen Hintergrundjob, auf den es möglicherweise wartet? Leider scheinen Jobs in einem ssh-Skript nichts zurückzugeben. Beispiel: ssh <yourusername>@localhost '(ls; sleep 10 &); echo Done; jobs'listet Dateien auf, zeigt sie fertig an und wartet 10 Sekunden, bevor sie zurückkehrt.
Asoundmove

Antworten:


19

Der Exit im Shell-Skript funktioniert nicht, da das Skript und nicht die Shell beendet werden. Um die Shell nach Beendigung des Skripts zu verlassen, gehen Sie wie folgt vor

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

Dadurch wird das Skript ausgeführt und die Shell beendet.


3
Es sollte aufregend sein. Das Skript ist die Shell.
Bis auf weiteres angehalten.

@ Tennis: Es funktioniert nicht für ihn, so kann dies stattdessen funktionieren.
Wuffers

2
@Herr. Mann: Ihr Befehl entspricht dem Original, mit der Ausnahme, dass eine Shell zwischen sshdund der ausgeführten Shell vorhanden sein muss myscript.sh. Das, was exitSie geschrieben haben, wird beim Beenden des Skripts ausgeführt, was nicht hilft. Die einzige Möglichkeit, wie Ihre Lösung funktionieren könnte, besteht darin, dass das Skript etwas Seltsames sshdausführt, wenn das übergeordnete Element eine Shell ist, und dies nicht, wenn das übergeordnete Element eine Shell ist.
Gilles 'SO- hör auf böse zu sein'

Wie hilft es nicht? Beenden wird die Shell schließen und die Verbindung beenden, richtig? Und ist es nicht das, was das Plakat tun will?
Wuffers

3
@MrMan: wird ~/my_script.sh && exitsofort beendet ~/my_script.sh. Wenn das Shell-Skript nicht beendet würde, würde Ihr Befehl exitsowieso nie auf das Bit zugreifen. Also ist es einfach nutzlos.
Gilles 'SO- hör auf böse zu sein'

12

Die ssh-Verbindung bleibt geöffnet, wenn der von ssh (hier eine Shell) gestartete Prozess beendet wird, sofern andere Prozesse ihn noch verwenden. Ich kenne die genauen Regeln, denen der ssh-Daemon folgt, nicht, aber es wird eine Verbindung verwendet, zumindest wenn die Standardausgabe eines untergeordneten Prozesses noch mit der von ssh bereitgestellten ursprünglichen Pipe verbunden ist. Vergleichen Sie:

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

Wenn Sie einen Daemon starten, sollten Sie ihn im Hintergrund ausführen und seine Dateideskriptoren schließen. Zumindest benutze dies:

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

Möglicherweise möchten Sie vor hinzufügen nohup; Hier macht es keinen Unterschied, aber es wäre nützlich, wenn das Skript von einem Terminal aus ausgeführt würde. Viele Programme, die als Daemon fungieren sollen, verfügen über Befehlszeilenoptionen, mit denen sie verzweigt werden können, Dateideskriptoren schließen, Signale ignorieren und andere Vorteile erzielen können. Überprüfen Sie in der qaswvdDokumentation, ob es eine hat. Sie können auch die Dienstprogramme "Daemonizer" untersuchen.


Hatte das gleiche Problem und das funktioniert. Die akzeptierte Antwort funktioniert nicht.
Andy

5

Ich habe diesen Beitrag gesehen, als ich nach der Lösung der gleichen Situation gegoogelt habe. Obwohl es ein bisschen spät ist, das Problem von @ Oliver zu lösen, da die akzeptierte Antwort weder für OP noch für mich funktioniert hat (ich weiß nicht, warum sie akzeptiert wird), möchte ich dennoch meine eigene Lösung für den zukünftigen Googler veröffentlichen. Es ist ganz einfach: Fügen Sie dem Befehl eine -fOption hinzu ssh:

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

BEARBEITEN

Die Auswirkung der -fOption ist, dass sie sshin den Hintergrund gestellt wird. Ohne weitere hinzugefügte Option ist es möglich, dass die Verbindung noch besteht, auch wenn es den Anschein hat, dass sie unterbrochen ist. Bei Interesse kann auf die Antwort in einem anderen Beitrag auf dieser Website verwiesen werden.


Achtung: Dieses (-f) funktioniert nicht, wenn das ursprüngliche Skript Eingabeaufforderungen für Benutzereingaben enthält.
madD7

3

Wie Ignacio bin ich neugierig, was in deinem Drehbuch steht.

Vielleicht könnten Sie versuchen, Ihr Skript auf das kleinstmögliche Beispiel zu reduzieren, das die Fehlerbedingung erzeugt.

Oder beginnen Sie mit einem leeren Skript und fügen Sie jeweils einen Befehl hinzu, bis Sie das Problem sehen. Dann wissen Sie, durch welchen Befehl Ihr Skript abstürzt.

Wenn das leere Skript ein Problem verursacht, möchten Sie möglicherweise Ihre ssh-Konfiguration untersuchen. Ist beispielsweise .bash_logout oder ein solcher Aufruf beim Beenden ein Problem?


Vielen Dank für Ihren Vorschlag, ich habe jetzt das Beispiel meines Skripts in meine Frage aufgenommen.
Olivier Pons

@Olivier: Sie haben nur irrelevante Teile Ihres Skripts hinzugefügt. Veröffentlichen Sie ein Skript (und ggf. eine Bedienungsanleitung), mit dem die Leser Ihr Problem reproduzieren können . Vereinfachen Sie das Skript so weit wie möglich, aber nicht weiter.
Gilles 'SO- hör auf böse zu sein'

@ Gilles Danke. Ich habe meine Frage geändert und das gesamte Skript hinzugefügt. Hoffe das hilft. Es scheint, dass das Problem möglicherweise darin besteht, dass ich einen Hintergrundprozess starte ( die Zeile "./qaswvd &" ). Könnte dies der Ursprung des Problems sein?
Olivier Pons

1
@Olivier: Ja, Ihr Hauptprozess wartet, bis der Hintergrundprozess beendet ist, bevor er beendet wird. Wenn Sie möchten, dass nach dem Beenden etwas weiterläuft, sollten Sie nohup ausprobieren. Ich bin mir nicht sicher, ob es mit ssh funktioniert, aber probiere es aus, es tut nicht weh.
Asoundmove

2

Möglicherweise verwenden Sie Jobs in Ihrem Skript. In diesem Fall wartet die Shell nur darauf, dass Ihre Aufträge abgeschlossen sind, und möchte sich nicht von selbst lösen.

Ich werde nicht erneut posten, sondern Sie einfach weiterleiten http://en.wikipedia.org/wiki/Nohup#Existing_jobs


Ich habe meine Frage geändert und das gesamte Skript hinzugefügt. Hoffe das hilft. Es scheint, dass das Problem möglicherweise darin besteht, dass ich einen Hintergrundprozess starte (die Zeile "./qaswvd &"). Wenn Sie Recht haben, könnte dies der Grund für das Problem sein?
Olivier Pons

Der Hintergrundprozess ist das Problem, ist aber nohuphier nicht direkt das Problem, da es auf der Serverseite kein Terminal gibt: Ich denke, der Schuldige ist speziell der offene Dateideskriptor.
Gilles 'SO - hör auf böse zu sein'

Ja, ich denke, das ist das Problem, Sie können versuchen, dies zu kommentieren oder den Hack über den obigen Link anwenden
Oleksiy Khilkevich

1

Sie müssen den übergeordneten Prozess in Ihrem Skript beenden.

kill -SIGHUP $PPID


0

Das Problem ist wahrscheinlich die folgende Zeile.

./qaswvd &

Dieser Befehl wird wahrscheinlich noch ausgeführt und hält die SSH-Pipe offen, bis stdin und stdout & stderr geschlossen werden.

Verwenden Sie dies stattdessen:

./qaswvd </dev/null >/dev/null 2>&1 &
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.