Сценарии, которые должны выполняться интерпретатором, обычно имеют строку shebang вверху, чтобы сообщить ОС, как их выполнять.
Если у вас есть сценарий с именем 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
команду с вашим сценарием в качестве аргумента.
См. Также этот вопрос (и мой ответ ) для более подробного обсуждения #!/usr/bin/env
трюка.
Между прочим, в моей системе (Linux Mint 17.2) он установлен как /usr/bin/nodejs
. По моим записям, он изменился от /usr/bin/node
до /usr/bin/nodejs
между Ubuntu 12.04 и 12.10. #!/usr/bin/env
Трюк не поможет с этим (если вы создали символическую ссылку или что - то подобное).
ОБНОВЛЕНИЕ: комментарий mtraceur (переформатированный) говорит:
Обходной путь для решения проблемы nodejs vs node - запустить файл со следующими шестью строками:
#!/bin/sh -
':' /*-
test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
test2=$(node --version 2>&1) && exec node "$0" "$@"
exec printf '%s\n' "$test1" "$test2" 1>&2
*/
Сначала будет предпринята попытка, nodejs
а затем попытка node
, и будут распечатаны сообщения об ошибках, только если они оба не найдены. Объяснение выходит за рамки этих комментариев, я просто оставляю его здесь на тот случай, если оно поможет кому-нибудь справиться с проблемой, поскольку этот ответ вызвал проблему.
В последнее время я не использовал NodeJS. Я надеюсь, что проблема nodejs
vs. node
была решена за годы, прошедшие с тех пор, как я впервые опубликовал этот ответ. В Ubuntu 18.04 nodejs
пакет устанавливается /usr/bin/nodejs
как символическая ссылка на /usr/bin/node
. В некоторых более ранних ОС (Ubuntu или Linux Mint, я не уверен в какой) был nodejs-legacy
пакет, который предоставлялся node
как символическая ссылка на nodejs
. Нет гарантии, что у меня есть все подробности.
node