回答:
実用的な違いがあります。
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