Welchen Zweck erfüllt das [ -n "$PS1" ]
In [ -n "$PS1" ] && source ~/.bash_profile;
? Diese Zeile ist in .bashrc
einem Dotfiles- Repo enthalten .
10
Welchen Zweck erfüllt das [ -n "$PS1" ]
In [ -n "$PS1" ] && source ~/.bash_profile;
? Diese Zeile ist in .bashrc
einem Dotfiles- Repo enthalten .
Hiermit wird überprüft, ob die Shell interaktiv ist oder nicht. In diesem Fall wird die ~/.bash_profile
Datei nur bezogen, wenn die Shell interaktiv ist.
Siehe "Ist diese Shell interaktiv?" im Bash-Handbuch, das diese spezifische Redewendung zitiert. (Es wird außerdem empfohlen, zu überprüfen, ob die Shell interaktiv ist, indem getestet wird, ob die $-
spezielle Variable das i
Zeichen enthält. Dies ist ein besserer Ansatz für dieses Problem.)
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
dem einfach gedruckt wird[]
. Es scheint , zsh nicht das gleiche tun, zumindest aus einem Experiment ... In jedem Fall ist die Absicht der[ -n "$PS1" ]
zu prüfen ist , ob die Shell interaktiv ist oder nicht.bash
Deaktivieren von PS1, wenn es nicht interaktiv ist (Tippfehler in Ihrem vorherigen Kommentar), ist ein IMO-Fehler. PS1 ist keine Bash-spezifische Variable. Es hat kein Geschäft, es zu deaktivieren. Dies ist die einzige Shell, die dies tut (obwohl sieyash
auch dannPS1
auf einen Standardwert gesetzt wird, wenn sie nicht interaktiv ist).[[ $- = *i* ]] && source ~/.bash_profile
).[ -n "${PS1}" ]
, aber ich habe meine Antwort immer noch aktualisiert, um hervorzuheben, dass das Bash-Handbuch auch eine Inspektion vorschlägt / empfiehlt,$-
um festzustellen, ob die Shell interaktiv ist. Ich hoffe, Sie finden, dass dies die Antwort verbessert. Prost!Was das macht
Dies ist eine weit verbreitete Methode, um zu testen, ob die Shell interaktiv ist. Beachten Sie, dass es nur in Bash funktioniert, nicht mit anderen Shells. Es ist also in Ordnung (wenn auch albern)
.bashrc
, aber es würde nicht funktionieren.profile
(was von sh gelesen wird und bash ist nur eine der möglichen Implementierungen von sh und nicht die häufigste).Warum es funktioniert (nur in Bash!)
Eine interaktive Shell setzt die Shell-Variable
PS1
auf die Standard-Eingabeaufforderungszeichenfolge. Wenn die Shell also interaktiv ist,PS1
ist sie festgelegt (es sei denn, der Benutzer.bashrc
hat sie entfernt, was oben noch nicht geschehen ist.bashrc
, und Sie könnten davon ausgehen, dass dies sowieso eine dumme Sache ist).Das Gegenteil ist in bash der Fall: Nicht interaktive Instanzen von bash werden
PS1
beim Start nicht gesetzt. Beachten Sie, dass dieses Verhalten spezifisch für Bash ist und möglicherweise ein Fehler ist (warum sollte esbash -c '… do stuff with $var…'
nicht funktionieren, wenn esvar
istPS1
?). Aber alle Versionen von Bash bis einschließlich 4.4 (die neueste Version, wie ich sie schreibe) tun dies.Viele Systeme exportieren
PS1
in die Umwelt. Es ist eine schlechte Idee, da viele verschiedene ShellsPS1
eine andere Syntax verwenden (z. B. unterscheiden sich die Eingabeaufforderungen von bash von den Eingabeaufforderungen von zsh vollständig ). Es ist jedoch weit genug verbreitet, dass das Festlegen in der PraxisPS1
kein verlässlicher Indikator dafür ist, dass die Shell interaktiv ist. Die Shell hat möglicherweisePS1
von der Umgebung geerbt .Warum wird es hier (falsch) verwendet?
.bashrc
ist die Datei, die Bash beim Start liest, wenn sie interaktiv ist. Eine weniger bekannte Tatsache ist, dass bash auch.bashrc
eine Anmeldeshell liest und die Heuristiken von bash zu dem Schluss kommen, dass es sich um eine Remote-Sitzung handelt (bash prüft, ob das übergeordnete Elementrshd
oder istsshd
). In diesem zweiten Fall ist es unwahrscheinlich, dassPS1
dies in der Umgebung festgelegt wird, da noch keine Punktdatei ausgeführt wurde.Die Art und Weise, wie der Code diese Informationen verwendet, ist jedoch kontraproduktiv.
.bash_profile
in dieser Shell ausgeführt. Ist.bash_profile
aber ein Login-Time-Skript. Möglicherweise werden einige Programme ausgeführt, die nur einmal pro Sitzung ausgeführt werden sollen. Möglicherweise werden einige Umgebungsvariablen überschrieben, die der Benutzer vor dem Ausführen dieser Shell absichtlich auf einen anderen Wert festgelegt hat. Das Ausführen.bash_profile
in einer Shell ohne Anmeldung ist störend..bash_profile
. Dies ist jedoch der Fall, wenn das Laden.bash_profile
nützlich sein kann, da eine nicht interaktive Anmeldeshell nicht automatisch geladen wird/etc/profile
und~/.profile
.Ich denke , der Grund , warum Menschen diese für die Nutzer zu tun ist , die sich anmelden über eine GUI (eine sehr häufige Fall) und die ihre Einstellungen der Umgebungsvariablen setzen in
.bash_profile
statt.profile
. Die meisten GUI-Anmeldemechanismen rufen auf,.profile
aber nicht.bash_profile
(das Lesen.bash_profile
würde das Ausführen von bash als Teil des Sitzungsstarts anstelle von sh erfordern). Wenn der Benutzer bei dieser Konfiguration ein Terminal öffnet, erhält er seine Umgebungsvariablen. Der Benutzer erhält seine Umgebungsvariablen jedoch nicht in GUI-Anwendungen, was sehr häufig zu Verwirrung führt. Die Lösung besteht darin, Umgebungsvariablen zu verwenden,.profile
anstatt sie.bash_profile
festzulegen. Das Hinzufügen einer Brücke zwischen.bashrc
und.bash_profile
schafft mehr Probleme als es löst.Was ist stattdessen zu tun?
Es gibt eine einfache, tragbare Methode, um zu testen, ob die aktuelle Shell interaktiv ist: Testen Sie, ob die Option
-i
aktiviert ist.Dies ist nützlich
.bashrc
, um.profile
nur zu lesen , wenn die Shell nicht interaktiv ist - dh das Gegenteil von dem, was der Code tut! Lesen Sie,.profile
ob bash eine (nicht interaktive) Anmeldeshell ist, und lesen Sie es nicht, wenn es sich um eine interaktive Shell handelt.quelle
[[ -o interactive ]]
(ksh, bash, zsh) odercase $- in (*i*) ...; esac
(POSIX)PS1
wenn sie nicht interaktiv ausgeführt wird. Es ist einfach zu testen:PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
druckt nichts, währendPS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
der Wert von$PS1
set in Ihren Bash-Startdateien gedruckt wird (es wird nicht die Zeichenfolge "cuckoo" gedruckt).$-
enthälti
eine interaktive Shell.[ -n "${PS1}" ]
falsches Anrufen etwas zu weit geht, schließlich bricht es nur ab, wenn jemand PS1 exportiert (was Sie in Ihrer Antwort als schlechte Idee bezeichnen und sogar auf die Gründe dafür eingehen), und das hat keinen Einfluss Bash sowieso (da es PS1 und PS2 deaktiviert, wenn die Shell nicht interaktiv ist.) Vielleicht wäre es besser gewesen, ein Wort wie "entmutigt" zu verwenden oder über die "Einschränkungen" des Ansatzes zu sprechen. Ich denke nicht, dass es insgesamt "falsch" ist. Wenn beim Exportieren von PS1 etwas nicht stimmt, ist das sicher! Wie auch immer, danke, dass Sie auf die Details eingegangen sind.Es scheint, dass dieses seltsame Konzept auf die Tatsache zurückzuführen ist, dass
bash
es nicht als POSIX-Shell-Klon, sondern alsBourne Shell
Klon gestartet wurde .Infolgedessen wurde das interaktive Verhalten von POSIX (
$ENV
wird für interaktive Shells aufgerufen) später hinzugefügtbash
und ist nicht allgemein bekannt.Es gibt eine Shell, die ein ähnliches Verhalten zulässt. Dies ist
csh
und csh gewährt,$prompt
die bestimmte Werte hat:Dies gilt jedoch weder für die Bourne-Shell noch für POSIX-Shells.
Für eine POSIX-Shell besteht die einzige gewährte Methode darin, Code für interaktive Shells in die Datei einzufügen:
das hat einen Shell-spezifischen Namen. Es ist zB
Andere Leute erwähnten das Shell-Flag
-i
, aber dies ist für eine zuverlässige Programmierung nicht verwendbar. POSIX erfordert weder, dass diesset -i
funktioniert, noch dass es$-
einei
für interaktive Shells enthält. POSIX erfordert lediglich, dasssh -i
die Shell in den interaktiven Modus versetzt wird.Da die Variable
$PS1
aus der Umgebung importiert werden kann, kann sie auch im nicht interaktiven Modus einen Wert haben. Die Tatsache, dassbash
unset
sPS1
in einer nicht interaktiven Shell enthalten ist, wird vom Standard nicht gewährt und von keiner anderen Shell ausgeführt.Saubere Programmierung (auch mit
bash
) bedeutet also, die Befehle für interaktive Shells einzugeben$HOME/.bashrc
.quelle
Ich werde zuerst darüber sprechen, was Debian ist, und die meiste Zeit setzt auch Ubuntu auf Bash. Und letztere berühren andere Systeme.
Bei der Einstellung von Shell-Startdateien gibt es viele Meinungen.
Ich habe auch meine Meinung, aber ich werde versuchen, vorhandene Beispiele für korrekte Einstellungen zu zeigen.
Ich werde Debuan verwenden, da es ziemlich einfach ist, Beispiele für seine Dateien zu finden.
Und Debian wird häufig verwendet, daher wurden die Einstellungen gut getestet.
Was ist das Ziel, um zu überprüfen, ob PS1 eingestellt ist?
Nur um herauszufinden, ob die Shell interaktiv ist.
Die Standardeinstellung
/etc/profile
in Debian und Ubuntu (aus / usr / share / base-files / profile):Das if lautet: Wenn interaktiv (PS1-Standard festgelegt) und es sich um eine Bash-Shell handelt (die jedoch nicht als Standard fungiert
sh
), ändern Sie PS1 in eine bestimmte neue (nicht die Standard- Shell ).Die Standardeinstellung
/etc/bash.bashrc
in Debian enthält außerdem:Was ziemlich klar ist, was es tut: Wenn interaktiv nicht beschaffen (der Rest).
Jedoch in
/etc/skel/.bashrc
ist ein Beispiel der richtigen Art und Weise zu Test für eine interaktive Shell (mit$-
):Das sollte klar zeigen, warum PS1 und eine Alternative.
Die richtige Reihenfolge
Die Einstellung, die Sie melden, sollte vermieden werden.
Die Reihenfolge (von Systemeinstellungen auf spezifischere Benutzereinstellungen (für bash)) ist
/etc/profile
,/etc/bash.bashrc
,~/.profile
und schließlich~/.bashrc
. Dadurch werden die breitesten Effekte (und für mehr Shells) in/etc/profile
(die Root gehören) gefolgt von/etc/bash.bashrc
(die auch Root gehören) platziert, aber nur Bash beeinflusst. Dann kommen die persönlichen Einstellungen$HOME
, die erste ist~/.profile
für die meisten Muscheln und~/.bashrc
(fast gleichbedeutend mit~/.bash_profile
) nur für Bash spezifisch.Es ist daher falsch zu Quelle
~/.bashrc
in~/.profile
, es einen bestimmten Benutzer für bash auf eine allgemeinere Einstellung verwandelt , die sich mehr Schalen zu beeinflussen . Außer wenn dies folgendermaßen gemacht wird :Es überprüft, ob bash ausgeführt wird und lädt nur,
.bashrc
wenn dies der Fall ist.Dies ist eine vorgelagerte Entscheidung von Debian. Die Begründung wird hier erläutert .
Umgekehrt werden bei der Beschaffung
~/.profile
in~/.bash_profile
(oder~/.bashrc
) nur allgemeine Regeln erneut angewendet, die bereits auf einen bestimmten Anwendungsfall geladen werden sollten, und daher "nicht so schlecht" (ich sage nicht "gut"). Und ich sage nicht gut, weil es dazu führen kann, dass sich das Sourcing von Dateien wiederholt. Wie wenn ein Unterverzeichnis ein übergeordnetes Element lädt, ist dies eine Verzeichnisschleife.Und in diesem Cross-Sourcing macht die Prüfung auf interaktive Shell Sinn. Nur wenn eine Shell interaktiv ist
~/.bashrc
, wird sie geladen, aber sie wird möglicherweise geladen~/.profile
(oder umgekehrt). In diesem Fall kann die Suche nach einer interaktiven Shell verwendet werden.quelle