Pourquoi le $ PATH d'une commande à distance ssh diffère-t-il de celui d'un shell interactif?

20

J'ai un utilisateur qui n'a apporté aucune modification au $ PATH dans aucun fichier dot: c'est exactement le paramètre par défaut du système. Depuis un shell de connexion:

$ ssh example.com
user@example.com:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$SHELL"
echo "$PATH"

user@example.com:~$ /tmp/hello.hs
/bin/bash
/usr/local/bin:/usr/bin:/bin

Exactement comme spécifié dans /etc/profile. Je trouve cela plutôt inattendu:

$ ssh example.com '/tmp/hello.sh'
/bin/bash       
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

Comme je l'ai dit, il n'y a pas de modification de $ PATH dans ~/.bashrc, ni dans /etc/bash.bashrc. Non ~/.ssh/environmentnon plus. La ssh(1)déclare que la variable d'environnement PATHest

Définissez le PATH par défaut, comme spécifié lors de la compilation de ssh.

mais ce fil de StackOverflow et cet article de liste de diffusion suggèrent que je devrais être capable d'influencer $ PATH pour une commande donnée simplement en modifiant / etc / profile, l'un des fichiers de démarrage du shell, etc.

Que se passe t-il ici?

vin de truite
la source

Réponses:

16

De ssh(1)la page de manuel: "Si la commande est spécifiée, elle est exécutée sur l'hôte distant au lieu d'un shell de connexion."

Donc, en bref, lorsque vous vous connectez réellement à la machine bash est démarré en tant que shell de connexion et charge les fichiers appropriés, lorsque vous vous connectez à distance et émettez une commande, elle est exécutée à la place de bash, ce qui signifie que ces fichiers ne se chargent PAS. Vous pouvez contourner ce problème avec using su -l -cou similaire dans la partie commande de ssh.

Dans certains cas, j'ai également vu des -targuments pour que ssh fonctionne (allocate tty).

Edit 1 :
Je pense que les informations PATH que vous avez trouvées, que le chemin par défaut (sauf si nous le remplaçons) est celui compilé dans sshd. Je me suis assuré que mon / etc / profile, / etc / bash *, les fichiers dot locaux, etc. ne contenaient aucune information PATH, puis je me suis connecté et j'avais toujours un PATH. J'ai cherché celui-ci dans sshd et je l'ai trouvé là-bas. Donc, comment la page de manuel dit:

ahnberg@remote$ strings /usr/sbin/sshd | grep -i x11 | grep bin
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

Ensuite, j'ajoute PATH=$PATH:/my/testtout en haut de mon .bashrcfichier sur la télécommande et je vérifie à nouveau:

ahnberg@local$ ssh ahnberg@remote "env | grep PATH"
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/my/test

Je peux donc absolument l'influencer, et PATH par défaut est celui compilé dans sshd. :)

Mattias Ahnberg
la source
Hmm, cette phrase "exécutée sur l'hôte distant" signifie beaucoup plus qu'elle ne le dit, je pense. Le bit le plus intéressant, que j'ai manqué plus tôt, se trouve dans la section 'ENVIRONNEMENT' de la même page de manuel: "PATH Défini sur le PATH par défaut, comme spécifié lors de la compilation de ssh." Sauf que cela suggère que je devrais pouvoir influencer le CHEMIN d'une commande.
troutwine
Eh bien, le fait est que ce n'est pas un shell de connexion, donc il ne lance pas / source / inclut les fichiers de démarrage de la même manière que pour un shell de connexion, d'où mes suggestions d'essayer. Mettre les choses en place .bashrcpourrait également fonctionner, mais dans l'ensemble, je contournerais cela si PATH est important. Ou pourquoi ne pas simplement spécifier des chemins d'accès complets si vous avez besoin de la méthode «command» pour exécuter ssh? :)
Mattias Ahnberg
J'ai légèrement modifié mon message. Maintenant, il y a un shell de connexion, un shell sans connexion et des variantes interactives / non interactives de celui-ci. Les commandes SSH sont appelées dans le shell de l'utilisateur sous une forme non interactive et sans connexion. L' bash(1)INVOCATION suggère qu'aucun fichier de démarrage n'est lu de cette façon, mais je ne trouve pas de documentation sur la façon dont ssh appelle le shell. Cela semble contraire aux sources liées ci-dessus, sauf si d'autres ont le fichier de démarrage / etc / ssh / sshrc que je n'ai pas. (Il existe des solutions de contournement, bien sûr, mais il s'agit de comprendre exactement comment Debian SSHD gère les chemins par défaut.)
troutwine
Si je modifie le PATH dans /etc/profileles mises à jour du chemin de ma boîte distante pour moi, alors ssh user@remotebox 'env'me montre le PATH mis à jour. La même chose se passe si j'ajoute export PATH=$PATH:/my/testpathà .bashrc (mais dans mon cas en haut du fichier avant de vérifier les shells interactifs ( -z "$PS1").
Mattias Ahnberg
Mis à jour avec mes tests / résultats.
Mattias Ahnberg
3

J'ai pu obtenir ssh pour exécuter des commandes en utilisant le chemin d'accès distant en exécutant:

ssh dist@d6 "bash --login -c 'env'"

Ici, env peut être remplacé par la commande que vous souhaitez.

J'ai des clés autorisées, je n'ai donc pas eu besoin d'un mot de passe pour exécuter la commande ou ssh.

Ian
la source
3

J'ai trouvé une solution différente pour résoudre le problème. Ma préférence personnelle est de créer de nouveaux fichiers de configuration au lieu de modifier ceux existants. De cette façon, je peux plus facilement supprimer les modifications de la configuration par défaut.

Voici le contenu de /etc/profile.d/ssh_login.sh:

#!/bin/sh
if [ "$SSH_CONNECTION" ]; then
    echo "User '$USER' logged in from '${SSH_CONNECTION%% *}'"
    . /etc/environment
fi

En utilisant dropbearà la place de openssh-server(cela devrait également fonctionner avec openssh), la variable SSH_CONNECTION est définie automatiquement lorsque je me connecte à distance. J'ai créé une nouvelle configuration de profil de shell pour détecter les connexions SSH, afficher certaines informations à l'écran et, surtout, charger les paramètres d'environnement global à partir de /etc/environmentpour remplacer les valeurs compilées. Veuillez noter que cela n'affecte que les shells SSH interactifs, pas l'exécution des commandes à distance.

Alternativement , si vous utilisez openssh et que vous souhaitez toujours charger l'environnement global, qu'il s'agisse d'un shell interactif, vous pouvez placer un lien symbolique ~/.ssh/comme ceci:

ln -s /etc/environment ~/.ssh/environment

Ensuite, vous devez activer l' PermitUserEnvironmentoption dans /etc/sshd/sshd_config. Ne faites cela que pour les utilisateurs de confiance, car cela pourrait leur permettre de contourner les restrictions d'accès dans certaines configurations à l'aide de mécanismes tels que LD_PRELOAD. Veuillez consulter man sshd_configpour plus d'informations, en particulier comment utiliser des Matchblocs pour contraindre les options à des utilisateurs / groupes spécifiques.

tachylatus
la source
0

Si vous souhaitez charger le chemin du profil, essayez:

#!/bin/bash -i

en haut du script. De cette façon, le shell est en mode interactif lors de l'exécution du script.

Lorsque bash est invoqué en tant que shell de connexion interactif, ou en tant que shell non interactif avec l'option --login, il lit et exécute d'abord les commandes du fichier / etc / profile, si ce fichier existe. Après avoir lu ce fichier, il recherche ~ / .bash_profile, ~ / .bash_login et ~ / .profile, dans cet ordre, et lit et exécute les commandes à partir du premier qui existe et est lisible. L'option --noprofile peut être utilisée lorsque le shell est démarré pour inhiber ce comportement.

http://linux.die.net/man/1/bash

Adam Brand
la source