Pliki startowe Zsh: .zprofile a .zshrc w systemach macOS i Linux
Tłumaczenie automatyczne Ten artykuł został automatycznie przetłumaczony z angielskiego oryginału.
Jeśli terminal działa wolno albo zmienna środowiskowa pojawia się w jednym terminalu, ale nie w innym, przyczyną często jest tryb uruchamiania Zsh. Dwa pliki, po które najczęściej sięgamy, to ~/.zprofile i ~/.zshrc, ale sama nazwa pliku nie mówi jeszcze, czy dana linia powinna się w nim znaleźć.
Zsh wybiera pliki startowe na podstawie dwóch niezależnych właściwości: tego, czy powłoka jest powłoką logowania, oraz tego, czy jest interaktywna. Aplikacje terminalowe w systemach macOS i Linux mogą wybierać różne kombinacje, dlatego zamiast zakładać, że decyduje o tym system operacyjny, sprawdź uruchomioną powłokę.
W skrócie. Umieść inicjalizację sesji logowania w
.zprofile, a zachowanie interaktywne w.zshrc. Zachowaj.zshenvw stanie cichym i minimalistycznym, gdy ustawiona jestRCS. Nie przenoś interaktywnych hooków menedżerów wersji do.zprofileani nie wczytuj całego profilu z.zshrc; sprawdź kod generowany przez dane narzędzie i postępuj zgodnie z jego aktualnymi instrukcjami dotyczącymi Zsh.
Zsh ocenia dwie niezależne flagi
Powłoka może być:
- logowania i interaktywna, gdy Apple Terminal jest skonfigurowany tak, aby uruchamiać domyślną powłokę logowania konta
- niebędąca powłoką logowania, ale interaktywna, jak zagnieżdżona
zshlub w wielu konfiguracjach terminali w systemie Linux - logowania i nieinteraktywna, jak
zsh -lc 'command' - niebędąca powłoką logowania i nieinteraktywna, jak
zsh -c 'command'
Aplikacje terminalowe, IDE, sesje zdalne, multipleksery i jawne flagi powłoki mogą wybierać różne tryby, dlatego sam system operacyjny nie określa wyniku.
Zapytaj uruchomioną powłokę, zamiast zgadywać:
print -r -- "interactive=$options[interactive] login=$options[login]"
Rzeczywista kolejność plików startowych
Zsh wczytuje pliki globalne, a następnie odpowiedni plik użytkownika. Przy domyślnych opcjach RCS kolejność plików użytkownika jest następująca:
$ZDOTDIR/.zshenvprzy każdym uruchomieniu Zsh$ZDOTDIR/.zprofile, jeśli powłoka jest powłoką logowania$ZDOTDIR/.zshrc, jeśli powłoka jest interaktywna$ZDOTDIR/.zlogin, jeśli powłoka jest powłoką logowania$ZDOTDIR/.zlogoutprzy normalnym zakończeniu powłoki logowania
Jeśli ZDOTDIR nie jest ustawiona, Zsh używa $HOME. Lokalizacje plików systemowych zależą od instalacji; typowe wartości domyślne to /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin i /etc/zlogout (podręcznik Zsh).
zsh -f rozpoczyna działanie z wyłączoną RCS, więc zwykle pomija wymienione wyżej pliki użytkownika $ZDOTDIR; /etc/zshenv jest zawsze wczytywany i może zmienić tę opcję.
.zprofile jest wykonywany raz dla każdego procesu powłoki logowania, a nie raz na logowanie do komputera. Jeśli każda nowa karta terminala uruchamia powłokę logowania, każda karta go wczyta.
Co powinno znajdować się w każdym pliku
| Plik | Reguła wyboru | Dobry wybór | Czego unikać |
|---|---|---|---|
.zshenv | Każdy Zsh z ustawioną RCS | Rzadko używane zmienne wymagane przez każdy proces Zsh | wyjście, aliasy, prompty, wywołania sieciowe, wolne polecenia |
.zprofile | Powłoki logowania | konfiguracja ścieżki sesji logowania i eksportowane wartości domyślne | hooki interaktywne, uzupełnianie, mapowania klawiszy |
.zshrc | Powłoki interaktywne | prompt, uzupełnianie, aliasy, opcje powłoki, interaktywne hooki narzędzi | wyjście lub modyfikacje przeznaczone dla skryptów |
.zlogin | Powłoki logowania, po .zshrc | rzadkie działania wykonywane po interaktywnej sesji logowania | konfiguracja, która musi poprzedzać .zshrc |
.zlogout | Zakończenie powłoki logowania | niewielkie działania czyszczące lub reset terminala | ważny stan, który musi przetrwać awarię lub exec |
Zachowaj .zshenv w prostym stanie, gdy ustawiona jest RCS
Gdy ustawiona jest RCS, każda nieinteraktywna zsh -c wczytuje .zshenv (podręcznik Zsh). echo, wywołanie menedżera pakietów lub kosztowny podproces w tym miejscu może uszkodzić wyjście poleceń i spowolnić skrypty. Większość użytkowników potrzebuje w tym pliku niewiele albo niczego.
Zmienna eksportowana w .zprofile jest dziedziczona przez procesy potomne tej powłoki logowania. Nie jest automatycznie wstrzykiwana do niezależnych aplikacji GUI, usług ani powłok, których proces nadrzędny nie wczytał tego pliku.
Użyj .zprofile do konfiguracji wyłącznie dla sesji logowania
Niewielki profil może ustawić eksportowane wartości domyślne i idempotentną ścieżkę:
# ~/.zprofile
export EDITOR=nvim
export VISUAL=nvim
# Zsh ties the path array to the PATH scalar.
typeset -U path PATH
path=("$HOME/.local/bin" $path)
export PATH
typeset -U usuwa zduplikowane elementy tablicy. Dzięki temu wielokrotne wczytywanie jest bezpieczniejsze, choć pliki startowe nadal powinny unikać zbędnej pracy.
Użyj .zshrc do konfiguracji stanu interaktywnego
# ~/.zshrc
setopt auto_cd hist_ignore_all_dups share_history
autoload -Uz compinit
compinit
alias ll='ls -lah'
bindkey -e
Aliasy, widgety uzupełniania, mapowania klawiszy, prompty i hooki zmiany katalogu należą do interaktywnej powłoki, która z nich korzysta.
Menedżery wersji wykraczają poza prosty podział plików
Rada „umieść menedżery wersji w .zprofile, bo działają wolno” jest zawodna. Menedżer wersji może generować kilka rodzajów kodu:
- statyczną ścieżkę lub zmienną root
- ścieżkę do command shim potrzebną procesom potomnym
- definicje uzupełniania
- funkcje powłoki zmieniające bieżącą powłokę
- hooki zmiany katalogu służące do automatycznego przełączania wersji
Części interaktywne muszą istnieć w każdej interaktywnej powłoce, w tym w zagnieżdżonej zsh uruchomionej z edytora. Dlatego aktualna konfiguracja fnm dla Zsh umieszcza ten hook w .zshrc:
eval "$(fnm env --use-on-cd --shell zsh)"
Aktualna konfiguracja pyenv dla Zsh również umieszcza pełną inicjalizację interaktywną w .zshrc:
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && path=("$PYENV_ROOT/bin" $path)
eval "$(pyenv init - zsh)"
Dokumentacja Pyenv opisuje węższy tryb pyenv init --path służący do konfiguracji ścieżki shimów, natomiast pełne pyenv init instaluje również uzupełnianie i funkcje powłoki. Zanim rozdzielisz konfigurację, sprawdź aktualną dokumentację narzędzia i generowane przez nie dane wyjściowe.
Jeśli uruchamianie jest wolne, najpierw zmierz jego czas, a dopiero potem przenoś kod do trybu, w którym przestanie działać.
Nie wczytuj całego profilu z .zshrc
Często spotykane obejście problemów między platformami wygląda tak:
# Avoid this blanket coupling.
source ~/.zprofile
Zmienia ono działania wykonywane wyłącznie podczas logowania w działania wykonywane przy każdej interaktywnej powłoce i może powtarzać uruchamianie agenta, dostęp do keychaina, wyjście lub modyfikowanie ścieżki.
Jeśli zarówno interaktywne powłoki logowania, jak i powłoki niebędące powłokami logowania potrzebują niewielkiego zestawu statycznych eksportów, wyodrębnij idempotentny fragment i wczytuj go jawnie:
# ~/.config/zsh/environment.zsh
typeset -U path PATH
path=("$HOME/.local/bin" $path)
export PATH EDITOR=nvim VISUAL=nvim
# ~/.zprofile
source "$HOME/.config/zsh/environment.zsh"
# ~/.zshrc
if [[ ! -o login ]]; then
source "$HOME/.config/zsh/environment.zsh"
fi
# Interactive-only configuration follows.
Ten wzorzec oddziela współdzielone dane od efektów ubocznych logowania. Inną poprawną opcją jest spójne skonfigurowanie terminala lub menedżera sesji zamiast obsługiwania obu trybów.
Diagnozowanie powolnej powłoki lub brakującego stanu
Odtwórz bezpośrednio każdy tryb:
zsh -lic 'print "login interactive"'
zsh -ic 'print "non-login interactive"'
zsh -lc 'print "login non-interactive"'
zsh -c 'print "non-login non-interactive"'
Zmierz tryb faktycznie uruchamiany przez użytkowników:
time zsh -lic exit
time zsh -ic exit
Śledź wykonywanie plików i poszczególnych linii, gdy źródło problemu nie jest jasne:
PS4='%N:%i> ' zsh -xlic exit
Uruchom śledzenie na czystym koncie testowym albo sprawdź je przed udostępnieniem: polecenia startowe mogą rozwinąć tokeny i inne poufne wartości.
W przypadku brakującego pliku wykonywalnego sprawdź zarówno tryb, jak i ścieżkę:
print -r -- "interactive=$options[interactive] login=$options[login]"
print -l -- $path
whence -va python node uv
Podsumowanie
Najważniejsze rozróżnienie nie przebiega między „środowiskiem a aliasami”. Chodzi o stan wyłącznie dla sesji logowania i stan interaktywny, a także o niewielką część konfiguracji, która musi wpływać na każdy proces Zsh, gdy ustawiona jest RCS.
Potwierdź flagi powłoki, zachowaj ciszę plików startowych i umieść każdy generowany hook w miejscu, w którym dostępne są wszystkie wymagane przez niego funkcje. Dzięki temu konfiguracja będzie przenośna między aplikacjami terminalowymi, bez udawania, że systemy macOS i Linux mają po jednym stałym trybie uruchamiania.