Unterschied zwischen .bashrc und .bash_profile

450

Was ist der Unterschied zwischen .bashrcund .bash_profileund welches soll ich verwenden?

cfischer
quelle
2
Siehe auch diese ähnliche Frage unter ubuntu.stackexchange.com/questions/1528/bashrc-or-bash-profile
Stefan Lasiewski
Wenn Sie eine umfassendere Erklärung wünschen, die auch einschließt .profile, werfen Sie einen Blick auf diese Frage: superuser.com/questions/789448/…
Flimm
Diese Antwort behandelt auch einige Aspekte stackoverflow.com/questions/415403/…
Sergey Voronezhskiy

Antworten:

518

Wenn Sie sich in ein Unix-System einloggen, startet das System normalerweise ein Programm für Sie. Dieses Programm ist eine Shell, dh ein Programm zum Starten anderer Programme. Es ist eine Kommandozeilen-Shell: Sie starten ein anderes Programm, indem Sie dessen Namen eingeben. Die Standardshell, eine Bourne-Shell, liest Befehle, ~/.profilewenn sie als Anmeldeshell aufgerufen wird.

Bash ist eine Bourne-ähnliche Shell. Es liest Befehle ab dem ~/.bash_profileZeitpunkt, an dem es als Anmeldeshell aufgerufen wird, und wenn diese Datei nicht existiert¹, wird ~/.profilestattdessen versucht, sie zu lesen .

Sie können eine Shell jederzeit direkt aufrufen, indem Sie beispielsweise einen Terminalemulator in einer GUI-Umgebung starten. Wenn die Shell keine Anmeldeshell ist, wird sie nicht gelesen ~/.profile. Wenn Sie bash als interaktive Shell starten (dh kein Skript ausführen), liest es ~/.bashrc(außer wenn es als Anmeldeshell aufgerufen wird ), dann liest es nur ~/.bash_profileoder ~/.profile.

Deshalb:

  • ~/.profile Hier können Sie Informationen ablegen, die für Ihre gesamte Sitzung gelten, z. B. Programme, die Sie beim Anmelden starten möchten (nicht jedoch grafische Programme, die in eine andere Datei verschoben werden), und Umgebungsvariablendefinitionen.

  • ~/.bashrcist der Ort, an dem Dinge abgelegt werden, die nur für Bash selbst gelten, wie Alias- und Funktionsdefinitionen, Shell-Optionen und Einstellungen für Eingabeaufforderungen. (Sie können dort auch Tastenkombinationen einfügen, aber für Bashs werden sie normalerweise verwendet ~/.inputrc.)

  • ~/.bash_profilekann anstelle von verwendet werden ~/.profile, wird aber nur von bash gelesen, nicht von einer anderen Shell. (Dies ist hauptsächlich dann von Belang, wenn Sie möchten, dass Ihre Initialisierungsdateien auf mehreren Computern ausgeführt werden und Ihre Anmeldeshell nicht alle von ihnen unterstützt.) Dies ist eine logische Angabe, ~/.bashrcwenn die Shell interaktiv ist. Ich empfehle folgende Inhalte in ~/.bash_profile:

    if [ -r ~/.profile ]; then . ~/.profile; fi
    case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

Bei modernen Unices tritt eine zusätzliche Komplikation auf ~/.profile. Wenn Sie sich in einer grafischen Umgebung anmelden (d. H., Wenn das Programm, in das Sie Ihr Kennwort eingeben, im Grafikmodus ausgeführt wird), wird nicht automatisch eine Anmeldeshell angezeigt, die den Text liest ~/.profile. Abhängig vom grafischen Anmeldeprogramm, vom Windows-Manager oder der Desktop-Umgebung, die Sie anschließend ausführen, und davon, wie Ihre Distribution diese Programme konfiguriert hat, können Sie ~/.profilemöglicherweise gelesen werden oder nicht. Wenn dies nicht der Fall ist, können Sie normalerweise an einer anderen Stelle Umgebungsvariablen und Programme definieren, die beim Anmelden gestartet werden sollen. Es gibt jedoch leider keinen Standardspeicherort.

Beachten Sie, dass hier und da möglicherweise Empfehlungen angezeigt werden, Umgebungsvariablendefinitionen einzufügen ~/.bashrcoder Anmeldeshells immer in Terminals zu starten. Beides sind schlechte Ideen. Das häufigste Problem bei diesen beiden Ideen ist, dass Ihre Umgebungsvariablen nur in Programmen festgelegt werden, die über das Terminal gestartet werden, nicht in Programmen, die direkt mit einem Symbol oder einem Menü oder einer Tastenkombination gestartet werden.

¹ Der Vollständigkeit .bash_profilehalber auf Anfrage: Falls nicht vorhanden, versucht bash es auch, .bash_loginbevor auf zurückgegriffen wird .profile. Fühlen Sie sich frei zu vergessen, dass es existiert.

Gilles
quelle
11
+1 für guten Beitrag. AUCH danke, dass Sie den Abschnitt "Login Grafik vs Login-Shell" hinzugefügt haben ... Ich hatte das Problem, bei dem ich dachte, ~ / .profile würde IMMER für Grafik / Shell ausgeführt ... aber es wird nicht ausgeführt, wenn sich der Benutzer anmeldet über grafisches Login. Danke, dass Sie dieses Rätsel gelöst haben.
Trevor Boyd Smith
4
@Gilles: Können Sie anhand von Beispielen näher erläutern, warum es eine schlechte Idee ist, in jedem Terminal eine Login-Shell zu betreiben? Ist dies nur ein Problem mit Desktop-Linux? (Ich habe festgestellt, dass unter OS X Terminal jedes Mal eine Login-Shell ausgeführt wird, und ich habe keine Nebenwirkungen bemerkt (obwohl ich normalerweise iTerm verwende). Aber dann kann ich mir nicht viele Umgebungsvariablen vorstellen, die mir außerhalb von wichtig sind ein Terminal. (Vielleicht HTTP_PROXY?))
Iconoclast
2
@Brandon Wenn Sie in jedem Terminal eine Anmeldeshell ausführen, werden die von der Umgebung bereitgestellten Umgebungsvariablen überschrieben. In alltäglichen Situationen können Sie damit durchkommen, aber es kommt und beißt Sie früher oder später, wenn Sie verschiedene Variablen in einem Terminal einrichten möchten (z. B. um eine andere Version eines Programms auszuprobieren): a Die Login-Shell würde Ihre lokalen Einstellungen überschreiben.
Gilles
4
Die Anweisung ~/.bash_profilekann anstelle von verwendet werden ~/.profile, Sie müssen jedoch auch angeben, ~/.bashrcob die Shell interaktiv ist. ist irreführend, da dies orthogonale Probleme sind. Egal, ob Sie verwenden ~/.bash_profileoder ob Sie in die von Ihnen verwendete ~/.profileeinbeziehen müssen, ~/.bashrcwenn die Einstellungen von dort in der Anmeldeshell wirksam werden sollen.
Piotr Dobrogost
3
@ Gilles Sicher, aber die Art und Weise, wie der Satz in der Antwort formuliert ist, deutet darauf hin, dass die Notwendigkeit des Einschlusses ~/.bashrcetwas mit der Auswahl zu tun hat, ~/.bash_profileanstatt dass ~/.profiledies nicht wahr ist. Wenn jemand ein ~/.bashrcSkript in ein Skript einbezieht, das zur Anmeldezeit bezogen wird (hier entweder ~/.bash_profileoder ~/.profile), möchte er, dass die Einstellungen ~/.bashrcauf die Anmelde-Shell genauso angewendet werden, wie sie auf Nicht-Anmelde-Shell angewendet werden.
Piotr Dobrogost
53

Aus diesem kurzen Artikel

Der Bash-Manpage zufolge wird .bash_profile für Anmeldeshells ausgeführt, während .bashrc für interaktive Shells ohne Anmeldung ausgeführt wird.

Was ist eine Login- oder Nicht-Login-Shell?

Wenn Sie sich über die Konsole anmelden (z. B. Benutzername und Kennwort eingeben), entweder während des Bootvorgangs physisch am Computer oder remote über ssh: .bash_profile, werden die Dinge vor der ersten Eingabeaufforderung konfiguriert.

Wenn Sie sich jedoch bereits bei Ihrem Computer angemeldet haben und ein neues Terminalfenster (xterm) in Gnome oder KDE öffnen, wird .bashrc vor der Eingabeaufforderung des Fensters ausgeführt. .bashrc wird auch ausgeführt, wenn Sie eine neue Bash-Instanz durch Eingabe von / bin / bash in einem Terminal starten.

Jarvin
quelle
12
Geringfügige Aktualisierungen: 'Ausgeführt' ist wahrscheinlich ein leicht irreführender Begriff, beide stammen von uns. Ausgeführt hört sich an, als würde es als Skript ausgeführt, fork / exec yadda yadda. Es wird im Kontext der aktuellen Shell ausgeführt. Noch wichtiger ist, dass .bashrc viel häufiger ausgeführt wird. Es wird bei jedem Bash-Skript-Lauf ausgeführt und auch, wenn Sie kein .bash_profile haben. Je nachdem, wie Sie Ihre xterms eingerichtet haben, können Sie auch eine Shell erstellen, die .bash_profile
Rich Homolka
36

Früher, als Pseudo-Tty nicht pseudo und eigentlich gut getippt waren und Modems so langsam auf UNIXes zugegriffen haben, dass Sie sehen konnten, wie jeder Buchstabe auf Ihrem Bildschirm gedruckt wurde, war Effizienz von höchster Wichtigkeit. Um die Effizienz zu verbessern, hatten Sie das Konzept eines Hauptanmeldefensters und aller anderen Fenster, die Sie früher verwendet haben. In Ihrem Hauptfenster möchten Sie Benachrichtigungen zu neuen E-Mails erhalten und möglicherweise andere Programme im Hintergrund ausführen.

Um dies zu unterstützen, haben Shells eine Datei .profilespeziell für "Login-Shells" bereitgestellt. Dies würde das Besondere tun, einmal eine Sitzung einzurichten. Bash hat dies etwas erweitert, um zuerst nach .bash_profile und dann nach .profile zu suchen. Auf diese Weise können Sie nur Bash-Elemente einfügen (damit die Bourne-Shell usw., die sich auch mit .profile befasst, nicht beschädigt wird). Andere Shells, die sich nicht anmelden, geben nur die RC-Datei .bashrc (oder .kshrc usw.) aus.

Das ist jetzt ein bisschen wie ein Anachronismus. Sie melden sich nicht so oft bei einer Haupt-Shell an wie bei einem GUI-Fenstermanager. Es gibt kein anderes Hauptfenster als jedes andere.

Mein Vorschlag - mach dir keine Sorgen um diesen Unterschied, er basiert auf einem älteren Unix-Stil. Beseitigen Sie den Unterschied in Ihren Dateien. Der gesamte Inhalt von .bash_profile sollte sein:

[ -f $HOME/.bashrc ] && . $HOME/.bashrc

Und setzen Sie alles, was Sie wirklich wollen, in .bashrc

Denken Sie daran, dass .bashrc für alle Shells (interaktiv und nicht interaktiv) bereitgestellt wird. Sie können das Sourcing für nicht interaktive Shells kurzschließen, indem Sie diesen Code oben in .bashrc einfügen:

[[ $- != *i* ]] && return

Reiche Homolka
quelle
6
Das ist eine schlechte Idee, siehe meine Antwort . Insbesondere werden Ihre Umgebungsvariablen nur in Programmen festgelegt, die über das Terminal gestartet wurden, nicht in Programmen, die direkt mit einem Symbol, einem Menü oder einer Tastenkombination gestartet wurden.
Gilles
4
@ Gilles Ich verstehe nicht, warum du das behauptest. Mit .$HOME/.bashrcals Rich oben zeigte, in Einstellungen .bashrcwerden in Login - Shells und damit die Desktop - Umgebung als auch zur Verfügung. Zum Beispiel auf meinem Fedora - System gnome-sessionwird gestartet, -$SHELL -c gnome-sessionso .profilegelesen wird.
Mikel
2
@PiotrDobrogost Oh ja, es gibt ein weiteres Problem mit Richs Antwort. Das Einbinden .bashrcin .profilefunktioniert normalerweise nicht, da .profilees von /bin/shund ohne Bash ausgeführt werden kann (z. B. unter Ubuntu für eine grafische Anmeldung standardmäßig) und diese Shell möglicherweise nicht interaktiv ist (z. B. für eine grafische Anmeldung).
Gilles
3
@Gilles re: ".bashrc in .profile einbinden" ist überhaupt nicht empfehlenswert (im Gegenteil). Entweder wurde die Antwort bearbeitet (es scheint nicht so), oder Ihre Kommentare stimmen nicht mit dem überein, was gesagt wird.
Michael
2
Im Allgemeinen +1, aber ich würde der Empfehlung hinzufügen, "Kurzschluss ... für nicht interaktive Shells" ("in der Nähe der Spitze von .bashrc: [[ $- != *i* ]] && return"); Ich möchte, dass einige von meinen .bashrcauch für nicht interaktive Shells ausgeführt werden, insbesondere um env vars bei der Ausgabe festzulegen ssh hostname {command}, damit die Remote-Befehle korrekt ausgeführt werden (obwohl die Shell nicht interaktiv ist). Andere Einstellungen später .bashrcsollten jedoch ignoriert werden. Normalerweise überprüfe ich, ob TERM = dumm und / oder nicht gesetzt ist, und steige dann früh aus.
Michael
18

Schauen Sie sich diesen ausgezeichneten Blog-Beitrag von ShreevatsaR an . Hier ist ein Auszug, aber gehen Sie zum Blog-Beitrag, der eine Erklärung für Begriffe wie "Login-Shell", ein Flussdiagramm und eine ähnliche Tabelle für Zsh enthält.

Für Bash arbeiten sie wie folgt. Lesen Sie die entsprechende Spalte. Führt A, dann B, dann C usw. aus. B1, B2, B3 bedeutet, dass nur die erste der gefundenen Dateien ausgeführt wird.

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+
Flimm
quelle
Anstatt die gleiche Antwort auf mehrere Fragen zu posten, ist es vorzuziehen, wenn Sie Ihre Antwort auf die spezifischen Bedürfnisse des Fragestellers zuschneiden können. Wenn die Antwort für beide Fragen genau gleich ist, sollten Sie eine einzige Antwort veröffentlichen und abstimmen, um die anderen Fragen als Duplikate des Originals zu schließen.
Mokubai
1
@Mokubai Die andere Frage wurde bereits als Duplikat dieser Frage markiert.
Flimm
@ElipticalView: von Satz nichts zu tun, Sie beziehen sich auf die Zeile: [ -z "$PS1" ] && return? Die Tabelle in meiner Antwort enthält die Liste der von Bash ausgeführten Skripte, unabhängig vom Inhalt der Skripte. Wenn das Skript selbst die Zeile enthält [ -z "$PS1" ] && return, würde dies natürlich wirksam, aber ich denke nicht, dass dies bedeuten sollte, dass ich die ändern sollte Tabelle.
Flimm
5

EIN BESSERER KOMMENTAR FÜR DEN KOPF VON / ETC / PROFILE

Aufbauend auf der großartigen Antwort von Flimm oben habe ich diesen neuen Kommentar an der Spitze meines Debian / etc / -Profils eingefügt (möglicherweise müssen Sie ihn für Ihre Distribution anpassen) :

# For BASH: Read down the appropriate column. Executes A, then B, then C, etc.
# The B1, B2, B3 means it executes only the first of those files found.  (A)
# or (B2) means it is normally sourced by (read by and included in) the
# primary file, in this case A or B2.
#
# +---------------------------------+-------+-----+------------+
# |                                 | Interactive | non-Inter. |
# +---------------------------------+-------+-----+------------+
# |                                 | login |    non-login     |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   ALL USERS:                    |       |     |            |
# +---------------------------------+-------+-----+------------+
# |BASH_ENV                         |       |     |     A      | not interactive or login
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile                     |   A   |     |            | set PATH & PS1, & call following:
# +---------------------------------+-------+-----+------------+
# |/etc/bash.bashrc                 |  (A)  |  A  |            | Better PS1 + command-not-found 
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/bash_completion.sh|  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/vte-2.91.sh       |  (A)  |     |            | Virt. Terminal Emulator
# |/etc/profile.d/vte.sh            |  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   A SPECIFIC USER:              |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_profile    (bash only)   |   B1  |     |            | (doesn't currently exist) 
# +---------------------------------+-------+-----+------------+
# |~/.bash_login      (bash only)   |   B2  |     |            | (didn't exist) **
# +---------------------------------+-------+-----+------------+
# |~/.profile         (all shells)  |   B3  |     |            | (doesn't currently exist)
# +---------------------------------+-------+-----+------------+
# |~/.bashrc          (bash only)   |  (B2) |  B  |            | colorizes bash: su=red, other_users=green
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_logout                   |    C  |     |            |
# +---------------------------------+-------+-----+------------+
#
# ** (sources !/.bashrc to colorize login, for when booting into non-gui)

Und dieser Hinweis am Kopf jeder der anderen Setup-Dateien, um darauf zu verweisen:

# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE

Bemerkenswert finde ich, dass Debians / etc / profile standardmäßig /etc/bash.bashrc (also /etc/bash.bashrc) enthält. So lesen Anmeldeskripte beide / etc-Dateien, während Nicht-Anmeldeskripte nur bash.bashrc lesen.

Zu beachten ist auch, dass /etc/bash.bashrc so eingestellt ist, dass es nichts tut, wenn es nicht interaktiv ausgeführt wird. Diese beiden Dateien sind also nur für interaktive Skripte gedacht.

Elliptische Ansicht
quelle
4

Die Konfigurationslogik von bash selbst ist nicht verrückt kompliziert und wird in anderen Antworten auf dieser Seite, auf serverfault und in vielen Blogs erklärt. Das Problem ist jedoch, was die Linux-Distributionen aus bash machen , ich meine die komplexen und verschiedenen Arten, wie sie bash standardmäßig konfigurieren. http://mywiki.wooledge.org/DotFiles erwähnt einige dieser Macken kurz. Hier ist ein Beispiel-Trace für Fedora 29, der zeigt, welche Dateien welche anderen Dateien in welcher Reihenfolge als Quelle haben: Remote-Verbindung mit ssh und Starten einer weiteren Subshell:

ssh fedora29
 └─ -bash # login shell
      ├── /etc/profile
      |    ├─ /etc/profile.d/*.sh
      |    ├─ /etc/profile.d/sh.local
      |    └─ /etc/bashrc
      ├── ~/.bash_profile
      |    └─ ~/.bashrc
      |          └─ /etc/bashrc
      |
      |
      └─ $ bash  # non-login shell
            └─ ~/.bashrc
                 └─ /etc/bashrc
                       └─ /etc/profile.d/*.sh

Fedoras komplexeste Logik ist in /etc/bashrc. Wie oben zu sehen /etc/bashrcist, weiß eine Datei Bash selbst nichts, ich meine nicht direkt. Fedoras /etc/bashrcTests, ob:

  • es wird von einer Login-Shell bezogen,
  • es wird von einer interaktiven Shell bezogen,
  • es wurde bereits beschafft

... und macht dann ganz andere Sachen je nachdem.

Wenn Sie denken, dass Sie sich an das obige Diagramm erinnern können, ist dies zu schade, da es bei weitem nicht ausreicht: Dieses Diagramm beschreibt nur ein einziges Szenario. Beim Ausführen nicht interaktiver Skripte oder Starten einer grafischen Sitzung treten geringfügig andere Probleme auf. Ich habe weggelassen ~/.profile. Ich habe bash_completionSkripte weggelassen . Aus Gründen der Abwärtskompatibilität wird durch Aufrufen von bash as /bin/shstatt /bin/bashdessen Verhalten geändert. Was ist mit zsh und anderen Shells? Und natürlich machen verschiedene Linux-Distributionen die Dinge anders, zum Beispiel werden Debian und Ubuntu mit einer nicht-standardmäßigen Version von bas h ausgeliefert, es hat Debian-spezifische Anpassungen. Es sucht insbesondere nach einer ungewöhnlichen Datei:/etc/bash.bashrc. Selbst wenn Sie sich an eine einzelne Linux-Distribution halten, entwickelt sich diese wahrscheinlich im Laufe der Zeit weiter. Warten Sie: Wir haben noch nicht einmal MacOS, FreeBSD, ... angerührt. Lassen Sie uns zum Schluss einen Gedanken über die noch kreativeren Methoden machen, mit denen die Administratoren das zu verwendende System konfiguriert haben.

Wie der endlose Strom von Diskussionen zu diesem Thema zeigt, ist es eine verlorene Sache. Solange Sie nur neue Werte hinzufügen möchten, ist ein gewisser "Versuch und Irrtum" in der Regel ausreichend. Der wahre Spaß beginnt, wenn Sie in einer (Benutzer-) Datei etwas ändern möchten, das bereits in einer anderen (in / etc) definiert ist. Stellen Sie sich dann darauf ein, einige Zeit mit der Entwicklung einer Lösung zu verbringen, die niemals portabel sein wird.

Für ein letztes bisschen Spaß ist hier das "Quelldiagramm" für das gleiche, einfache Szenario unter Clear Linux ab Juni 2019:

ssh clearlinux
 └─ -bash # login shell
      ├── /usr/share/defaults/etc/profile
      |    ├─ /usr/share/defaults/etc/profile.d/*
      |    ├─ /etc/profile.d/*
      |    └─ /etc/profile
      ├── ~/.bash_profile
      |
      |
      └─  $ bash   # non-login shell
           ├─ /usr/share/defaults/etc/bash.bashrc
           |      ├─ /usr/share/defaults/etc/profile
           |      |    ├─ /usr/share/defaults/etc/profile.d/*
           |      |    ├─ /etc/profile.d/*
           |      |    └─ /etc/profile
           |      └─ /etc/profile
           └─ ~/.bashrc
März
quelle