So führen Sie einen Tunnel im Hintergrund als Teil eines Shell-Skripts aus

726
abbood

Ich führe diese beiden Befehle ständig aus, um eine Verbindung zu meiner rds-Instanz auf einem hinter einer Firewall geschützten aws herzustellen (also tunnle ich durch die ec2-Instanz):

Befehl 1: Tunnel öffnen (im Hintergrund ausführen)

ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub & 

Befehl 2: Verbindung zum DB über Tunnelport:

PGPASSWORD=password psql dbname -U user -h ip_address -p port; 

Das ist großartig, aber ich möchte beide in einer einzigen Funktion zusammenfassen. Aber mit mir hat nichts funktioniert:

Versuch 1: Ohne Hintergrundmaterial laufen:

function db() { ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub & PGPASSWORD=password psql dbname -U user -h ip_address -p port; } 

sagt mir einfach das:

$proddb [1] 62924 psql: could not connect to server: Connection refused Is the server running on host "127.0.0.1" and accepting TCP/IP connections on port 6666? 

obwohl der ursprüngliche Befehl im Hintergrund ausgeführt wird:

ps aux | grep host (standard input):435:abdullah 62924 0.0 0.0 4315660 5828 s006 S 3:06PM 0:00.03 ssh -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub 

und wenn ich sofort den nächsten Befehl ausführen lasse .. ich verbinde mich mit der DB gut!

PGPASSWORD=password psql dbname -U user -h ip_address -p port; user=> 

Wie mache ich das?

1

1 Antwort auf die Frage

2
A.B

Der erste Befehl hatte keine Zeit, um einen Tunnel einzurichten, als der zweite Befehl ausgeführt wurde, wodurch eine "Verbindung abgelehnt" wurde.

Verwenden Sie einfach nicht &die Option, sondern verwenden Sie stattdessen die Option -f:

-f
Fordert ssh auf, vor der Befehlsausführung in den Hintergrund zu wechseln. Dies ist nützlich, wenn ssh nach Passwörtern oder Passwörtern fragt, der Benutzer dies jedoch im Hintergrund wünscht. Dies impliziert -n. Die empfohlene Methode zum Starten von X11-Programmen an einem Remote-Standort ist etwa ssh -f host xterm.
Wenn die Konfigurationsoption ExitOnForwardFailure auf "yes" gesetzt ist, wartet ein mit -f gestarteter Client, bis alle Remote-Port-Weiterleitungen erfolgreich eingerichtet wurden, bevor er sich im Hintergrund befindet.

Wenn Sie all dies zusammenstellen, ersetzen Sie die ssh-Zeile in der Funktion durch:

ssh -o ExitOnForwardFailure=yes -f -N -L port:host:5432 user@$ip -i ~/.ssh/key.pub 

Wenn Sie die Funktion mehrmals ausführen, wird (multiple-1) nutzlos ssh nicht ausgeführt.

Es ist auch möglich, durch -Neinen kurzen Remote-Sleep-Befehl zu ersetzen . Auf diese Weise wird es keinen langlebigen ssh-Befehl im Leerlauf geben, der durchsucht werden muss, wenn er getötet werden muss. Ssh wartet immer noch mit dem Ende der Tunnelnutzung, bevor es beendet wird. Die kurze Verzögerung ist also kein Problem:

ssh -o ExitOnForwardFailure=yes -f -L port:host:5432 user@$ip -i ~/.ssh/key.pub sleep 15 
Tolle Antwort .. aber können Sie bitte das `|| erklären : `Teil oder ist es ein Tippfehler? abbood vor 6 Jahren 0
Wenn Sie die Shell -E-Option irgendwo setzen, würde ein Fehler alles abbrechen. `:` ist no-op (ein kürzerer Befehl 'true'). also mit einem `|| : `Konstruiere einfach lokal '-e'. Es wird erwartet, dass ssh beim zweiten Aufruf fehlschlägt, da das vorherige ssh immer noch ausgeführt wird (es verzieht sich wie ein Daemon und stirbt nicht). ohnehin ist es möglicherweise nutzlos zu sagen, vielleicht ist "-e" bereits in einer Funktion deaktiviert. Es ist auch möglich, -N durch einen kurzen Schlafbefehl zu ersetzen: ssh würde das Ende der Tunnelnutzung noch abwarten, bevor es beendet wird A.B vor 6 Jahren 0
Was passiert, wenn der erste Aufruf fehlschlägt? Dh meine Tunnelberechtigungen sind ungültig? Würde das sofort alles abbrechen? abbood vor 6 Jahren 0
pgsql würde sich wie vorher beschweren "Verbindung abgelehnt" A.B vor 6 Jahren 0
Jedenfalls entferne ich das `|| : `. Es ist nicht sehr nützlich und wird die Leute verwirren, die die Antwort lesen A.B vor 6 Jahren 0
@abbood hat eine alternative Option hinzugefügt A.B vor 6 Jahren 0