バックグラウンドプロセスが終了するまで関数が返されないのはなぜですか?

バックグラウンドプロセスが終了するまで関数が返されないのはなぜですか?

次のスクリプトを考えてみましょう。

#!/bin/bash
function start {
  leafpad &
  echo $!
}
PID=$(start)
echo "PID is $PID"

スクリプトは、リーフパッドプロセスが終了するまで閉じる中括弧を通過し続けます。これはバックグラウンドプロセスであっても同様です。

なぜこれですか?関数でバックグラウンドプロセスを開始できますか?

答え1

関数は返されますが、バックグラウンドジョブを作成しましたが、stdout fdがまだ開いているため、コマンドの置き換えはブロックされます。>/dev/nullオフにする前に追加するだけです&

#!/bin/bash
function start {
  leafpad >/dev/null &
  echo $!
}
PID=$(start)
echo "PID is $PID"

プロセスがstdin、stdout、stderrも閉じるようにするには、次のコマンドを使用します。

leafpad >/dev/null 0>&1 2>&1 &

これにより、stdin(0)、stdout(1)、stderr(2)が閉じ、背景(&)が閉じます。さらに、これらを使用するときはストリームリダイレクト「なりすまし」になったことを忘れないでください。つまり、実行順に複製されるという意味です。

1>/dev/null 2>&1

そして

2>&1 1>/dev/null

いいえ、同じです!前者はストリームを/ dev / null(必要なもの)にコピーし、後者では/ dev / stdoutをstderrにコピーしてstdoutを閉じます。したがって、送信されたすべてのメッセージはstderrコンソールに表示されます。

関連情報