Warum kann Bash den Befehl nicht finden, obwohl $ PATH richtig angegeben ist?

9

Ich gebe den Pfad zu meinem Befehl in der Datei / etc / profile an :

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

Mein Befehl befindet sich in:

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

Wenn ich also eine "echo $ PATH" -Ausgabe durchführe, sieht es so aus:

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

Und alles ist in Ordnung, aber wenn ich versuche, meinen Befehl über SSH zu starten, wird folgende Fehlermeldung angezeigt:

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

Aber mein Weg ist immer noch vorhanden:

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

Bitte erläutern Sie mir, warum Bash ydisplay während der SSH-Sitzung nicht finden kann und wie SSH ordnungsgemäß konfiguriert wird, um dieses Problem zu vermeiden.

Darüber hinaus funktioniert alles korrekt, wenn ich im aktuellen Benutzer $ PATH in der lokalen Datei .bashrc angegeben habe. Ich möchte jedoch nur eine Datei ändern und stattdessen viele Dateien für jeden Benutzer angeben. Deshalb frage ich.

SIGSEGV
quelle
1
funktioniert nur Laufen ydisplay? funktioniert ssh 127.0.0.1 /usr/app/cpn/bin/ydisplay?
Bananguin
@ user1129682 Ja, ydisplay mit vollständig angegebenem Namen funktioniert und nur ydisplay funktioniert
SIGSEGV
Wenn Sie nicht protokolliert sind (Sie haben keine Remotesitzung), sondern nur einen Befehl remote senden, haben Sie keinen Zugriff auf Umgebungsvariablen auf die gleiche Weise, da Ihre .bashrc / .profile-Dateien nicht ausgeführt werden. Dies ist der Grund, da sie für das Festlegen von Variablen für die aktuelle Sitzung verantwortlich sind.
Mnmnc
14
Nur eine Randnotiz: ssh 127.0.0.1 echo $PATHTut nicht das, was Sie vielleicht denken: Die Shell erweitert $ PATH, bevor ssh überhaupt ausgeführt wird, sodass nichts bewiesen oder widerlegt wird.
Ulrich Schwarz
2
Diese Stackoverflow-Frage könnte hilfreich sein
bsd

Antworten:

5

tl; dr

Laufende ssh 127.0.0.1 ydisplayQuellen ~/.bashrcanstatt /etc/profile. Ändern Sie ~/.bashrcstattdessen Ihren Pfad .

Einzelheiten

Es wird nur /etc/profilegelesen, wenn Ihre Shell eine "Login-Shell" ist.

Aus dem Bash-Referenzhandbuch :

Wenn bash als Login-Shell aufgerufen wird, ... liest es zuerst Befehle aus der Datei / etc / profile und führt sie aus

Aber wenn Sie ausführen ssh 127.0.0.1 ydisplay, bashwird nicht als Login-Shell gestartet. Es wird jedoch eine andere Startdatei gelesen. Das Bash-Referenzhandbuch lautet:

wenn ... ausgeführt von ... sshd. ... liest und führt Befehle von aus~/.bashrc

Sie sollten also Ihre PATHEinstellungen vornehmen ~/.bashrc.

Auf den meisten Systemen ~/.bash_profileQuellen ~/.bashrc, so dass Sie Ihre Einstellungen nur in, ~/.bashrcanstatt in beiden Dateien zu speichern.

Es gibt keine Standardmethode die Einstellung für alle Benutzer zu ändern, aber die meisten Systeme haben ein /etc/bashrc, /etc/bash.bashrcoder ähnliches.

Andernfalls richten Sie pam_envdie PATHEinstellung ein und setzen sie ein /etc/environment.

Siehe auch:

Mikel
quelle
1

In der Vergangenheit wurden die Profildateien ( /etc/profileund ~/.profile) beim Anmelden (auf der Textkonsole, was noch?) Aufgerufen und dienten vielen Zwecken:

  • Legen Sie Umgebungsvariablen und andere Parameter (z. B. umask) für die Sitzung fest.
  • Führen Sie zu Beginn der Sitzung zusätzliche Programme aus (z. B. E-Mail-Benachrichtigung).
  • Führen Sie das Programm für die Sitzung aus, falls es sich von der Shell unterscheidet (z. B. eine andere Shell oder ein anderes X-Fenster).
  • Stellen Sie die Terminalparameter ein (z stty. B. ).
  • Stellen Sie Shell-Parameter ein (z. B. Aliase).

Alle diese Zwecke wurden erst später als getrennt identifiziert. Da die Profilskripte möglicherweise Dinge tun, die nur in einer interaktiven Sitzung sinnvoll sind (Terminalinteraktion, Starten anderer Programme), haben die Marken von rsh bei Einführung des Remote-Shell-Aufrufs ( rsh ) beschlossen, die Remote-Shell nicht als Anmeldeshell aufzurufen. damit die Profilskripte nicht ausgeführt werden. (Einige Versionen von rshdhaben die Option, die Remote-Shell als Anmeldeshell auszuführen.) Ssh hat dieses Verhalten kopiert, um als Drop-In-Ersatz für rsh zu fungieren.

Wenn Sie Ihre Profilskripte ausführen lassen möchten, können Sie sie explizit aufrufen.

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

Beachten Sie den Befehl .zum Laden der Profilskripte in die Shell: Es handelt sich um Befehle, die in dieser Shell ausgeführt werden sollen, nicht um ein externes Programm.

Wenn Sie eine Umgebungsvariable global für alle Benutzer festlegen möchten, gibt es auf vielen Systemen eine andere Methode: Anstatt sie zu definieren /etc/profile, definieren Sie sie in /etc/environment. Diese Datei wird durch das pam_envModul gelesen . Die meisten Linux-Distributionen sind zum Lesen eingerichtet.

Wenn Ihre Login-Shell bash ist, gibt es eine weitere Möglichkeit. Normalerweise sollten Sie keine Umgebungsvariablen festlegen.bashrc (da diese in X-Sitzungen nur festgelegt werden, wenn Sie ein Terminal mit einer interaktiven Shell durchlaufen, da sie nicht festgelegt werden, wenn Sie sich interaktiv an einer Textkonsole oder darüber anmelden ssh, weil sie benutzerdefinierte Einstellungen überschreiben, wenn Sie eine Shell in einem anderen Programm aufrufen). Bash hat jedoch eine seltsame Funktion, die ich nie verstanden habe: Es liest sich ~/.bashrcunter zwei nicht zusammenhängenden Umständen:

  • in interaktiven Shells, die keine Login-Shells sind;
  • in nicht interaktiven Shells, die keine Login-Shells sind, wenn bash glaubt, dass sie von rshdoder aufgerufen wurden sshd.

Wenn Sie einen Befehl über ssh ausführen, befinden Sie sich im zweiten Fall. Sie können veranlassen, dass Ihr Profil durch Lesen /etc/profileund .profilevon gelesen wird .bashrc. Fügen Sie den folgenden Code in Ihren ein ~/.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 - hör auf böse zu sein'
quelle