Wybieranie między .bashrc, .profile, .bash_profile itp. [Duplikat]

197

To pytanie ma już odpowiedź tutaj:

Jest to kłopotliwe, ale po wielu latach korzystania z systemów POSIX w pełnym wymiarze czasu, nadal mam twardy czas na zastanawianie się, czy personalizacja powłoki powinny iść w .bashrc, .profilelub gdzieś indziej. Nie wspominając o niektórych plikach konfiguracyjnych specyficznych dla systemu operacyjnego, takich jak .pam_environment.

Tak, wiem, jak rozwiązywać problemy z dokumentacją i dowiedzieć się, kiedy każdy plik jest ładowany lub nie. Zastanawiam się, czy ktokolwiek opracował wyczerpujące wytyczne, jak zdecydować, w którym pliku umieścić dany typ dostosowania.

Avdi
źródło
6
to pytanie nie powinno być oznaczone jako duplikat, ponieważ .profil nie jest dostępny w dodanym pytaniu.
Premraj,

Odpowiedzi:

222

TL; DR:

  • ~/.bash_profilepowinno być super proste i po prostu ładować .profilei .bashrc(w tej kolejności)

  • ~/.profilema rzeczy NIE związane konkretnie z bash, takie jak zmienne środowiskowe ( PATHi znajomi)

  • ~/.bashrcma cokolwiek chcesz w interaktywnym wierszu poleceń. Wiersz polecenia, EDITORzmienne, aliasy bash na mój użytek

Kilka innych uwag:

  • Wszystko, co powinno być dostępne dla aplikacji graficznych LUB dla sh (lub bash wywoływanego jako sh) MUSI być w~/.profile

  • ~/.bashrc nie wolno niczego wyprowadzać

  • Powinno się tam znaleźć wszystko, co powinno być dostępne tylko do logowania ~/.profile

  • Upewnij się, że ~/.bash_loginnie istnieje.

Dan Rabinowitz
źródło
3
+1, pozwala ~/.profileto poprawnie ustawić środowisko dla usług takich jak GDM / LightDM / LXDM, które jawnie uruchamiają / bin / sh.
grawity
12
Moje .bashrcwyniki to całkiem sporo, czy możesz to skomentować? W szczególności, gdzie powinienem umieścić wyjście z pozdrowieniami?
Calimo
14
@ Calimo: Ustaw, aby wyświetlał tylko rzeczy w trybie interaktywnym. Możesz to sprawdzić za pomocą [[ $- == *i* ]], tzn. Szukając „i” w $-zmiennej specjalnej . Oczywiście ma to znaczenie przede wszystkim w systemach, w których bash jest kompilowany do odczytu .bashrcw trybie nieinteraktywnym. (To znaczy, Debian, ale nie Arch.) Ale to jest częstą przyczyną tajemniczych komunikatów o błędach podczas próby połączenia przy użyciu sftplub scplub podobnych narzędzi.
grawity
4
Teraz muszę wiedzieć - dlaczego .bash_login nie powinien istnieć? Co to robi?
tedder42
11
@ tedder42: Robi to samo co .bash_profilei .profile. Ale bash czyta tylko pierwszy z trzech. Czyli, jeśli masz .bash_login, a następnie oba .profilei .bash_profilebędzie tajemniczo ignorowane.
grawity
54

W ciągu ostatnich kilku lat, miałem dużo czasu do stracenia, więc zostały zbadane to na nieco ponad 10 minut. Nie mam pojęcia, czy jest to najlepszy układ, tylko taki, który działa poprawnie w prawie wszystkich przypadkach.

Wymagania:

  • ~/.profile musi być kompatybilny z dowolnym / bin / sh - dotyczy to bash, dash, ksh, czegokolwiek innego, z czego może skorzystać dystrybucja.

  • Zmienne środowiskowe muszą być umieszczone w pliku odczytywanym zarówno przez loginy konsoli (tj. Powłokę „login”), jak i loginy graficzne (tj. Menedżery wyświetlania, takie jak GDM, LightDM lub LXDM).

  • Nie ma sensu mieć obu ~/.profile i ~/.bash_profile. Jeśli tego drugiego brakuje, bash z przyjemnością użyje tego pierwszego, a wszelkie linie specyficzne dla basha mogą być strzeżone za pomocą czeku na $BASHlub $BASH_VERSION.

  • Odstęp między *profilei *rcpolega na tym, że ten pierwszy służy do powłok logowania, a drugi za każdym razem, gdy otwierasz okno terminala. Jednak bash w trybie „logowania” nie jest źródłem ~/.bashrc, dlatego ~/.profilemusi to zrobić ręcznie.

Najprostsza konfiguracja będzie:

  • Niech a ~/.profileustawia wszystkie zmienne środowiskowe (oprócz tych specyficznych dla bash), być może drukuje linię lub dwie, a następnie źródła, ~/.bashrcjeśli są uruchamiane przez bash, w przeciwnym razie trzymają się składni kompatybilnej z sh.

    eksport TZ = „Europa / Paryż”
    eksport EDITOR = "vim"
    jeśli [„$ BASH”]; następnie
        . ~ / .bashrc
    fi
    czas pracy
    
  • Niech a ~/.bashrcwykona konfigurację specyficzną dla powłoki, strzeżoną przez sprawdzenie trybu interaktywnego, aby uniknąć zepsucia rzeczy takich jak sftpna Debianie (gdzie bash jest kompilowany z opcją ładowania ~/.bashrcnawet dla nieinteraktywnych powłok):

    [[$ - == * i *]] || zwróć 0
    
    PS1 = „\ h \ w \ $”
    
    start () {usługa sudo „$ 1” start; }
    

Istnieje jednak problem polegający na tym, że niektóre nieinteraktywne polecenia (np. ssh <host> ls) Pomijają ~/.profile, ale zmienne środowiskowe byłyby dla nich bardzo przydatne.

  • Niektóre dystrybucje (np. Debian) kompilują swój bash z opcją źródła ~/.bashrcdla takich nieinteraktywnych loginów. W tym przypadku uważam, że użyteczne jest przeniesienie wszystkich zmiennych środowiskowych ( export ...wierszy) do osobnego pliku ~/.environ, i źródło ich z obu .profile oraz .bashrc, ze strażnikiem, aby uniknąć zrobienia tego dwa razy:

    Jeśli ! [„$ PREFIX”]; następnie    # lub $ EDITOR lub $ TZ, albo ... 
        . ~ / .environ            # ogólnie każda zmienna, którą sam ustawiłby .environ
    fi
    
  • Niestety w przypadku innych dystrybucji (np. Arch) nie znalazłem bardzo dobrego rozwiązania. Jedną z możliwości jest użycie (domyślnie włączonego) modułu PAM pam_env, wprowadzając następujące elementy ~/.pam_environment:

    BASH_ENV =. /. Environment         # nie literówka; musi to być ścieżka, ale ~ nie będzie działać
    

    Potem oczywiście aktualizacja ~/.environdo unset BASH_ENV.


Wniosek? Muszle to ból. Zmienne środowiskowe są uciążliwe. Opcje czasu kompilacji specyficzne dla dystrybucji są ogromnym bólem w dupie.

grawitacja
źródło
2
+1 do ostatniego akapitu, ale wolę pozyskiwania .profilei .bashrcod .bash_profilei utrzymanie .profileczystości.
nyuszika7h
@ nyuszika7h: Mój .profile jest czysty , dzięki.
grawitacja
1
Zwróć uwagę, że komentarz dotyczący każdego otwarcia okna jest odwrotny dla OSX
Mark
1
„Jest bardzo mało sensu posiadające zarówno ~/.profilei ~/.bash_profile”: I disdagree. Zobacz odpowiedź Dana, dlaczego.
rubenvb
@rubenvb Czy możesz podać odpowiednią część? Myślę, że dobrze jest mieć tylko .profilei chronić bashczęści specyficzne za pomocą warunkowych.
Kelvin
36

Obejrzyj ten znakomity post na blogu autorstwa ShreevatsaR . Oto wyciąg, ale przejdź do postu na blogu, zawiera wyjaśnienie terminów takich jak „powłoka logowania”, schemat blokowy i podobna tabela dla Zsh.

W przypadku Bash działają one w następujący sposób. Przeczytaj odpowiednią kolumnę. Wykonuje A, następnie B, a następnie C itd. B1, B2, B3 oznacza, że ​​wykonuje tylko pierwszy ze 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      |           |      |
+----------------+-----------+-----------+------+
Flimm
źródło
To jest miłe. Ważne jest, aby pamiętać, że zwykle /etc/profilepołączenia /etc/bash.bashrci ~/.profilepołączenia ~.bashrc. Tak skutecznie /etc/bash.bashrci ~/.bashrcsą również wykonywane dla Logowań interaktywnych.
wisbucky,
Zauważ, że niektóre dystrybucje wydają się zastępować ten schemat (z dziwnymi konsekwencjami) - patrz np. Mój raport o błędzie do opensuse tutaj: bugzilla.opensuse.org/show_bug.cgi?id=1078124
Christian Herenz
Btw. przynajmniej przy bash żaden z tych plików nie jest wykonywany, gdy bash jest wywoływany przez/bin/sh
JepZ
@JepZ Masz rację, tak wyjaśnia trzecia kolumna „Skrypt”.
Flimm
1
@Flimm Cóż, kolumna „Skrypt” opisuje, co dzieje się, gdy uruchamiasz nieinteraktywny skrypt za pomocą bash (np. / Bin / bash). Jeśli jednak uruchomisz skrypt za pomocą sh (a / bin / sh jest dowiązaniem symbolicznym do / bin / bash), żadne z powyższych nie zostanie wykonane (nawet nie BASH_ENV). Powiązany akapit strony podręcznika bash można znaleźć, wyszukując If bash is invoked with the name sh.
JepZ
21

Oferuję ci moje „kompleksowe” wytyczne:

  • Wykonaj .bash_profilei .profilezaładuj, .bashrcjeśli istnieje, używając np [ -r $HOME/.bashrc ] && source $HOME/.bashrc
  • Włóż wszystko inne .bashrc.
  • Przestań się martwić.
  • Co około cztery lata poświęć dziesięć minut na badanie tego samego pytania, zanim poddasz się i wrócisz do „nie martwienia się”.

EDYCJA: Dodano przestraszone cytaty do „kompleksowych” na wypadek, gdyby ktoś miał ochotę w to uwierzyć. ;)

Ryba mechaniczna
źródło
3
Posiadanie obu .bash_profilei .profilejest nieco zbędne; potrzebujesz tylko tego drugiego. Musisz jednak uczynić go / bin / sh-proof: if [ "$BASH" ] && [ -r ~/.bashrc ]; then . ~/.bashrc; fiponieważ istnieją programy (mianowicie gdm / lightdm), które ręcznie pobierają plik ze skryptu / bin / sh. Oznacza to również, że utrzymywane środowisko .bashrcbyłoby nieskuteczne. Musiałem -1, ponieważ twoje „kompleksowe” wytyczne nie będą działać na wielu systemach, jak kilkakrotnie się nauczyłem.
grawity
Nie ma problemu, z radością zapłaciłbym -1 za odpowiedź, która nie jest tylko „wyczerpującym”, i na pewno zasłużyłeś sobie na ten tytuł.
Mechanical Fish
0

Zrezygnowałem z prób rozgryzienia tego i stworzyłem jeden skrypt ( ~/.shell-setup), który pozyskuję ze wszystkich pozostałych.

To podejście wymaga ~/.shell-setupdwóch funkcji:

  1. Uruchom tylko raz, nawet jeśli są wielokrotnie pozyskiwane (użyj Dołącz osłony )
  2. Nie generuj niechcianych danych wyjściowych (wykryj, kiedy dane wyjściowe są prawidłowe)

# 1 jest dość standardowy, chociaż może nie jest często używany w skryptach powłoki.

# 2 jest trudniejsze. Oto, czego używam w bash:

if [ "" == "$BASH_EXECUTION_STRING" -a "" == "$DESKTOP_SESSION" ]; then
    echo "Hello user!" # ... etc
fi

Niestety nie pamiętam, jak to wymyśliłem ani dlaczego wykrycie interaktywnej powłoki nie było wystarczające.

ShadSterling
źródło
-2

Włóż wszystko, .bashrca następnie źródło .bashrcz.profile

Ze strony podręcznika użytkownika bash (w OS X 10.9):

Po uruchomieniu interaktywnej powłoki, która nie jest powłoką logowania, bash czyta i wykonuje polecenia z ~ / .bashrc, jeśli plik istnieje. Można temu zapobiec, używając opcji --norc. Opcja pliku --rcfile zmusi bash do odczytu i wykonywania poleceń z pliku zamiast ~ / .bashrc

Powyższy tekst jest powodem, dla którego wszystko jest włożone .bashrc. Jednak zachowanie powłoki logowania jest nieco inne. Ponownie, cytując ze strony man:

Kiedy bash jest wywoływany jako interaktywna powłoka logowania lub jako nieinteraktywna powłoka z opcją --login, najpierw czyta i wykonuje polecenia z pliku / etc / profile, jeśli plik ten istnieje. Po odczytaniu tego pliku szuka ~ / .bash_profile, ~ / .bash_login i ~ / .profile, w tej kolejności, i odczytuje i wykonuje polecenia z pierwszego, który istnieje i jest czytelny. Opcji --noprofile można użyć, gdy powłoka zostanie uruchomiona w celu zahamowania tego zachowania.

.profilejest odczytywany dla powłok logowania, ale .bashrcnie jest. Powielanie wszystkich tych rzeczy .bashrcjest złe ™, więc musimy je .profilezdobyć, aby zachowanie pozostało spójne.

Jednak nie chcemy pozyskać .bashrcod .profilebezwarunkowo. Dodatkowe informacje można znaleźć w komentarzach i innych odpowiedziach.

mattr-
źródło
4
-1, NIE źródło .bashrcz .profile. Zobacz odpowiedź @ DanRabinowitz.
nyuszika7h
Przynajmniej nie bezwarunkowo.
nyuszika7h
[ -n "$BASH" -a -f ~/.bashrc ] && . ~/.bashrcbyłby słodki oneliner dla .profile.
John WH Smith
@ nyuszika7h, dlaczego nie? Wszyscy wydają się to sugerować.
Pacerier