2008-10-19 11 views
172

Ich habe einen Befehl, der fein läuft, wenn ich auf eine Maschine ssh und führen Sie es, aber nicht, wenn ich versuche, es zu betreiben einen Remote-Befehl ssh verwenden wie:Warum erhält ein SSH-Remote-Befehl weniger Umgebungsvariablen als wenn er manuell ausgeführt wird?

ssh [email protected] <command> 

die Ausgabe von „env“, beide unter Verwendung Vergleich Methoden ergeben sich in verschiedenen Umgebungen. Wenn ich manuell an der Maschine anmelden und env laufen lasse, erhalte ich dann mehr Umwelt viel Variablen, wenn ich laufen:

ssh [email protected] "env" 

Jede Idee, warum?

+8

Warum genau ist diese Frage als Off-Thema geschlossen? – jottr

+8

Wahrscheinlich, weil es nicht programmiert ist. Es sollte zu Super User verschoben worden sein, anstatt geschlossen zu sein. –

Antwort

128

Es gibt verschiedene Arten von Schalen. Die SSH-Befehlsausführungsshell ist eine nicht interaktive Shell, während Ihre normale Shell entweder eine Login-Shell oder eine interaktive Shell ist. Beschreibung folgt von Mann Bash:

 
     A login shell is one whose first character of argument 
     zero is a -, or one started with the --login option. 

     An interactive shell is one started without non-option 
     arguments and without the -c option whose standard input 
     and error are both connected to terminals (as determined 
     by isatty(3)), or one started with the -i option. PS1 is 
     set and $- includes i if bash is interactive, allowing a 
     shell script or a startup file to test this state. 

     The following paragraphs describe how bash executes its 
     startup files. If any of the files exist but cannot be 
     read, bash reports an error. Tildes are expanded in file 
     names as described below under Tilde Expansion in the 
     EXPANSION section. 

     When bash is invoked as an interactive login shell, or as 
     a non-interactive shell with the --login option, it first 
     reads and executes commands from the file /etc/profile, if 
     that file exists. After reading that file, it looks for 
     ~/.bash_profile, ~/.bash_login, and ~/.profile, in that 
     order, and reads and executes commands from the first one 
     that exists and is readable. The --noprofile option may 
     be used when the shell is started to inhibit this behav­ 
     ior. 

     When a login shell exits, bash reads and executes commands 
     from the file ~/.bash_logout, if it exists. 

     When an interactive shell that is not a login shell is 
     started, bash reads and executes commands from ~/.bashrc, 
     if that file exists. This may be inhibited by using the 
     --norc option. The --rcfile file option will force bash 
     to read and execute commands from file instead of 
     ~/.bashrc. 

     When bash is started non-interactively, to run a shell 
     script, for example, it looks for the variable BASH_ENV in 
     the environment, expands its value if it appears there, 
     and uses the expanded value as the name of a file to read 
     and execute. Bash behaves as if the following command 
     were executed: 
       if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi 
     but the value of the PATH variable is not used to search 
     for the file name. 

+6

Große Antwort, das war genau das Problem, die benötigten Umgebungsvariablen befinden sich in/etc/bashrc, die nicht im nicht interaktiven Modus bezogen wird. Das Verschieben nach/etc/profile löste das Problem. Vielen Dank! –

+0

Diese Antwort in nur einer Teillösung. Hier sind einige weitere Informationen: Fügen Sie eine andere Umgebungsvariable (z. B. export SOURCED_SYSTEM_ETC_BASHRC) zu den verschiedenen Dateien hinzu, die abgerufen werden:/etc/profile, etc/bashrc, ~/.profile, ~/.bash_profile, ~/bashrc. Suchen Sie dann nach der eindeutigen Variable in der Jenkins-Ausgabe. In meinem Fall habe ich/etc/bashrc aktualisiert, um 'export SOURCED_SYSTEM_ETC_BASHRC = yes' zu enthalten, und diese Variable wurde im Jenkins-Protokoll für den Knoten angezeigt. Um in meinem Fall Umgebungsvariablen für jenkins-Slaves zu setzen, müssen sie in/etc/bashrc gehen. Jenkins ssh-Login * nur * Quelle/etc/bashrc. –

+0

Korrektur: Ich meinte /etc/bash.bashrc, nicht/etc/bashrc. –

93

Wie Sourcing das Profil vor dem Ausführen des Befehls?

ssh [email protected] "source /etc/profile; /path/script.sh"

Sie könnte es am besten finden, dass ~/.bash_profile zu ändern, ~/.bashrc, oder was auch immer.

(A here (linuxquestions.org))

+1

Hatte dieses Problem, diese Lösung hat super funktioniert. – Sam152

+5

Immer extra Code eingeben, um die Umgebung zu finden, ist lächerlich! – Michael

+4

Man gibt selten diese Art von Dingen ein, normalerweise würde es innerhalb eines Skripts sein, und als solches ist es egal, wie viel "Extra-Code" es gibt, solange es funktioniert: tm: –

47

hatte ich ähnliches Problem, aber am Ende fand ich heraus, dass ~/.bashrc alles war ich brauchte.

jedoch in Ubuntu, ich hatte die Linie zu kommentieren, die Verarbeitung stoppt ~/.bashrc:

#If not running interactively, don't do anything 
[ -z "$PS1" ] && return 
+5

Alternativ können Sie einfach Ihren gesamten "nicht-interaktiven" Code über diese Zeile setzen. – machineghost

+0

schön, ersparte mir viel zeit :) danke –

+0

Das hilft. thx –

4

Ich fand eine einfache Lösung für dieses Problem Quelle hinzuzufügen war/etc/profile auf die oben auf der script.sh-Datei, die ich auf dem Zielsystem ausführen wollte. Auf den Systemen führte dies dazu, dass die Umgebungsvariablen, die von script.sh benötigt wurden, so konfiguriert wurden, als würden sie von einer Login-Shell ausgehen.

In einer der früheren Antworten wurde vorgeschlagen, ~/.bashr_profile usw. zu verwenden. Ich habe nicht viel Zeit damit verbracht, aber das Problem damit ist, wenn Sie ssh zu einem anderen Benutzer auf dem Zielsystem als die Shell auf dem Quellsystem, aus dem Sie sich einloggen, mir erschien, dass dies das Quellsystem verursacht Benutzername, der für das ~ verwendet werden soll.

+0

Perfekt! Schöne One-Line-Lösung für das Problem. – corpico

3

Exportieren Sie die gewünschten Umgebungsvariablen über die Prüfung für eine nicht interaktive Shell in ~/.bashrc.

68

Die Shell-Umgebung wird beim Ausführen des Befehls remote ssh nicht geladen.

vi ~/.ssh/environment 

Das Format ist:

VAR1=VALUE1 
VAR2=VALUE2 

Überprüfen Sie auch sshd Konfiguration für PermitUserEnvironment = yes Option können Sie ssh-Umgebungsdatei bearbeiten.

+1

Perfektion! +100 wenn ich könnte :) – Dexter

+0

VisualGDB war mit dem Fehler "bash: gcc: Befehl nicht gefunden" fehlgeschlagen und diese Lösung hat das behoben. – KalenGi

+0

fantastisch. Ich wünschte, ich hätte das vor Jahren gewusst. – gravitation

Verwandte Themen