it-swarm.com.de

Wie kann ich eine im Hintergrund befindliche/getrennte SSH-Sitzung beenden?

Ich nutze das Programm Synergie zusammen mit einem SSH-Tunnel

Es funktioniert, ich muss nur eine Konsole öffnen und diese beiden Befehle eingeben:

ssh -f -N -L localhost:12345:otherHost:12345 [email protected]
synergyc localhost

weil ich faul bin, habe ich ein Bash-Script erstellt, das mit einem Mausklick auf ein Icon ausgeführt wird: 

#!/bin/bash
ssh -f -N -L localhost:12345:otherHost:12345 [email protected]
synergyc localhost

das obige Bash-Script funktioniert auch, aber jetzt möchte ich auch die Synergie und den SSH-Tunnel über einen Mausklick abtöten. Daher muss ich die PIDs der Synergie und SSH in einer Datei speichern, um sie später zu beenden:

#!/bin/bash

mkdir -p /tmp/synergyPIDs || exit 1
rm -f /tmp/synergyPIDs/ssh || exit 1
rm -f /tmp/synergyPIDs/synergy || exit 1

[ ! -e /tmp/synergyPIDs/ssh ] || exit 1
[ ! -e /tmp/synergyPIDs/synergy ] || exit 1

ssh -f -N -L localhost:12345:otherHost:12345 [email protected]
echo $! > /tmp/synergyPIDs/ssh
synergyc localhost
echo $! > /tmp/synergyPIDs/synergy

Die Dateien dieses Skripts sind jedoch leer.

Wie erhalte ich die PIDs von SSH und Synergien?
(Ich versuche, ps aux | grep ... | awk ... | sed ...-Kombinationen zu vermeiden, es muss einen einfacheren Weg geben.)

58
Skaarj

nun, ich möchte kein & am Ende der Befehle hinzufügen, da die Verbindung abbricht, wenn das Konsole-Fenster geschlossen wird ... also habe ich eine ps-grep-awk-sed-combo erhalten

ssh -f -N -L localhost:12345:otherHost:12345   [email protected]
echo `ps aux | grep -F 'ssh -f -N -L localhost' | grep -v -F 'grep' | awk '{ print $2 }'` > /tmp/synergyPIDs/ssh
synergyc localhost
echo `ps aux | grep -F 'synergyc localhost' | grep -v -F 'grep' | awk '{ print $2 }'` > /tmp/synergyPIDs/synergy

(Sie könnten grep in awk integrieren, aber ich bin jetzt zu faul)

12
Skaarj

Kurze Zusammenfassung: Funktioniert nicht.

Meine erste Idee ist, dass Sie die Prozesse im Hintergrund starten müssen, um ihre PIDs mit $! zu erhalten.

Ein Muster wie

some_program &
some_pid=$!
wait $some_pid

vielleicht tun Sie, was Sie brauchen ... außer dass dann ssh nicht mehr im Vordergrund steht, um nach Passphrasen zu fragen.

Nun, vielleicht brauchen Sie doch etwas anderes. ssh -f führt wahrscheinlich zu einem neuen Prozess, den Ihre Shell niemals von dem Aufruf wissen kann. Idealerweise bietet ssh selbst eine Möglichkeit, seine PID in eine Datei zu schreiben.

72
ndim

Bei allem Respekt für die Benutzer von pgrep, pkill, ps | awk usw. gibt es einenmuch- besseren Weg.

Wenn Sie sich auf ps -aux | grep ... verlassen, um einen Prozess zu finden, riskieren Sie eine Kollision. Sie haben möglicherweise einen Anwendungsfall, bei dem dies unwahrscheinlich ist, aber in der Regel ist dies nicht der richtige Weg.

SSH bietet einen Mechanismus zum Verwalten und Steuern von Hintergrundprozessen. Aber wie bei so vielen SSH-Dingen handelt es sich um eine "fortgeschrittene" Funktion, und viele Leute (es scheint die anderen Antworten hier zu sein) sind sich ihrer Existenz nicht bewusst.

In meinem eigenen Anwendungsfall habe ich eine Workstation zu Hause, auf der ich einen Tunnel verlassen möchte, der eine Verbindung zu einem HTTP-Proxy im internen Netzwerk in meinem Büro herstellt, und eine weitere, die mir einen schnellen Zugriff auf Verwaltungsschnittstellen auf nebeneinander liegenden Servern ermöglicht . So erstellen Sie die grundlegenden Tunnel, die von zu Hause aus initiiert werden:

$ ssh -fNT -L8888:proxyhost:8888 -R22222:localhost:22 officefirewall
$ ssh -fNT -L4431:www1:443 -L4432:www2:443 colocatedserver

Diese führen dazu, dass sich ssh im Hintergrund befindet und die Tunnel geöffnet bleiben. Aber wenn der Tunnel wegfällt, bin ich festgefahren, und wenn ich ihn finden will, muss ich meine Prozessliste analysieren und nach Hause bringen. Ich habe die "richtige" SSH (falls ich versehentlich mehrere gestartet habe, die aussehen) ähnlich).

Wenn ich mehrere Verbindungen verwalten möchte, verwende ich stattdessen die Option ControlMaster config von SSH zusammen mit der Befehlszeilenoption -O zur Steuerung. Zum Beispiel mit dem folgenden in meiner ~/.ssh/config-Datei:

Host officefirewall colocatedserver
    ControlMaster auto
    ControlPath ~/.ssh/cm_sockets/%[email protected]%h:%p

wenn die obigen ssh-Befehle ausgeführt werden, bleibt ~/.ssh/cm_sockets/ in der Umgebung, die dann Zugriff auf die Steuerung gewähren kann. Beispiel:

$ ssh -O check officefirewall
Master running (pid=23980)
$ ssh -O exit officefirewall
Exit request sent.
$ ssh -O check officefirewall
Control socket connect(/home/ghoti/.ssh/cm_socket/[email protected]:22): No such file or directory

An diesem Punkt ist der Tunnel (und die kontrollierende SSH-Sitzung) weg, ohne dass ein Hammer (kill, killall, pkill usw.) verwendet werden muss.

Zurück zu deinem Anwendungsfall bringen ...

Sie richten den Tunnel ein, durch den syngergyc mit syngergys am TCP - Port 12345 sprechen soll. Dazu würde ich Folgendes tun.

Fügen Sie Ihrer ~/.ssh/config-Datei einen Eintrag hinzu:

Host otherHosttunnel
    HostName otherHost
    User otherUser
    LocalForward 12345 otherHost:12345
    RequestTTY no
    ExitOnForwardFailure yes
    ControlMaster auto
    ControlPath ~/.ssh/cm_sockets/%[email protected]%h:%p

Beachten Sie, dass die -L-Option der Befehlszeile mit dem Schlüsselwort LocalForward behandelt wird und dass die Zeilen Control {Master, Path} enthalten sind, um sicherzustellen, dass Sie die Kontrolle haben, nachdem der Tunnel eingerichtet wurde.

Dann können Sie Ihr Bash-Skript folgendermaßen ändern:

#!/bin/bash

if ! ssh -f -N otherHosttunnel; then
    echo "ERROR: couldn't start tunnel." >&2
    exit 1
else
    synergyc localhost
    ssh -O exit otherHosttunnel
fi

Die Option -f hinterlegt den Tunnel und hinterlässt einen Socket in ControlPath, um den Tunnel später zu schließen. Wenn die ssh fehlschlägt (was möglicherweise auf einen Netzwerkfehler oder ExitOnForwardFailure zurückzuführen ist), muss der Tunnel nicht beendet werden. Wenn er jedoch nicht fehlgeschlagen ist (else), wird synergyc gestartet und der Tunnel nach dem Beenden geschlossen.

Vielleicht möchten Sie auch nachsehen, ob Sie mit der SSH-Option LocalCommand rechts in Ihrer ssh-Konfigurationsdatei synergyc starten können.

53
ghoti

ich bin gerade auf diesen Thread gestoßen und wollte das Linux-Dienstprogramm "pidof" erwähnen:

$ pidof init
1
21
zrathen

Sie können lsof verwenden, um die PID des Prozesses anzuzeigen, der Port 12345 auf localhost abhört:

lsof -t -i @localhost:12345 -sTCP:listen

Beispiele:

PID=$(lsof -t -i @localhost:12345 -sTCP:listen)
lsof -t -i @localhost:12345 -sTCP:listen >/dev/null && echo "Port in use"
15
Atle

Sie können den -f fallen lassen, wodurch er im Hintergrund ausgeführt wird, dann mit eval und zwingen Sie ihn selbst in den Hintergrund. 

Sie können dann die pid greifen. Stellen Sie sicher, dass der & in die eval-Anweisung eingefügt wird.

eval "ssh -N -L localhost:12345:otherHost:12345 [email protected] & " 
tunnelpid=$!
9
l0k3y3

Dies ist eher ein Spezialfall für Synergyc (und die meisten anderen Programme, die versuchen, sich selbst zu dämonisieren). Mit $! funktioniert, außer dass synergyc während der Ausführung einen clone () -Syscall ausführt, der ihm eine andere PID gibt als die, von der bash geglaubt hat. Wenn Sie dies umgehen möchten, damit Sie $! Verwenden können, können Sie synergyc anweisen, im Forground zu bleiben und es dann im Hintergrund zu verwenden.

synergyc -f -n mydesktop remoteip &
synergypid=$!

synergyc führt auch einige andere Dinge aus, z. B. den Autorestart, den Sie möglicherweise deaktivieren möchten, wenn Sie versuchen, dies zu verwalten.

4
deltaray

Eine andere Option ist die Verwendung von pgrep, um die PID des neuesten SSH-Prozesses zu ermitteln

ssh -fNTL 8073:localhost:873 [email protected]
tunnelPID=$(pgrep -n -x ssh)
synergyc localhost
kill -HUP $tunnelPID
3
Lenny

Sie können nach der SSH-Prozedur Ausschau halten, die an Ihren lokalen Port gebunden ist, indem Sie folgende Zeile verwenden:

netstat -tpln | grep 127\.0\.0\.1:12345 | awk '{print $7}' | sed 's#/.*##'

Es gibt die PID des Prozesses über Port 12345/TCP für localhost zurück. Sie müssen also nicht alle ssh-Ergebnisse aus ps filtern.

Wenn Sie nur überprüfen müssen, dass if an diesen Port gebunden ist, verwenden Sie:

netstat -tln | grep 127\.0\.0\.1:12345 >/dev/null 2>&1

Gibt 1 zurück, wenn keine Bindung besteht, oder 0, wenn dieser Port abgehört wird.

2
foo

Basierend auf der sehr guten Antwort von @ghoti, folgt ein einfacheres Skript (zum Testen), das die SSH-Steuersockel verwendet ohne dass eine zusätzliche Konfiguration erforderlich ist:

#!/bin/bash
if ssh -fN -MS /tmp/mysocket -L localhost:12345:otherHost:12345 [email protected]; then
    synergyc localhost
    ssh -S /tmp/mysocket -O exit otherHost
fi

synergyc wird nur gestartet, wenn der Tunnel erfolgreich eingerichtet wurde. Der Vorgang wird geschlossen, sobald synergyc zurückgegeben wird . Die Lösung weist jedoch keine ordnungsgemäße Fehlerberichterstattung auf.

0
doak