2015-11-03 7 views
43

Я видел эту строку #!/usr/bin/env node в начале некоторых примеров в nodejs, и у меня была googled, не найдя ни одной темы, которая могла бы ответить на причину этой строки.Что именно делает «/ usr/bin/env node» в начале файлов узлов?

Характер слов делает поиск не таким простым.

Недавно я прочитал несколько книг javascript и nodejs, и я не помню, чтобы их видели в любом из них.

Если вы хотите пример, вы можете увидеть RabbitMQ чиновника tutorial, они его почти во всех своих примерах, вот один из них:

#!/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); 
}); 

Может кто-нибудь объяснить мне, что это значит эта линия?

В чем разница, если я положил или удалю эту строку? В каких случаях он мне нужен?

+1

Он в основном принимает среду вызывающей оболочки и заполняет эту среду в любом приложении. в этом случае 'node' –

+0

На самом деле нет, я не из Windows, но спасибо за обновление вашего ответа. Я просто жду, чтобы увидеть, что кто-то еще придумывает разные мнения. Есть только одна вещь, о которой, я думаю, вы не упомянули в своем ответе, я просто нахожу ее пару часов назад. То, что они упоминают здесь, кажется важным, но пока еще недостаточно ясно для меня. http://stackoverflow.com/questions/14517535/directly-call-globally-installed-node-js-modules (вы можете обновить, если хотите, я действительно буду это оценивать, но не чувствую, что это как обязательство, ваше ответ достаточно хорош прямо сейчас). – Gepser

+0

@ Гепсер: Получил. Короче говоря, если вы хотите, чтобы «npm» установил исходный скрипт Node.js как (возможно глобально доступный) _CLI_, вы _must_ используете строку shebang - и 'npm' даже сделает эту работу в Windows; см. мой еще раз обновленный ответ. – mklement0

ответ

55

#!/usr/bin/env node является экземпляра shebang line: очень первой линии в исполняемом текстовом файле на Unix-подобные платформы, которые сообщают системе, какой интерпретатор передает этот файл на выполнение, через командную строку, следуя магии #! префикс (shebang).

Примечание: Окна делает не поддержки притон линии, поэтому они эффективно игнорировали там; в Windows это только имя файла данного файла, определяющее, какой исполняемый файл будет его интерпретировать. Тем не менее, вы все еще нуждаетесь в них в контексте npm. [1]

Далее, общее обсуждение хижину линий ограничена Unix-подобных платформах:

В дальнейшем изложении я буду считать, что файл, содержащий исходный код для исполнения узла .js просто называется file.

  • Вы НУЖНА эта линия, если вы хотите, чтобы вызвать узел.js исходный файл непосредственно, как самостоятельный исполняемый файл - это предполагает, что файл был помечен как исполняемый с помощью команды, такой как chmod +x ./file, которая затем позволяет вызывать файл, например, ./file, или, если он расположен в одной из каталогов, перечисленных в переменной $PATH, просто как file.

    • В частности, вам нужно притон линию для создания CLIs на основе исходных файлов Node.js как часть НПМ пакета, с CLI (ы), которые будут установлены на npm на основе стоимости "bin" key in a package's package.json file; также см. this answer о том, как это работает с глобально установлены пакеты. Сноска [1] показывает, как это обрабатывается в Windows.
  • Вы не нужен эту строку, чтобы вызвать файл в явном виде через node переводчика, например, node ./file


Дополнительно справочная информация:

#!/usr/bin/env <executableName> является способ портативно, указав переводчика: в двух словах он говорит: выполните <executableName> везде, где вы (сначала) найдете его среди каталогов, перечисленных в переменной $PATH (и неявно передайте ему путь к файлу под рукой).

Это объясняет тот факт, что данный интерпретатор может быть установлен в разных местах на разных платформах, что определенно имеет место с node, двоичным кодом Node.js.

В отличие от этого, расположение env полезности само по себе может полагаться быть в же место на разных платформах, а именно /usr/bin/env - и указав полный путь к исполняемому файлу является требуется в хижину линии ,

Обратите внимание, что утилита POSIX env в настоящее время переориентированы здесь, чтобы найти по имени файла и выполнить исполняемый в $PATH.
Настоящая цель env - управлять окружающей средой для команды - см. env's POSIX spec и Keith Thompson's helpful answer.


Стоит также отметить, что Node.js делает синтаксис исключение для хижину линий, при условии, что они не правильный код JavaScript (# не символ комментария в JavaScript, в отличие от POSIX-как снарядов и других переводчиков).


[1] В интересах последовательности кросс-платформенной, npm создает оболочки*.cmd файлы (командные файлы) на Windows, при установке исполняемых файлов, указанных в package.json файл из пакета (через "bin" собственности) , По сути, эти пакетные файлы обертки mimic Функциональность Unix shebang: они явно ссылаются на целевой файл с исполняемым файлом, указанным в строке shebang - таким образом, ваши сценарии должны включать строку shebang, даже если вы только когда-либо собираетесь их запускать Windows - см. this answer из моих подробностей.
С *.cmd файлы могут быть активированы без расширения .cmd. Это обеспечивает беспрепятственное кросс-платформенное использование: как в Windows, так и в Unix вы можете эффективно запускать CLI с своим оригинальным именем без расширения.

+0

Можете ли вы дать объяснение или резюме для таких манекенов, как я? –

+1

@AndrewLam: В Windows расширения файлов, такие как '.cmd' и' .py', определяют, какая программа будет использоваться для выполнения таких файлов. В Unix линия shebang выполняет эту функцию. Чтобы заставить npm работать на всех поддерживаемых платформах, вам нужна линия shebang даже в Windows. – mklement0

0

Короткий ответ: Это путь к интерпретатору.

EDIT (длинный ответ): Причина отсутствия косой черты перед «узлом» заключается в том, что вы не всегда можете гарантировать надежность #!/Bin /. Бит «/ env» делает программу более кросс-платформенной, запустив скрипт в модифицированной среде и надежно найдя программу интерпретатора.

Вам не обязательно, но это хорошо использовать для обеспечения переносимости (и профессионализма)

+1

бит '/ usr/bin/env' не изменяет среду. Это просто команда в известном местоположении (в основном), которое вызывает другую команду, заданную в качестве аргумента, и ищет '$ PATH', чтобы найти ее. Дело в том, что строка '#!' Требует полного пути к вызываемой команде, и вы не обязательно знаете, где установлен «узел». –

+0

Это было то, что я собирался, спасибо за разъяснение! – Quantum

12

Сценарии, которые должны быть выполнены интерпретатором, обычно имеют shebang line в верхней части, чтобы сообщить ОС, как их выполнять.

Если у вас есть сценарий с именем 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 с вашим скриптом в качестве аргумента.

Смотрите также this questionmy answer) для более детального обсуждения на #!/usr/bin/env трюком.

Кстати, в моей системе (Linux Mint 17.2) она установлена ​​как /usr/bin/nodejs. Согласно моим заметкам, он изменился с /usr/bin/node на /usr/bin/nodejs между Ubuntu 12.04 и 12.10. Трюк #!/usr/bin/env не поможет с этим (если вы не установили символическую ссылку или что-то подобное).

+0

Это было очень полезно, я просто не могу принять два ответа. Спасибо. – Gepser