web-dev-qa-db-fra.com

Script Bash pour configurer un tunnel SSH temporaire

Sur Cygwin, je souhaite qu'un script Bash puisse:

  1. Créez un tunnel SSH sur un serveur distant.
  2. Faites des travaux localement qui utilisent le tunnel.
  3. Puis fermez le tunnel.

La partie arrêt a été 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 the Shell is quit.
ssh -nNT -L 50000:localhost:3306 [email protected]

Puis, dans une autre fenêtre de Shell, je fais mon travail:

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

Enfin, lorsque j'ai terminé, je ferme la première fenêtre Shell pour supprimer le tunnel.

Je voudrais faire tout cela dans un script comme:

# Create tunnel
# Do work
# Kill tunnel

Comment puis-je suivre le processus de tunnel pour savoir lequel tuer?

122
jm.

Vous pouvez le faire proprement avec une 'socket de contrôle' ssh. Pour parler à un processus SSH déjà en cours d'exécution et obtenir son pid, tuez-le, etc. Utilisez le 'socket de contrôle' (-M pour 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 créé.

J'ai reçu cette information de ne réponse très RTFM sur la liste de diffusion OpenSSH .

301
Chris McCormick

Vous pouvez indiquer à SSH de se fonder avec l'option -f mais vous n'obtiendrez pas le PID avec $ !. De plus, au lieu de laisser votre script dormir une quantité de temps arbitraire avant d'utiliser le tunnel, vous pouvez utiliser -o ExitOnForwardFailure = yes avec -f et SSH attendra que tous les transferts de 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 soyez sûr que vous obtenez le PID souhaité

19
Maine Guy
  • Vous pouvez dire à ssh de passer en arrière-plan avec & et ne créez pas de shell de l’autre côté (ouvrez simplement le tunnel) avec un indicateur de ligne de commande (je vois que vous l’avez déjà fait avec -N).
  • Enregistrez le PID avec PID=$!
  • Fais tes affaires
  • kill $PID

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

18
ZeissS

Je préfère lancer un nouveau shell pour des tâches distinctes et j'utilise souvent la combinaison de commandes suivante:

  $ Sudo bash; exit

ou parfois:

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

Ces commandes créent un shell imbriqué dans lequel je peux effectuer tout mon travail. Quand j'ai terminé, j'appuie sur CTRL-D et le parent Shell nettoie et quitte également. Vous pourriez facilement jeter bash; dans votre script de tunnel ssh juste avant la partie kill de sorte que, lorsque vous vous déconnectez du shell imbriqué, votre tunnel soit fermé:

#!/bin/bash
ssh -nNT ... &
PID=$!
bash
kill $PID
4
too much php

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

2
Phil Pelanne

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

2
Valentin Rocher