Universal Node.js shebang?

Universal Node.js shebang?

Node.js最近はかなり人気があり、それを利用してスクリプトを作成しています。残念ながら、互換性が問題です。正式にNode.jsインタプリタはとして呼び出される必要がありますnodeが、DebianとUbuntuはnodejs

私はできるだけ多くの状況で利用できるNode.js移植可能なスクリプトが欲しいです。ファイル名がと仮定すると、foo.jsスクリプトは2つの方法で実行されることを望みます。

  1. ./foo.jsnodeまたはがnodejsある場合は、スクリプトを実行してください$PATH
  2. node foo.jsまた、スクリプトを実行します(インタプリタが呼び出されると仮定node)。

メモ:xavierm02と私の答えは、多言語スクリプトの2つのバリエーションです。私は純粋なshebangソリューションが存在する場合はまだ興味があります。

答え1

私が思いついた最高のものは、実際にはマルチ言語(Bourne shell / Node.js)スクリプトである「2行シェバン」です。

#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

console.log('Hello world!');

明らかに、最初の行はBourne shell shebangです。 Node.jsは見つかったすべてのshebangをバイパスするので、Node.jsに関する限り、これは有効なJavaScriptファイルです。

:2行目は引数を使用してシェルのno-opを呼び出し、//ファイル名を引数として実行しますnodejs。移植性の代わりに使用されます。コマンドの代替構文は厳密に言えばBourneではないため、1980年代にこのコマンドを実行する場合はバックティックを選択してください。nodecommand -vwhich$(...)

Node.jsは何もしないかのように動作する文字列を評価し、':'残りの行はコメントとして解析されます。

ファイルの残りの部分は普通の古いJavaScriptです。サブシェルはexec2 行目の完了後に終了するため、シェルはファイルの残りの部分を読み取ることはありません。

インスピレーションを受けたxavierm02と、追加情報をいただいたコメントの投稿者に感謝します。

答え2

これは、ポリシーが意味を克服する Debian ベースのシステムでのみ発生する問題です。

Fedoraがnodejsというバイナリをいつ提供したかはわかりませんが、見たことがありません。パッケージはnodejsと呼ばれ、node.jsというバイナリをインストールします。

シンボリックリンクを使用して Debian ベースのシステムに常識を適用する場合は、正気である Shebang を使用することをお勧めします。とにかく、他の人は通常のshebangを使用するので、対応するシンボリックリンクが必要です。

#!/usr/bin/env node

console.log("Spread the love.");

答え3

#!/bin/sh
//bin/false || `which node || which nodejs` << `tail -n +2 $0`
console.log('ok');

//bin/false/bin/false2番目のスラッシュがノードのコメントに変わるのと同じです。これがここにある理由です。次に、最初の項目の右側を||評価します。'which node || which nodejs'引用符の代わりにバックティックを使用してノードを起動し、右側の<<内容を指定します。このようにダンスで始まる区切り文字を使用することも//動作するかもしれませんが、最初は2行だけを使用する方がきれいであることがわかったので、tail -n +2 $0最初の2行を除いてファイル自体を読み取るようにしました。

nodeで実行すると、最初の行はshebangとして認識され、無視され、2行目は1行コメントになります。

(もちろん、tailの代わりにsedを使用することもできます。最初の行と最後の行を除いてファイルの内容を印刷します。)


編集する前に答えてください:

#!/bin/sh
`which node || which nodejs` <<__HERE__
console.log('ok');
__HERE__

望むことができないので、シェルスクリプトを実行する必要があります#!/bin/sh。したがって、シェルスクリプトはノードの実行に必要なファイルのパスを取得します。つまり、ノードwhich node || which nodejsが実行されるようにバックティックがここにあります。したがって、'which node || which nodejs'引用符の代わりにバックティックを使用してnode.jsを呼び出すだけです。次にスクリプトの区切り記号です<<__HERE__これはconsole.log('ok');サンプルスクリプトなので、ユーザーのスクリプトで置き換える必要があります。

答え4

完成度を上げるために2行目を実行する別の方法は次のとおりです。

// 2>/dev/null || echo yes
false //|| echo yes

ただし、どちらも選択した回答よりも利点はありません。

':' //; || echo yes

nodeまたは、どちらか一方しか見つからないことがわかっている場合は、nodejs次のことを実行できます。

exec `command -v node nodejs` "$0" "$@"

しかし、それは大きな「もし」なので、選択した答えがまだ最高の答えだと思います。

関連情報