Сценарии, которые должны быть выполнены интерпретатором, обычно имеют shebang line в верхней части, чтобы сообщить ОС, как их выполнять.
Если у вас есть сценарий с именем foo
, чья первая строка #!/bin/sh
, система будет читать эту первую строку и выполнить эквивалент /bin/sh foo
. Из-за этого большинство интерпретаторов настроены так, чтобы принимать имя файла сценария в качестве аргумента командной строки.
Имя переводчика, соответствующее #!
, должно быть полным путем; ОС не будет искать ваш $PATH
, чтобы найти переводчика.
Если у вас есть сценарий, который будет выполнен по node
, очевидный способ написания первой линии:
#!/usr/bin/node
, но это не работает, если команда node
не установлена в /usr/bin
.
Обычным решением является использование env
команды (который был не действительно предназначен для этой цели):
#!/usr/bin/env node
Если ваш скрипт называется foo
, операционная система будет делать эквивалент
/usr/bin/env node foo
Команда env
выполняет другую команду, имя которой задано в командной строке, передавая ей следующие аргументы. Причина, по которой здесь используется, заключается в том, что env
будет искать команду $PATH
. Поэтому, если node
установлен в /usr/local/bin/node
, и у вас есть /usr/local/bin
в вашем $PATH
, команда env
будет вызывать /usr/local/bin/node foo
.
Основная цель команды env
- выполнить еще одну команду с измененной средой, добавив или удалив указанные переменные среды перед запуском команды. Но без дополнительных аргументов он просто выполняет команду с неизменной средой, которая вам нужна в этом случае.
Есть некоторые недостатки этого подхода. Большинство современных Unix-подобных систем имеют /usr/bin/env
, но я работал над более старыми системами, в которых команда env
была установлена в другом каталоге. Могут быть ограничения на дополнительные аргументы, которые вы можете передать с помощью этого механизма. Если у пользователя нет, есть каталог, содержащий команду node
в $PATH
, или имеет некоторую другую команду под названием node
, тогда она может вызвать неправильную команду или вообще не работать.
Другие подходы:
- Используйте
#!
строку, которая определяет полный путь к самой node
команды, обновление сценария по мере необходимости для различных систем; или
- Вызовите команду
node
с вашим скриптом в качестве аргумента.
Смотрите также this question (и my answer) для более детального обсуждения на #!/usr/bin/env
трюком.
Кстати, в моей системе (Linux Mint 17.2) она установлена как /usr/bin/nodejs
. Согласно моим заметкам, он изменился с /usr/bin/node
на /usr/bin/nodejs
между Ubuntu 12.04 и 12.10. Трюк #!/usr/bin/env
не поможет с этим (если вы не установили символическую ссылку или что-то подобное).
Он в основном принимает среду вызывающей оболочки и заполняет эту среду в любом приложении. в этом случае 'node' –
На самом деле нет, я не из Windows, но спасибо за обновление вашего ответа. Я просто жду, чтобы увидеть, что кто-то еще придумывает разные мнения. Есть только одна вещь, о которой, я думаю, вы не упомянули в своем ответе, я просто нахожу ее пару часов назад. То, что они упоминают здесь, кажется важным, но пока еще недостаточно ясно для меня. http://stackoverflow.com/questions/14517535/directly-call-globally-installed-node-js-modules (вы можете обновить, если хотите, я действительно буду это оценивать, но не чувствую, что это как обязательство, ваше ответ достаточно хорош прямо сейчас). – Gepser
@ Гепсер: Получил. Короче говоря, если вы хотите, чтобы «npm» установил исходный скрипт Node.js как (возможно глобально доступный) _CLI_, вы _must_ используете строку shebang - и 'npm' даже сделает эту работу в Windows; см. мой еще раз обновленный ответ. – mklement0