In my Arch installieren /etc/bash.bashrc
und /etc/skel/.bashrc
diese Zeilen enthalten:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
Auf Debian /etc/bash.bashrc
hat:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Und /etc/skel/.bashrc
:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Laut man bash
nicht-interaktiven Shells werden diese Dateien jedoch nicht einmal gelesen:
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 com‐
mand 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.
Wenn ich es richtig verstehe, werden die *.bashrc
Dateien nur gelesen, wenn sie BASH_ENV
darauf verweisen. Dies kann nicht zufällig geschehen und tritt nur auf, wenn jemand die Variable explizit entsprechend eingestellt hat.
Dies scheint die Möglichkeit zu zerstören, dass Skripte einem Benutzer .bashrc
automatisch eine Quelle geben, indem sie Einstellungen vornehmen BASH_ENV
, was sich als nützlich erweisen könnte. Angesichts der Tatsache, dass bash diese Dateien niemals liest, wenn sie nicht interaktiv ausgeführt werden, es sei denn, es wird ausdrücklich dazu aufgefordert, warum lassen die Standarddateien dies *bashrc
nicht zu?
Antworten:
Dies ist eine Frage, die ich vor ein paar Wochen hier posten wollte. Wie bei Terdon habe ich verstanden, dass a
.bashrc
nur für interaktive Bash-Shells bereitgestellt wird , sodass nicht.bashrc
überprüft werden muss, ob es in einer interaktiven Shell ausgeführt wird. Verwirrenderweise hatten alle von mir verwendeten Distributionen (Ubuntu, RHEL und Cygwin) eine Art Prüfung (Test$-
oder$PS1
), um sicherzustellen, dass die aktuelle Shell interaktiv ist. Ich mag keine Frachtkultprogrammierung, deshalb habe ich mich daran gemacht, den Zweck dieses Codes in meinem zu verstehen.bashrc
.Bash hat einen speziellen Fall für Remote-Shells
Nachdem ich das Problem untersucht hatte, stellte ich fest, dass Remote-Shells unterschiedlich behandelt werden. Während nicht interaktive Bash-Shells normalerweise keine
~/.bashrc
Befehle beim Start ausführen, wird ein Sonderfall gemacht, wenn die Shell vom Remote-Shell-Daemon aufgerufen wird :Beispiel
Fügen Sie am Anfang einer Fernbedienung Folgendes ein
.bashrc
. (Wenn.bashrc
von.profile
oder bezogen.bash_profile
, deaktivieren Sie dies vorübergehend während des Tests):Führen Sie die folgenden Befehle lokal aus:
i
in$-
gibt an, dass die Shell nicht interaktiv ist .-
in$0
zeigt an, dass die Schale nicht um ein Login - Shell .In der Fernbedienung definierte Shell-Funktionen
.bashrc
können auch ausgeführt werden:Ich bemerkte , dass das
~/.bashrc
ist nur bezogen , wenn ein Befehl für als Argument angegeben wirdssh
. Dies ist sinnvoll: wennssh
zum Starten einer regulären Anmeldeshell verwendet.profile
oder.bash_profile
ausgeführt wird (und.bashrc
nur dann, wenn dies ausdrücklich durch eine dieser Dateien erfolgt).Der Hauptvorteil, den ich
.bashrc
beim Ausführen eines (nicht interaktiven) Remote-Befehls habe, ist, dass Shell-Funktionen ausgeführt werden können. Die meisten Befehle in einem Typical.bashrc
sind jedoch nur in einer interaktiven Shell relevant, z. B. werden Aliase nur dann erweitert, wenn die Shell interaktiv ist.Remote-Dateiübertragungen können fehlschlagen
Dies ist normalerweise kein Problem , wenn
rsh
oderssh
verwendet , um ein interaktiv Login - Shell oder wenn nicht-interaktiver Shells zu beginnen , wird verwendet , um Befehle auszuführen. Aber es kann ein Problem sein für Programme wiercp
,scp
undsftp
dass verwenden Remote - Schalen für die Datenübertragung.Es stellt sich heraus, dass die Standard-Shell des Remote-Benutzers (wie Bash) implizit gestartet wird, wenn der
scp
Befehl verwendet wird. Es gibt keine Erwähnung in der Manpage - nur eine Erwähnung,scp
diessh
für die Datenübertragung verwendet wird. Dies hat zur Folge, dass die.bashrc
Dateiübertragung fehlschlägt , wenn der Befehl Befehle enthält, die an die Standardausgabe gesendet werden. Beispielsweise schlägt scp fehlerfrei fehl .Siehe auch diesen verwandten Red Hat-Fehlerbericht von vor 15 Jahren, scp bricht ab, wenn es einen Echo-Befehl in / etc / bashrc gibt (der schließlich geschlossen wurde als
WONTFIX
).Warum
scp
undsftp
scheiternSCP (Secure Copy) und SFTP (Secure File Transfer Protocol) haben ihre eigenen Protokolle für die lokale und die entfernte Seite, um Informationen über die übertragenen Dateien auszutauschen. Unerwarteter Text vom entfernten Ende wird (falsch) als Teil des Protokolls interpretiert und die Übertragung schlägt fehl. Laut FAQ aus dem Schneckenbuch
Details zum SCP-Protokoll
Für diejenigen, die sich für die Details der Funktionsweise von SCP interessieren, fand ich interessante Informationen unter Funktionsweise des SCP-Protokolls , einschließlich Details zum Ausführen von scp mit gesprächigen Shell-Profilen auf der Remote-Seite. :
Fazit / TLDR
Die meisten Anweisungen in einem Typical
.bashrc
sind nur für eine interaktive Shell nützlich - nicht, wenn Remotebefehle mitrsh
oder ausgeführt werdenssh
. In den meisten solchen Situationen Setzen von Shell - Variablen, Aliase und Funktionen definieren , nicht erwünscht ist - und Druck eines beliebigen Textes an der Standardausgabe ist aktiv schädlich , wenn Dateien mit Programmen wie die Übertragungscp
odersftp
. Das Beenden nach der Überprüfung, ob die aktuelle Shell nicht interaktiv ist, ist das sicherste Verhalten für.bashrc
.quelle
Die Manpage vernachlässigt zu erwähnen, dass
bash
auch Quellen.bashrc
für nicht interaktive Remote-Shells wie inhttp://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010
http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050
quelle
.bash_profile
würde das gleiche Verhalten aufweisen.rsh
(was ich nie benutzt habe) Quellen~/.bashrc
? Und dass Linux-Distributionen es generell blockieren,bash
nur für den Fall, dass jemand jemals versucht, ein Skript damit auszuführenrsh
?ssh server
sollte nicht anfassen,.bashrc
da dies sowieso eine Login-Shell ist. Es sei denn, Ihr System ist eines der Systeme, aus denen ~ / .bashrc` stammt~/.profile
. Undssh server command
sollte das nicht einmal tun. Auf meinem System sicherlich nicht.bash
Quelle verbunden, nicht mit derrsh
Quelle. :) Der Kommentar giltssh
auch für, er wurde erst vor sehr langer Zeit geschrieben. Siehe aktualisierte Antwort mit mehr Quelle.echo
ganz oben in/etc/bash.bashrc
und~/.bashrc
(vor den interaktiven Shell-Tests) einzufügen und dann ssh in den Zielcomputer mitssh server hostname
und währendhostname
der Ausführung habe ich keines meiner Echos gesehen. Ist es das meineshell_level
(was auch immer das ist) nicht<2
?Konventionell
.bashrc
ist der Ort, an dem der Benutzer die angepasste Konfiguration für die Shell speichert.Diese benutzerdefinierten Konfigurationen können Umgebungsvariablen, Aliase und ausgefallene Eingabeaufforderungen sein. Bei einer nicht interaktiven Shell sind diese kurzen Dinge bedeutungslos. Darüber hinaus kann eine nicht interaktive Shell in vielen Kontexten aufgerufen werden. Sie sind sich nicht sicher, ob diese Umgebungsvariablen zu falsch negativen Groß- und Kleinschreibung oder sogar zu Sicherheitslücken führen können.
Ein naheliegendes Beispiel ist ein Alias wie:
Dann bleibt Ihre nicht interaktive Shell für immer hängen.
Also führen Sie die Überprüfung oben durch,
.bashrc
um sicherzustellen, dass wir keine Probleme bekommen.Da die Shell als nicht interaktive Anmeldeshell aufgerufen werden kann , ist ein explizites Block-Sourcing
*bashrc
nicht sinnvoll.Wenn die Schale wurde als nicht-interaktive Login - Shell genannt , es Quelle
/etc/profile
, Quelle dann die erste gefunden~/.bash_profile
,~/.bash_login
und~/.profile
:Nichts hindert diese Dateien daran, sich
.bashrc
selbst zu beschaffen , so dass die Prüfung im Inneren.bashrc
sicherer und einfacher ist.quelle
*bashrc
. Meine Frage ist, warum verschiedene Linux-Anbieter sich die Mühe machen, nicht interaktive Shells explizit für das Lesen dieser Dateien zu sperren, wenn diese Dateien ohnehin nicht von nicht interaktiven Shells gelesen werden..bash_profile
, die Quelle sein kann.bashrc
.$BASH_ENV
. Beides*profile
und*bashrc
werden ignoriert. Zumindest steht das auf der Manpage. Wie Mikel jedoch gezeigt hat, könnte die Manpage lügen.bash -l -c :
, eine nicht interaktive Anmeldeshell aufzurufen?--login
100 Mal gelesen, aber anscheinend hatte er sich nie registriert. Vielen Dank!