Node.js очень популярен в наши дни, и я написал для него несколько скриптов. К сожалению, совместимость является проблемой. Официально должен вызываться интерпретатор Node.js node
, но nodejs
вместо этого Debian и Ubuntu поставляют исполняемый файл .
Мне нужны переносимые скрипты, с которыми Node.js может работать в максимально возможном количестве ситуаций. Предполагая, что имя файла есть foo.js
, я действительно хочу, чтобы скрипт выполнялся двумя способами:
./foo.js
запускает скрипт, если либоnode
илиnodejs
находится в$PATH
.node foo.js
также запускает скрипт (при условии, что вызывается переводчикnode
)
Примечание . Ответы xavierm02 и меня являются двумя вариантами сценария полиглота. Я все еще заинтересован в чистом решении Шебанга, если таковое существует.
scripting
compatibility
node.js
dancek
источник
источник
node
для вашего скрипта, либо использовать скрипт make, который изменяет shebang.alphacentauri
и тому подобное. Если есть исполняемый файлnodejs
, вы можете быть на 99% уверены, что это Node.js. Почему бы не поддержать и то,nodejs
и другоеnode
?Ответы:
Лучшее, что я придумал, - это «двухстрочный шебанг», который на самом деле является сценарием полиглота (Bourne shell / Node.js):
Первая строка - это, очевидно, оболочка Борна. Node.js обходит любой обнаруженный шебанг, так что это допустимый файл javascript в отношении Node.js.
Вторая строка вызывает оболочку no-op
:
с аргументом//
и затем выполняетnodejs
илиnode
с именем этого файла в качестве параметра.command -v
используется вместоwhich
для переносимости. Синтаксис подстановки команд$(...)
не является строго Bourne, поэтому выбирайте обратные пометки, если вы запустите это в 1980-х годах.Node.js просто оценивает строку
':'
, которая похожа на no-op, а остальная часть строки анализируется как комментарий.Остальная часть файла - просто старый javascript. Подоболочка закрывается после завершения
exec
второй строки, поэтому остальная часть файла никогда не читается оболочкой.Спасибо xavierm02 за вдохновение и всем комментаторам за дополнительную информацию!
источник
':'
подходу является использование// 2>/dev/null
(что иnvm
делает): для bash это ошибка (bash: //: Is a directory
), которую перенаправление2>/dev/null
спокойно игнорирует; для JavaScript вся строка становится комментарием. Кроме того - и я не ожидаю, что это вызовет проблемы в IRL -command
есть особенность, при которой он также сообщает о функциях оболочки и псевдонимах-v
- даже при том, что он фактически не вызывает их. Таким образом, если у вас есть экспортированные функции оболочки или даже псевдонимы (при условииshopt -s expand_aliases
) с именемnode
илиnodejs
, вещи могут сломаться.mksh
,bash
,dash
и других оболочек в современных системах Unix и GNU.#!/usr/bin/env sh
вместо этого#!/bin/sh
( вместо en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability ) можно было бы использовать даже более переносимый#!/usr/bin/env sh
как с «более портативной». В той же статье в Википедии написано: «Это в основном работает, потому что путь / usr / bin / env обычно используется для утилиты env ...» Это не замечательное подтверждение, и я предполагаю, что вы будете работать с системами без/usr/bin/env
более частого Вы сталкиваетесь с системами без/bin/sh
, если есть какая-либо разница в частоте вообще.//bin/sh -c :; exec ...
ли более чистая версия второй линии?//bin/false
это то же самое,/bin/false
за исключением того, что второй слеш превращает его в комментарий для узла, и именно поэтому он здесь. Затем||
оценивается правая сторона первого .'which node || which nodejs'
с кавычками вместо кавычек запускает узел и<<
кормит его тем, что находится справа. Я мог бы использовать разделитель, начинающийся с//
того же, что и dancek, он бы сработал, но я нахожу более чистым, чтобы в начале было только две строки, поэтому я имел обыкновениеtail -n +2 $0
читать сам файл, кроме первых двух строк.И если вы запускаете его в узле, первая строка распознается как шебанг и игнорируется, а вторая - как однострочный комментарий.
(Очевидно, sed можно использовать для замены содержимого файла tail tail без первой и последней строк )
Ответ перед редактированием:
Вы не можете делать то, что хотите, поэтому вместо этого вы запускаете скрипт оболочки, отсюда и
#!/bin/sh
. Этот сценарий оболочки получит путь к файлу, необходимому для выполнения узла, то естьwhich node || which nodejs
. Обратные'which node || which nodejs'
кавычки здесь, чтобы он выполнялся, поэтому (с обратными кавычками вместо кавычек) просто вызывается узел. Затем вы просто кормите свой сценарий для него<<
. Это__HERE__
разделители вашего сценария. Иconsole.log('ok');
это пример скрипта, который вы должны заменить своим скриптом.источник
<<'__HERE__'
.//bin/false
это не работает в моей среде MSYS, и мне нужны кавычки вокруг обратных галочек, так как мойnode
находится по адресуC:\Program Files\...
. Да, я работаю в ужасной обстановке ...//bin/false
на Mac OS X тоже не работает. Извините, но это больше не кажется переносимым.which
также не является переносимой.Это проблема только в системах на основе Debian, где политика преодолела смысл.
Я не знаю, когда Fedora предоставила двоичный файл с именем nodejs, но я никогда не видел его. Пакет называется nodejs и устанавливает двоичный файл с именем node.
Просто используйте символическую ссылку, чтобы применить здравый смысл к системам, основанным на Debian, и тогда вы сможете использовать разумный шебанг. В любом случае, другие люди будут использовать вменяемые шебанги, поэтому вам понадобится эта символическая ссылка.
источник
nodejs
исполняемый файл , но это не вина Fedora. Извините за искажение факта.#!/usr/bin/perl
. Тем не менее, вы не обязаны любить или применять мои предложения. Мир.Если вы не возражаете против создания небольшого
.sh
файла, у меня есть для вас небольшое решение. Вы можете создать небольшой скрипт оболочки, чтобы определить, какой исполняемый файл узла использовать, и использовать этот скрипт в своем шебанге:shebang.sh :
script.js :
Пометить как исполняемый файл, так и запустить
./script.js
.Таким образом, вы избегаете сценариев полиглота. Я не думаю, что использование нескольких линий Шебанга возможно, хотя это кажется хорошей идеей.
Хотя это решает проблему так, как вы хотите, похоже, никто не заботится об этом. Например, uglifyjs и coffeescript использует
#!/usr/bin/env node
, npm использует сценарий оболочки в качестве точки входа, которая снова вызывает исполняемый файл явно с именемnode
. Я пользователь Ubuntu, и я не знал этого, так как я всегда компилирую узел. Я собираюсь сообщить об этом как об ошибке.источник
chmod +x
написать сценарий sh ... так что вы можете также попросить его установить переменную, указывающую местоположение для исполняемого файла его узла ...chmod +x
"d. И я согласен, что переменная NODE лучше, чемwhich node || which nodejs
. Но дознаватель хочет предоставить готовый опыт, хотя многие крупные проекты узлов просто используют#!/usr/bin/env node
.Просто для полноты вот пара других способов сделать вторую строку:
Но ни один из них не имеет никакого преимущества перед выбранным ответом:
Кроме того, если вы знали, что будет найден один
node
илиnodejs
(но не оба), следующие работы:Но это большое «если», поэтому я думаю, что выбранный ответ остается лучшим.
источник
foobar // 2>/dev/null
еслиfoobar
это не команда. И многие утилиты, найденные в любой системе POSIX, могут быть запущены с//
аргументом.Я понимаю, что это не отвечает на вопрос, но я убежден, что вопрос задается с ложной предпосылкой.
Ubuntu здесь не так. Написание универсального шебанга для вашего собственного скрипта не изменит другие пакеты, над которыми вы не имеете никакого контроля, которые используют стандарт де-факто
#!/usr/bin/env node
. Ваша система должна обеспечитьnode
в ,PATH
если он желает для любых сценариев , ориентированных на nodejs , чтобы работать на нем.Например, даже
npm
пакет, предоставленный Ubuntu, не переписывает shebangs в пакетах:источник