Измените рабочий каталог в моем текущем контексте оболочки при запуске Node script

Я пытаюсь изменить рабочий каталог моего Node.js script, когда он запускается из bin script. У меня есть что-то вроде следующего:

#!/usr/bin/env node
process.chdir('/Users')

Когда я запускаю этот файл с ./bin/nodefile, он завершается, но рабочий каталог текущего контекста оболочки не изменился. Я также пробовал shelljs, но это тоже не работает.

Каков наилучший способ сделать это? Я понимаю, что это работает, но это просто в отдельном процессе.

Ответ 1

Правильный способ изменения каталогов на самом деле с process.chdir(directory). Вот пример из документации:

console.log('Starting directory: ' + process.cwd());
try {
  process.chdir('/tmp');
  console.log('New directory: ' + process.cwd());
}
catch (err) {
  console.log('chdir: ' + err);
}

Это также можно проверить в Node.js REPL:

[[email protected] ~]$ node
> process.cwd()
'/home/monitor'
> process.chdir('../');
undefined
> process.cwd();
'/home'

Ответ 2

Нет встроенного метода для Node для изменения CWD базовой оболочки, запускающей процесс Node.

Вы можете изменить текущий рабочий каталог процесса Node с помощью команды process.chdir().

var process = require('process');
process.chdir('../');

Когда процесс Node существует, вы вернетесь в CWD, в котором вы запустили процесс.

Ответ 3

То, что вы пытаетесь сделать, невозможно. Причина этого в том, что в системе POSIX (Linux, OSX и т.д.) Дочерний процесс не может изменять среду родительского процесса. Это включает в себя изменение родительского рабочего процесса и переменных среды.

Когда вы находитесь в командной строке, и вы идете выполнить свой Node script, ваш текущий процесс (bash, zsh, что угодно) порождает новый процесс, который имеет свою собственную среду, обычно копию текущую среду (это можно изменить с помощью системных вызовов, но это выходит за рамки этого ответа), позволяя этому процессу делать все, что ему нужно, в полной изоляции. Когда выйдет подпроцесс, управление возвращается в ваш процесс оболочки, где среда не была затронута.

Есть много причин для этого, но для одного представьте, что вы выполнили script в фоновом режиме (через ./foo.js &), и по мере его запуска он начал изменять рабочий каталог или переопределять ваш PATH, Это был бы кошмар.

Если вам нужно выполнить некоторые действия, требующие изменения рабочего каталога вашей оболочки, вам нужно написать функцию в своей оболочке. Например, если вы используете Bash, вы можете поместить это в свой ~/.bash_profile:

do_cool_thing() {
  cd "/Users"
  echo "Hey, I'm in $PWD"
}

и тогда эта классная вещь выполнима:

$ pwd
/Users/spike
$ do_cool_thing
Hey, I'm in /Users
$ pwd
/Users

Если вам нужно делать более сложные вещи, вы всегда можете вызывать ваш nodejs script из этой функции.

Это единственный способ выполнить то, что вы пытаетесь сделать.

Ответ 4

Короткий ответ: нет (легко?), но вы можете сделать что-то, что служит вашей цели.

Я сделал аналогичный инструмент (небольшая команда, которая, учитывая описание проекта, устанавливает среду, пути, каталоги и т.д.). То, что я делаю, это настроить все, а затем создать оболочку с помощью:

spawn('bash', ['-i'], {
  cwd: new_cwd,
  env: new_env,
  stdio: 'inherit'
});

После выполнения вы будете в оболочке с новым каталогом (и, в моем случае, средой). Конечно, вы можете изменить bash для любой оболочки, которую вы предпочитаете. Основные отличия от того, что вы изначально просили:

  • Существует дополнительный процесс, поэтому...
  • вам нужно написать "exit", чтобы вернуться, а затем...
  • после существующего, все изменения будут отменены.

Однако для меня эти различия желательны.