Hi,
Ich versuche, die .bashrc-Datei zu laden (dh source /home/ubuntu/.bashrc), wenn ich den run-Befehl von Fab ausfĂŒhre, um einige Umgebungsvariablen hinzuzufĂŒgen und die Pfadvariable zu erweitern:
run('source /home/ubuntu/.bashrc && echo $PFAD')
Das zeigt mir nur:
[[email protected]] aus: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin: /bin:/usr/games:/usr/local/games
anstelle einer viel lÀngeren Liste von Pfaden, die ich sehe, wenn ich mich manuell beim Remote-Server anmelde.
Wie kann ich die .bashrc-Datei richtig in mein Remote-Home-Verzeichnis importieren?
Dankeschön!
Das ist eine Bash-Sache, keine tolle Sache.
Welche Dateien die Bash beim Start als Quelle wÀhlt, kann kompliziert sein http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html und debian/ubuntu (und die meisten Distributionen) haben einige Anpassungen in /etc/profile
und standardmĂ€Ăig ~/.bashrc
.
Die Standard-Shell-Fab ist /bin/bash -l -c
, und -l
macht sie zu einer "Login"-Shell. Ohne die debian/ubuntu-Anpassung ist es fĂŒr eine bash-"login"-Shell möglich, ~/.bash_profile
aber nicht ~/.bashrc
.
Aber unter Ubuntu 16.04 scheint es standardmĂ€Ăig .bashrc
sogar fĂŒr die Login-Shell. Aber Zeilen, die am unteren Rand eines Standard- .bashrc
hinzugefĂŒgt werden, werden nicht verarbeitet, da es am oberen Rand aussteigt, wenn es erkennt, dass es nicht interaktiv ausgefĂŒhrt wird.
Hier habe ich dem Ubuntu-16.04-Standardbenutzer .bashrc
zwei Zeilen hinzugefĂŒgt
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
export VAR1=val1
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
export VAR2=val2
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
...
Hier ist eine Fabfile, mit der ich teste:
from fabric.api import run, env, task
<strong i="23">@task</strong>
def get_myvars():
run("echo VAR1=$VAR1 VAR2=$VAR2")
Die Ergebnisse:
$ fab -H testpy05.ec2.st-av.net get_myvars
[testpy05.ec2.st-av.net] Executing task 'get_myvars'
[testpy05.ec2.st-av.net] run: echo VAR1=$VAR1 VAR2=$VAR2
[testpy05.ec2.st-av.net] out: VAR1=val1 VAR2=
[testpy05.ec2.st-av.net] out:
...
Klingt auf den ersten Blick echt, danke @ploxiln!
Vielen Dank fĂŒr die ausfĂŒhrliche Antwort!
Dies scheint sich vom Standard-SSH-Verhalten zu unterscheiden und war schwer zu debuggen. Wenn ich manuell ssh'd, funktionierte alles gut, wobei Fabric einen anderen PATH-Wert hatte, weil .bash_profile in OSX nicht ausgefĂŒhrt wurde.
@bitprophet Dies kann ein OSX-Fehler sein??
@code-tree Verwenden Sie Stoff 1 oder 2? 1.x verwendet explizite Shell-Wrapper, weshalb es sich vom Standard-OpenSSH-Client unterscheiden wĂŒrde; Version 2 macht kein Wrapping und sollte sich in Bezug auf das, was der sshd in Ihrem Namen ausfĂŒhrt, eher wie der OpenSSH-Client verhalten.
Version 1 hat einige env config-Wert-Optionen zum Ăndern dieses Shell-Wrappers, also sollten Sie versuchen, Flags hinzuzufĂŒgen, wie -i
die IIRC ist Bash fĂŒr "Run interaktiven Modus und source einige zusĂ€tzliche Dateien".
Das ist seltsam, weil ich die Version 2.2.1
. Derzeit muss ich Folgendes tun, damit meine App funktioniert:
c.run('bash -l -c "python3 ./configure.py"')
Wie bei der Installation von Python 3 hat es sich ĂŒber mein .bash_profile
zu PATH hinzugefĂŒgt, das nicht von Fabric ausgefĂŒhrt wird. Ich habe auch keine Ănderungen an der standardmĂ€Ăig eingebauten sshd-Konfiguration vorgenommen.
Das ist dann seltsam, ich muss sehen, ob ich replizieren kann. Ich habe nur eine kurze geistige Spur gemacht, um zu beweisen, was ich meine bezĂŒglich: Fabric 2 macht nichts "Besonderes" bezĂŒglich: sshd-gesteuerte AusfĂŒhrung:
command
command
ssh myserver <command>
@code-tree auch, wenn Sie können, posten Sie bitte einige weitere Details darĂŒber, was Sie genau ausfĂŒhren und andere Umgebungsdetails (Client- und Server-Betriebssystem / -Version usw. usw.).
Klar, ich verwende eine alte OSX-Version als Server. Wenn Sie bestÀtigen können, dass alles auf einem neueren MacOS funktioniert, dann na ja. Aber wenn nicht, dann vielleicht ein Problem mit MacOS als Server im Allgemeinen?
Randnotiz, ich frage mich, ob dies tatsÀchlich ein Fall von Fehldiagnose ist:
Fabric hatte einen anderen PATH-Wert, weil .bash_profile in OSX nicht ausgefĂŒhrt wurde
Könnte dies stattdessen ein Beispiel fĂŒr #1744 sein, bei dem sich Fabric 2 von ssh
in Bezug auf das Rangieren lokaler Umgebungsvariablen in der Leitung unterscheidet? (HĂ€ngt von den genauen env vars ab und ob sie lokal und remote Ă€hnlich sein könnten; @code-tree könnte diese Theorie leicht widerlegen, indem es die genauen Werte im Spiel ĂŒberprĂŒft: ihr lokales und entferntes bash_profile ... đ)
Aber ich werde dies trotzdem sofort beheben, nur damit ich weiĂ, dass ich nicht verrĂŒckt bin in Bezug auf mein VerstĂ€ndnis davon, was die sshd in Bezug auf Shells und Quelldateien tut.
Ich frage mich auch, ob dies mit dem Szenario / der Intelligenz von #1816 zusammenhÀngt, bei dem es auch um Shells und Startdateien geht. Es ist _wahrscheinlich_ nicht direkt relevant, da hier behauptet wird, dass sich ssh
eine Richtung und Fabric in eine andere Richtung verhÀlt (im Gegensatz dazu, wie "sshd die Shell normalerweise aufruft"), aber es lohnt sich auf jeden Fall, verlinkt zu werden.
Ich habe festgestellt, dass ich in den letzten Monaten versucht habe, ĂŒber einen Haufen tiefer sshd-Code-TauchgĂ€nge zu stolpern, die mit etwas in dieser Richtung zu tun haben. Ich kann es jetzt aber nicht finden, was nervt. BEARBEITEN: ah, ich denke, es war ein nicht verwandtes Paramiko-Problem (kein Verlinken, da es keinen Sinn macht, Dinge zu verwirren) ĂŒber das AusfĂŒhren von Befehlen vor der Authentifizierung. OK.
Alles klar, was passiert also wirklich, wenn wir Command Exec anfordern?
shell
Kanalanfrage (die das definierte Login-Shell-Programm des Benutzers lÀdt und keine command
) oder einen exec
Kanal machen request (die nur sagt "fĂŒhrt eine gegebene Befehlszeichenfolge aus, die einen Pfad enthalten kann" und gibt nicht mehr an)775f8a23f2353f5869003c57a213d14b28e0736e
)Nun, zuerst werde ich ein bisschen herumalbern. LĂ€uft gegen einen beliebigen Debian 8.10-Container (der OpenSSH 6.7 ausfĂŒhrt!) Ich sehe dies in den Protokollen der DEBUG3-Ebene, wenn ich ssh localhost whoami
mache:
debug1: server_input_channel_req: channel 0 request exec reply 1
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req exec
Starting session: command for root from 172.17.0.1 port 42598
fab -H localhost -- whoami
tun:
debug1: server_input_channel_req: channel 0 request exec reply 1
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req exec
Starting session: command for root from 172.17.0.1 port 42610
OK, sie machen beide exec
...das ist zu erwarten. Etwas anders im Prozessbaum? sollte nicht sein, und ... gibt es nicht. beide sehen so aus:
sshd,1 -D -e
ââsshd,1535
ââpstree,1537 -alpU
Also definitiv keine Muschel im Spiel? Was macht es ĂŒberhaupt? Kann ich Shelly-Dinge wie &&
?
Ich kann! zB whoami && id
funktioniert gut. Angesichts meines VerstÀndnisses von Unix-Prozesskontrolle ist das etwas seltsam; es scheint unwahrscheinlich, dass sshd nur buchstÀblich exec(string)
ausfĂŒhrt, aber wenn es eine Shell zum Interpretieren verwenden wĂŒrde, wĂŒrden wir das nicht in pstree
?
Ich denke, es ist an der Zeit, sich mit openssh-portable auseinanderzusetzen und zu sehen, was was ist.
session_input_channel_req
passiert, in (Sie haben es erraten) session_input_channel_req , die protokolliert und dann je nach Sitzungstyp (Shell, pty open, exec, Subsystem usw.) an verschiedene Funktionen weiterleitet.exec
was session_exec_req bedeutetdo_exec_pty
oder (in unserem Fall, weil wir keinen Pty angefordert haben; Sie können es daran erkennen, dass die Protokollzeilen nichts ĂŒber die Tty-Nummer enthalten) kickt. do_exec_no_ptyAuch, huh, ich habe einen Teil dieser Nachverfolgung (aber aus einem anderen Grund/Schwerpunkt) in der Vergangenheit gemacht, wie im Dezember 2016: https://github.com/paramiko/paramiko/pull/398#issuecomment -264281759. Hatte total vergessen...
Der Grund, warum ich die Shell in pstree
nicht sehe, liegt an der Verwendung von execve
, die einen Elternprozess ersetzt, anstatt ein Kind zu erzeugen. Gut zu wissen. (EDIT: falsch, das ersetzt nur den sshd-Kind-Proc durch die Shell; die Shell selbst fĂŒhrt dann möglicherweise auch einen Exec-Aufruf im Stil von replace-me durch; siehe Kommentare unten.)
Wie auch immer, so! Dies sollte immer noch bedeuten, dass die Clients von Fabric und OpenSSH in Bezug auf die Shell-AusfĂŒhrung genau dasselbe tun; nichts von ihnen wĂŒrde diese Teile der OpenSSH-Codebasis modifizieren. Es sollte immer so etwas wie bash -c "python3 ./configure.py"
, mit dem tatsÀchlichen Wert von bash
abhÀngig vom macOS-Level-Benutzer von @code-tree und seiner konfigurierten Shell.
Ich frage mich, ob meine Vermutung, dass die env var-Ăbertragung das Unterscheidungsmerkmal ist, richtig ist, da dies das einzige andere ist, was mir einfĂ€llt: wie sich die beiden AusfĂŒhrungsumgebungen unterscheiden könnten. FWIW in meinen CLI-fokussierten Tests meldet env
auf beiden Systemen dasselbe, und unabhÀngig von diesen anderen umgebungsbezogenen Problemen sollte das _default_-Verhalten (aufgrund der SSH-Sicherheitsrichtlinie) immer so sein, dass keine lokale Umgebung "durchsickert". Die andere Seite.
Ja, ich bin mir ziemlich sicher, dass sshd die Befehlszeichenfolge immer in der Shell des Benutzers ausfĂŒhrt (konfiguriert in /etc/passwd). Es stellt jedoch der Befehlszeichenfolge "exec" voran, wenn es die Befehlszeichenfolge analysieren und feststellen kann, dass es sich um einen einzelnen Befehl handelt.
$ ssh testdeploy02.ec2.st-av.net pstree -a
...
|-sshd -D
| `-sshd
| `-sshd
| `-pstree -a
$ ssh testdeploy02.ec2.st-av.net 'pstree -a && sleep 1'
...
|-sshd -D
| `-sshd
| `-sshd
| `-bash -c pstree -a && sleep 1
| `-pstree -a
$ ssh testdeploy02.ec2.st-av.net 'VAR=-a sh -c "exec pstree \$VAR"'
...
|-sshd -D
| `-sshd
| `-sshd
| `-pstree -a
Die Umgebungsvariablen werden hauptsÀchlich von den ssh-Client- und sshd-Server-Konfigurationen gesteuert:
$ grep Env /etc/ssh/*_config
/etc/ssh/ssh_config: SendEnv LANG LC_*
/etc/ssh/sshd_config:AcceptEnv LANG LC_*
Der ssh-Client sendet also explizit einige Variablen (auĂerhalb des Befehlsstrings selbst) und sie werden von sshd gefiltert. Aber es gibt anscheinend einige Ausnahmen:
$ ssh testdeploy02.ec2.st-av.net env | grep TERM
$ ssh -t testdeploy02.ec2.st-av.net env | grep TERM
TERM=xterm-256color
TatsĂ€chlich denke ich, dass das Verhalten "automatische AusfĂŒhrung zum Ersetzen der Shell durch einen einzelnen Befehl" eine Funktion von bash ist:
$ dash -c "pstree -a"
...
ââsshd -D
â ââsshd
â ââsshd
â ââbash
â ââdash -c pstree -a
â ââpstree -a
$ bash -c "pstree -a"
ââsshd -D
â ââsshd
â ââsshd
â ââbash
â ââpstree -a
EDIT: Der VollstÀndigkeit halber:
$ bash -c "pstree -a && sleep 1"
ââsshd -D
â ââsshd
â ââsshd
â ââbash
â ââbash -c pstree -a && sleep 1
â ââpstree -a
Ah ja, ich habe mich geirrt, execve
bedeutet nur, dass der sshd-Kind-Proc ersetzt wird, also was danach passiert, liegt an der Shell selbst und was sie fĂŒr -c xxx
tut. Meine Tests waren in zsh, fwiw.
Auch @ploxiln ja, die Sache mit env vars verweist auf andere oben verlinkte Tickets, obwohl es abzuwarten bleibt, ob @code-tree wirklich ein anderes Symptom als diese aufweist.
Tut mir leid, ich denke, das ist ein Fehlalarm. Mir war nicht bewusst, dass es einen Unterschied zwischen der AusfĂŒhrung eines Befehls ĂŒber ssh inline und der AusfĂŒhrung nach der Anmeldung ĂŒber ssh gibt. Wenn ich ssh host 'echo $PATH'
mache, hat es auch PATH nicht aktualisiert, wÀhrend echo $PATH
nach dem Anmelden gut funktioniert.
Ich verstehe immer noch nicht wirklich, warum ssh dies tut (scheint, als mĂŒsste ich tatsĂ€chlich ssh host 'bash -l -c "python3 ./configure.py"'
tun). UnabhĂ€ngig davon kann man mit Sicherheit sagen, dass dies kein Fabric-Problem ist. Entschuldigung fĂŒr die Verwirrung.
@code-tree es hĂ€ngt mit dem zusammen, was zuvor erwĂ€hnt wurde - Shells haben ein paar verschiedene Modi, in denen sie arbeiten, hĂ€ufig als "Anmeldung" und "interaktiv" bezeichnet (und normalerweise liegen diese ĂŒber einem Basismodus, der als keiner angesehen wird) und welcher Modus die Shell ausgefĂŒhrt wird, Ă€ndert den Satz von rc-Dateien, die sie lĂ€dt.
Der hervorstechende Punkt hier ist, dass bash -c xxx
nicht als "interaktiv" angesehen wird und daher das Laden bestimmter Dateien ĂŒberspringt - wie .bash_profile
- sondern nur bash
ohne -c
ist normalerweise interaktiv und lÀdt Profildateien.
Wie Sie oben gesehen haben, fĂŒhrt sshd immer bash -c <command send down the pipe>
wenn Sie es auffordern, einen einzelnen Befehl auszufĂŒhren (wie es Fabric oder ssh host command
tut) und befindet sich daher immer im nicht interaktiven Modus. (Es sei denn , Sie tun , was Stoff 1 tut , und fĂŒhren Sie Ihre eigene, verschachtelt, Shell mit -l
... aber dann Sie laufen bash -c "bash -l -c \"oh god escaping is hard help\""
und ich werde einige đ„ jetzt gehen.
Wie auch immer, nicht alles ist verloren, ich muss meine Erinnerung an diesen Teil der Dinge anscheinend alle paar Jahre auffrischen, also Ă€h...jetzt bin ich erfrischt đ
Das ist eine Bash-Sache, keine tolle Sache.
Welche Dateien die Bash beim Start als Quelle wÀhlt, kann kompliziert sein http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html und debian/ubuntu (und die meisten Distributionen) haben einige Anpassungen in
/etc/profile
und standardmĂ€Ăig~/.bashrc
.Die Standard-Shell-Fab ist
/bin/bash -l -c
, und-l
macht sie zu einer "Login"-Shell. Ohne die debian/ubuntu-Anpassung ist es fĂŒr eine bash-"login"-Shell möglich,~/.bash_profile
aber nicht~/.bashrc
.Aber unter Ubuntu 16.04 scheint es standardmĂ€Ăig
.bashrc
sogar fĂŒr die Login-Shell. Aber Zeilen, die am unteren Rand eines Standard-.bashrc
hinzugefĂŒgt werden, werden nicht verarbeitet, da es am oberen Rand aussteigt, wenn es erkennt, dass es nicht interaktiv ausgefĂŒhrt wird.Hier habe ich dem Ubuntu-16.04-Standardbenutzer
.bashrc
zwei Zeilen hinzugefĂŒgt# ~/.bashrc: executed by bash(1) for non-login shells. # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) # for examples export VAR1=val1 # If not running interactively, don't do anything case $- in *i*) ;; *) return;; esac export VAR2=val2 # don't put duplicate lines or lines starting with space in the history. # See bash(1) for more options HISTCONTROL=ignoreboth ...
Hier ist eine Fabfile, mit der ich teste:
from fabric.api import run, env, task <strong i="24">@task</strong> def get_myvars(): run("echo VAR1=$VAR1 VAR2=$VAR2")
Die Ergebnisse:
$ fab -H testpy05.ec2.st-av.net get_myvars [testpy05.ec2.st-av.net] Executing task 'get_myvars' [testpy05.ec2.st-av.net] run: echo VAR1=$VAR1 VAR2=$VAR2 [testpy05.ec2.st-av.net] out: VAR1=val1 VAR2= [testpy05.ec2.st-av.net] out: ...
Du hast mein Leben gerettet. Dies ist die perfekte Antwort, die ich finde :) Vielen Dank!
Hilfreichster Kommentar
Das ist eine Bash-Sache, keine tolle Sache.
Welche Dateien die Bash beim Start als Quelle wÀhlt, kann kompliziert sein http://blog.flowblok.id.au/2013-02/shell-startup-scripts.html und debian/ubuntu (und die meisten Distributionen) haben einige Anpassungen in
/etc/profile
und standardmĂ€Ăig~/.bashrc
.Die Standard-Shell-Fab ist
/bin/bash -l -c
, und-l
macht sie zu einer "Login"-Shell. Ohne die debian/ubuntu-Anpassung ist es fĂŒr eine bash-"login"-Shell möglich,~/.bash_profile
aber nicht~/.bashrc
.Aber unter Ubuntu 16.04 scheint es standardmĂ€Ăig
.bashrc
sogar fĂŒr die Login-Shell. Aber Zeilen, die am unteren Rand eines Standard-.bashrc
hinzugefĂŒgt werden, werden nicht verarbeitet, da es am oberen Rand aussteigt, wenn es erkennt, dass es nicht interaktiv ausgefĂŒhrt wird.Hier habe ich dem Ubuntu-16.04-Standardbenutzer
.bashrc
zwei Zeilen hinzugefĂŒgtHier ist eine Fabfile, mit der ich teste:
Die Ergebnisse: