sh Startdateien über ssh

10

Ich habe einige wichtige Befehle, die ich ausführen muss, bevor eine sh-Shell gestartet wird. Dies ist erforderlich, um SSH-Befehle im SSH-Befehl ( ssh host somecommand) und in anderen Programmen, die Befehle ausführen, zu übergeben.

In meinem habe .profileich folgendes:

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

Dies schlägt jedoch fehl:

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

Beachten Sie die fehlenden PATH-Optionen

Wie lautet der richtige Name für das sh-Profil? Hinweis: Ich habe keinen Root-Zugriff und möchte nicht, dass dies auf andere Benutzer angewendet wird. Gibt es einen anderen Weg, dies zu tun?


EDIT: Es scheint /bin/shLinks zu bash, was nicht überraschend ist. Überraschend ist, dass mein Profil immer noch ignoriert wird. Irgendwelche Vorschläge?

TheLQ
quelle
1
Ich möchte nicht wiederholen, was auf der Manpage steht. Schauen Sie also einfach in die Bash-Manpage unter dem Abschnitt 'INVOCATION'. Es befindet sich ganz oben und beschreibt alles, was Sie wissen müssen.
Camh
Sie könnten versuchen, zu verwenden ssh name@host -t echo $PATH.
Gert
@Gert Ausgabe ist die gleiche
TheLQ
@camh Glaubst du, ich würde diese Frage stellen, wenn ich die Manpages nicht schon überprüft hätte? Ich habe sie oft gelesen + andere Beiträge, konnte aber nie eine Antwort auf dieses spezielle Problem finden, da ich nicht sicher bin, in welcher Stufe ssh-Befehle und die Befehle anderer Programme ausgeführt werden
TheLQ
1
@TheLQ: Ich kenne dich nicht, also weiß ich nicht, ob du die Manpage überprüfen würdest. Ich wusste nur, dass die Antworten genau dort waren. Anstatt sie Wort für Wort zu wiederholen, habe ich Sie darauf hingewiesen. Ein spezifischerer Zeiger ist das Nachschlagen nicht interaktiver Shells, da dies Ihr SSH-Szenario ist. Wenn etwas in der Manpage nicht klar ist, können Sie vielleicht eine spezifischere Frage stellen.
Camh

Antworten:

8

Es scheint erwähnenswert, dass der Befehl, den Sie in Ihrer Frage erwähnen

ssh name@host echo $PATH

wird so ziemlich nie nützlich sein. Die Variablensubstitution für $ PATH wird von Ihrer lokalen Shell durchgeführt und an ssh übergeben, das das Echo auf dem Remote-System ausführt, um den Inhalt der Pfadvariablen zu drucken, wie es auf Ihrem lokalen System erweitert wurde. Hier ist ein Beispiel dafür, wie ich etwas Ähnliches zwischen meinem Mac und einem Linux-Computer in meinem Netzwerk mache:

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$ 

Beachten Sie, wie ich Anführungszeichen verwenden musste, um zu verhindern, dass meine lokale Shell die Variable erweitert.

Wrosecrans
quelle
In Windows Cygwin landen einfache Anführungszeichen nichts in Cygwin oder der Eingabeaufforderung. Seltsamerweise erweitern doppelte Anführungszeichen den PATH vollständig auf meinen lokalen Computer in Cygwin. Also, was auch immer ssh mir gab, war nicht mein Weg, es war der des Servers
TheLQ
@TheLQ Die einfachen Anführungszeichen sind an einer Unix-Eingabeaufforderung (einschließlich Cygwin) erforderlich, an einer cmd-Eingabeaufforderung benötigen Sie jedoch keine Anführungszeichen.
Gilles 'SO - hör auf böse zu sein'
12

~/.profilewird nur von Login-Shells ausgeführt. Das Programm, das die Shell aufruft, entscheidet, ob die Shell eine Anmeldeshell ist (indem a -als erstes Zeichen des nullten Arguments in den Shell-Aufruf eingefügt wird). Es wird normalerweise nicht ausgeführt, wenn Sie sich anmelden, um einen bestimmten Befehl auszuführen.

Insbesondere OpenSSH ruft eine Login-Shell nur auf, wenn Sie keinen Befehl angeben. Wenn Sie also einen Befehl angeben, ~/.profilewird dieser nicht gelesen.

OpenSSH ermöglicht das Festlegen von Umgebungsvariablen auf der Serverseite. Dies muss in der Serverkonfiguration mit der PermitUserEnvironmentDirektive aktiviert werden . Die Variablen können in der Datei festgelegt werden ~/.ssh/environment. Angenommen, Sie verwenden die Authentifizierung mit öffentlichem Schlüssel, können Sie auch Variablen pro Schlüssel in ~/.ssh/authorized_keys: add environment="FOO=bar"am Anfang der entsprechenden Zeile festlegen .

Ssh unterstützt auch das Senden von Umgebungsvariablen. Verwenden Sie in OpenSSH die SendEnvDirektive in ~/.ssh/config. Die spezifische Umgebungsvariable muss jedoch mit einer AcceptEnvAnweisung in der Serverkonfiguration aktiviert werden, sodass dies für Sie möglicherweise nicht funktioniert.

Eine Sache, die meiner Meinung nach immer funktioniert (seltsamerweise), solange Sie die Authentifizierung mit öffentlichem Schlüssel verwenden, ist die (ab) Verwendung der command=Option in der authorized_keysDatei . Ein Schlüssel mit einer commandOption ist nur zum Ausführen des angegebenen Befehls geeignet. Der Befehl in der authorized_keysDatei wird jedoch mit der Umgebungsvariablen ausgeführt, SSH_ORIGINAL_COMMANDdie auf den vom Benutzer angegebenen Befehl festgelegt ist. Diese Variable ist leer, wenn der Benutzer keinen Befehl angegeben hat und daher eine interaktive Shell erwartet. Sie können also so etwas in verwenden ~/.ssh/authorized_keys(dies gilt natürlich nicht, wenn Sie diesen Schlüssel nicht zur Authentifizierung verwenden):

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

Eine andere Möglichkeit besteht darin, Wrapper-Skripte auf den Server zu schreiben. So etwas wie das Folgende in ~/bin/ssh-wrapper:

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

Dann machen Sie symbolische Links zu diesem Skript aufgerufen rsync, unisonusw. Pass --rsync-path='bin/rsync'auf der rsyncKommandozeile, und so weiter für andere Programme. Alternativ können Sie mit einigen Befehlen ein ganzes Shell-Snippet angeben, das remote ausgeführt werden soll. Auf diese Weise können Sie den Befehl in sich geschlossen machen. Beispielsweise können Sie ihn mit rsync verwenden --rsync-path='. ~/.profile; rsync'.

Es gibt noch eine andere Möglichkeit, die davon abhängt, ob Ihre Login-Shell bash oder zsh ist. Bash liest immer, ~/.bashrcwenn es von rshd oder sshd aufgerufen wird, auch wenn es nicht interaktiv ist (aber nicht, wenn es als aufgerufen wird sh). Zsh liest immer ~/.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 - hör auf böse zu sein'
quelle
Was ist mit Befehlen, die andere Befehle ausführen? In diesem Fall wären es Mercurial-Haken. Mercurial muss auf dem Weg sein, damit der Haken überhaupt daran denkt zu arbeiten
TheLQ
Verwenden Sie eine der von mir angegebenen Techniken, um Ihr Profil in nicht interaktiven ssh-Befehlen auszuführen. Einer von ihnen ( command=in authorized_keys) arbeitet transparent. Andere erfordern eine bestimmte Shell oder Optionen in der SSH-Serverkonfiguration. Das Mercurial-Äquivalent von --rsync-pathist --remotecmd.
Gilles 'SO - hör auf böse zu sein'
Es könnte sinnvoll sein, einige den gleichen voll schließen command=Befehl wie in Ihrem Beitrag superuser.com/a/207262/137762
mforbes
1

Normalerweise liest bash beim Anmelden Befehle von:

~ / .bash_profile
~ / .bashrc

Von der Bash-Manpage:

~ / .bash_profile
Die persönliche Initialisierungsdatei, die für Login-Shells ausgeführt wird

~ / .bashrc
Die individuelle Startdatei für die interaktive Shell

Alexander Pogrebnyak
quelle
0

Ich habe keine Zeit mehr, dies zu testen, schaue mir aber die Manpages an, die ich gefunden habe:

man bash: Wenn bash nicht interaktiv gestartet wird, um beispielsweise ein Shell-Skript auszuführen, sucht es in der Umgebung nach der Variablen BASH_ENV, erweitert ihren Wert, wenn er dort angezeigt wird, und verwendet den erweiterten Wert als Namen einer Datei für lesen und ausführen. Bash verhält sich so, als ob der folgende Befehl ausgeführt würde: if [-n "$ BASH_ENV"]; dann . "$ BASH_ENV"; fi aber der Wert der PATH-Variablen wird nicht verwendet, um nach dem Dateinamen zu suchen.

man ssh: ~ / .ssh / environment Enthält zusätzliche Definitionen für Umgebungsvariablen; siehe UMWELT oben.

Die Kombination schlägt vor, wie ssh Ihr .profile ausführen kann

Leider hat mein Server PermitUserEnvironment auf den Standardwert no, was dazu führt, dass dies bei mir nicht funktioniert (und wie gesagt, ich habe nicht die Zeit, mehr damit zu spielen).

Kasterma
quelle
Selbst wenn ich SSH durch explizite Angabe einiger Umgebungsvariablen in der Umgebung zum
Laufen bringen könnte,
In Ihrem Beispiel setzen Sie lediglich Umgebungsvariablen. Was möchten Sie sonst noch tun?
Kasterma
0

(entfernt ... kann nur einen Hyperlink als neuen Benutzer haben ~)

Aktualisieren

Entschuldigung, ich habe nicht gesehen, dass es sich um eine nicht interaktive Sitzung handelt, für die der obige Link nicht gilt.

Wenn Bash im SH-Kompatibilitätsmodus gestartet wird, wird versucht, das Startverhalten historischer Versionen von sh so genau wie möglich nachzuahmen und dabei auch dem POSIX®-Standard zu entsprechen. Die gelesenen Profildateien sind / etc / profile und ~ / .profile, wenn es sich um eine Login-Shell handelt.

Wenn es sich nicht um eine Anmeldeshell handelt, wird die Umgebungsvariable ENV ausgewertet und der resultierende Dateiname als Name der Startdatei verwendet.

Nachdem die Startdateien gelesen wurden, wechselt Bash in den POSIX (r) -Kompatibilitätsmodus (zum Ausführen, nicht zum Starten!).

Bash startet im sh-Kompatibilitätsmodus, wenn:

  • Der Basisdateiname in argv [0] ist sh (:!: Achtung, liebe, überaus clevere Linux-Benutzer ... / bin / sh ist möglicherweise mit / bin / bash verknüpft, aber das bedeutet nicht, dass es sich wie / bin / bash verhält :! :)

Die Frage ist also, warum es nicht ausgeführt wird, obwohl Ihre Shell so gestartet wurde.

Quelle


quelle
Ich habe nachgesehen, aber wie ich Camh sagte, weiß ich nicht, in welcher Phase SSH-Befehle und andere Programmbefehle ausgeführt werden. Ich habe die Manpages und andere Anleitungen bereits viele Male gelesen
TheLQ