以下を実行するシェルスクリプトがあります。
export FOO=foo # step 1
/usr/bin/java my-server # step 2
シェルスクリプトは、ステップ2で開始されたプロセスのPIDを知る必要がある親プログラムによって開始されます。現在、これはexec
サーバーで実行コマンドを実行してシェルを手順2のコマンドに置き換えることによって行われます。したがって、シェルスクリプトのPIDとスクリプトを実行するプロセスは、「my-server」プロセスのPIDになります。
手順2で起動したサーバーをすばやく確認するには、このシェルスクリプトに別のコマンドを追加する必要があります。今私のプログラムは次のようになります。
export FOO=foo # step 1
exec /usr/bin/java my-server & # step 2
/usr/bin/java my-validation # step 3
上記の手順3を追加できますか?このアプローチの代替案は何ですか?
答え1
他の回答とコメントを組み合わせて、以下を追加します。
exec your_command &
無意味。コマンドラインは非同期サブシェルで実行され、デフォルトでexec
は無視されます。- それはわずかな単純化する。私たちが言うなら
(コマンド1;コマンド2)&
その後、非同期サブシェルで実行されます(完了したら)。しかし、私たちが言うならcommand1
command2
command2
command1
(実装する コマンド1;コマンド2)&
これは実行されますが、実行されません。command1
command2
- それはわずかな単純化する。私たちが言うなら
- リダイレクトだけでなく、スクリプトで正しく設定されたコマンド
exec
に従うすべてのエントリは無視されます。exec
失敗しても、後続の行を実行せずにシェルが終了します(command exec ...
またはオプションbash
を使用して、失敗した場合にシェルが終了するのをexecfail
防ぐことができます)。exec
- inまたはまたはなど
exec
のサブシェルで実行されている場合、そのサブシェルのみが終了します。exec cmd &
exec cmd | cmd2
(exec cmd3)
- 確認コマンドでサーバープロセスのPIDを知る必要がある場合は、幸運ではないかもしれません。
そうでなく、サーバーが起動するまでverifyコマンドが自動的にしばらく待つ場合は、次のようにします。
export FOO=foo # step 1 /usr/bin/java my-validation & # step 1½ exec /usr/bin/java my-server # step 2
それ以外の場合はこれを行うことができます
export FOO=foo # step 1 (sleep 10; /usr/bin/java my-validation) & # step 1½ exec /usr/bin/java my-server # step 2
警告:「my-server」プロセスがすぐに終了すると、「my-validation」コマンドが実行される前にスクリプトが終了する可能性が高く、親プロセスは制御を取り戻して実行を再開します。親プロセスと「my-validation」コマンドの両方が同じ場所に出力を書き込むと、混在する可能性があります。
ただし、親プロセスがスクリプトが終了するのを待たないと、これは問題にならない可能性があります。
答え2
exec program
スクリプトのプロセスをnewに置き換えるので、program
意味がある場合にのみ使用してください。つまり、現在のスクリプトが消え、後続のコマンドを実行できません(exec program
失敗しない限り)。
exec program
シェルスクリプトの最後の行は、program
長い間実行されたときに役に立ち、役に立たないシェルプロセスが終了するまでプロセスツリーに残ることを望まないからですprogram
。または他の処理ツールを使用して、pstree
次の違いを確認してください。
#!/bin/sh
echo $$
sleep 9999
そして
#!/bin/sh
echo $$
exec sleep 9999
exec program
後で他のシェルコマンドを実行したい場合はまったくexec
役に立ちません。届かない(exec
失敗しない限り)。
実際に起動後に何かを確認するのは非常に面倒です。/usr/bin/java my-server
始めるのに時間がかかるからです。 (Javaはこれに関して非常に遅くなる可能性があります。Javaプロセスが使用可能になるか、自己終了するのに45秒以上かかることを覚えています...)システム使用量によって異なります。度またはスケジュールによっては、検証プロセスがmy-server
前後に実行されることがあります。クルーガーとして、次の方法で検証ステップを遅らせることができます。
export FOO=foo
/usr/bin/java my-server &
sleep 10
exec /usr/bin/java my-validation
セルフスタートには10秒かかりますがmy-server
、これはシステムの使用量とmy-server
起動にかかる時間によっては十分である可能性があります。今回も、Javaプロセスを開始するのに45秒以上かかり、使用量の多いシステムでは長くかかることがわかりました。立ち上がって実行されるのを待つのに十分スマートであれば、これはsleep
必要ないかもしれません。my-validation
my-server
ただサーバーを起動する方が合理的かもしれません。
#!/bin/sh
export FOO=foo
exec /usr/bin/java my-server
サービスが実行されていることを確認してください。モニタリングフレームワークを通じて、他の場所。
別のアプローチは、systemd
シェルスクリプトよりも優れたプロセス制御を提供する他の最新のinitフレームワークと統合することです。たとえば、プロセスがsystemd
正しく開始されたかどうかに関する情報を返したり、systemd
さまざまな条件でサービスを自動的に再起動したりできます。