Comment définir $ PATH pour que `ssh user @ host command` fonctionne?

129

Je n'arrive pas à définir un nouveau $ PATH tel qu'il soit utilisé lors de l'exécution de commandes via ssh user@host command. J'ai essayé d'ajouter export PATH=$PATH:$HOME/new_pathà ~ / .bashrc et ~ / .profile sur la machine distante, mais l'exécution ssh user@host "echo \$PATH"montre que le changement n'a pas été pris en compte (il montre / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / games). La machine distante exécute Ubuntu 8.04.

Je suis sûr que je pourrais le pirater dans / etc / profile, mais ce n'est pas une solution propre et cela ne fonctionne que lorsque l'on a un accès root.

Denver Gingerich
la source
1
J'ai essayé d'ajouter export PATH=$PATH:$HOME/new_pathà la fois ~ / .bash_login et ~ / .bash_profile (en plus des ~ / .bashrc et ~ / .profile précédemment essayés). Aucun des deux ne fonctionne. Dans les deux cas, j'ai dû créer le fichier.
Denver Gingerich le
Dans mon cas d'utilisation particulier, il n'est pas facile de modifier la commande envoyée à ssh. J'utilise stfufs ( guru-group.fi/too/sw/stfufs ), qui construit la commande ssh elle-même. Je me rends compte que sa méthode n'est pas une bonne solution, mais ce serait bien de la corriger sans modifier stfufs.
Denver Gingerich
Vous pouvez mettre un wrapper ssh à la manière de stfufs, appeler le vrai ssh avec des arguments modifiés, si c'est plus facile
Hasturkun

Réponses:

180

Comme l'a dit grawity, ~ / .bashrc est ce que vous voulez, car il provient de shells non interactifs sans connexion.

Je pense que le problème que vous rencontrez est lié au fichier par défaut Ubuntu ~ / .bashrc. Cela commence généralement par quelque chose comme ceci:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Vous voulez mettre n'importe quoi pour les shells non interactifs avant cette ligne.

singpolyma
la source
1
Oui, j'ai déplacé la export PATH=$PATH:$HOME/new_pathligne ci-dessus et cela a fonctionné. Merci!
Denver Gingerich le
3
.bashrc n'est pas fiable. man bash: "Bash tente de déterminer quand il est exécuté avec son entrée standard connectée à une connexion réseau". Cela fonctionne sur RHEL, mais pas sur Archlinux. J'ai dû éditer / etc / environment pour changer le PATH par défaut
bassin
Vous devriez ajouter une mention de .zshenvpour les utilisateurs de zsh, il m'a fallu un certain temps pour le trouver dans les commentaires sur les autres réponses
Mike
30

Avez-vous un ~/.bash_loginou ~/.bash_profile?

Bash en mode interactif vérifie ces fichiers et utilise le premier existant , dans cet ordre:

  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile

Donc, si vous en avez un ~/.bash_profile, les changements que vous apportez ne ~/.profileseront pas visibles.

Bash en mode non interactif lit parfois le fichier ~/.bashrc(qui est également souvent source à partir des scripts interactifs.) Par "parfois", je veux dire qu'il dépend de la distribution: assez curieusement, il existe une option de compilation pour l'activer . Debian permet la ~/.bashrclecture, contrairement à Arch.

ssh semble utiliser le mode non interactif, cela ~/.bashrcdevrait suffire. Lorsque j'ai des problèmes comme celui-ci, j'ajoute généralement quelques échos pour voir quels fichiers sont en cours d'exécution.

user1686
la source
L'ajout des échos a aidé ... mais je suis toujours à la recherche d'un moyen d'exécuter 'ssh -X remotemachine "xterm"' et d'avoir le chemin complet du système / utilisateur depuis / etc / profile et ~ / home / username / .bash_profile. Si je source les deux fichiers dans la commande, cela fonctionne .. mais c'est moche :).
Jess
Comment savez-vous que "Bash en mode non interactif lit le fichier ~/.bashrc"? Je ne vois pas cette déclaration dans la page de manuel. Merci
nknight
4
Si vous voulez un shell non interactif non connecté à la source ~/.bashrc, il semble que vous deviez en plus définir la variable d'environnement BASH_ENV; voir superuser.com/a/585699/100843 . Pour les shells de connexion non interactifs, vous devrez probablement modifier l'un des trois scripts de démarrage que vous avez mentionnés.
nknight
3
Pour ZSH, le fichier non interactif est:.zshenv
math
2
@math .zshenvest toujours source; peu importe que ce soit interactif ou non.
JoL
19

La documentation ssh dit:

Si la commande est spécifiée, elle est exécutée sur l'hôte distant au lieu d'un shell de connexion.

c'est pourquoi l'ajout aux fichiers bashrc ne fonctionne pas. vous disposez cependant des options suivantes:

  1. Si l' PermitUserEnvironmentoption est définie dans la configuration sshd, vous pouvez ajouter votre paramètre PATH à~/.ssh/environment

  2. ssh remotemachine 'bash -l -c "somecommand"'

Hasturkun
la source
1. Il n'est pas défini dans ma configuration sshd et man sshd_configindique qu'il est désactivé par défaut, il est donc peu probable que cette solution fonctionne pour la plupart des gens. 2. Cela fonctionnerait, mais je ne peux pas facilement modifier la commande envoyée à ssh (voir le deuxième commentaire sur ma question).
Denver Gingerich le
1
1. Ne fonctionne pas comme prévu, car dans ~ / .ssh / environnement, vous ne pouvez pas ajouter de chemins à PATH, car $ PATH ne sera pas résolu.
not2savvy
8

Vous pouvez toujours dire:

ssh remotemachine 'export PATH=wedontneedastinkingpath; echo $PATH'
Chas. Owens
la source
Cette solution ne nécessite aucune modification sur la machine distante, ce qui est une bonne chose.
Ronny Andersson le
2

En plus de la réponse @signpolyma, vous devrez ajouter votre export avant ces lignes

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac
Codage heureux
la source
Je viens de commenter ces lignes dans leur ensemble - trouvées dans ~ / .bashrc dans le bureau Ubuntu 16.04 LTS. Tout ne fonctionne pas. Définissez également PermitUserEnvironment sur yes.
Ernie S
2

J'ai juste eu le même problème moi-même, je l'ai résolu avec:

ssh user@remotehost PATH=\$HOME/bin:\$PATH\; remote-command
Indé
la source