Вопрос или проблема
Моя оболочка для входа – zsh. Я добавил следующие две строки в свой файл .zprofile
:
path+=$HOME/foobar123
alias foo='echo bar'
Затем, если я переключусь на bash или fish, введя bash
или fish
и нажав Return, echo $PATH
продолжит показывать часть foobar123
, но алиас foo
не будет работать.
Почему это так? Почему алиасы и изменения пути обрабатываются по-разному?
path
– это массив переменных оболочки, связанный с переменной оболочки PATH
, которая, в свою очередь, связана с переменной окружения PATH
.
При выполнении команды вся память процесса очищается.
Переменные окружения – это способ передачи данных в разных запусках. Как и аргументы команд, они представляют собой список строк, разделенных нулевыми символами, но в отличие от аргументов, по соглашению:
- они принимают форму
VAR=значения
- команды (будь то оболочки или что-то еще) запоминают список переменных окружения, которые они получили при выполнении, и передают их командам, которые они выполняют, если они или их дочерние процессы это делают, реализуя таким образом форму унаследованной и унаследуемой среды. Есть стандартный C API (
putenv()
,setenv()
,unsetenv()
, переменнаяenviron
), чтобы поддерживать этот список запомненных переменных окружения (environ) и выполнять команды, передавая этот список (execl()
,execvp()
… которые являются оболочками для системного вызоваexecve()
).
Специфически для оболочек, помимо этого, они создают переменную в своем языке для некоторых переменных окружения, которые они получают, и имя которой совместимо с именем переменной оболочки. Оболочки, подобные Bourne, могут продвигать переменную оболочки в переменную окружения с помощью встроенной команды export
(другие оболочки имеют эквиваленты).
Оболочки csh, tcsh, zsh, yash, fish имеют способы связывать $PATH
или другие переменные со значениями, разделенными :
(в основном переменные окружения, такие как PATH
), с массивами переменных.
Для сравнения, perl (также интерпретатор языков программирования, но не оболочка) сопоставляет переменные окружения со своими ассоциативными массивами %ENV
(например, переменная окружения PATH
доступна в $ENV{PATH}
), awk
делает то же самое через ENVIRON["PATH"]
, vim
имеет $var
для переменных окружения, в то время как для своих собственных переменных просто var
или @x
для регистров и т.д.
В заключение, переменные окружения, такие как PATH
, являются универсальными и понимаются всеми и наследуются (по соглашению) по мере выполнения.
Нет эквивалента для алиасов оболочки, что является (плохой) особенностью некоторых оболочек (не всех), изначально введенной в csh, синтаксис которой варьируется от оболочки к оболочке, и не существует других структур данных в каком-либо языке.
Некоторые оболочки, такие как rc
и его производные или bash
, могут экспортировать свои функции (также массивы в rc
и его производных), чтобы сделать это, они захватывают переменные окружения, где определение функции хранится в специфическом формате, но только другие экземпляры той же оболочки могут загружать эти переменные из окружения и восстанавливать функции (или массивы), которые они закодировали. Эти переменные не имеют смысла для других оболочек (или perl
, vim
, awk
…), синтаксис которых в любом случае отличается.
Чтобы передать свой список алиасов zsh в bash
для создания эквивалентных алиасов bash, вам нужно создать код на языке bash
, который, будучи выполненным, восстановит эти алиасы. bash
и zsh
имеют некоторый общий синтаксис, в частности, основной синтаксис встроенной команды alias
был скопирован в обе оболочки из оболочки Korn, а не из csh, но zsh добавила больше функций, таких как глобальные алиасы или алиасы с суффиксами и не имеет тех же ограничений, что и bash, когда речь идет об именах алиасов, а алиасы bash не могут содержать нулевые символы ни в имени, ни в значении, поэтому не все алиасы zsh могут быть преобразованы в алиасы bash.
Синтаксис кавычек также отличается между двумя оболочками, хотя они понимают одинарные кавычки одинаково (если только rcquotes
не включен в zsh
). zsh делает список своих простых алиасов доступным в специальном ассоциативном массиве $aliases
, и, как и bash
, может выводить список определений алиасов с помощью alias -L
.
Но в последнем случае он не всегда использует одинарные кавычки и может выводить алиасы, имя или значения которых не будут работать в bash, поэтому вам лучше обойти $aliases
, отфильтровать те, которые не могут работать в bash
, и сделать кавычки вручную (как с флагом расширения параметра qq
).
Ответ или решение
Наследование изменений в PATH против наследования псевдонимов
Введение
Когда вы используете терминал, система выполняет интерпретацию ваших команд в зависимости от выбранной оболочки, такой как bash
или zsh
. В этом контексте важно понимать разницу между наследованием изменений в переменной среды PATH
и наследованием псевдонимов. Данная статья подробнее объясняет, почему изменения в PATH
продолжают действовать при переключении между оболочками, в то время как псевдонимы не наследуются.
Изменения в PATH: как это работает?
Переменные окружения, такие как PATH
, представляют собой способ передачи данных между процессами и оболочками. Когда вы добавляете новый путь в переменную PATH
в вашем файле ~/.zprofile
, вы фактически обновляете массив, связанный с переменной окружения:
path+=$HOME/foobar123
При запуске новой оболочки, такой как bash
или fish
, эта переменная среды наследуется. В результате вы увидите, что содержимое переменной PATH
(включая добавленный вами путь) продолжает существовать в новой оболочке. Это объясняется тем, что переменные окружения автоматически передаются детям (подпроцессам) и могут быть использованы другими программами и процессами.
Псевдонимы: их ограничения
С другой стороны, псевдонимы определяются на уровне оболочки и существуют только в её контексте. Когда вы создаете псевдоним, например:
alias foo='echo bar'
Этот псевдоним является частью локальной среды командной оболочки zsh
и не передается новым процессам bash
или fish
. Причиной этого является то, что псевдонимы не являются общепринятыми переменными управления, такими как PATH
, и их синтаксис и использование зависят от конкретной оболочки.
Псевдонимы в zsh
и bash
имеют разные реализации и синтаксис. Например, bash
наследует свои собственные переменные, но не поддерживает наследование псевдонимов из других оболочек, поскольку это концептуально отличается от переменных окружения.
Возможные пути интеграции
Для передачи ваших псевдонимов из zsh
в bash
вам потребуется создать скрипты или конфигурационные файлы, которые будут содержать эквиваленты ваших псевдонимов, так как оболочки не могут автоматически интерпретировать их из-за различий в синтаксисе и функциональности. Это может потребовать ручной работы по преобразованию фиксированных псевдонимов в соответствующие команды для каждого типа оболочки, что является одной из причин, почему некоторым пользователям рекомендуется придерживаться одной оболочки для предотвращения путаницы.
Заключение
В конечном итоге, различие в поведении между наследованием изменений в переменной PATH
и наследованием псевдонимов объясняется различиями в их реализации и концептуальными подходами к управлению окружением в различных оболочках. Переменные окружения, такие как PATH
, являются универсальными и могут быть переданы, в то время как псевдонимы существуют в рамках специфичной для оболочки логики. Понимание этих различий помогает лучше управлять вашими окружениями и обеспечивать более эффективное выполнение команд в различных оболочках.
Поиск выхода
Чтобы избежать путаницы, рекомендуется создавать отдельные конфигурации для каждой оболочки, что позволит вам сохранять порядок и согласованность в вашем рабочем процессе. Это особенно важно для системных администраторов и разработчиков, которые часто переключаются между различными оболочками и средами исполнения.