2015-11-03 7 views
43

私はnodejsのいくつかの例の冒頭にこの行#!/usr/bin/env nodeを見て、私はその行の理由に答えることができるトピックを見つけることなくグーグルで探検しました。"/ usr/bin/env node"はノードファイルの先頭で何をしますか?

単語の性質上、検索が簡単ではありません。

私は最近、javascriptnodejsの本を読んでいましたが、私はそれを見て覚えていませんでした。

あなたが例をしたい場合、あなたは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からは来ていませんが、あなたの答えを更新していただきありがとうございます。他の誰かが別の意見を持っているかどうかを確認するのを待っているだけです。あなたの答えに言及していないと思うものが1つだけあります。私はそれを数時間前に見つけます。彼らがここで言及していることは重要だと思われますが、私にとってはまだ十分ではありません。 http://stackoverflow.com/questions/14517535/directly-call-globally-installed-node-js-modules(必要に応じて更新することができます。私はそれを本当に評価しますが、それは義務のようには感じません。答えは今のところ十分です)。 – Gepser

+0

@Gepser:入手しました。もし、 'npm'がNode.jsのソーススクリプトを(おそらくグローバルに利用可能な)_CLI_としてインストールしたいのであれば、シバン行を使用する必要があります - そして' npm'はWindows上で動作させるでしょう。私の一度だけ更新された答えを見てください。 – mklement0

答えて

55

#!/usr/bin/env nodeshebang lineインスタンスである:実行可能なプレーンテキストファイルで非常に最初の行魔法#!接頭次のコマンドラインを介して、実行のためにそのファイルを渡すためにどのような通訳システムに指示Unixライクなプラットフォームに(シェバングと呼ばれます)。

注:彼らは効果的を無視しているようのWindowsは、ないサポートシェバング行を行います。 Windows上では、指定されたファイルのというファイル名の拡張子のみが、実行可能ファイルを解釈するかどうかを決定します。 しかし、あなたはnpmの文脈でそれらを必要とします。私は、ファイルノードによって実行するためのソースコードを含むと仮定します以下の説明において

[1]

以下、シェバング線の一般的な議論ははUnixライクなプラットフォームに制限されています.jsは単にfileという名前です。

  • あなたがノードを起動したい場合は、この行をNEED 。jsソースファイルを直接として実行可能ファイルとして指定します。これは、ファイルがchmod +x ./fileなどのコマンドで実行可能とマークされていることを前提としています。このファイルでは、たとえば./fileでファイルを呼び出すことができます。変数$PATHに記載されているディレクトリの1つにあり、単にfileとなっています。 CLI(s)はの値に基づいてnpmによってインストールされるように具体的に、あなたは、NPM パッケージの一部としてのNode.jsのソースファイルに基づいてのCLIを作成するために、シェバング行を必要とする

    • "bin" key in a package's package.json file;また、どのようにグローバルにインストールパッケージで動作するかについては、this answerを参照してください。脚注[1]は、これがWindows上でどのように処理されるかを示しています。
  • あなたは例えば、nodeインタプリタを経由して、明示的にファイルを呼び出すためににこのラインを必要としないnode ./file


オプションの背景情報

#!/usr/bin/env <executableName>がありますの移植方法:インタプリタを指定すると:$PATH変数にリストされているディレクトリの中で(最初に)それを見つけて(そして暗黙のうちにそのファイルへのパスを渡して)どこでも、<executableName>を実行してください。

これは、特定のインタプリタがプラットフォーム間で異なる場所にインストールされる可能性があることを説明しています。これは、明らかにNode.jsバイナリnodeの場合です。

対照的に、envユーティリティ自体の位置は、プラットフォーム間同じ位置、すなわち/usr/bin/envになるように依拠することができる - と実行に完全パスを指定はシェバングラインにを必要とされます。 POSIXユーティリティenvがファイル名で検索し、$PATHに実行可能ファイルを実行するためにここでに再利用されていること

注意。
envの真の目的は、コマンドの環境を管理することです。env's POSIX specKeith Thompson's helpful answerを参照してください。


それは#は、POSIXのようなとは異なり、JavaScriptでコメント文字ではありません(彼らは有効なJavaScriptコードじゃないことを考えると、また、Node.jsのはシェバングラインの構文例外を作っていることは注目に値しますシェルや他の通訳)。


"bin"プロパティを経由して)パッケージのpackage.jsonファイルで指定された実行可能ファイルをインストールするときに、[1]クロスプラットフォームの一貫性の関心は、npmは、Windowsラッパー*.cmdファイル(バッチファイル)を作成します。これらのラッパーバッチファイル模倣 UNIXシバン機能:は、シバン線で指定された実行可能ファイルで明示的にターゲットファイルを呼び出す - これを実行するつもりであってもスクリプトにはシバン線が含まれていなければなりませんWindows - 詳しくはthis answerを参照してください。
.cmd拡張子なしでファイルを呼び出すことができるので、シームレスなクロスプラットフォーム環境が実現します.WindowsとUnixの両方で、インストールされたnpmのCLIを効果的に元のエクステンションレス名で呼び出すことができます。

+0

私のような人形の説明や要約を提供できますか? –

+1

@AndrewLam:Windowsでは、 '.cmd'や' .py'などのファイル拡張子によって、そのようなファイルを実行するために使用されるプログラムが決まります。 Unixでは、シバン線がその機能を実行します。サポートされているすべてのプラットフォームで 'npm 'を動作させるには、Windows上でもシバン線が必要です。 – mklement0

0

短い回答: これはインタープリタへのパスです。

EDIT(長い回答): 「ノード」の前にスラッシュがないのは、#!/ bin /の信頼性を必ずしも保証できないためです。 "/ env"ビットは、修正された環境でスクリプトを実行し、より確実にインタープリタプログラムを見つけることができるようにすることにより、プログラムをよりクロスプラットフォームにします。

あなたは、必ずしもそれを必要としないが、移植性(とプロフェッショナリズム)を確保するために使用することが良いです

+1

'/ usr/bin/env'ビットは環境を変更しません。それは引数として与えられた別のコマンドを起動し、それを見つけるために '$ PATH'を検索する(ほとんど)既知の場所での単なるコマンドです。要点は、 '#!'行には、呼び出されるコマンドへのフルパスが必要であり、 'node'がインストールされている場所を必ずしも知っているとは限りません。 –

+0

それは私が行っていたことでした、明確化のおかげで! – Quantum

12

インタープリタによって実行されるスクリプトは、通常、実行方法をOSに伝えるために、先頭にshebang lineがあります。

fooという名前のスクリプトの最初の行が#!/bin/shの場合、システムはその最初の行を読み取り、/bin/sh fooに相当するものを実行します。このため、ほとんどのインタプリタは、スクリプトファイルの名前をコマンドライン引数として受け入れるように設定されています。

#!に続くインタプリタ名はフルパスでなければなりません。 OSはあなたの$PATHを検索してインタプリタを見つけません。

あなたはnodeが実行するスクリプトを持っている場合は、最初の行を記述する明白な方法は次のとおりです。

#!/usr/bin/node 

しかしnodeコマンドが/usr/binにインストールされていない場合には動作しません。

共通の回避策は、(この目的のために意図本当にませんでした)envコマンドを使用することです:

#!/usr/bin/env node 

スクリプトがfoo呼び出された場合、OSは

と同等のものを行います
/usr/bin/env node foo 

envコマンドは、コマンドラインで指定された名前の別のコマンドを実行し、そのコマンドに続く引数を渡します。ここで使用される理由は、envがコマンドのために$PATHを検索することです。したがってが/usr/local/bin/nodeにインストールされていて、$PATH/usr/local/binがある場合、envコマンドは/usr/local/bin/node fooを呼び出します。

コマンドの主な目的は、変更された環境で別のコマンドを実行し、コマンドを実行する前に指定された環境変数を追加または削除することです。しかし、追加の引数がなくても、変更されていない環境でコマンドを実行するだけです。この場合、必要なのはすべてです。

このアプローチにはいくつかの欠点があります。最近のUnixライクなシステムのほとんどは/usr/bin/envですが、私は古いディレクトリでenvコマンドを別のディレクトリにインストールしていました。このメカニズムを使用して渡すことができる追加の引数には制限があります。ユーザのディレクトリに$PATHnodeコマンドを含むディレクトリを持っていないか、またはnodeという別のコマンドがある場合、間違ったコマンドを呼び出すか、まったく動作しない可能性があります。

他のアプローチは、以下のとおりです。

  • は、異なるシステムのために、必要に応じてスクリプトを更新し、nodeコマンド自体への完全なパスを指定#!ラインを使用します。または
  • スクリプトを引数としてnodeコマンドを呼び出します。

#!/usr/bin/envトリックのより多くの議論のためにもthis question(およびmy answer)を参照してください。

私のシステム(Linux Mint 17.2)では、/usr/bin/nodejsとしてインストールされています。私のメモによると、それはから/usr/bin/nodejsに、Ubuntu 12.04と12.10の間で変更されました。 #!/usr/bin/envトリックはそれを助けません(シンボリックリンクなどを設定しない限り)。

+0

これは非常に便利で、私はちょうど2つの答えを受け入れることができませんでした。ありがとうございました。 – Gepser

関連する問題