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

StackOverflow https://stackoverflow.com/questions/29142

  •  09-06-2019
  •  | 
  •  

Question

Il s'agit d'une question complémentaire à Comment utiliser ssh dans un script shell ? question.Si je souhaite exécuter une commande sur la machine distante qui s'exécute en arrière-plan sur cette machine, comment puis-je renvoyer la commande ssh ?Lorsque j'essaie simplement d'inclure l'esperluette (&) à la fin de la commande, elle 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 les connexions à la machine cible produisent toujours une bannière de texte et j'ai SSH clés configurées de sorte qu’aucun mot de passe n’est requis.

Était-ce utile?

La solution

J'ai eu ce problème dans un programme que j'ai écrit il y a un an. Il s'avère que la réponse est plutôt compliquée.Vous devrez utiliser nohup ainsi que la redirection de sortie, comme expliqué dans l'article Wikipédia sur non, copié ici pour votre commodité.

Les travaux en arrière-plan nohuping sont par exemple utiles lorsqu'ils sont connectés via SSH, car les travaux fondamentaux peuvent entraîner la déconnexion du shell en raison d'une condition de course [2].Ce problème peut également être surmonté en redirigeant les trois flux d'E / S:

nohup myprogram > foo.out 2> foo.err < /dev/null &

Autres conseils

Cela a été 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 qui s'exécute après ceci est la commande réelle sur la machine distante

Rediriger les 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èses

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

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

Coquille Nohup

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

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

Joli lancement

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 fonctionnel 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 disposez des droits nécessaires pour 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

Pour répertorier les sessions d’écran :

screen -ls

Pour rattacher une session :

screen -d -r remote-command

Notez que screen peut également créer plusieurs shells au sein de 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

Pour répertorier les sessions d’écran :

tmux list-sessions

Pour rattacher une session :

tmux attach <session number>

La clé de contrôle tmux par défaut, 'ctrl-b', est quelque peu difficile à utiliser, mais il existe plusieurs exemples de configurations tmux fournies avec tmux que vous pouvez essayer.

Le moyen le plus rapide et le plus simple consiste à utiliser la commande « at » :

ssh user@target "à l'heure actuelle -f /home/foo.sh"

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 que vous mettez le tout entre guillemets, vous obtenez :

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

ce qui semble fonctionner pour moi.Avec nohup, vous n'avez pas besoin d'ajouter le & à la commande à exécuter.De plus, si vous n'avez pas besoin de lire le résultat 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.

Cela a fonctionné pour moi plusieurs fois :

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 compliquée sur une machine distante, j'aime placer la commande dans un script sur la machine de destination et exécuter simplement 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 $8}'

Et puis je lance simplement cette commande sur la machine source :

ssh user@ip "/path/to/simple_script.sh"

J'essayais de faire la même chose, mais avec la complexité supplémentaire que j'essayais de le faire depuis Java.Ainsi, sur une machine exécutant Java, j'essayais d'exécuter un script sur une autre machine, en arrière-plan (avec nohup).

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

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

Notez que sur ma ligne de commande, il y a un argument après le "-c", qui est tout entre guillemets.Mais pour que cela fonctionne à l'autre bout, il a toujours besoin des guillemets, j'ai donc dû y mettre des guillemets échappés.

Depuis 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 quelques essais et erreurs pour que cela fonctionne, mais cela semble bien fonctionner maintenant.

Vous pouvez le faire comme ça...

sudo /home/script.sh -opt1 > /tmp/script.out &

Il m'a semblé très pratique d'avoir un télécommande session tmux utilisant le tmux new -d <shell cmd> syntaxe comme celle-ci :

ssh someone@elsewhere 'tmux new -d sleep 600'

Cela lancera une nouvelle session sur elsewhere Les commandes host et ssh sur la machine locale reviendront au shell presque instantanément.Vous pouvez ensuite vous connecter en SSH à l'hôte distant et tmux attach à cette séance.Notez qu'il n'y a rien sur l'exécution de tmux local, seulement à distance !

De plus, si vous souhaitez que votre session persiste une fois le travail terminé, ajoutez simplement un lanceur de shell après votre commande, mais n'oubliez pas de la mettre entre guillemets :

ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'

Je pense que c'est ce dont tu as besoin :Au début, vous devez 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

Suivez d’abord cette procédure :

Connectez-vous sur A en tant qu'utilisateur a et générez une paire de clés d'authentification.Ne saisissez pas de phrase secrète :

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

Utilisez maintenant ssh pour créer un répertoire ~/.ssh en tant qu'utilisateur b sur B.(Le répertoire existe peut-être déjà, ce qui est très bien) :

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

Ajoutez enfin la nouvelle clé publique de a à b@B:.ssh/authorized_keys et saisissez une dernière fois le mot de passe de b :

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

À partir de maintenant, vous pouvez vous connecter à B en tant que b depuis A en tant que a sans mot de passe :

a@A:~> ssh b@B

alors cela fonctionnera sans entrer de mot de passe

ssh b@B "cd /some/répertoire ;programme à exécuter &"

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top