execは常にシェルスクリプトの最後の行でなければなりませんか?

execは常にシェルスクリプトの最後の行でなければなりませんか?

以下を実行するシェルスクリプトがあります。

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)&
      その後、非同期サブシェルで実行されます(完了したら)。しかし、私たちが言うならcommand1command2command2command1
      実装する コマンド1;コマンド2)&
      これは実行されますが、実行されません。command1command2
  • リダイレクトだけでなく、スクリプトで正しく設定されたコマンド 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」コマンドの両方が同じ場所に出力を書き込むと、混在する可能性があります。

    ただし、親プロセスがスクリプトが終了するのを待たないと、これは問題にならない可能性があります。

おすすめ記事