[!NOTE] Автоматический перевод Эта статья была автоматически переведена с оригинальной английской версии.

Файлы для запуска Zsh: ~/.zprofile против ~/.zshrc на macOS и Linux

Если терминал работает медленно или какая‑то переменная среды видна в одном терминале, но отсутствует в другом, причиной часто является режим запуска Zsh. Самые популярные файлы, к которым обращаются в таких случаях, — это ~/.zprofile и ~/.zshrc, однако само название файла не позволяет судить о том, принадлежит ли та или иная строка именно ему.

Zsh выбирает файлы для запуска на основе двух независимых критериев: того, является ли оболочка оболочкой входа, и того, является ли она интерактивной. Приложения в терминалах под macOS и Linux могут использовать разные комбинации этих параметров, поэтому рекомендуется проверять текущую оболочку, а не полагаться на автоматический выбор операционной системы.

Кратко. Реализуйте инициализацию процесса входа-сессия внутри .zprofile и интерактивное поведение в .zshrc. Сохранить .zshenv беззвучно и с минимальными затратами. Не перемещайте хуки интерактивного менеджера версий внутрь .zprofile или загрузить весь профиль из .zshrc; проанализируйте код, сгенерированный инструментом, и выполните приведённые в нём текущие инструкции для Zsh.

Zsh обрабатывает два независимых флага

Файлы запуска Zsh, выбираемые в режимах входа в систему и интерактивной работы

Шелл может быть:

Терминальные приложения, среды разработки, удалённые сессии, мультиплексоры и явные флаги оболочки могут выбирать различные режимы работы. Операционная система сама по себе не определяет итоговый результат.

Спросите у запущенной оболочки вместо того, чтобы гадать:

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

Фактический порядок запуска

Zsh сначала читает глобальные файлы, а затем соответствующий пользовательский файл. При использовании стандартных настроек RCS Варианты: порядок файлов пользователя — следующий:

  1. $ZDOTDIR/.zshenv при каждом запуске Zsh $ZDOTDIR/.zprofile если оболочка является оболочкой входа $ZDOTDIR/.zshrc если оболочка интерактивна $ZDOTDIR/.zlogin если оболочка является оболочкой входа $ZDOTDIR/.zlogout когда оболочка входа выходит в нормальном режиме

Если ZDOTDIR есть значение по умолчанию, Zsh использует $HOME. Местоположения файлов в системе определяются конкретной версией ПО; распространённые стандартные значения — /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin, и /etc/zlogout.

Последовательность запуска Zsh для четырёх режимов оболочки

Этот порядок представляет собой фильтр, а не гарантию на протяжении всего жизненного цикла. .zprofile этот код выполняется один раз на процесс входного шелла, а не один раз при каждом входе в компьютер. Поскольку каждая новая вкладка терминала запускает входной шелл, она также загружает этот код.

Что должно находиться в каждом файле

ФайлПравило выбораХорошие кандидатыИзбегайте
.zshenvКаждый ZshРедкие переменные, необходимые для каждого процесса Zshрезультат выполнения, псевдонимы, промпты, сетевые вызовы, медленные команды
.zprofileШеллы входанастройка пути входа-сессия и экспортируемые стандартные параметрыинтерактивные хуки, автодополнение, привязки клавиш
.zshrcИнтерактивные оболочкипромпт — механизм автодополнения, возможность создания псевдонимов, настройка опций оболочки и интеграция с интерактивными хуками инструментов.результаты вывода или мутации, предназначенные для скриптов
.zloginШеллы входа, после .zshrcредкие действия входа после интерактивного взаимодействияконфигурация, которая должна предшествовать .zshrc
.zlogoutВыход из оболочки входанебольшие операции по очистке или сбросу терминалаважное состояние, которое должно сохраняться при сбоях exec

Сохранить .zshenv скучный

Каждый неконфликтный zsh -c загружает данные .zshenv. Ан echoВызов инструмента управления пакетами или ресурсоемкий вспомогательный процесс могут повредить результат выполнения команды и замедлить работу скриптов. Большинству пользователей в этом файле требуется минимум настроек или их совсем не нужно.

экспортируемая переменная в .zprofile Этот параметр наследуется дочерними процессами данной оболочки входа. Он не вставляется автоматически в независимые графические приложения, сервисы или оболочки, родительские процессы которых никогда не читали этот файл.

Использование .zprofile для конфигурации с доступом только при входе

Небольшой профиль может определять экспортируемые значения по умолчанию и идемпотентный путь:

# ~/.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 Удаляет дублирующиеся элементы массива. Это повышает надёжность многократного использования источников данных, однако файлы запуска всё равно следует делать менее ресурсоёмкими.

Использование .zshrc для интерактивного состояния

# ~/.zshrc
setopt auto_cd hist_ignore_all_dups share_history

autoload -Uz compinit
compinit

alias ll='ls -lah'
bindkey -e

Псевдонимы, компоненты автодополнения, карты клавиш, промпты, а также хуки для изменения каталога являются частью интерактивной оболочки, которая их использует.

Менеджеры версий преодолевают простые границы файлов

«Внедрите инструменты управления версиями в» .zprofile Такой совет, как «потому что они медленные», является ненадёжным. Менеджер версий может генерировать несколько типов кода:

Интерактивные компоненты должны присутствовать во всех интерактивных оболочках, включая вложенные. zsh запущен из редактора. В настоящее время fnm Документация поэтому размещает этот хук в .zshrc:

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

Текущая документация pyenv также описывает полную интерактивную процедуру инициализации .zshrc:

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

Pyenv описывает более узкий диапазон pyenv init --path режим настройки shim-path, но полный pyenv init Кроме того, устанавливает механизмы автодополнения и функции оболочки. Перед разбиением инструмента рекомендуется изучить его текущую документацию и генерируемый результат.

Если время запуска медленное, измерьте его до того, как перевести код в режим, в котором он больше не будет работать.

Не загружайте весь профиль из .zshrc

Распространённым кроссплатформенным решением является:

# Avoid this blanket coupling.
source ~/.zprofile

Это превращает операции, доступные только при входе в систему, в операции, выполняемые в рамках каждой интерактивной оболочки, и может приводить к повторному запуску агента, получению доступа к ключевой сборке, выводу данных или изменению пути.

Если как интерактивные оболочки с входом в систему, так и без него требуют небольшой группы статических экспортов, следует извлечь идемпотентный фрагмент и намеренно им воспользоваться:

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

Данный паттерн позволяет изолировать общедоступные данные от эффектов, связанных с процессом входа. Ещё одним рациональным решением является последовательная настройка терминала или менеджера сессия, вместо поддержки обоих режимов одновременно.

Диагностика оболочки с низкой производительностью или отсутствующим состоянием

Воспроизведите каждый режим напрямую:

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

Измерьте частоту запуска модов, которые фактически используют пользователи:

time zsh -lic exit
time zsh -ic exit

Трейс Выполнение файла и строки при неясности исходного кода:

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

Запустите трейс в чистом тестовом аккаунте или внимательно его проверьте перед распространением: команды запуска могут расширять токены и другие конфиденциальные значения.

Для отсутствующего исполняемого файла необходимо проверить как режим доступа, так и путь к нему:

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

Заключение

Полезное различие заключается не в «среде против псевдонимов», а в состоянии, доступном только при входе в систему, и интерактивном состоянии, плюс небольшом наборе элементов, которые действительно должны влиять на каждый процесс Zsh.

Подтвердите флаги оболочки, не вмешивайтесь в работу файлов запуска, и размещайте каждый сгенерированный хук там, где доступны все необходимые для него функции. Это обеспечивает портабельность конфигурации между различными терминальными приложениями, без необходимости предполагать, что у macOS и Linux существует по одному фиксированному режиму запуска.

Список литературы