Управление специализированными окружениями в Windows
Наверняка все знают, что в операционных системах Windows и Linux есть
специальная переменная окружения PATH
, которая должна включать в себя список
путей к директориям с исполняемыми файлами. Если оболочку просят запустить
исполняемый файл без указания абсолютного пути к нему — она осуществит поиск в
переменной окружения PATH
, иногда с некоторыми модификациями (например, в
Windows поиск будет осуществлён с подстановкой расширений файлов из другой
переменной окружения, PATHEXT
).
Часто с этой переменной окружения приходится работать при использовании консольных приложений или систем сборки. Её можно модифицировать во время выполнения процесса, и дочерние процессы будут наследовать изменённое значение (в общем-то, так работают любые переменные окружения).
В среднем под Windows неправильно настроенный PATH
доставляет больше проблем,
поскольку выполняемые файлы программ не складываются в какие-то централизованные
директории, типа /bin
и /usr/bin
в FHS, и поэтому каждая программа
управляет этим самостоятельно. Разумеется, в результате получается зоопарк:
какие-то программы при установке добавляются туда без запроса, какие-то не
добавляются, даже если пользователь этого хотел бы, а какие-то могут забыть
удалиться из PATH
при деинсталляции. В итоге каждому, кто хоть немного работал
с консольными программами в Windows, хочется каких-то инструментов и практик для
того, чтобы не засорять эту переменную окружения, и упорядочить обращение с ней.
К счастью, есть несколько способов и средств, которые существенно улучшают
ситуацию и позволяют практически не заботиться о проблемах, связанных с тем, что
кто-нибудь опять испортил переменную окружения PATH
.
Откуда берётся PATH
Начнём с основ: откуда же берётся эта переменная окружения изначально?
Как и все переменные окружения, в каждом конкретном процессе она формируется на
основании значения из родительского процесса. Главным родителем всех
пользовательских процессов является explorer.exe
, так что за передачу
начального варианта окружения отвечает именно этот процесс.
Пользовательская переменная PATH
получается путём сложения из двух мест: из
пользовательского окружения и из общесистемного. При этом данное поведение
явлется уникальным: для других переменных значения пользовательского окружения
заменяют значения системного, а не дополняют его.
Для редактирования переменных окружения используется стандартная программа
SystemPropertiesAdvanced.exe
. Стоит отметить, что после редактирования этих
настроек уже запущенные процессы не обнаружат изменений своего окружения;
более того, не все вновь запущенные процессы будут использовать новый вариант
окружения!
Дело в том, что, как я уже говорил, копия окружения получается всегда из родительского процесса, и не меняется во время работы процесса (если он сам его не поменяет, конечно). Часто можно видеть, как люди меняют переменные окружения, запускают какие-то новые процессы из любимого файлового менеджера (не перезапуская его после изменений окружения, разумеется), и потом удивляются тому, что окружение не поменялось. Получается, что это и не должно работать.
А каким же тогда образом изменяется окружение в explorer.exe
? Дело в том, что
он подписывается на глобальное событие WM_SETTINGCHANGE
, и
автоматически обновляет своё окружение. Пользовательская программа может делать
точно так же, если для неё важно перезагружать переменные окружения.
(Я не уверен на 100%, что explorer.exe
работает буквально именно таким
образом, но во всяком случае система ведёт себя именно так.)
Максимальный размер PATH
В (не таких уж и) старых версиях Windows (вплоть до 7 SP 1 / Server 2008 R2 SP1)
имеется достаточно жёсткое ограничение на максимальный размер PATH
: это всего
2047 символов (к сожалению, сложно сказать наверняка, в какой мере этот лимит
распространяется на пользовательское, системное и комбинированное окружение).
Если лимит превышен, то всё становится очень плохо, из PATH
теряются записи, а
запуск новых программ начинает работать очень ограниченно.
Примечательно, что в условиях сломанной переменной PATH
не получается даже
запустить SystemPropertiesAdvanced.exe
, в том числе и из панели управления,
т.к. путь к этой программе там тоже берётся из окружения (которое, напомню,
сломано). В общем, лучше такого не допускать :)
Для того, чтобы немного расширить допустимые размеры окружения, есть
специальный патч от Microsoft. Он расширяет максимальный размер
PATH
до 4095 символов.
Я не проверял этот патч на новых версиях Windows; также я не проверял и максимальную длину окружения на них, т.к. начал пользоваться прочими способами управления окружением, перечисленными ниже.
Редактирование окружения
Для редактирования переменных окружения я рекомендую использовать бесплатную
программу Rapid Environment Editor. Она особенно хороша тем, что
умеет подсвечивать некорректные фрагменты внутри PATH
, что позволяет быстро
избавиться ссылок на различного рода неправильные или удалённых пути внутри этой
переменной.
Установка программ
Выше я упоминал, что многие программы забывают добавиться в PATH
при
установке, несмотря даже на то, что для пользователя это было бы удобным.
Отчасти это может быть связано с тем, что, если все начнут туда добавляться, то
переменная PATH
неминуемо начнёт расти неконтролируемыми темпами, и очень
быстро превысит безопасные лимиты.
Простым решением этой проблемы может стать размещение в каком-то одном месте
группы небольших скриптов, ссылающихся на все приложения, которые должны быть в
PATH
, и добавление этого единого каталога со скриптами в PATH
.
Конечно, хочется это как-то автоматизировать, чтобы не заморачиваться с этим
после установки каждой небольшой программы. К счастью, существует проект
Chocolatey, в рамках которого, помимо простых консольных
установщиков для множества программ, прилагаются также скрипты для вызова т.н.
shimgen
— программы для генерации исполняемых файлов в каком-то внутреннем
каталоге Chocolatey, который уже добавлен в PATH
. Короче говоря, если нужная
вам программа доступна через Chocolatey — высока вероятность того, что эта
программа или будет корректно добавляться в PATH
при установке, или же
использует shimgen
для размещения ссылок на свои исполняемые файлы в каталоге,
который уже добавлен в PATH
.
Пользуйтесь Chocolatey, товарищи.
Локальное управление окружением
К сожалению, даже использование Chocolatey не решает всех проблем с присутствием
программ в PATH
, так что какие-то меры всё-таки приходится предпринимать.
Самое простое, что можно сделать — это добавить псевдонимы для часто используемых программ в профиль используемого вами интерпретатора команд оболочки. Мой профиль PowerShell (а я пользуюсь именно этим интерпретатором) начинается с определений псевдонимов:
New-Alias appcsxcad E:\Programs\openEMS\AppCSXCAD.exe
New-Alias cmake 'c:\Program Files (x86)\CMake\bin\cmake.exe'
New-Alias ccl c:\Programs\ccl-1.9\ccl\wx86cl64.exe
New-Alias dub e:\Programs\dub\dub.exe
Это позволяет вызывать перечисленные команды из PowerShell, не модифицируя
переменных окружения и не расходуя ценное место в PATH
.
Конечно же, этого зачастую также недостаточно: иногда хочется получить доступ
сразу к целому каталогу с исполняемыми файлами, да и в окружении его иметь тоже
иногда хочется (например, если мы хотим, чтобы изменённый PATH
был доступен
дочерним процессам, которые мы запускаем из оболочки — ведь к псевдонимам из
локальной сессии PowerShell они не смогут получить доступ). Для этой цели я
создаю в профиле специальные функции наподобие вот таких:
function android-environment {
Add-Path -CurrentUser e:\Programs\AndroidSdk\tools
}
function cabal-environment {
Add-Path -CurrentUser T:\cabal\bin
}
function git-tfs-environment {
Add-Path -CurrentUser e:\Programs\GitTfs\
}
function elixir-environment {
erlang-environment
Add-Path -CurrentUser c:\ProgramData\chocolatey\Elixir\bin
}
function erlang-environment {
Add-Path -CurrentUser 'c:\Program Files\erl6.3\bin'
Add-Path -CurrentUser 'E:\Programs\rebar'
}
В дальнейшем, если я, например, хочу поработать с Elixir, я выполняю команду
elixir-environment
— и в текущей сессии становятся доступны все исполняемые
файлы Elixir. При этом они не засоряют глобального окружения и не появляются в
нём до тех пор, пока они мне не окажутся нужны.
Add-Path
— это простой скрипт из моего пакета для PowerShell,
однако можно достигнуть той же цели прямым модифицированием переменной
$env:PATH
. Само собой, решение по форме не специфично для PowerShell, и его
можно использовать из любого интерпретатора команд, который позволяет
модифицировать переменные окружения: например, bash
или cmd
.
Заключение
Пользуясь этим простым набором подходов, вы никогда больше не окажетесь в
ситуации, когда PATH
доставляет вам существенные неудобства при работе в
Windows. До новых встреч!