dockerの多くのentrypoint.shスクリプトが次のようなことをしていることに気づきました。
#!/bin/bash
set -e
... code ...
exec "$@"
どのようなものset -e
とexec "$@"
するために?
回答:
基本的にentrypoint.sh
、渡されたコマンドライン引数を受け取り、それらをコマンドとして実行します。基本的には、「この.shスクリプトですべてを実行してから、同じシェルでユーザーがコマンドラインで渡したコマンドを実行する」ことを目的としています。
見る:
exec "$@"
、現在実行中のプロセスが、渡された引数に対して生成された新しいプロセスに置き換えられることにも注意してください。ドッカーシグナリングのための重要:stackoverflow.com/a/32261019/99717
set -e
実行中のコマンドがゼロ以外の終了コードで終了した場合にすぐに終了するようにシェルオプションを設定します。スクリプトは、失敗したコマンドの終了コードとともに戻ります。bashのmanページから:
セット-e:
パイプライン(単一の単純なコマンドで構成されている場合があります)、リスト、または複合コマンド(上記のSHELL GRAMMARを参照)がゼロ以外のステータスで終了した場合は、すぐに終了します。失敗したコマンドがwhileまたはuntilキーワードの直後のコマンドリストの一部、ifまたはelifの予約語に続くテストの一部、&&または||で実行されるコマンドの一部である場合、シェルは終了しません。最後の&&または||に続くコマンド、パイプライン内の最後以外のコマンド、またはコマンドの戻り値が!で反転されている場合を除くリスト。-eが無視されている間にコマンドが失敗したために、サブシェル以外の複合コマンドがゼロ以外のステータスを返した場合、シェルは終了しません。ERRのトラップが設定されている場合は、シェルが終了する前に実行されます。
-eが無視されている状況で複合コマンドまたはシェル関数が実行される場合、-eが設定され、コマンドがaを返しても、複合コマンドまたは関数本体内で実行されるコマンドはいずれも-e設定の影響を受けません。障害ステータス。-eが無視されるコンテキストで実行中に複合コマンドまたはシェル関数が-eを設定した場合、その設定は、複合コマンドまたは関数呼び出しを含むコマンドが完了するまで効果がありません。
exec "$@"
通常、エントリポイントをパススルーしてdockerコマンドを実行するために使用されます。現在実行中のシェルを、を"$@"
指しているコマンドに置き換えます。デフォルトでは、その変数はコマンドライン引数を指します。
entrypoint.shを指すエントリポイントを持つイメージがあり、コンテナをとしてdocker run my_image server start
実行entrypoint.sh server start
すると、コンテナでの実行に変換されます。exec行entrypoint.sh
で、pid1として実行されているシェルはそれ自体をコマンドに置き換えますserver start
。
これは、信号処理にとって重要です。を使用しない場合exec
、server start
上記の例のは別のpidとして実行され、終了した後、シェルスクリプトに戻ります。pid 1のシェルでは、SIGTERMはデフォルトで無視されます。つまりdocker stop
、コンテナに送信する正常な停止信号は、server
プロセスによって受信されることはありません。10秒後(デフォルト)、docker stop
正常なシャットダウンをあきらめてSIGKILLを送信すると、アプリは強制的に終了しますが、データが失われたり、ネットワーク接続が閉じられたりすると、アプリ開発者はシグナルを受信した場合にコードを記述できます。また、コンテナが停止するまでに常に10秒かかることも意味します。
shift
およびのようなシェルコマンドを使用するとset --
、の値を変更できることに注意してください"$@"
。たとえば/bin/sh -c "..."
、次の場合にdockerのシェル構文を使用した場合に表示される可能性のあるコマンドからを削除するスクリプトの短い部分を次に示しますCMD
。
# convert `/bin/sh -c "server start"` to `server start`
if [ $# -gt 1 ] && [ x"$1" = x"/bin/sh" ] && [ x"$2" = x"-c" ]; then
shift 2
eval "set -- $1"
fi
....
exec "$@"
test
仕様を参照してください-a
。[ "$#" -gt 1 ] && [ "$1" = /bin/sh ]
は正しい置換です(x"$1"
廃止されていない構文のみを使用する場合は、ハッカーは必要ありません)。
shift 2; set -- $1
方法eval
とはまったく同じではありません。考えてみましょう/bin/sh -c 'printf "%s\n" "hello world" "goodbye world"'
あなたは、具体的なテストケースをしたい、と見た場合、引数に文字列を変換する際のBashが解析引用符ません。
eval
と/bin/sh -c
、文字列での動作を反映したいと思いますが、何かが足りない場合はお知らせください。
exec
確かに、リダイレクトを実行する使用モードがありますが、これはそのモードではありません。
set -e
、手書きのエラー処理よりもはるかにエラーが発生しやすいと考えられているのですか。(急いでいる場合は、以下の演習の上部にある類推をスキップしてください)。