Сценарії, які повинен виконати інтерпретатор, зазвичай мають верхню рядок 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