bash:子プロセスが失敗した場合は、親プロセスのPIDを取得しないでください。

bash:子プロセスが失敗した場合は、親プロセスのPIDを取得しないでください。

(ソース - bash:バックグラウンドでのコマンド実行とpidキャプチャ)

$!これは、子プロセスの起動に失敗した場合(たとえば、「コマンドが見つかりません」など)が呼び出しプロセスのpidに設定を残す可能性があるbashの予期しない動作に対処するため、他の質問の[重複]ではありません。子プロセスpidまたは""(null)が失敗するよりも。 ——文書の回収

bash 4.1スクリプトを書いています...

  • バックグラウンドで別のスクリプト(または内部機能)を実行したいのですが...
  • そしてフォアグラウンドスクリプトの変数からバックグラウンドジョブのpidをキャプチャします。
  • ジョブが開始されていない場合、変数は空でなければなりません(例: "")。

バックグラウンドジョブが常に開始されると、両方の方法が機能します。

cmd &
VAR=$!

or...

( cmd & ); VAR=$!

実行すると、cmd最後のコマンドで始まったpid($!)が私たちが望むものになり、$ VARが正しいです。

ただしcmd、開始されていない場合、$ VARは最後のコマンドのpidになります。それの前に開始されるのは、前景スクリプト自体のpidです。後で特定の条件でプロセスを終了するにはpidが必要になるため、cmd無効なpidを取得すると機能しない可能性があります。

本当に必要なのは、バックグラウンドジョブが実行されている場合にのみVARを変更することです。文法エラーのようです。

VAR=
( cmd & );  && VAR=$!

実装されたソリューション

このコメントとJoseph Rの答えは非常に役立ちます。同様の問題を経験している人のために...

次のbash関数はバックstandbyグラウンドでGtkDialogスクリプトを実行します。子プロセスで独自に実行される関数の内部では、standby失敗時にスクリプトのPIDの代わりに呼び出しスクリプトのPIDを取得するのを防ぐために必要な分離を提供しているようですstandby

function standbyBg () {
  ifHelpShow "$1" 'standbyBg
    Run standby (busy "throbber") in background and echo its pid.
    Example:
        standbyPID=$(standbyBg)
    Revised:
        20131123 docsalvager'  && return
  #
  standby  >/dev/null 2>&1  &
  echo $!
}

答え1

少しハッキングされたソリューション:

jobs &>/dev/null
cmd &
new_job_started="$(jobs -n)"
if [ -n "$new_job_started" ];then
    VAR=$!
else
    VAR=
fi

私の注目を集めた彼のコメントについて@terdonに感謝しますhelp jobs

関連情報