Fichiers de démarrage Zsh : .zprofile ou .zshrc sur macOS et Linux
Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.
Si votre terminal semble lent, ou si une variable d’environnement apparaît dans un terminal mais pas dans un autre, la cause est souvent le mode de démarrage de Zsh. Les deux fichiers que la plupart des utilisateurs consultent sont ~/.zprofile et ~/.zshrc, mais aucun nom de fichier ne suffit à déterminer à lui seul où placer une ligne.
Zsh choisit ses fichiers de démarrage selon deux propriétés indépendantes : le shell est-il un login shell et est-il interactif ? Les applications de terminal sur macOS et Linux peuvent choisir différentes combinaisons ; inspectez donc le shell en cours d’exécution au lieu de supposer que le système d’exploitation décide pour vous.
En bref. Placez l’initialisation de la session de connexion dans
.zprofileet le comportement interactif dans.zshrc. Gardez.zshenvsilencieux et minimal lorsqueRCSest défini. Ne déplacez pas les hooks interactifs des gestionnaires de versions dans.zprofileet ne sourcez pas l’intégralité du profile depuis.zshrc; inspectez le code généré par l’outil et suivez ses instructions Zsh à jour.
Zsh évalue deux flags indépendants
Un shell peut être :
- login et interactif, lorsque Apple Terminal est configuré pour ouvrir le login shell par défaut du compte
- non-login et interactif, comme un
zshimbriqué ou dans de nombreuses configurations de terminaux Linux - login et non interactif, comme
zsh -lc 'command' - non-login et non interactif, comme
zsh -c 'command'
Les applications de terminal, les IDE, les sessions distantes, les multiplexeurs et les flags explicites du shell peuvent choisir des modes différents. Le système d’exploitation seul ne suffit donc pas à déterminer le résultat.
Demandez directement au shell en cours d’exécution au lieu de deviner :
print -r -- "interactive=$options[interactive] login=$options[login]"
L’ordre réel de démarrage
Zsh lit les fichiers globaux, puis le fichier utilisateur correspondant. Avec les options RCS par défaut, l’ordre des fichiers utilisateur est le suivant :
$ZDOTDIR/.zshenvà chaque invocation de Zsh$ZDOTDIR/.zprofilesi le shell est un login shell$ZDOTDIR/.zshrcsi le shell est interactif$ZDOTDIR/.zloginsi le shell est un login shell$ZDOTDIR/.zlogoutlorsqu’un login shell se termine normalement
Si ZDOTDIR n’est pas défini, Zsh utilise $HOME. Les emplacements des fichiers à l’échelle du système dépendent de l’installation ; les valeurs par défaut courantes sont /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin et /etc/zlogout (manuel de Zsh).
zsh -f démarre avec RCS non défini ; il ignore donc normalement les fichiers utilisateur $ZDOTDIR ci-dessus. /etc/zshenv est toujours lu et peut modifier cette option.
.zprofile est exécuté une fois par processus de login shell, et non une fois par connexion de l’utilisateur à l’ordinateur. Si chaque nouvel onglet de terminal démarre un login shell, chaque onglet le lit.
Que placer dans chaque fichier
| Fichier | Règle de sélection | Bons candidats | À éviter |
|---|---|---|---|
.zshenv | Chaque Zsh avec RCS défini | Variables rares requises par chaque processus Zsh | sortie, aliases, prompts, appels réseau, commandes lentes |
.zprofile | Login shells | configuration du PATH de la session de connexion et valeurs par défaut exportées | hooks interactifs, complétions, raccourcis clavier |
.zshrc | Shells interactifs | prompt, complétion, aliases, options du shell, hooks d’outils interactifs | sortie ou mutations destinées aux scripts |
.zlogin | Login shells, après .zshrc | rares actions de connexion post-interactives | configuration qui doit précéder .zshrc |
.zlogout | Fin du login shell | petites opérations de nettoyage ou de réinitialisation du terminal | état important qui doit survivre aux plantages ou à exec |
Gardez .zshenv minimal lorsque RCS est défini
Lorsque RCS est défini, chaque zsh -c non interactif lit .zshenv (manuel de Zsh). Un echo, un appel à un gestionnaire de paquets ou un sous-processus coûteux à cet endroit peut corrompre la sortie des commandes et ralentir les scripts. La plupart des utilisateurs n’ont besoin de presque rien dans ce fichier.
Une variable exportée dans .zprofile est héritée par les processus enfants de ce login shell. Elle n’est pas automatiquement injectée dans des applications graphiques, des services ou des shells indépendants dont le parent n’a jamais lu le fichier.
Utilisez .zprofile pour la configuration propre aux sessions de connexion
Un profile minimal peut définir des valeurs par défaut exportées ainsi qu’un PATH idempotent :
# ~/.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 supprime les entrées en double dans les tableaux. Cela rend le sourcing répété plus sûr, même si les fichiers de démarrage doivent toujours éviter le travail inutile.
Utilisez .zshrc pour l’état interactif
# ~/.zshrc
setopt auto_cd hist_ignore_all_dups share_history
autoload -Uz compinit
compinit
alias ll='ls -lah'
bindkey -e
Les aliases, widgets de complétion, raccourcis clavier, prompts et hooks de changement de répertoire appartiennent au shell interactif qui les utilise.
Les gestionnaires de versions dépassent la simple séparation entre fichiers
Dire « placez les gestionnaires de versions dans .zprofile parce qu’ils sont lents » est un conseil peu fiable. Un gestionnaire de versions peut produire plusieurs types de code :
- un PATH statique ou une variable racine
- un chemin vers un shim de commande requis par les processus enfants
- des définitions de complétion
- des fonctions shell qui modifient le shell courant
- des hooks de changement de répertoire pour le changement automatique de version
Les éléments interactifs doivent exister dans chaque shell interactif, y compris un zsh imbriqué lancé depuis un éditeur. La configuration Zsh actuelle de fnm place donc ce hook dans .zshrc :
eval "$(fnm env --use-on-cd --shell zsh)"
La configuration Zsh actuelle de pyenv place elle aussi l’initialisation interactive complète dans .zshrc :
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && path=("$PYENV_ROOT/bin" $path)
eval "$(pyenv init - zsh)"
Pyenv documente un mode pyenv init --path plus ciblé pour configurer le chemin vers les shims, tandis que le pyenv init complet installe également la complétion et les fonctions shell. Consultez la documentation actuelle de l’outil et inspectez sa sortie générée avant de séparer ces éléments.
Si le démarrage est lent, mesurez-le avant de déplacer du code vers un mode dans lequel il ne fonctionnera plus.
Ne sourcez pas l’intégralité du profile depuis .zshrc
Une solution de contournement courante et portable entre les plateformes consiste à faire ceci :
# Avoid this blanket coupling.
source ~/.zprofile
Cela transforme les actions propres aux sessions de connexion en actions exécutées dans chaque shell interactif et peut répéter le démarrage d’un agent, l’accès au trousseau, la sortie ou la modification du PATH.
Si les shells interactifs login et non-login ont tous deux besoin d’un petit ensemble d’exports statiques, extrayez un fragment idempotent et sourcez-le explicitement :
# ~/.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.
Ce pattern sépare les données partagées des effets de bord propres aux sessions de connexion. Une autre option valide consiste à configurer le terminal ou le gestionnaire de sessions de manière cohérente, plutôt qu’à prendre en charge les deux modes.
Diagnostiquez le shell lent ou dépourvu de certains états
Reproduisez directement chaque mode :
zsh -lic 'print "login interactive"'
zsh -ic 'print "non-login interactive"'
zsh -lc 'print "login non-interactive"'
zsh -c 'print "non-login non-interactive"'
Mesurez le mode réellement lancé par les utilisateurs :
time zsh -lic exit
time zsh -ic exit
Tracez l’exécution des fichiers et des lignes lorsque l’origine du problème n’est pas claire :
PS4='%N:%i> ' zsh -xlic exit
Exécutez la trace dans un compte de test propre ou inspectez-la avant de la partager : les commandes de démarrage peuvent développer des tokens et d’autres valeurs sensibles.
Pour un exécutable introuvable, inspectez à la fois le mode et le PATH :
print -r -- "interactive=$options[interactive] login=$options[login]"
print -l -- $path
whence -va python node uv
Conclusion
La distinction utile n’est pas « environnement contre aliases ». Il s’agit de l’état propre aux sessions de connexion par opposition à l’état interactif, ainsi que de la petite quantité de configuration qui doit affecter chaque processus Zsh lorsque RCS est défini.
Confirmez les flags du shell, gardez les fichiers de démarrage silencieux et placez chaque hook généré là où toutes ses fonctionnalités requises sont disponibles. La configuration devient ainsi portable entre les applications de terminal, sans prétendre que macOS et Linux possèdent chacun un mode de lancement unique et fixe.