[Перевод] Как потерять управление оболочкой… Расследование
Несколько недель назад я хакал языковые сервера в Zed, пытаясь заставить Zed определять, когда заданный бинарник языкового сервера, например gopls , уже присутствует в $PATH . Если так, вместо загрузки нового бинарника Zed должен использовать его. Трудность: часто $PATH динамически изменяется такими инструментами, как direnv , asdf , mise и другими, которые позволяют в данной папке установить определённый $PATH . Почему эти инструменты так делают? Потому что это даёт возможность, скажем, в начале $PATH добавить ./my_custom_binaries , пока вы находитесь в my-cool-project . Поэтому нельзя просто использовать $PATH , связанный с процессом Zed, нужен $PATH , как он есть, когда выполняется cd в каталог проекта. Легко, подумал я. Просто запусти $SHELL , выполни cd в проект, чтобы запустить direnv и всё такое, запусти env , сохрани окружение, выбери $PATH , найди в нём бинарники. И это было легко. Вот часть кода, та часть, которая запускает $SHELL , cd и получает env : fn load_shell_environment(dir: &Path) -> Result<HashMap<String, String>> {
// Получает $SHELL
let shell = std::env::var("SHELL")?;
// Конструирует команду, которую хочется выполнить в $SHELL
let command = format!("cd {:?}; /usr/bin/env -0;", dir);
// Запускает $SHELL как интерактивную оболочку (чтобы использовались файлы пользователя rc).
// и выполняет `command`:
let output = std::process::Command::new(&shell)
.args(["-i", "-c", &command])
.output()?;
// [... проверка кода выхода, получение stdout, превращение stdout в HashMap и т. д. ...]
} За исключением одного: после запуска экземпляра Zed в терминале, который выполнял эту функцию, я больше не мог убить Zed, нажав Ctrl-C . Что?
https://habr.com/ru/articles/800037/
#zsh #*nix #rust #оболочки #профессиональная_литература