Dlaczego Bash nie może znaleźć polecenia, nawet jeśli $ PATH jest poprawnie określony?

9

Podaję ścieżkę do mojego polecenia w pliku / etc / profile :

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

Moje polecenie znajduje się w:

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

Kiedy więc wykonuję „echo $ PATH”, wyjście wygląda następująco:

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

I wszystko jest w porządku, ale kiedy próbuję uruchomić polecenie za pośrednictwem SSH, pojawia się błąd:

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

Ale moja ścieżka jest wciąż obecna:

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

Wyjaśnij mi, dlaczego Bash nie może znaleźć wyświetlania podczas sesji SSH i jak prawidłowo skonfigurować SSH, aby uniknąć tego problemu.

Co więcej, jeśli podam $ PATH w lokalnym pliku .bashrc w bieżącym użytkowniku, wszystko działa poprawnie. Ale chcę zmodyfikować tylko jeden plik, zamiast tego określając wiele plików dla każdego użytkownika. Właśnie dlatego pytam.

SIGSEGV
źródło
1
czy właśnie działa ydisplay? nie ssh 127.0.0.1 /usr/app/cpn/bin/ydisplaydziała?
Bananguin,
@ user1129682 Tak, ydisplay z pełną podaną nazwą działa i po prostu ydisplay działa
SIGSEGV,
Gdy nie jesteś zalogowany (nie masz sesji zdalnej), ale wysyłasz komendę tylko zdalnie, nie masz dostępu do zmiennych środowiskowych w ten sam sposób, ponieważ pliki .bashrc / .profile nie są wykonywane. Jest to powód, ponieważ są oni odpowiedzialni za ustawianie zmiennych dla bieżącej sesji.
mnmnc
14
Na marginesie: ssh 127.0.0.1 echo $PATHnie robi tego, co mogłoby się wydawać: powłoka rozwija $ PATH, zanim ssh zostanie nawet wykonany, więc to niczego nie dowodzi ani nie obala.
Ulrich Schwarz,
2
to pytanie dotyczące
przepełnienia stosu

Odpowiedzi:

5

tl; dr

Uruchamianie ssh 127.0.0.1 ydisplayźródeł ~/.bashrczamiast /etc/profile. ~/.bashrcZamiast tego zmień swoją ścieżkę .

Detale

/etc/profileOdczytywany jest tylko czas, gdy twoja powłoka jest „powłoką logowania”.

Z podręcznika użytkownika Bash :

Gdy bash jest wywoływany jako powłoka logowania, ... najpierw czyta i wykonuje polecenia z pliku / etc / profile

Ale po uruchomieniu ssh 127.0.0.1 ydisplay, bashnie jest uruchomiona jako powłoka logowania. Jednak odczytuje inny plik startowy. Instrukcja Bash referencyjny mówi:

kiedy ... wykonane przez ... sshd. ... odczytuje i wykonuje polecenia z~/.bashrc

Więc powinieneś wprowadzić swoje PATHustawienia ~/.bashrc.

W większości systemów, ~/.bash_profileźródeł ~/.bashrc, więc możesz umieścić swoje ustawienia tylko ~/.bashrczamiast umieszczania ich w obu plikach.

Nie ma standardowy sposób, aby zmienić ustawienia dla wszystkich użytkowników, ale większość systemów mają /etc/bashrc, /etc/bash.bashrclub podobny.

W przeciwnym razie skonfiguruj pam_envi wprowadź PATHustawienie /etc/environment.

Zobacz też:

Mikel
źródło
1

Historycznie pliki profilu ( /etc/profilei ~/.profile) były wywoływane po zalogowaniu (w konsoli tekstowej, co jeszcze?) I służyły wielu celom:

  • Ustaw zmienne środowiskowe i inne parametry (np. Umask) dla sesji.
  • Uruchom dodatkowe programy na początku sesji (np. Powiadomienie e-mail).
  • Uruchom program dla sesji, jeśli różni się od powłoki (np. Innej powłoki lub X Window).
  • Ustaw parametry terminala (np stty.).
  • Ustaw parametry powłoki (np. Aliasy).

Wszystkie te cele zostały zidentyfikowane jako odrębne dopiero później. Ponieważ skrypty profilowe mogą robić rzeczy, które mają sens tylko w sesji interaktywnej (interakcja terminalu, uruchamianie innych programów), kiedy wprowadzono zdalne wywoływanie powłoki ( rsh ), marki rsh zdecydowały, że nie będą wywoływać powłoki zdalnej jako powłoki logowania, aby skrypty profilu nie były wykonywane. (Niektóre wersje rshdmają opcję uruchamiania powłoki zdalnej jako powłoki logowania.) Ssh skopiowało to zachowanie, aby zastąpić rsh.

Jeśli chcesz, aby skrypty profilowe były wykonywane, możesz je wywołać jawnie.

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

Zanotuj polecenie .załadowania skryptów profilu wewnątrz powłoki: są to polecenia do wykonania w tej powłoce, a nie program zewnętrzny.

Jeśli chcesz ustawić zmienną środowiskową globalnie dla wszystkich użytkowników, w wielu systemach istnieje inna metoda: zamiast definiować ją w /etc/profile, zdefiniuj ją w /etc/environment. Ten plik jest czytany przez pam_envmoduł; większość dystrybucji Linuksa jest skonfigurowana do czytania.

Jeśli twoja powłoka logowania jest bash, istnieje kolejna możliwość. Zwykle nie należy ustawiać zmiennych środowiskowych w.bashrc (ponieważ nie zostaną one ustawione w sesjach X, chyba że przejdziesz przez terminal z interaktywną powłoką, ponieważ nie zostaną one ustawione, jeśli zalogujesz się interaktywnie w konsoli tekstowej lub ssh, ponieważ zastąpią ustawienia niestandardowe, jeśli wywołasz powłokę w innym programie). Jednak bash ma dziwną funkcję, której nigdy nie rozumiałem: czyta się ~/.bashrcw dwóch niepowiązanych okolicznościach:

  • w interaktywnych powłokach, które nie są powłokami logowania;
  • w nieinteraktywnych powłokach, które nie są powłokami logowania, jeśli bash uważa, że ​​zostało wywołane przez rshdlub sshd.

Gdy uruchomisz polecenie przez ssh, znajdziesz się w drugim przypadku. Możesz ustalić, że Twój profil będzie czytany przez czytanie /etc/profilei .profileod .bashrc. Dołącz następujący kod do ~/.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- przestań być zły”
źródło