web-dev-qa-db-fra.com

Exécuter des commandes à distance, se détachant complètement de la connexion ssh

J'ai 2 ordinateurs, localpc et remoteserver.

J'ai besoin de localpc pour exécuter certaines commandes sur remoteserver. Il doit notamment démarrer un script de sauvegarde qui s'exécute pendant plusieurs heures. Je voudrais que la commande sur localpc "se déclenche" et soit exécutée de manière totalement indépendante sur remoteserver, comme localpc n'était jamais là en premier lieu.

Voici ce que j'ai fait jusqu'à présent:

remoteserver contient le script:

/root/backup.sh

localpc est prévu pour exécuter ceci:

ssh root@remoteserver 'Nohup /root/backup.sh' &

Suis-je en train de faire la bonne façon? Y a-t-il une meilleure manière de faire cela? Vais-je avoir du mal à le faire de cette façon?

53
LVLAaron

Vous devriez probablement utiliser screen sur l'hôte distant, pour avoir une vraie commande détachée:

ssh root@remoteserver screen -d -m ./script
50
enzotib

Fermer, mais pas exactement.

Indépendamment de tout terminal

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

Vous devez fermer tous les descripteurs de fichiers connectés au socket ssh, car la session ssh ne se fermera pas tant qu'un processus distant aura le socket ouvert. Si vous n'êtes pas intéressé par la sortie du script (probablement parce que le script lui-même prend soin d'écrire dans un fichier journal), redirigez-le vers /dev/null (mais notez que cela masquera les erreurs telles que l'impossibilité de démarrer le script).

L'utilisation de Nohup n'a aucun effet utile ici. Nohup fait en sorte que le programme qu'il exécute ne reçoive pas de signal HUP si le terminal de contrôle du programme disparaît, mais ici il n'y a pas de terminal en premier lieu, donc rien ne va envoyer un SIGHUP au processus hors du bleu. De plus, Nohup redirige la sortie standard et l'erreur standard (mais pas l'entrée standard) vers un fichier, mais uniquement s'ils sont connectés à un terminal, ce qui, encore une fois, ne l'est pas.

Détachement d'un terminal

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# Nohup /root/backup.sh </dev/null &
 Nohup: appending output to `Nohup.out'
 [1] 12345
 root@remoteserver# exit
 aaron@localpc$ 

Utilisez Nohup pour détacher le script de son terminal de contrôle afin qu'il ne reçoive pas SOUPIR lorsque le terminal disparaît. Nohup redirige également la sortie standard et l'erreur standard du script vers un fichier appelé Nohup.outsi ils sont connectés au terminal; vous devez vous occuper de l'entrée standard vous-même.

Garder un terminal distant

Si vous souhaitez conserver la commande en cours d'exécution dans un terminal distant mais ne pas la connecter à la session SSH, exécutez-la dans un multiplexeur de terminal tel que Screen ou Tmux .

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

Vous pouvez ultérieurement vous reconnecter au terminal sur lequel le script s'exécute en appelant screen -S backup -rd en tant que root sur cette machine.

Automatisation d'une commande à distance

Pour une sécurité légèrement meilleure, n'ouvrez pas trop largement les connexions root distantes directes. Créez une paire de clés spéciale et donnez-lui une commande forcée dans /root/.ssh/authorized_keys . Le contenu du fichier de clé publique est AAAA…== [email protected]; ajouter une liste d'options séparées par des virgules, y compris command="…" qui spécifie que la clé ne peut être utilisée que pour exécuter cette commande spécifique. Assurez-vous de conserver les options et la clé sur une seule ligne.

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== [email protected]

La recette standard pour exécuter une commande à distance à partir d'une connexion à distance comme SSH est la suivante:

Nohup command </dev/null >command.log 2>&1 &

Si command est un script Shell qui prend soin de se connecter à un fichier lui-même, vous pouvez modifier command.log à /dev/null. Une fois que vous avez commencé, déconnectez-vous immédiatement.

Vous avez besoin de tout sur cette ligne.

Nohup indique au Shell de ne pas perturber le processus si la session de connexion est déconnectée.

</dev/null lui dit de ne jamais attendre la saisie

>command.log lui dit d'envoyer des messages à ce fichier journal nommé

2>&1 lui dit d'envoyer tous les messages stderr au même fichier journal. Dans certains cas, il est préférable d'avoir deux fichiers, le second pour collecter les messages d'erreur et le premier pour collecter les messages d'activité normale. Cela peut faciliter la vérification du bon fonctionnement de tout.

& lui dit de détacher ce processus et de l'exécuter en arrière-plan en tant que processus démon.

12
Michael Dillon

Ce fil était très utile mais ma solution devait être un peu différente.

Je n'aime pas la solution d'écran car elle laisse un processus d'écran en cours dont je n'ai pas besoin. Les redirections et nohups utilisés comme ceci:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

ne fonctionnaient PAS pour moi lorsqu'il était utilisé avec la commande ssh.

J'ai créé un script wrapper sur la machine distante qui exécute le script réel. Le script wrapper définit la redirection et Nohup. Quelque chose comme ça:

backupwrapper.sh:
Nohup backup.sh > /dev/null 2>&1 &

Ensuite, sur ma machine cliente, je lance (pas de redirection):

# ssh remotemachine "backupwrapper.sh"
#

La commande ssh revient immédiatement, la connexion est interrompue et le script est en cours d'exécution.

11
rui

Comme Nils dit , c'est un risque de sécurité pour permettre à root de se connecter via ssh. Et je déconseille d'exécuter un travail important sur une machine sans journal. Si quelque chose ne va pas, vous souhaiterez avoir reçu des messages de dépannage. Il existe d'autres réponses vous montrant comment procéder. Mais voici comment je recommande d'accomplir exactement ce que vous avez demandé. Tout est intégré à sh (1). Pas besoin de GNU (bien que je pense que c'est une solution intelligente). Ajoutez cette chaîne à votre commande: >&- 2>&- <&- &. >&- signifie fermer la sortie standard. 2>&- signifie fermer stderr. <&- signifie fermer stdin. & signifie exécuté en arrière-plan, par exemple.

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely
$
6
tbc0

Vous devez mettre la commande à distance en arrière-plan sur remoteserver. La façon dont vous le faites mettra en arrière-plan la commande ssh sur localpc.

En dehors de cela, c'est une mauvaise idée d'autoriser root-ssh.

Donc, configurez sur remoteserver: Une ligne sudoers qui exécutera /root/backup.sh en tant que root par l'utilisateur backup.

Vous pouvez créer cet utilisateur sans "bon" mot de passe.

Mettez la commande Sudo /root/backup.sh & comme commande dans ~backup/.ssh/authorized_keys - avec la clé publique de localpc (celui qui déclenche ce script).

0
Nils