[!NOTE] Automatische vertaling Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.

Zsh-startopbestanden: ~/.zprofile vs ~/.zshrc op macOS en Linux

Als je terminal traag aanvoelt, of wanneer een omgevingsvariabele in de ene terminal wel verschijnt maar niet in een andere, ligt de oorzaak vaak bij de startmodus van Zsh. De twee bestanden waarna de meeste mensen op zoek gaan zijn ~/.zprofile en ~/.zshrcMaar zelfs de bestandsnaam alleen geeft geen indicatie of een regel daarin thuishoort.

Zsh kiest de startbestanden op basis van twee onafhankelijke eigenschappen: of het shell een login shell is en of het interactief is. Terminaltoepassingen op macOS en Linux kunnen verschillende combinaties kiezen; controleer daarom de actieve shell in plaats van te veronderstellen dat het besturingssysteem dit voor u beslist.

TL;DR. Plaats de initialisatie van het inlogproces-session in .zprofile en interactief gedrag in .zshrc. Houd aan. .zshenv stil en minimaal. Verplaats de interactieve hooks van de versiebeheerder niet naar binnen .zprofile of haal het hele profiel rechtstreeks op van .zshrc; Controleer de door het hulpprogramma gegenereerde code en volg de huidige instructies van Zsh.

Zsh evalueert twee onafhankelijke flaggen

Zsh-startbestanden die worden geselecteerd door de inlog- en interactieve modi

Een shell kan zijn:

Terminaltoepassingen, IDE’s, externe sessions, multiplexers en expliciete shellflags kunnen verschillende modi kiezen. Het besturingssysteem alleen bepaalt het resultaat niet.

Vraag het lopende shell in plaats van te gissen:

print -r -- "interactive=$options[interactive] login=$options[login]"

De daadwerkelijke opstartvolgorde

Zsh leest eerst de globale bestanden en daarna de overeenkomstige gebruikersbestanden. Met de standaardinstellingen RCS Opties: de volgorde van de gebruikersbestanden is:

  1. $ZDOTDIR/.zshenv voor elke oproep van Zsh
  2. $ZDOTDIR/.zprofile als de shell een login-shell is
  3. $ZDOTDIR/.zshrc als de shell interactief is
  4. $ZDOTDIR/.zlogin als de shell een login-shell is
  5. $ZDOTDIR/.zlogout wanneer een inlogshell normaal wordt afgesloten

Als ZDOTDIR is niet ingesteld, Zsh gebruikt $HOME. De systeemwijde bestandspaden zijn specifiek voor elke installatie; de gebruikelijke standaardwaarden zijn /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin, en /etc/zlogout.

Zsh-opstartvolgorde voor vier shell-modi

De opdracht fungeert als een filter en biedt geen garantie voor de levenscyclus. .zprofile Het wordt één keer uitgevoerd per login-shell-proces, en niet één keer bij elke computerlogin. Aangezien elk nieuw terminaltabblad een login shell start, wordt het bestand door elk tabblad gelezen.

Wat hoort er in elk bestand

BestandSelectieregelGoede kandidatenVermeed
.zshenvElk ZshZeldzame variabelen die door elk Zsh-proces vereist zijnuitvoer, aliasen, prompts, netwerkoproepen, trage commando’s
.zprofileInlogschillenInloggen – instellingen van de session-paden en geëxporteerde standaardwaardeninteractieve hooks, voltooien van invoer, toetsbindingen
.zshrcInteractieve shellsprompt, voltooiing, aliasen, shell-opties, interactieve hulphooksUitvoer of mutaties die bedoeld zijn voor scripts
.zloginInlogschelpen, na .zshrcZeldzame acties bij inloggen na interactieconfiguratie die vooraf moet gaan .zshrc
.zlogoutVertrek uit de inlogshellKleine opmaakacties of acties ter herstel van de terminalbelangrijke toestand die moet overleven bij crashes of exec

Bewaren .zshenv saai

Elk niet-interactief element zsh -c leest .zshenv. Een echoEen oproep van de package-manager of een dure subprocess kan de uitvoer van een commando beschadigen en scripts vertragen. De meeste gebruikers hebben weinig of helemaal niets in dit bestand nodig.

Een geëxporteerde variabele in .zprofile Het wordt geërfd door de kindprocessen van die login-shell. Het wordt niet automatisch ingevoegd in ongerelateerde GUI-applicaties, diensten of shells wier ouderproces het bestand nooit heeft gelezen.

Gebruik .zprofile voor een configuratie die alleen voor inloggen is bedoeld

Een klein profiel kan geëxporteerde standaardwaarden en een idempotente route definiëren:

# ~/.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 Het verwijdert dubbele elementen uit het array. Hierdoor wordt herhaaldelijk ophalen van gegevens veiliger, hoewel startbestanden toch onnodige bewerkingen moeten vermijden.

Gebruik .zshrc voor interactieve staat

# ~/.zshrc
setopt auto_cd hist_ignore_all_dups share_history

autoload -Uz compinit
compinit

alias ll='ls -lah'
bindkey -e

Aliassen, vulwidgets, toetsenbordmappen, prompts, en hooks voor het wijzigen van de map maken deel uit van de interactieve shell die ze gebruikt.

Versiebeheerders overstijgen de eenvoudige bestandsgrens

“Plaats versiebeheerders in” .zprofile “Omdat ze traag zijn” is onbetrouwbare advies. Een versiebeheerder kan verschillende soorten code genereren:

De interactieve onderdelen moeten in elke interactieve shell aanwezig zijn, inclusief een genestelde zsh gestart vanuit een editor. Huidig fnm De documentatie plaatst deze hook dus op deze locatie. .zshrc:

eval "$(fnm env --use-on-cd --shell zsh)"

De huidige documentatie van pyenv plaatst eveneens de volledige interactieve initialisatie in .zshrc:

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && path=("$PYENV_ROOT/bin" $path)
eval "$(pyenv init - zsh)"

Pyenv documenteert een smaller bereik. pyenv init --path Modus voor de configuratie van shim-paden, maar volledig pyenv init Het installeert tevens functies voor automatische completering en shell-functies. Controleer eerst de huidige documentatie en de gegenereerde uitvoer van een hulpmiddel voordat u deze splitst.

Als de opstarttijd traag is, meet deze dan voordat je de code naar een modus verplaatst waarin deze niet langer functioneert.

Haal het hele profiel niet uit een externe bron .zshrc

Een veelgebruikte oplossing die op meerdere platforms werkt, is:

# Avoid this blanket coupling.
source ~/.zprofile

Dit zorgt ervoor dat acties die alleen bij inloggen worden uitgevoerd, worden omgezet in acties per interactieve shell, waardoor herhaalde agent-acties zoals opstarten, toegang tot het sleutelbos, weergeven van output of wijzigen van paden mogelijk zijn.

Als zowel de inloggende als de niet-inloggende interactieve shells een klein aantal statische exports nodig hebben, haal dan een idempotent fragment eruit en importeer dit bewust:

# ~/.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.

Dit patroon houdt de gedeelde gegevens gescheiden van de gevolgen van het inloggen. Een andere haalbare optie is om de terminal of de session-manager consequent in te stellen, in plaats van beide modi te ondersteunen.

Diagnoseer de shell die traag is of geen status weergeeft

Reproduceer elke modus direct:

zsh -lic 'print "login interactive"'
zsh -ic  'print "non-login interactive"'
zsh -lc  'print "login non-interactive"'
zsh -c   'print "non-login non-interactive"'

Meet de modus die gebruikers daadwerkelijk starten:

time zsh -lic exit
time zsh -ic exit

Trace uitvoering van bestanden en regels wanneer de bron onduidelijk is:

PS4='%N:%i> ' zsh -xlic exit

Voer trace uit in een schone testaccount of controleer het eerst voordat u het deelt: opstartcommando’s kunnen tokens en andere gevoelige waarden onthullen.

Voor een ontbrekend uitvoerbaar bestand, controleer zowel de modus als het pad:

print -r -- "interactive=$options[interactive] login=$options[login]"
print -l -- $path
whence -va python node uv

Conclusie

De relevante onderscheiding ligt niet tussen “omgeving versus alias”. Het gaat om de staat die alleen bestaat tijdens inloggen versus de interactieve staat, plus die kleine hoeveelheid elementen die daadwerkelijk invloed moeten hebben op elke Zsh-process.

Bevestig de shell-opties, houd de startbestanden stil en plaats elke gegenereerde hook op een locatie waar al zijn benodigde functies aanwezig zijn. Hierdoor blijft de configuratie bruikbaar in verschillende terminaltoepassingen, zonder te doen alsof macOS en Linux elk een vaste startmodus hebben.

Referenties