Amener ssh à exécuter une commande en arrière-plan sur la machine cible

il s'agit d'une question complémentaire au comment utiliser ssh dans un script shell? question. Si je veux exécuter une commande sur la machine distante qui s'exécute en arrière-plan sur cette machine, comment puis-je obtenir la commande ssh pour revenir? Lorsque j'essaie simplement d'inclure l'esperluette (&) à la fin de la commande se bloque. La forme exacte de la commande ressemble à ceci:

ssh user@target "cd /some/directory; program-to-execute &"

des idées? Une chose à noter est que se connecte au la machine cible produit toujours une bannière de texte et j'ai les touches SSH configurées de sorte qu'aucun mot de passe n'est requis.

252
demandé sur Community 2008-08-27 02:55:58

12 réponses

j'ai eu ce problème dans un programme que j'ai écrit il y a un an -- s'avère que la réponse est plutôt compliqué. Vous aurez besoin d'utiliser nohup ainsi que la redirection de sortie, comme expliqué dans l'artcle wikipedia sur nohup , copié ici pour votre commodité.

Nohuping backgrounded emplois est pour exemple utile lors de la connexion via SSH, depuis backgrounded des travaux peut provoquer la coque pour accrocher sur déconnexion pour une course état [2]. Ce le problème peut également être surmonté en redirigeant les trois Flux e/S:

nohup myprogram > foo.out 2> foo.err < /dev/null &
260
répondu Jax 2008-08-26 23:18:41

C'est la façon la plus propre de le faire pour moi: -

ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"

La seule chose à courir après, c'est la commande sur la machine distante

231
répondu Russ 2013-03-20 13:13:44

Rediriger fd

La sortie

doit être redirigée avec &>/dev/null qui redirige à la fois stderr et stdout vers /dev/null et est synonyme de >/dev/null 2>/dev/null ou >/dev/null 2>&1 .

Parenthèse

la meilleure façon est d'utiliser sh -c '( ( command ) & )' où la commande est n'importe quoi.

ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Nohup Shelll

vous pouvez également utiliser nohup directement pour lancer le shell:

ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Nice Launch

une autre astuce consiste à utiliser nice pour lancer la commande/shell:

ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'
24
répondu AskApache Webmaster 2012-03-17 08:09:14

je voulais juste montrer un exemple de travail que vous pouvez couper et coller:

ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""
16
répondu cmcginty 2012-09-05 19:50:27

si vous ne pouvez pas maintenir la connexion ouverte , vous pouvez utiliser écran , si vous avez les droits de l'installer.

user@localhost $ screen -t remote-command
user@localhost $ ssh user@target # now inside of a screen session
user@remotehost $ cd /some/directory; program-to-execute &

pour détacher la session d'écran: ctrl-a d

À l'écran de la liste des sessions:

screen -ls

Pour remettre en place une session:

screen -d -r remote-command

notez que l'écran peut aussi créer plusieurs shells chaque session. Un effet similaire peut être obtenu avec tmux .

user@localhost $ tmux
user@localhost $ ssh user@target # now inside of a tmux session
user@remotehost $ cd /some/directory; program-to-execute &

pour détacher la session tmux: ctrl-b d

À l'écran de la liste des sessions:

tmux list-sessions

Pour remettre en place une session:

tmux attach <session number>

la clé de contrôle tmux par défaut, ' ctrl-b ', est quelque peu difficile à utiliser, mais il ya plusieurs exemple tmux configure ce vaisseau avec tmux que vous pouvez essayer.

16
répondu hometoast 2015-09-06 20:19:51

je pense que vous devrez combiner quelques-unes de ces réponses pour obtenir ce que vous voulez. Si vous utilisez nohup en conjonction avec le point-virgule, et envelopper le tout entre guillemets, puis vous obtenez:

ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"

qui semble fonctionner pour moi. Avec nohup, vous n'avez pas besoin d'ajouter le & à la commande à exécuter. Aussi, si vous n'avez pas besoin de lire tout de la sortie de la commande, vous pouvez utiliser

ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"

pour rediriger toutes les sorties vers /dev/null.

7
répondu 2008-09-11 14:34:14

la manière la plus rapide et la plus facile est d'utiliser la commande "at":

ssh utilisateur@target "à maintenant -f /home/foo.sh"

7
répondu neil 2014-07-11 11:19:10

Cela a fonctionné pour moi, peut parfois:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & " 
3
répondu fs82 2013-07-25 16:01:01

en fait, chaque fois que j'ai besoin d'exécuter une commande sur une machine distante qui est compliquée, j'aime mettre la commande dans un script sur la machine de destination, et juste exécuter ce script en utilisant ssh.

par exemple:

# simple_script.sh (located on remote server)

#!/bin/bash

cat /var/log/messages | grep <some value> | awk -F " " '{print }'

et ensuite j'exécute cette commande sur la machine source:

ssh user@ip "/path/to/simple_script.sh"
1
répondu PaulT 2017-06-14 05:16:43

j'ai essayé de faire la même chose, mais avec la complexité que j'essayais de le faire à partir de Java. Donc sur une machine qui exécute java, j'essayais d'exécuter un script sur une autre machine, en arrière-plan (avec nohup).

à partir de la ligne de commande, voici ce qui a fonctionné: (vous n'avez peut-être pas besoin du "- i keyFile" si vous n'en avez pas besoin pour ssh vers l'hôte)

ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""

notez qu'à ma ligne de commande, il y a un argument après le "- c", qui est tous entre guillemets. Mais pour qu'il fonctionne de l'autre côté, il a encore besoin des citations, donc j'ai dû y mettre des citations évitées.

de java, voici ce qui a fonctionné:

ProcessBuilder b = new ProcessBuilder("ssh", "-i", "keyFile", "bash", "-c",
 "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\"");
Process process = b.start();
// then read from process.getInputStream() and close it.

Il a fallu un peu de l'essai et de l'erreur de le faire fonctionner, mais il semble bien fonctionner maintenant.

0
répondu Randy Wilson 2012-12-03 12:14:19

suivre D'abord cette procédure:

connectez-vous sur que l'utilisateur a et générer une paire de clés d'authentification. N'inscrivez pas de phrase de passe:

a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa): 
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

utilise maintenant ssh pour créer un répertoire ~/.SSH comme utilisateur B sur B. (le répertoire peut déjà exister, ce qui est bien):

a@A:~> ssh b@B mkdir -p .ssh
b@B's password: 

finalement ajoute la nouvelle clé publique de a à b@B:.SSH / authorized_keys et entrez le mot de passe de b une dernière fois:

a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
b@B's password: 

désormais, vous pouvez vous connecter à B as B à partir de A sans mot de passe:

a@A:~> ssh b@B

alors cela fonctionnera sans entrer de mot de passe

ssh b@B "cd /certains/répertoire; programme à exécuter et"

-2
répondu Kevin Duterne 2011-06-24 07:07:10

je pense que c'est ce dont vous avez besoin: Vous devez d'abord installer sshpass sur votre machine. alors vous pouvez écrire votre propre script:

while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE
-2
répondu MLSC 2014-01-26 05:43:46