Сценарии, которые должны выполняться интерпретатором, обычно имеют строку 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. Я надеюсь, что проблема nodejsvs. nodeбыла решена за годы, прошедшие с тех пор, как я впервые опубликовал этот ответ. В Ubuntu 18.04 nodejsпакет устанавливается /usr/bin/nodejsкак символическая ссылка на /usr/bin/node. В некоторых более ранних ОС (Ubuntu или Linux Mint, я не уверен в какой) был nodejs-legacyпакет, который предоставлялся nodeкак символическая ссылка на nodejs. Нет гарантии, что у меня есть все подробности.
node