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