nodejs
のいくつかの例の冒頭でこの行#!/usr/bin/env node
を見て、その行の理由に答えられるトピックを見つけずにグーグルで検索しました。
単語の性質上、検索はそれほど簡単ではありません。
最近、いくつかのjavascript
とnodejs
の本を読んだことがありますが、それらのいずれかで見たことを覚えていませんでした。
例が必要な場合は、RabbitMQ
official tutorial を見ることができます。ほとんどすべての例に含まれています。以下にその1つを示します。
#!/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);
});
誰かがこの行の意味を教えてくれますか?
この行を追加または削除した場合の違いは何ですか?どのような場合に必要ですか?
インタプリタによって実行されるスクリプトには、通常、OSにそれらの実行方法を指示する シェバンライン があります。
最初の行が#!/bin/sh
であるfoo
という名前のスクリプトがある場合、システムはその最初の行を読み取り、/bin/sh foo
に相当するものを実行します。このため、ほとんどのインタープリターは、スクリプトファイルの名前をコマンドライン引数として受け入れるように設定されています。
#!
に続くインタープリター名はフルパスである必要があります。 OSは$PATH
を検索してインタープリターを見つけません。
node
によって実行されるスクリプトがある場合、最初の行を記述する明白な方法は次のとおりです。
#!/usr/bin/node
node
コマンドが/usr/bin
にインストールされていない場合は機能しません。
一般的な回避策は、env
コマンドを使用することです(この目的のために(reallyではありません)):
#!/usr/bin/env node
スクリプトの名前がfoo
の場合、OSは同等の処理を行います
/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
コマンドが別のディレクトリにインストールされている古いシステムで作業しました。このメカニズムを使用して渡すことができる追加の引数には制限がある場合があります。ユーザーがいない場合、$PATH
にnode
コマンドを含むディレクトリがあるか、node
の場合、間違ったコマンドを呼び出すか、まったく機能しない可能性があります。
他のアプローチは次のとおりです。
node
コマンド自体へのフルパスを指定する#!
行を使用し、異なるシステムの必要に応じてスクリプトを更新します。またはnode
コマンドを呼び出します。#!/usr/bin/env
トリックの詳細については、 この質問 (および 私の答え )も参照してください。
ちなみに、私のシステム(Linux Mint 17.2)では、/usr/bin/nodejs
としてインストールされています。私のメモによると、Ubuntu 12.04と12.10の間で/usr/bin/node
から/usr/bin/nodejs
に変更されました。 #!/usr/bin/env
トリックはそれを助けません(シンボリックリンクなどをセットアップしない限り)。
更新:mtraceurによるコメントは(再フォーマットされた)と言います:
Nodejsとnodeの問題の回避策は、次の6行でファイルを開始することです。
#!/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
をインストールします。いくつかの以前のOS(UbuntuまたはLinux Mint、どちらかわからない)では、node
をnodejs
へのシンボリックリンクとして提供するnodejs-legacy
パッケージがありました。すべての詳細が正しいという保証はありません。
短い答え:通訳へのパスです。
編集(長い回答):「ノード」の前にスラッシュがない理由は、#!/ bin /の信頼性を常に保証できるとは限らないためです。 「/ env」ビットは、修正された環境でスクリプトを実行し、インタープリタープログラムをより確実に見つけることができるようにすることで、プログラムをよりクロスプラットフォームにします。
必ずしも必要ではありませんが、移植性(およびプロフェッショナリズム)を確保するために使用するとよいでしょう。