[!NOTE] Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.

Fichiers de démarrage de Zsh : ~/.zprofile vs ~/.zshrc sur macOS et Linux

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 auxquels la plupart des utilisateurs se tournent sont ~/.zprofile et ~/.zshrcCependant, le nom de fichier seul ne permet pas non plus de déterminer si une ligne doit y figurer.

Zsh sélectionne les fichiers de démarrage en se basant sur deux critères indépendants : le fait que la shell soit une shell de connexion et qu’elle soit interactive. Les applications de terminal sous macOS et Linux peuvent choisir des combinaisons différentes ; il convient donc d’examiner la shell en cours d’exécution plutôt que de supposer que c’est le système d’exploitation qui prend cette décision à votre place.

TL;DR. Placer l’initialisation de la session de connexion dans .zprofile ainsi que le comportement interactif dans .zshrc. Conserver .zshenv silencieux et minimaliste. Ne déplacez pas les hooks interactifs du gestionnaire de versions à l’intérieur .zprofile ou charger l’ensemble du profil depuis .zshrc; Vérifiez le code généré par l’outil et suivez ses instructions Zsh actuelles.

Zsh évalue deux flags indépendants

Fichiers de démarrage Zsh sélectionnés selon les modes connexion et interactif

Un shell peut être :

Les applications en ligne de commande, les IDE, les sessions distantes, les multiplexeurs ainsi que les flags explicites du shell peuvent sélectionner différents modes. Le système d’exploitation seul ne détermine pas le résultat.

Demandez à la shell en cours d’exécution plutôt que de deviner :

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

L’ordre réel de démarrage

Zsh lit d’abord les fichiers globaux, puis le fichier utilisateur correspondant. Avec la configuration par défaut RCS Options : l’ordre des fichiers utilisateurs est le suivant :

  1. $ZDOTDIR/.zshenv pour chaque invocation de Zsh
  2. $ZDOTDIR/.zprofile si le shell est un shell de connexion
  3. $ZDOTDIR/.zshrc si le shell est interactif
  4. $ZDOTDIR/.zlogin si le shell est un shell de connexion
  5. $ZDOTDIR/.zlogout lorsqu’un shell de connexion se termine normalement

Si ZDOTDIR n’est pas défini, Zsh utilise $HOME. Les emplacements des fichiers à l’échelle du système sont spécifiques à chaque installation ; les valeurs par défaut courantes sont /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin, et /etc/zlogout.

Sequence de démarrage de Zsh pour les quatre modes de shell

Cette commande constitue un filtre, et non une garantie de cycle de vie. .zprofile Il s’exécute une fois par processus de shell de connexion, et non une fois par connexion au poste de travail. Puisque chaque nouvelle fenêtre de terminal lance une shell de connexion, chacune d’elles la lit.

Quelles éléments doivent figurer dans chaque fichier

FichierRègle de sélectionDe bons candidatsÉviter
.zshenvChaque ZshVariables rares requises par chaque processus Zshsortie, alias, prompts, appels réseau, commandes lentes
.zprofileShells de connexionConfiguration du chemin de la session de connexion et valeurs par défaut exportéesdes goupilles interactives, des complétions et des raccourcis clavier
.zshrcBourreaux interactifsprompt : complétion, alias, options de shell, points d’ancrage pour des outils interactifsLes sorties ou mutations destinées aux scripts
.zloginLes shells de connexion, après .zshrcActions de connexion rares après interaction utilisateurconfiguration qui doit précéder .zshrc
.zlogoutSortie de la shell de connexionpetites opérations de nettoyage ou de réinitialisation du terminalÉtat critique qui doit persister en cas de panne ou d’erreur. exec

Conserver .zshenv ennuyeux

Chaque élément non interactif zsh -c lit .zshenv. Un echoUne invocation du gestionnaire de paquets, ou un sous-processus coûteux, peut corrompre la sortie des commandes et ralentir les scripts. La plupart des utilisateurs n’ont besoin que de très peu, voire de rien, dans ce fichier.

Une variable exportée dans .zprofile Il est hérité par les enfants de cette shell de connexion. Il n’est pas injecté automatiquement dans des applications GUI, des services ou des shells non apparentés dont le processus parent n’a jamais lu ce fichier.

Utilisation .zprofile pour une configuration réservée uniquement à la connexion

Un profil réduit peut définir des valeurs par défaut exportées ainsi qu’un chemin 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 Il supprime les éléments dupliqués de l’array. Cela rend la récupération répétée des données plus fiable, bien que les fichiers de démarrage doivent néanmoins éviter tout travail inutile.

Utilisation .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 alias, les widgets de complétion, les mappages de touches, prompts, ainsi que les hooks de changement de répertoire font partie du shell interactif qui les utilise.

Les gestionnaires de versions franchissent les limites simples des fichiers

« Intégrez des gestionnaires de versions dans » .zprofile Car ils sont lents” constitue un conseil peu fiable. Un gestionnaire de versions peut générer plusieurs types de code :

Les parties interactives doivent être présentes dans chaque shell interactif, y compris ceux qui sont imbriqués. zsh démarré depuis un éditeur. Actuel fnm La documentation place donc ce hook à cet endroit. .zshrc:

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

La documentation actuelle de pyenv propose également une initialisation interactive complète en .zshrc:

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

Pyenv documente un champ plus restreint pyenv init --path mode pour la configuration de shim-path, mais complet pyenv init Il installe également des fonctionnalités de complétion ainsi que des fonctions de shell. Examinez la documentation actuelle d’une outil et les résultats générés avant de le diviser.

Si le démarrage est lent, mesurez-le avant de transférer le code dans un mode où il cesse de fonctionner.

Ne pas récupérer l’ensemble du profil depuis .zshrc

Une solution de contournement courante sur plusieurs plateformes est :

# Avoid this blanket coupling.
source ~/.zprofile

Cela transforme les actions réservées à la connexion en actions spécifiques à chaque shell interactif, et permet de répéter le démarrage de l’agent, l’accès au trousseau de clés, l’affichage des résultats ou la modification des chemins.

Si tant les shells interactifs en mode connexion que ceux hors connexion nécessitent un petit ensemble d’exports statiques, extrayez un fragment idempotent et chargez-le délibérément :

# ~/.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 schéma permet de séparer les données partagées des effets secondaires liés à la connexion. Une autre option valable consiste à configurer de manière cohérente le gestionnaire de terminaux ou de sessions, plutôt que de prendre en charge les deux modes en même temps.

Diagnostiquer le shell qui présente des lenteurs ou un manque d’état

Reproduisez chaque mode directement :

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

Mesurer le mode d’exécution réellement utilisé par les utilisateurs :

time zsh -lic exit
time zsh -ic exit

Fichier de trace et suivi de l’exécution ligne par ligne lorsque la source est peu claire :

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

Exécutez le suivi sur un compte de test propre ou examinez-le avant de le partager : les commandes de démarrage peuvent déployer des tokens ainsi que d’autres valeurs sensibles.

Pour un exécutable manquant, vérifiez à la fois le mode et le chemin :

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

Conclusion

La distinction pertinente n’est pas « environnement contre alias ». Il s’agit plutôt de l’état réservé à la connexion contre l’état interactif, ainsi que de la petite partie de données qui doit réellement impacter chaque processus Zsh.

Vérifiez les flags de la shell, assurez-vous que les fichiers de démarrage restent silencieux, et placez chaque crochet généré là où se trouvent toutes les fonctionnalités nécessaires. Cela permet à la configuration d’être portable entre les applications de terminal, sans prétendre que macOS et Linux disposent chacun d’un mode de lancement fixe.

Références