Я видел эту строку #!/usr/bin/env node
в начале некоторых примеров nodejs
и искал в Google, не найдя темы, которая могла бы ответить на причину этой строки.
Природа слов затрудняет поиск.
Я прочитал некоторые javascript
и nodejs
книги в последнее время, и я не помню , что видел его в любом из них.
Если вам нужен пример, вы можете увидеть RabbitMQ
официальное руководство , оно есть почти во всех своих примерах, вот один из них:
#!/usr/bin/env node
var amqp = require('amqplib/callback_api');
amqp.connect('amqp://localhost', function(err, conn) {
conn.createChannel(function(err, ch) {
var ex = 'logs';
var msg = process.argv.slice(2).join(' ') || 'Hello World!';
ch.assertExchange(ex, 'fanout', {durable: false});
ch.publish(ex, '', new Buffer(msg));
console.log(" [x] Sent %s", msg);
});
setTimeout(function() { conn.close(); process.exit(0) }, 500);
});
Может ли кто-нибудь объяснить мне, что означает эта строка?
Какая разница, если поставить или убрать эту строчку? В каких случаях мне это нужно?
node
npm
установить исходный сценарий Node.js в качестве (потенциально доступного глобально) интерфейса командной строки , вы должны использовать строку shebang - иnpm
даже заставить ее работать в Windows; см. мой еще раз обновленный ответ.Ответы:
#!/usr/bin/env node
является экземпляром строки shebang : самая первая строка в исполняемом текстовом файле на Unix-подобных платформах, которая сообщает системе, какой интерпретатор передать этот файл для выполнения , через командную строку, следующую за магическим#!
префиксом (называемым shebang ) .Примечание: Windows , никак не поддерживает притон линии , поэтому они эффективно игнорируются там; в Windows только расширение имени файла данного файла определяет, какой исполняемый файл будет его интерпретировать. Однако они все равно нужны вам в контексте
npm
. [1]Следующее общее обсуждение строк shebang ограничено Unix-подобными платформами:
В следующем обсуждении я предполагаю, что файл, содержащий исходный код для выполнения Node.js, имеет просто имя
file
.Вам НУЖНА эта строка , если вы хотите напрямую вызвать исходный файл Node.js как самостоятельный исполняемый файл - это предполагает, что файл был помечен как исполняемый с помощью такой команды, как
chmod +x ./file
, которая затем позволяет вам вызывать файл с, например,,./file
или, если он находится в одном из каталогов, перечисленных в$PATH
переменной, просто какfile
.npm
основе значения"bin"
ключа вpackage.json
файле пакета ; также посмотрите этот ответ, чтобы узнать, как это работает с глобально установленными пакетами. В сноске [1] показано, как это делается в Windows.Эта строка НЕ нужна для явного вызова файла через
node
интерпретатор, например,node ./file
Дополнительная справочная информация :
#!/usr/bin/env <executableName>
- это способ переносимого определения интерпретатора: в двух словах он гласит: выполнять<executableName>
везде, где вы (сначала) найдете его среди каталогов, перечисленных в$PATH
переменной (и неявно передать ему путь к файлу под рукой).Это объясняет тот факт, что данный интерпретатор может быть установлен в разных местах на разных платформах, что, безусловно, относится
node
к двоичному файлу Node.js.Напротив,
env
можно полагаться , что расположение самой утилиты будет в одном и том же месте на разных платформах, а именно/usr/bin/env
- и требуется указать полный путь к исполняемому файлу в строке shebang.Обратите внимание , что POSIX утилита
env
в настоящее время переориентирована здесь , чтобы найти по имени файла и выполнить исполняемый в$PATH
.Истинная цель
env
- управлять средой для команды - см. Спецификациюenv
POSIX и полезный ответ Кейта Томпсона .Также стоит отметить, что Node.js делает синтаксическое исключение для строк shebang, учитывая, что они не являются допустимым кодом JavaScript (
#
не является символом комментария в JavaScript, в отличие от POSIX-подобных оболочек и других интерпретаторов).[1] В интересах кросс-платформенной согласованности
npm
создает файлы- оболочки*.cmd
(командные файлы) в Windows при установке исполняемых файлов, указанных вpackage.json
файле пакета (через"bin"
свойство). По сути, эти пакетные файлы оболочки имитируют функциональность Unix shebang: они явно вызывают целевой файл с исполняемым файлом, указанным в строке shebang - таким образом, ваши сценарии должны включать строку shebang, даже если вы собираетесь запускать их только в Windows - см. Этот ответ для подробностей.Поскольку
*.cmd
файлы можно вызывать без.cmd
расширение, это обеспечивает беспроблемный кроссплатформенный опыт: как в Windows, так и в Unix вы можете эффективно вызывать установленныйnpm
интерфейс командной строки по его оригинальному имени без расширения.источник
.cmd
и,.py
определяют, какая программа будет использоваться для выполнения таких файлов. В Unix эту функцию выполняет строка shebang. Чтобыnpm
работать на всех поддерживаемых платформах, вам понадобится строка shebang даже в Windows.Сценарии, которые должны выполняться интерпретатором, обычно имеют строку shebang вверху, чтобы сообщить ОС, как их выполнять.
Если у вас есть сценарий с именем
foo
первой строки#!/bin/sh
, система прочитает эту первую строку и выполнит эквивалент/bin/sh foo
. Из-за этого большинство интерпретаторов настроены так, чтобы принимать имя файла сценария в качестве аргумента командной строки.Имя интерпретатора после
#!
символа должно быть полным путем; ОС не будет искать у вас$PATH
переводчика.Если у вас есть сценарий для выполнения
node
, очевидный способ написать первую строку:но это не работает, если
node
команда не установлена в/usr/bin
.Обычный обходной путь - использовать
env
команду (которая на самом деле не предназначена для этой цели):Если ваш скрипт вызывается
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. Я надеюсь, что проблема
nodejs
vs.node
была решена за годы, прошедшие с тех пор, как я впервые опубликовал этот ответ. В Ubuntu 18.04nodejs
пакет устанавливается/usr/bin/nodejs
как символическая ссылка на/usr/bin/node
. В некоторых более ранних ОС (Ubuntu или Linux Mint, я не уверен в какой) былnodejs-legacy
пакет, который предоставлялсяnode
как символическая ссылка наnodejs
. Нет гарантии, что у меня есть все подробности.источник
nodejs
vsnode
- запустить файл со следующими шестью строками: 1)#!/bin/sh -
, 2)':' /*-
3)test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
4)test2=$(node --version 2>&1) && exec node "$0" "$@"
, 5)exec printf '%s\n' "$test1" "$test2" 1>&2
6)*/
. Сначала будет предпринята попытка,nodejs
а затем попыткаnode
, и будут распечатаны сообщения об ошибках, только если они оба не найдены. Объяснение выходит за рамки этих комментариев, я просто оставляю его здесь на тот случай, если оно поможет кому-нибудь справиться с проблемой, поскольку этот ответ вызвал проблему.-
на#!
кону?-
В#!/bin/sh -
это просто привычка , которая гарантирует , что ведет себя оболочку прямо в очень узком и маловероятном стечении обстоятельств , что имя сценария или относительный путь , что оболочка видит начинается с-
. (Кроме того, да, похоже, что каждый основной дистрибутив вернулся кnode
основному имени. Я не копался, чтобы проверить, когда делал свой комментарий, но, насколько мне известно, использовалось только семейное древо дистрибутива Debiannodejs
, и это выглядит как будто все они вернулись к поддержке, какnode
только это сделал Debian.)-x
и-v
», но поскольку ранние борн-лайки анализировали только первый аргумент как возможные варианты, и поскольку оболочка запускается с отключенными этими параметрами , было злоупотреблением заставлять оболочку не пытаться анализировать имя сценария, начиная с оригинала, и, таким образом, остается объектом злоупотреблений, поскольку поведение поддерживается в современных борн-лайках по соображениям совместимости. Если я правильно помню всю свою историю Борна и мелочи по переносимости.Краткий ответ: это путь к интерпретатору.
РЕДАКТИРОВАТЬ (длинный ответ): Причина, по которой перед «узлом» нет косой черты, заключается в том, что вы не всегда можете гарантировать надежность #! / Bin /. Бит «/ env» делает программу более кроссплатформенной за счет запуска сценария в измененной среде и более надежного поиска программы-интерпретатора.
Вам это не обязательно нужно, но его можно использовать для обеспечения портативности (и профессионализма)
источник
/usr/bin/env
Бит не изменяет окружающую среду. Это просто команда в (в основном) известном месте, которая вызывает другую команду, заданную в качестве аргумента, и ищет$PATH
ее. Дело в том, что в#!
строке требуется полный путь к вызываемой команде, и вы не обязательно знаете, гдеnode
она установлена.