web-dev-qa-db-fra.com

Exécuter la commande sur un serveur distant via SSH - sans quitter

Je me connecte fréquemment au laboratoire Linux de mon école pour travailler sur mes tâches de programmation à distance. Parfois, lorsque de nombreux autres étudiants sont connectés au serveur, la connexion est lente et je perds du travail pendant les délais de connexion. Il existe plusieurs serveurs dans le laboratoire et je veux pouvoir exécuter automatiquement who dès que la connexion est établie, afin que je puisse voir à quel point le serveur est encombré et en utiliser un autre s'il est joli. plein. À l’heure actuelle, j’utilise une fonction dans mon fichier .bash_aliases pour rationaliser l’entrée de la connexion et du mot de passe:

Dans le fichier ~/.bash_aliases:

#!/bin/bash

# ssh to the Linux lab. Takes hostnames defined in ~/.ssh/config as 
# parameters
function sshll()
{
    if [ "$@" ]
      echo "Connecting to hostname $@";
      sshpass -f <password_file> ssh $@;
    else
      echo "Connecting to default Host";
      sshpass -f <password_file> ssh <user@ipaddress>;
    fi
}

Cela fonctionne. J'ai donc ajouté who à la fin des commandes ssh:

Dans le fichier ~/.bash_aliases:

#!/bin/bash

# ssh to the linux lab. Takes hostnames defined in ~/.ssh/config as 
# parameters
function sshll()
{
    if [ "$@" ]
      echo "Connecting to hostname $@";
      sshpass -f <password_file> ssh $@ 'who';
    else
      echo "Connecting to default Host";
      sshpass -f <password_file> ssh <user@ipaddress> 'who';
    fi
}

Ceci se connecte, entre mon mot de passe automatiquement et lance who, mais ferme ensuite la connexion. Est-il possible d’exécuter who automatiquement, sans fermer la connexion par la suite?

5
Michael Hoffmann

TL; DR : La réponse d’int_ua est la voie à suivre, la plus simple et la plus simple.

Pourquoi cela fonctionne comme cela

Cela remonte au comportement de base de tout shell. Lorsque vous vous connectez simplement en tant que ssh [email protected], vous obtenez une version interactive du shell. Lorsque vous exécutez ssh [email protected] -t "command1;command2", vous obtenez essentiellement /bin/sh -c 'command1;command2'. Le premier vous permet d'exécuter ce que vous avez mis dans la stdin lors de la recherche des fichiers de points, tandis que le second exécute simplement ces commandes et quitte. Essentiellement, il n’existe aucun moyen d’exécuter une commande avant l’utilisation interactive (sauf s’il se trouve dans l’un des fichiers .dot) ou d’obtenir un shell interactif à partir de la commande unique sh -c (ou quel que soit le shell choisi, pas nécessairement). sh).

Idées manquantes ou incomplètes

Ma première idée est la suivante: si le shell utilise le .bashrc local du serveur, peut-il lui faire utiliser le fichier local du client sur le serveur? Bien, non . Non, sauf si vous copiez le fichier point sur le serveur distant avec scp ou rsync.

La deuxième idée que j'ai eu est le Prompt_COMMAND. Cette très jolie variable bash exécute la commande à chaque fois avant d'afficher votre invite PS1, alors pourquoi ne pas définir cette variable avant de générer le bash sur Prompt_COMMAND="who; unset Prompt_COMMAND" afin que nous l'exécutions en tant que coup?

Le problème est que cette variable doit être exportée vers le serveur distant, et Gilles répond m'a aidé à faire quelque chose comme ceci:

ssh -o SendEnv=PS1 ssh localhost -t bash

ou

ssh localhost -t " Prompt_COMMAND='who; unset Prompt_COMMAND' bash  "

Problème? L'option -o SendEnv doit autoriser la variable spécifique que vous essayez d'envoyer dans /etc/ssh/sshd_config et, dans les deux cas, vous devez toujours exécuter tout ce travail avec /bin/sh -c.

Légère amélioration de la réponse de int_ua

Nous pouvons donc maintenant voir que le modèle ssh user@server -t 'command1;Shell' fonctionne le mieux. Sauf qu'il y a un nitpick mineur: /bin/sh -c le processus est toujours là, alors pourquoi ne pas exécuter bash avec exec pour remplacer ce processus?

 ssh [email protected] -t 'who;exec bash'
2
Sergiy Kolodyazhnyy

Juste exécuter bash devrait suffire:

 sshpass -f <password_file> ssh <user@ipaddress> 'who; bash';
5
int_ua

C'est an réponse, mais certainement pas le réponse.

J'ai découvert que sshd (le démon des services ssh sur l'hôte distant) exécutera des commandes dans ~/.ssh/rc lors de la connexion. Je viens de créer ce fichier et y ai ajouté who. À présent, une liste d'utilisateurs est affichée à chaque fois que je me connecte à distance, et j'obtiens toujours un shell de connexion.

Sur l'hôte distant:

File ~/.ssh/rc:

#!/bin/bash

# This file is executed by sshd when a remote connection is started over ssh
who

Sur le client:

In file ~/.bash_aliases:

#!/bin/bash

# ssh to the linux lab. Takes hostnames defined in ~/.ssh/config as 
# parameters
function sshll()
{
    if [ "$@" ]
      echo "Connecting to hostname $@";
      sshpass -f <password_file> ssh $@;
    else
      echo "Connecting to default Host";
      sshpass -f <password_file> ssh <user@ipaddress>;
    fi
}

Je suis toujours intéressé à savoir comment procéder, côté client, pour les autres utilisateurs ayant des problèmes similaires qui ne peuvent pas utiliser ~/.ssh/rc faute d'autorisations ou pour toute autre raison.

3
Michael Hoffmann

réponse de int_ua c'est ce que j'utiliserais. Par souci d’exhaustivité, si vous pouvez éditer votre propre .profile ou .bashrc sur le serveur distant, vous pouvez l’ajouter à l’un des deux:

if [[ -n $SSH_TTY ]]
then
    who
fi

SSH définit diverses variables, dont SSH_TTY - vous pouvez les tester pour déterminer si vous êtes connecté via SSH. Les restrictions sur ~/.ssh/rc ne doivent pas vous empêcher de l'utiliser.


J'utilise ceci pour définir mon invite (remarquez comment je saute le nom d'hôte pour les shells locaux):

if [[ -n $SSH_TTY ]]
then
    PS1="\u@\h:\w \$ "
else
    PS1="\u:\w \$ "
fi
3
muru