Avec ssh, comment pouvez-vous exécuter une commande sur la machine distante sans quitter?

29

Normalement, si vous passez une commande à ssh comme ça

ssh [email protected] 'some-command.sh'

Vous obtenez une session non interactive et ssh se ferme dès que la commande (ou le script, ou autre) est exécutée. Comment puis-je obtenir une session interactive et exécuter une commande que j'ai spécifiée à partir de ma machine locale. Par exemple, j'aimerais pouvoir ouvrir l'écran et redémarrer une session d'écran spécifique:

ssh [email protected] 'screen -r 12345'

mais cela n'est pas autorisé, renvoyant l'erreur "Doit être connecté à un terminal". ce qui, je présume, signifie essentiellement "doit appeler cette commande à partir d'un shell interactif".

Comme autre exemple, j'utilise une tonne de machines au travail qui me demandent souvent d'utiliser un compte partagé pour avoir le droit de faire certaines choses (ouais je sais: mauvaise idée mais ne me blâmez pas, je n'ai pas mis en place des choses qui façon), et ils ont généralement ksh comme shell par défaut. Je souhaite me connecter, basculer vers bash (ou zsh) et rechercher le .bash_profile (ou .zshrc) de mon propre compte. Ce serait facile si je pouvais établir une session ssh interactive et passer une commande à la machine distante pour l'exécuter lors de la connexion.

J'ai une solution très louable (et non testée) à l'esprit que je publierai, mais j'espère que quelqu'un connaît une meilleure façon.

MISE À JOUR: pour ceux qui ne l'ont pas réalisé, je ne prévois pas de faire tout cela à la main, donc me dire d'ouvrir une session interactive et de le faire à la main ne résout rien.

2ème MISE À JOUR: Pour tenter une fois de plus de clarifier: j'essaie d'exécuter des commandes (arbitraires) sur le serveur (spécifié par programme sur le client) mais j'ai ensuite une session interactive ouverte qui est affectée par tout ce qui est fait par ces commandes programmatiques.

iconoclaste
la source
echo "command" | ssh user@remote_host
laggingreflex
2
Avez-vous manqué la partie "sans sortir" de la question? Je suis sûr que cela se terminera une fois la commande terminée.
iconoclaste du

Réponses:

26

Vous pouvez essayer la commande suivante pour démarrer bash et source votre propre profil lorsque vous ssh:

ssh  -t hostname "bash --rcfile ~user/.bashrc"
dogbane
la source
4
+1. Le -tcommutateur résout également le problème du questionneur screen.
Patchs du
3
Peut-il être utilisé avec des commandes arbitraires, sans fermer la connexion? Si j'essaye ssh -t www.dev "echo 'hi there'", la connexion est immédiatement fermée après l'exécution de la commande.
iconoclaste
11

S'appuyant sur la réponse de dogbane, une solution complète ressemble à:

ssh -t user@server 'cd /a/great/place; bash'

Ici, j'utilise -tpour forcer l'allocation d'un pseudo-terminal, qui est nécessaire pour un shell interactif. Ensuite, j'exécute deux commandes sur le serveur: d'abord la chose que je voulais faire avant d'ouvrir le shell interactif (dans mon cas, changer de répertoire dans un dossier spécifique), puis le shell interactif lui-même. bash voit qu'il a un pseudo-terminal et répond de manière interactive.

Les guillemets simples garantissent que le tout est transmis au serveur distant en tant que commande à exécuter par votre shell par défaut.

Merci encore à Dogbane d'avoir fourni les indices nécessaires -t. J'avais l'habitude de résoudre ce problème avec expect, ce qui tue définitivement une souris avec un canon. (:

user1179239
la source
2

Essayez cette solution.

echo "command" | ssh user@remote_host

La connexion est interactive et votre commande est passée comme si vous l'aviez tapée sur la ligne de commande interactive. La session se termine comme si vous aviez tapé

ssh user@remote_host 'command'
user210540
la source
3
Si la session se termine une fois la commande terminée, cela ne répond pas à la question. L'intégralité de la commande doit être laissée avec une session interactive après l'exécution de la commande, et pas seulement pour envoyer des commandes aux serveurs ssh.
iconoclaste
C'est au moins bon pour simuler une interaction pour que la commande s'exécute, sans utiliser -tou votre propre fichier bash. +1
laggingreflex
0

Utilisez ssh -X pour utiliser les cmds termIO.

Aussi - vous pouvez enchaîner vos cmds comme "ssh 'source ~ / .bashrc && cd && do'"

ethrbunny
la source
mais une fois la chaîne terminée, je n'ai plus de session interactive, non? Il ferme toujours, non?
iconoclaste du
Souhaitez-vous développer la solution termIO?
iconoclaste du
0

pourquoi ne pas installer detach sur le système distant et utiliser:

ssh -t [email protected] "/home/user/bin/detach ls"
Dan D.
la source
Est-ce que cela fonctionnera 'ls' et ALORS me laissera une session interactive? Que faire si, au lieu de «ls», j'exécute «source .somefile» pour obtenir des alias et des fonctions. Seront-ils disponibles dans ma session interactive ou auront-ils été exécutés dans une autre session?
iconoclaste du
Non, en raison de detach, lsne garde pas la session ouverte et se déconnectera sans imprimer la sortie de lsmais elle continuera de fonctionner.
Dan D.
J'essaie d'exécuter des commandes (arbitraires) sur le serveur (spécifié par programme sur le client) mais j'ai ensuite une session interactive ouverte qui est affectée par tout ce qui est fait par ces commandes programmatiques. Donc, si je vous comprends bien, cela ne m'aide pas.
iconoclaste
0

la réponse de laggingreflex est proche ... Je la changerais comme suit:

echo "command\n$(cat -)" | ssh user@remote_host

Malheureusement, il est peu probable que vous aimiez la façon dont cela fonctionne, car "cat" met en mémoire tampon les lignes qu'il écrit sur stdout ... Si nous créons un script appelé "echo-cat" qui ressemble à ceci:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

nous obtiendrons le même résultat sans mise en mémoire tampon:

echo-cat "command" | ssh user@remote_host

Cela vous rapprochera probablement beaucoup plus de votre objectif ...

Facture
la source
0

C'est kludgey, et non testé, mais je pense que cela devrait fonctionner.

Créez un script nommé (par exemple) démarreur à distance qui prend un argument cité après un argument user @ host:

remote-starter [email protected] 'some-command.sh arg1 arg2'

Ce script doit d'abord enregistrer la commande entre guillemets (sans guillemets) dans un fichier nommé (par exemple) .onetimesur la machine distante, puis exécuter une commande ssh normale, cette fois sans passer de commande à exécuter sur la machine distante. (Si vous exécutez ssh [email protected] à partir d'un script, cela peut fonctionner pour exécuter exec ssh [email protected].)

Pour que cela fonctionne, la machine distante doit source à .onetimepartir de son .bash_profile ou .zshrc ou autre. Après l'exécution .onetime, il doit être supprimé .onetime, afin que le fichier ne soit pas exécuté la prochaine fois que vous effectuez une connexion régulière.

iconoclaste
la source