Utilisation de SSH pour démarrer un processus à distance

18

J'ai écrit un script que j'utilise pour pousser et déployer un nouveau service sur plusieurs machines sous mon contrôle, et afin d'exécuter le processus, j'utilise ssh pour démarrer le processus à distance. Malheureusement, chaque fois que j'utilise SSH pour démarrer le processus, la commande SSH ne semble jamais revenir, provoquant le blocage du script.

La commande est spécifiée comme: ssh $ user @ $ host "/ root / command &". Chaque fois que j'exécute des commandes simples, telles que ps ou who, la commande SSH revient immédiatement, mais lorsque j'essaie de démarrer mon processus, elle ne revient pas. J'ai essayé des astuces comme envelopper mon processus dans un simple script bash qui démarre le processus puis se termine, mais cela bloque également la commande SSH (même si le script bash fait écho à un message de réussite et se termine normalement).

Quelqu'un a-t-il une idée de la cause de ce comportement et de la façon de récupérer la commande SSH dès que le processus a été démarré?

Merci pour vos idées!

rmrobins
la source
Postez la ligne de commande exacte que vous utilisez ... omettre les mots de passe / noms d'utilisateur / IP
Joseph Kern
ssh $ SSH_USER @ $ HOST_ADDR "/ root / AppName &"
rmrobins
Je dois mentionner que j'ai configuré des clés SSH, il n'est donc pas nécessaire d'utiliser des mots de passe pour exécuter des commandes sur les systèmes distants.
rmrobins
@rmrobins, une très bonne étape pour définir l'authentification par clé publique.
nik

Réponses:

28

SSH connecte stdin, stdout et stderr du shell distant à votre terminal local, afin que vous puissiez interagir avec la commande qui s'exécute sur le côté distant.

En tant qu'effet secondaire, il continuera à fonctionner jusqu'à ce que ces connexions soient fermées, ce qui ne se produit que lorsque la commande à distance et tous ses enfants (!) Sont terminés (car les enfants, qui sont ce que "&" démarre, héritent std * de leur processus parent et laissez-le ouvert).

Vous devez donc utiliser quelque chose comme

ssh user@host "/script/to/run < /dev/null > /tmp/mylogfile 2>&1 &"

Les <,> et 2> & 1 redirigent stdin / stdout / stderr loin de votre terminal. Le "&" fait ensuite passer votre script en arrière-plan. En production, vous devez bien sûr rediriger stdin / err vers un fichier journal approprié.

Voir

http://osdir.com/ml/network.openssh.general/2006-05/msg00017.html

Éditer:

Je viens de découvrir que ce qui < /dev/nullprécède n'est pas nécessaire (mais la redirection stdout / err l' est ). Je ne sais pas pourquoi ...

sleske
la source
Merci, c'est exactement ce que je cherchais - il ne m'est pas venu à l'esprit que le processus hériterait du std * même lors de l'utilisation de & pour le lancer en arrière-plan.
rmrobins
+1! Travaille pour moi. Et vous pouvez également imprimer la sortie en faisant écho au fichier journal: ssh user@host "/script/to/run > /tmp/ssh.stdout 2>&1 && cat /tmp/ssh.stdout && rm -f /tmp/ssh.stdout"
Fishdrowed
5

Vous pourriez essayer nohup . Man nohup pour plus de détails.

ssh host "nohup script &"

Si vous souhaitez conserver la sortie sur la machine distante, voici une variante .

ssh user@host 'export REMOTE=myname; nice nohup ./my-restart >
logfile.log 2>&1 &'
Jauder Ho
la source
5

Une autre alternative serait de tirer un détaché screen(1), quelque chose comme:

ssh -l user host "screen -d -m mycommand"

Cela démarrera un écran détaché (qui capture toutes les interactions à l'intérieur de celui-ci), puis reviendra immédiatement, mettant fin à la session ssh.

Avec un peu plus d'ingéniosité, vous pouvez résoudre des appels de commande à distance assez complexes de cette façon.

Towo
la source
4
 -f      Requests ssh to go to background just before command execution.
         This is useful if ssh is going to ask for passwords or
         passphrases, but the user wants it in the background.  This
         implies -n.  The recommended way to start X11 programs at a
         remote site is with something like ssh -f host xterm.

         If the ExitOnForwardFailure configuration option is set to “yes”,
         then a client started with -f will wait for all remote port for‐
         wards to be successfully established before placing itself in the
         background.
Teddy
la source
1
Le problème avec cette méthode est que la commande SSH n'est pas réellement terminée, elle est simplement cachée en arrière-plan, donc l'hôte exécutant le script aura un grand nombre de commandes SSH en arrière-plan qui ne reviennent jamais parce que les commandes SSH ne reviennent jamais ( c'est-à-dire le problème racine que je souhaite résoudre)
rmrobins
-1

Je pense que la bonne façon serait

ssh user@host exec script.sh &
nik
la source
Non, ça ne marche pas pour moi. Pourquoi cela?
sleske
Je n'ai pas utilisé le push de fond sur ssh, j'essayais sans terme à portée de main. ma faute.
nik