pliki startowe sh przez ssh

10

Mam kilka ważnych poleceń, które muszę wykonać przed uruchomieniem powłoki sh. Jest to wymagane do przekazywania poleceń SSH w poleceniu SSH ( ssh host somecommand) i innych programach uruchamiających polecenia.

W mojej .profilemam to:

ihammerhands@wreckcreations:~> cat .profile
#specific environment and startup programs
export PS1="\u@wreckcreations:\w> "
export PYTHONPATH=~/python/lib/python2.4/site-packages
export PATH=$PATH:~/bin:~/python/bin

Nie udaje się to jednak:

W:\programming\wreckcreations-site\test-hg>ssh name@host echo $PATH
Enter passphrase for key '/home/Owner/.ssh/id_rsa':
/usr/local/bin:/bin:/usr/bin

Zwróć uwagę na brakujące opcje ŚCIEŻKI

Jaka jest właściwa nazwa dla profilu sh? Uwaga: nie mam dostępu do konta root i nie chcę, aby dotyczyło to innych użytkowników. Czy jest na to inny sposób?


EDYCJA: Wydaje się, że /bin/shlinki do bash, co nie jest zaskakujące. Zaskakujące jest to, że mój profil jest nadal ignorowany. Jakieś sugestie?

TheLQ
źródło
1
Nie chcę powtarzać tego, co jest na stronie podręcznika, więc po prostu zajrzyj na stronę podręcznika użytkownika bash w sekcji „ZAPROSZENIE”. Jest blisko szczytu i opisuje wszystko, co musisz wiedzieć.
camh
Możesz spróbować użyć ssh name@host -t echo $PATH.
Gert,
Wyjście @Gert jest takie samo
TheLQ
@camh Czy myślisz, że zadałbym to pytanie, gdybym nie sprawdził już stron podręcznika? Przeczytałem je wiele razy + inne posty, ale nigdy nie mogłem znaleźć odpowiedzi na ten konkretny problem, ponieważ nie jestem pewien, w których komendach ssh i komendach innych programów są wykonywane
TheLQ
1
@TheLQ: Nie znam cię, więc nie wiem, czy sprawdziłbyś stronę podręcznika. Wiedziałem tylko, że odpowiedzi były tam, więc zamiast powtarzać słowo po słowie, wskazałem ci na to. Bardziej szczegółowym wskaźnikiem jest wyszukiwanie nieinteraktywnych powłok, ponieważ taki jest scenariusz ssh. Jeśli coś na stronie podręcznika nie jest jasne, być może możesz zadać bardziej szczegółowe pytanie.
camh

Odpowiedzi:

8

Warto zauważyć, że polecenie, o którym wspominasz w swoim pytaniu

ssh name@host echo $PATH

prawie nigdy się nie przyda. Podstawienie zmiennej dla $ PATH jest wykonywane przez lokalną powłokę i przekazywane do ssh, który wykonuje echo w systemie zdalnym, aby wydrukować zawartość zmiennej ścieżki, gdy została ona rozwinięta w systemie lokalnym. Oto przykład, jak robię coś podobnego między moim komputerem Mac a komputerem z systemem Linux w mojej sieci:

LibMBP:~ will$ echo $PATH
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren echo $PATH
will@warren's password: 
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren 'echo $PATH'
will@warren's password: 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
LibMBP:~ will$ 

Zwróć uwagę, jak musiałem używać cudzysłowów, aby moja lokalna powłoka nie rozwijała zmiennej.

wrosecrans
źródło
W środowisku Windows Cygwin pojedyncze cudzysłowy nic nie robią w Cygwin ani w wierszu polecenia. O dziwo, podwójne cudzysłowy sprawiają, że PATH rozszerza się całkowicie na moją lokalną maszynę w Cygwin. Więc cokolwiek dało mi ssh, nie było moją ścieżką, to było na serwerze
TheLQ,
@TheLQ Pojedyncze cudzysłowy są niezbędne w monicie unixowym (w tym Cygwin), ale nie potrzebujesz żadnych cudzysłowów po znaku zachęty cmd.
Gilles „SO- przestań być zły”
12

~/.profilejest wykonywany tylko przez powłoki logowania. Program, który wywołuje powłokę, decyduje, czy powłoka będzie powłoką logowania (umieszczając -jako pierwszy znak zerowego argumentu w wywołaniu powłoki). Zwykle nie jest wykonywany, gdy logujesz się, aby wykonać określone polecenie.

W szczególności OpenSSH wywołuje powłokę logowania tylko wtedy, gdy nie podano polecenia. Więc jeśli podasz polecenie, ~/.profilenie zostanie odczytane.

OpenSSH pozwala ustawiać zmienne środowiskowe po stronie serwera. To musi być włączone w konfiguracji serwera z PermitUserEnvironmentdyrektywą. Zmienne można ustawić w pliku ~/.ssh/environment. Zakładając, że korzystasz z uwierzytelniania za pomocą klucza publicznego, możesz również ustawić zmienne dla poszczególnych kluczy w ~/.ssh/authorized_keys: dodaj environment="FOO=bar"na początku odpowiedniego wiersza.

Ssh obsługuje również wysyłanie zmiennych środowiskowych. W OpenSSH użyj SendEnvdyrektywy w ~/.ssh/config. Jednak konkretna zmienna środowiskowa musi być włączona z AcceptEnvdyrektywą w konfiguracji serwera, więc może to nie zadziałać.

Jedną rzeczą, która moim zdaniem zawsze działa (co dziwne), o ile korzystasz z uwierzytelniania za pomocą klucza publicznego, to (ab) użycie command=opcji z authorized_keyspliku . Klawisz z commandopcją nadaje się tylko do uruchomienia określonej komendy; ale polecenie w authorized_keyspliku działa ze zmienną środowiskową SSH_ORIGINAL_COMMANDustawioną na polecenie określone przez użytkownika. Ta zmienna jest pusta, jeśli użytkownik nie określił polecenia i dlatego oczekiwał powłoki interaktywnej. Możesz więc użyć czegoś takiego w ~/.ssh/authorized_keys(oczywiście nie będzie to miało zastosowania, jeśli nie użyjesz tego klucza do uwierzytelnienia):

command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa 

Inną możliwością jest napisanie skryptów opakowania na serwerze. Coś takiego jak poniżej ~/bin/ssh-wrapper:

#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"

Następnie wykonaj dowiązania symboliczne do tego skryptu o nazwie rsync , unisonitd karnetów --rsync-path='bin/rsync'na rsynclinii poleceń, i tak dalej do innych programów. Alternatywnie, niektóre polecenia umożliwiają określenie całego fragmentu powłoki, który ma być uruchamiany zdalnie, co pozwala na samodzielne wykonanie polecenia: na przykład możesz użyć rsync --rsync-path='. ~/.profile; rsync'.

Istnieje inna droga, która zależy od tego, czy twoja powłoka logowania jest bash lub zsh. Bash zawsze czyta, ~/.bashrcgdy jest wywoływany przez rshd lub sshd, nawet jeśli nie jest interaktywny (ale nie, jeśli jest wywoływany jako sh). Zsh zawsze czyta ~/.zshenv.

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi
Gilles „SO- przestań być zły”
źródło
Co z poleceniami wykonywanymi przez inne polecenia? W tym przypadku byłyby to haczyki Mercurial. Mercurial musi być na
dobrej
Użyj dowolnej wskazanej przeze mnie techniki, aby Twój profil działał w nieinteraktywnych poleceniach ssh. Jeden z nich ( command=w authorized_keys) działa w sposób przejrzysty. Inne wymagają określonej powłoki lub opcji w konfiguracji serwera ssh. Odpowiednikiem rtęciowym --rsync-pathjest --remotecmd.
Gilles „SO- przestań być zły”
Niektórym może się przydać takie samo pełne command=polecenie, jak w swoim poście superuser.com/a/207262/137762
mforbes 25.04.2013
1

Zwykle po zalogowaniu bash czyta polecenia z:

~ / .bash_profile
~ / .bashrc

Ze strony podręcznika użytkownika bash:

~ / .bash_profile
Osobisty plik inicjujący, wykonywany dla powłok logowania

~ / .bashrc
Indywidualny plik startowy dla powłoki interaktywnej

Alexander Pogrebnyak
źródło
0

Nie mam czasu na przetestowanie tego, ale przeglądając strony podręcznika, które znalazłem:

man bash: Gdy bash jest uruchamiany nieinteraktywnie, aby na przykład uruchomić skrypt powłoki, szuka w środowisku zmiennej BASH_ENV, rozwija swoją wartość, jeśli się tam pojawia, i używa wartości rozwiniętej jako nazwy pliku przeczytaj i wykonaj. Bash zachowuje się tak, jakby wykonano następujące polecenie: if [-n "$ BASH_ENV"]; następnie . „$ BASH_ENV”; fi, ale wartość zmiennej PATH nie jest używana do wyszukiwania nazwy pliku.

man ssh: ~ / .ssh / environment Zawiera dodatkowe definicje zmiennych środowiskowych; patrz ŚRODOWISKO powyżej.

Ta kombinacja sugeruje, jak możesz ssh wykonać .profile

Niestety mój serwer ma PermitUserEnvironment do domyślnej wartości no, co sprawia, że ​​to nie działa dla mnie (i jak powiedziałem, nie mam czasu na zabawę z tym więcej).

Kasterma
źródło
Nawet jeśli mógłbym zmusić SSH do pracy poprzez jawne podanie niektórych zmiennych środowiskowych w środowisku, to nadal nie pomoże naprawić mojego profilu, gdy inne programy wywołują polecenia
TheLQ
W twoim przykładzie wszystko, co robisz, to ustawianie zmiennych środowiskowych. Co jeszcze chcesz zrobić?
kasterma
0

(usunięty ... może mieć tylko jedno hiperłącze jako nowy użytkownik ~)

Aktualizacja

Przepraszam, nie widziałem, że chodzi o sesję nieinteraktywną, do której powyższy link nie ma zastosowania.

Kiedy Bash uruchamia się w trybie kompatybilności SH, stara się naśladować zachowanie startowe historycznych wersji sh tak dokładnie, jak to możliwe, przy jednoczesnym zachowaniu zgodności ze standardem POSIX®. Odczytane pliki profilu to / etc / profile i ~ / .profile, jeśli jest to powłoka logowania.

Jeśli nie jest to powłoka logowania, zmienna środowiskowa ENV jest oceniana, a wynikowa nazwa pliku jest przyjmowana jako nazwa pliku startowego.

Po odczytaniu plików startowych Bash wchodzi w tryb zgodności z POSIX (r) (do uruchamiania, a nie do uruchamiania!).

Bash rozpoczyna się w trybie zgodności sh, gdy:

  • podstawową nazwą pliku w argv [0] jest sh (:!: Uwaga drodzy, uber-sprytni użytkownicy Linuksa ... / bin / sh może być połączony z / bin / bash, ale to nie znaczy, że działa jak / bin / bash :! :)

Pytanie brzmi: dlaczego go nie wykonuje, mimo że twoja powłoka jest uruchomiona w ten sposób?

Źródło


źródło
Patrzyłem, ale jak powiedziałem camh, nie wiem, na którym etapie są wykonywane polecenia ssh i inne polecenia programu. Przeczytałem już wiele razy strony podręcznika man i inne przewodniki
TheLQ