2010-02-10 9 views
98

Cygwin, je veux un script BASH à:script Bash pour configurer un tunnel SSH temporaire

  1. créer un tunnel SSH vers un serveur distant.
  2. Travaillez localement en utilisant le tunnel.
  3. Ensuite, fermez le tunnel.

La "partie d'arrêt" m'a perplexe.

Actuellement, j'ai une solution boiteuse. Dans un shell, je lance ce qui suit pour créer un tunnel.

# Create the tunnel - this works! It runs forever, until shell is quit. 
ssh -nNT -L 50000:localhost:3306 [email protected] 

Puis, dans une autre fenêtre shell, je fais mon travail

# Do some MYSQL stuff over local port 50000 (which goes to remote port 3306) 

Enfin, quand je suis fait. Je ferme la première fenêtre de shell pour tuer le tunnel.

Je voudrais faire tout cela dans un script comme: # Créer tunnel # ne fonctionnent # kill tunnel

Comment puis-je garder une trace du processus de tunnel, donc je sais que l'on tuer ?

+0

J'ai écrit un script qui aiderait à faire du tunnellisation ssh, vous pouvez le vérifier sur: https://github.com/gdbtek/ssh-tunneling.git –

Répondre

235

Vous pouvez le faire proprement avec une « prise de contrôle » ssh. Pour parler à un processus SSH déjà en cours d'exécution et l'obtenir est pid, tuer, etc. Utilisez la « prise de contrôle » (-M pour le maître et -S pour socket) comme suit:

$ ssh -M -S my-ctrl-socket -fnNT -L 50000:localhost:3306 [email protected] 
$ ssh -S my-ctrl-socket -O check [email protected] 
Master running (pid=3517) 
$ ssh -S my-ctrl-socket -O exit [email protected] 
Exit request sent. 

Notez que my-ctrl -socket sera un fichier réel qui est créé.

J'ai reçu cette information de a very RTFM reply on the OpenSSH mailing list.

+5

Ceci est la meilleure réponse que j'ai vu sur le sujet jusqu'à présent. Merci beaucoup, cela devrait être accepté. Je l'utilise pour me connecter à ma machine virtuelle Vagrant et exécuter un script de mise à jour FlywayDB. – Christian

+7

Juste merveilleux. Merci d'avoir partagé cela. +1 – slayedbylucifer

+2

Apparemment, les prises de contrôle ne fonctionnent pas partout. Par exemple, j'obtiens 'Opération non autorisée' sur l'environnement d'intégration continue de drone.io:' muxserver_listen: écouteur mux de lien ssh-ctrl-socket.wsASkszgSBlK7kqD => ssh-ctrl-socket: opération non permise' –

2

Vous pouvez lancer le ssh avec un & à la fin, pour le mettre en arrière-plan et saisir son identifiant lorsque vous le faites. Ensuite, vous avez juste à faire un kill de cet ID lorsque vous avez terminé.

+0

Sachez si vous utilisez l'esperluette ("&"). C'est une approche laide puisque vous devrez déterminer la connexion réelle établie pour vous-même. Cela peut entraîner l'exécution d'un code supplémentaire qui n'attend pas l'établissement complet de la connexion réelle. De plus, la connexion ne sera pas supprimée automatiquement si le script se casse. –

17
  • Vous pouvez dire ssh aller en arrière-plan avec & et ne pas créer une coquille de l'autre côté (il suffit d'ouvrir le tunnel) avec un indicateur de ligne de commande (je vous vois déjà fait cela avec -N).
  • Enregistrer le PID avec PID=$!
  • Faites vos trucs
  • kill $PID

EDIT: Fixe $? à $! et a ajouté le &

+7

$ ?? Non, $ !! . . – mob

+0

Si mon script meurt quelque part avant qu'il n'atteigne le KILL, je dois faire attention à le gérer. –

+0

@mobrule: votre droit. fixé. – ZeissS

4

Je préfère lancer un nouveau shell pour des tâches séparées et je l'utilise souvent la combinaison de commande suivante:

$ sudo bash; exit 

ou parfois:

$ : > sensitive-temporary-data.txt; bash; rm -f sensitive-temporary-data.txt; exit 

Ces commandes créent une coquille imbriquée où je peux faire tout mon travail; quand j'ai fini, j'appuie sur CTRL-D et le shell parent nettoie et quitte aussi. Vous pouvez facilement jeter bash; dans votre script tunnel ssh juste avant la partie kill de sorte que lorsque vous ouvrez une session hors de la coquille imbriquée votre tunnel sera fermé:

#!/bin/bash 
ssh -nNT ... & 
PID=$! 
bash 
kill $PID 
+0

Très intéressant. Cela peut mieux gérer le problème du "piège". Je vais devoir l'essayer. –

2

Une autre option possible - si vous pouvez installer le package attendre , vous devriez être capable de scripter le tout.Quelques bons exemples ici: http://en.wikipedia.org/wiki/Expect

13

Vous pouvez dire SSH à l'arrière-plan lui-même avec l'option -f mais vous n'obtiendrez pas le PID avec $ !. Au lieu d'avoir votre script en veille pendant un certain temps avant d'utiliser le tunnel, vous pouvez utiliser -o ExitOnForwardFailure = yes avec -f et SSH attend que tous les ports distants soient correctement établis avant de se placer en arrière-plan. Vous pouvez grep la sortie de ps pour obtenir le PID. Par exemple, vous pouvez utiliser

... 
ssh -Cfo ExitOnForwardFailure=yes -NL 9999:localhost:5900 $REMOTE_HOST 
PID=$(pgrep -f 'NL 9999:') 
[ "$PID" ] || exit 1 
... 

et être assez sûr que vous obtenez le PID souhaité

Questions connexes