回答:
実用的な違いがあります。
curl -sSL https://get.docker.com/ | sh
開始curl
とsh
の出力接続、同時にcurl
入力としますsh
。スクリプトを実行できるcurl
速度で(大体)ダウンロードsh
を実行します。サーバーは、タイミングの不規則性を検出し、リソースをファイルまたはバッファーに単にダウンロードするとき、またはブラウザーで表示するときに表示されない悪意のあるコードを挿入できます。
ではsh -c "$(curl -sSL https://get.docker.com/)"
、curl
が実行される前に厳密にsh
実行されます。リソースの内容全体がダウンロードされ、シェルsh
が開始される前にシェルに渡されます。シェルは、終了したsh
ときにのみ開始されcurl
、リソースのテキストをシェルに渡します。サーバーはsh
呼び出しを検出できません。接続が終了した後にのみ開始されます。最初にスクリプトをファイルにダウンロードすることに似ています。
(これはdockerの場合には関係ないかもしれませんが、一般的には問題になる可能性があり、2つのコマンドの実際の違いを強調しています。)
vulnerable to server-side detection
フレーズにリンクを付けました。それは彼らがそれを達成する方法を詳細に説明するブログ投稿につながります。TL; DR:スクリプトにスリープを設定し、サーバーでの受信の遅延を観察します。
私はそれらが実質的に同一であると信じています。ただし、まれに異なる場合があります。
$(cmd)
の結果で置換されますcmd
。その結果コマンドの長さがで返される引数の最大長を超えるgetconf ARG_MAX
と、結果が切り捨てられ、予測できない結果が生じる可能性があります。
パイプオプションにはこの制限はありません。curl
コマンドからの出力の各行bash
は、パイプから到着すると実行されます。
ただし、ARG_MAXは通常256,000文字の範囲です。Dockerのインストールでは、どちらの方法を使用しても自信があります。:-)
ARG_MAX
する場合、bashは、私のシステム上の131072バイトに個々の引数を制限しgetconf ARG_MAX
たプリント2097152
。しかし、いずれにしても、エラーでも切り捨てでも機能しません。
でcurl -sSL https://get.docker.com/ | sh
:
curl
およびの両方のコマンドは、sh
それぞれのサブシェルで同時に開始されます
からのSTDOUT curl
はSTDINとして渡されますsh
(これがパイプです、、、|
)
で一方sh -c "$(curl -sSL https://get.docker.com/)"
:
コマンド置換$()
が最初に実行されcurl
ます。つまり、サブシェルで最初に実行されます
コマンド置換、$()
はSTDOUTに置き換えられますcurl
sh -c
(非対話型、非ログインシェル)は、STDOUTを実行します curl