Różnica między .bashrc a .bash_profile
Jaka jest różnica między .bashrc
i .bash_profile
i którego z nich powinienem użyć?
Jaka jest różnica między .bashrc
i .bash_profile
i którego z nich powinienem użyć?
Tradycyjnie, gdy logujemy się do systemu Unix, system uruchamia dla nas jeden program. Ten program to powłoka, tj. program zaprojektowany do uruchamiania innych programów. Jest to powłoka wiersza poleceń: uruchamiasz inny program przez wpisanie jego nazwy. Domyślna powłoka, powłoka Bourne'a, czyta polecenia z ~/.profile
, gdy jest wywoływana jako powłoka logowania.
Bash jest powłoką podobną do powłoki Bourne'a. Odczytuje ona polecenia z ~/.bash_profile
gdy jest wywoływana jako powłoka zgłoszeniowa, a jeśli plik ten nie istnieje¹, to próbuje odczytać ~/.profile
zamiast niego.
Powłokę można wywołać bezpośrednio w dowolnym momencie, na przykład uruchamiając emulator terminala wewnątrz środowiska GUI. Jeżeli powłoka nie jest powłoką zgłoszeniową, to nie czyta ~/.profile
. Gdy uruchamiasz bash jako powłokę interaktywną (tj. nie po to, by uruchomić skrypt), czyta on ~/.bashrc
(z wyjątkiem sytuacji, gdy jest wywoływany jako powłoka zgłoszeniowa, wtedy czyta tylko ~/.bash_profile
lub ~/.profile
.
Dlatego:
~/.profile
jest miejscem do umieszczania rzeczy, które dotyczą całej sesji, takich jak programy, które chcesz uruchomić po zalogowaniu (ale nie programy graficzne, one trafiają do innego pliku), oraz definicje zmiennych środowiskowych.
~/.bashrc
jest miejscem do umieszczania rzeczy, które dotyczą tylko samego basha, takich jak definicje aliasów i funkcji, opcje powłoki i ustawienia zachęty. (Można tam również umieścić przypisania klawiszy, ale dla basha zwykle trafiają one do ~/.inputrc
).
~/.bash_profile
może być używane zamiast ~/.profile
, lecz jest ono odczytywane tylko przez bash, a nie przez inną powłokę. (Jest to głównie zmartwienie, jeśli chcesz by twoje pliki inicjalizacyjne działały na wielu maszynach, a twoją powłoką logowania nie jest bash na wszystkich). Jest to logiczne miejsce do umieszczenia ~/.bashrc
jeśli powłoka jest interaktywna. Zalecam następującą zawartość w ~/.bash_profile
:
Na nowoczesnych jednostkach, istnieje dodatkowa komplikacja związana z ~/.profile
. Jeśli logujesz się w środowisku graficznym (to znaczy, jeśli program, w którym wpisujesz swoje hasło, działa w trybie graficznym), nie otrzymasz automatycznie powłoki logowania, która czyta ~/.profile
. W zależności od graficznego programu logowania, menedżera okien lub środowiska graficznego, które uruchamiasz później, oraz od tego, jak twoja dystrybucja skonfigurowała te programy, twoje ~/.profile
może, ale nie musi być odczytane. Jeśli nie jest, zwykle jest inne miejsce, gdzie możesz zdefiniować zmienne środowiskowe i programy do uruchomienia po zalogowaniu, ale niestety nie ma standardowej lokalizacji.
Zauważ, że możesz zobaczyć tu i ówdzie zalecenia, by albo umieszczać definicje zmiennych środowiskowych w ~/.bashrc
, albo zawsze uruchamiać powłoki logowania w terminalach. Oba te pomysły są złe. Najczęstszym problemem z każdym z tych pomysłów jest to, że twoje zmienne środowiskowe będą ustawiane tylko w programach uruchamianych przez terminal, a nie w programach uruchamianych bezpośrednio za pomocą ikony, menu lub skrótu klawiaturowego.
¹ Dla kompletności, na żądanie: jeśli .bash_profile
nie istnieje, bash próbuje także .bash_login
przed powrotem do .profile
. Nie krępuj się zapomnieć, że istnieje.
Z tego krótki artykuł
Według strony man bash, .bash_profile jest wykonywany dla powłok logowania, podczas gdy .bashrc jest wykonywany dla interaktywnych powłok niezalogowania.
*Co to jest powłoka logowania lub nielogowania? *
Kiedy logujesz się (np. wpisujesz nazwę użytkownika i hasło) przez konsolę, albo fizycznie siedząc przy maszynie podczas uruchamiania, albo zdalnie przez ssh: .bash_profile jest wykonywany, by skonfigurować rzeczy przed początkowym znakiem zachęty.
Ale, jeśli już zalogowałeś się na maszynę i otworzysz nowe okno terminala (xterm) w Gnome lub KDE, wtedy .bashrc jest wykonywany przed oknem zachęty poleceń. .bashrc jest również uruchamiany, gdy rozpoczynasz nową instancję bash przez wpisanie /bin/bash w terminalu.
W dawnych czasach, kiedy pseudo tty nie były pseudo i faktycznie, cóż, pisało się na nich, a UNIXy były dostępne przez modemy tak wolne, że można było zobaczyć każdą literę drukowaną na ekranie, wydajność była najważniejsza. Aby nieco wspomóc wydajność, miałeś koncepcję głównego okna logowania i innych okien, których używałeś do pracy. W głównym oknie chciałbyś otrzymywać powiadomienia o nowej poczcie, ewentualnie uruchamiać inne programy w tle.
Aby to obsłużyć, powłoki pozyskały plik .profile
specjalnie na ‘powłoki logowania’. Wykonywałby on specjalne czynności, po skonfigurowaniu sesji. Bash rozszerzył to nieco, by spojrzeć najpierw na .bash przed .profile, w ten sposób można tam umieszczać tylko rzeczy związane z bashem (by nie spieprzyły powłoki Bourne'a, itp, która także patrzyła na .profile). Inne powłoki, nie-loginowe, będą po prostu pochodzić z pliku rc, .bashrc (lub .kshrc, etc).
To jest teraz trochę anachronizm. Nie logujesz się do głównej powłoki tak bardzo, jak logujesz się do menedżera okien gui. Nie ma głównego okna, które różniłoby się od każdego innego okna.
Moja sugestia - nie przejmuj się tą różnicą, jest ona oparta na starszym stylu używania Uniksa. Zlikwiduj tę różnicę w swoich plikach. Cała zawartość .bash_profile powinna być:
[-f $HOME/.bashrc] && . $HOME/.bashrc
A wszystko, co faktycznie chcesz ustawić, umieść w .bashrc
Pamiętaj, że .bashrc jest źródłowa dla wszystkich powłok, interaktywnych i nieinteraktywnych. Możesz skrócić źródło dla powłok nie-interaktywnych, umieszczając ten kod na górze .bashrc:
[[$- != *i*]] && return
Spójrz na ten doskonały wpis na blogu autorstwa ShreevatsaR . Oto fragment, ale przejdź do wpisu na blogu, zawiera on wyjaśnienie terminów takich jak “powłoka logowania”, schemat blokowy i podobną tabelę dla Zsh.
Dla Bash, działają one w następujący sposób. Przeczytaj w dół odpowiednią kolumnę. Wykonuje A, potem B, potem C, itd. B1, B2, B3 oznacza, że wykona tylko pierwszy z tych znalezionych plików.
+----------------+-----------+-----------+------+
| |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 | | |
+----------------+-----------+-----------+------+
BETTER COMMENT FOR THE HEAD OF /ETC/PROFILE
Bazując na świetnej odpowiedzi Flimma powyżej, umieściłem ten nowy komentarz w nagłówku mojego Debiana /etc/profile, (możesz potrzebować dostosować go do swojego distro.):
# 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)
I ta uwaga w nagłówku każdego z pozostałych plików konfiguracyjnych, aby się do niego odnieść:
# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE
Warte zauważenia jest to, że /etc/profile Debiana domyślnie pochodzi (zawiera) /etc/bash.bashrc (to wtedy, gdy /etc/bash.bashrc istnieje). Tak więc skrypty logowania czytają oba pliki /etc, podczas gdy skrypty niezalogowane czytają tylko bash.bashrc.
Warto również zauważyć, że /etc/bash.bashrc jest ustawiony tak, aby nic nie robił, gdy nie jest uruchamiany interaktywnie. Więc te dwa pliki są tylko dla interaktywnych skryptów.
Logika konfiguracji samego basha nie jest szalenie skomplikowana i wyjaśniona w innych odpowiedziach na tej stronie, na serverfault i na wielu blogach. Problemem jest jednak co dystrybucje Linuksa robią z basha, mam na myśli skomplikowane i różne sposoby, na jakie domyślnie konfigurują basha. http://mywiki.wooledge.org/DotFiles ](http://mywiki.wooledge.org/DotFiles) wspomina krótko o niektórych z tych dziwactw. Oto jeden przykładowy ślad na Fedorze 29, pokazuje on, które pliki są źródłem którego innego pliku(ów) i w jakiej kolejności dla bardzo prostego scenariusza: zdalne połączenie z ssh, a następnie uruchomienie innej podpowłoki:
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
Najbardziej złożona logika Fedory znajduje się w /etc/bashrc
. Jak widać powyżej /etc/bashrc
jest plikiem, o którym bash nie wie, to znaczy nie bezpośrednio. Fedora w /etc/bashrc
testuje, czy:
… a następnie w zależności od tego robi zupełnie inne rzeczy.
Jeśli myślisz, że pamiętasz powyższy wykres, to szkoda, bo to nie wystarczy: ten wykres opisuje tylko jeden scenariusz, nieco inne rzeczy dzieją się przy uruchamianiu nieinteraktywnych skryptów lub uruchamianiu sesji graficznej. Pominąłem ~/.profile
. Pominąłem skrypty bash_completion
. Ze względu na kompatybilność wsteczną, wywołanie basha jako /bin/sh
zamiast /bin/bash
zmienia jego zachowanie. A co z zsh i innymi powłokami? I oczywiście różne dystrybucje Linuksa robią różne rzeczy inaczej, na przykład Debian i Ubuntu mają niestandardową wersję bash, ma ona specyficzne dla Debiana dostosowania. W szczególności szuka on nietypowego pliku: /etc/bash.bashrc
. Nawet jeśli trzymasz się jednej dystrybucji Linuksa, prawdopodobnie ewoluuje ona z czasem. Czekaj: nie dotknęliśmy jeszcze macOS, FreeBSD,… Na koniec pomyślmy o użytkownikach, którzy utknęli w jeszcze bardziej kreatywnych sposobach, w jakie ich administratorzy skonfigurowali system, z którego muszą korzystać.
Jak pokazuje niekończący się strumień dyskusji na ten temat, jest to stracona sprawa. Tak długo, jak chcesz tylko dodawać nowe wartości, niektóre “próby i błędy” wydają się wystarczające. Prawdziwa zabawa zaczyna się, gdy chcesz zmodyfikować w jednym pliku (użytkownika) coś, co jest już zdefiniowane w innym (w /etc). Wtedy należy być przygotowanym na spędzenie trochę czasu na konstruowaniu rozwiązania, które nigdy nie będzie przenośne.
Dla ostatniej odrobiny zabawy oto “wykres źródłowy” dla tego samego, prostego scenariusza na Clear Linux na czerwiec 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