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.
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 &
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
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 ) & )"'
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 &\""
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.
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.
la manière la plus rapide et la plus facile est d'utiliser la commande "at":
ssh utilisateur@target "à maintenant -f /home/foo.sh"
Cela a fonctionné pour moi, peut parfois:
ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & "
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"
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.
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"
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