Pourquoi Bash est-il incapable de trouver la commande même si $ PATH est spécifié correctement?

9

Je spécifie le chemin d'accès à ma commande dans le fichier / etc / profile :

export PATH=$PATH:/usr/app/cpn/bin

Ma commande est située dans:

$ which ydisplay 
/usr/app/cpn/bin/ydisplay

Ainsi, lorsque j'exécute la sortie "echo $ PATH", cela ressemble à:

$ echo $PATH
...:/usr/app/cpn/bin

Et tout va bien, mais lorsque j'essaie de lancer ma commande via SSH, j'obtiens une erreur:

$ ssh 127.0.0.1 ydisplay
$ bash: ydisplay: command not found

Mais mon chemin est toujours présent:

$ ssh 127.0.0.1 echo $PATH
...:/usr/app/cpn/bin

Veuillez m'expliquer pourquoi Bash n'a pas pu trouver ydisplay pendant la session SSH et comment configurer correctement SSH pour éviter ce problème.

De plus, si je spécifie $ PATH dans le fichier local .bashrc dans l'utilisateur actuel, tout fonctionne correctement. Mais je veux modifier un seul fichier au lieu de spécifier un grand nombre de fichiers pour chaque utilisateur. C'est pourquoi je demande.

SIGSEGV
la source
1
fonctionne juste courir ydisplay? ça ssh 127.0.0.1 /usr/app/cpn/bin/ydisplaymarche?
Bananguin
@ user1129682 Oui, ydisplay avec le nom complet spécifié fonctionne et seulement ydisplay fonctionne
SIGSEGV
Lorsque vous n'êtes pas connecté (vous n'avez pas de session distante) mais qu'envoyant uniquement une commande à distance, vous n'avez pas accès aux variables d'environnement de la même manière car vos fichiers .bashrc / .profile ne sont pas exécutés. C'est la raison car ils sont responsables de la définition des variables pour la session en cours.
mnmnc
14
Juste une remarque: ssh 127.0.0.1 echo $PATHne fait pas ce que vous pourriez penser qu'il fait: la coquille se développe $ PATH avant ssh est même exécuté, de sorte que cela ne prouve pas ou quoi que ce soit réfuter.
Ulrich Schwarz
2
cette question de stackoverflow pourrait être d'une certaine aide
bsd

Réponses:

5

tl; dr

Exécuter des ssh 127.0.0.1 ydisplaysources ~/.bashrcplutôt que /etc/profile. Modifiez votre chemin d'accès à la ~/.bashrcplace.

détails

La seule heure de /etc/profilelecture est lorsque votre shell est un "shell de connexion".

Dans le manuel de référence de Bash :

Quand bash est invoqué en tant que shell de connexion, ... il lit et exécute d'abord les commandes du fichier / etc / profile

Mais lorsque vous exécutez ssh 127.0.0.1 ydisplay, bashn'est pas démarré en tant que shell de connexion. Pourtant, il lit un fichier de démarrage différent. Le manuel de référence de Bash dit:

quand ... exécuté par ... sshd. ... il lit et exécute les commandes de~/.bashrc

Vous devez donc mettre vos PATHparamètres ~/.bashrc.

Sur la plupart des systèmes, ~/.bash_profilesources ~/.bashrc, vous ne pouvez donc mettre vos paramètres que dans ~/.bashrcplutôt que de les mettre dans les deux fichiers.

Il n'y a aucun moyen standard pour modifier le paramètre pour tous les utilisateurs, mais la plupart des systèmes ont un /etc/bashrc, /etc/bash.bashrcou similaire.

À défaut, configurez pam_envet PATHdéfinissez le paramètre /etc/environment.

Voir également:

Mikel
la source
1

Historiquement, les fichiers de profil ( /etc/profileet ~/.profile) ont été invoqués lorsque vous vous êtes connecté (sur la console texte, quoi d'autre?) Et ont servi à de nombreuses fins:

  • Définissez les variables d'environnement et d'autres paramètres (par exemple umask) pour la session.
  • Exécutez des programmes supplémentaires au début de la session (par exemple, notification par e-mail).
  • Exécutez le programme pour la session, s'il est différent du shell (par exemple un autre shell ou X Window).
  • Définissez les paramètres du terminal (par exemple stty).
  • Définissez les paramètres du shell (par exemple les alias).

Tous ces objectifs n'ont été identifiés comme séparés que plus tard. Parce que les scripts de profil peuvent faire des choses qui n'ont de sens que dans une session interactive (interaction de terminal, démarrer d'autres programmes), lorsque l'invocation du shell distant ( rsh ) a été introduite, la marque de rsh a décidé de ne pas appeler le shell distant en tant que shell de connexion, afin que les scripts de profil ne soient pas exécutés. (Certaines versions de rshdont une option pour exécuter le shell distant en tant que shell de connexion.) Ssh a copié ce comportement afin de remplacer directement rsh.

Si vous souhaitez exécuter vos scripts de profil, vous pouvez les invoquer explicitement.

ssh 127.0.0.1 '. /etc/profile; . ~/.profile; ydisplay'

Notez la commande .pour charger les scripts de profil à l'intérieur du shell: ce sont des commandes à exécuter à l'intérieur de ce shell, pas un programme externe.

Si vous souhaitez définir une variable d'environnement globalement pour tous les utilisateurs, il existe une autre méthode sur de nombreux systèmes: au lieu de la définir dans /etc/profile, définissez-la dans /etc/environment. Ce fichier est lu dans le pam_envmodule; la plupart des distributions Linux sont configurées pour le lire.

Si votre shell de connexion est bash, il existe une autre possibilité. Normalement, vous ne devez pas définir de variables d'environnement dans.bashrc (car elles ne seront pas définies dans les sessions X, sauf si vous passez par un terminal avec un shell interactif, car elles ne seront pas définies si vous vous connectez de manière interactive sur une console de texte ou sur ssh, car ils remplaceront les paramètres personnalisés si vous appelez un shell dans un autre programme). Cependant, bash a une caractéristique étrange que je n'ai jamais comprise: il se lit ~/.bashrcdans deux circonstances indépendantes:

  • dans des shells interactifs qui ne sont pas des shells de connexion;
  • dans des shells non interactifs qui ne sont pas des shells de connexion, si bash pense qu'il a été invoqué par rshdou sshd.

Lorsque vous exécutez une commande sur ssh, vous êtes dans le deuxième cas. Vous pouvez faire en sorte que votre profil soit lu par lecture /etc/profileet à .profilepartir de .bashrc. Incluez le code suivant dans votre ~/.bashrc:

case $- in
  *i*) :;; # this is an interactive shell, fine
  *) # This is not an interactive shell! This must be a non-interactive remote shell session.
    . /etc/profile; . ~/.profile
    return;;
esac
Gilles 'SO- arrête d'être méchant'
la source