次のスクリプトを検討してください。
#!/bin/bash
function start {
leafpad &
echo $!
}
PID=$(start)
echo "PID is $PID"
このスクリプトは、バックグラウンドプロセスであっても、リーフパッドプロセスが終了するまで閉じかっこを通過し続けません。
どうしてこれなの?関数からバックグラウンドプロセスを起動することはできますか?
次のスクリプトを検討してください。
#!/bin/bash
function start {
leafpad &
echo $!
}
PID=$(start)
echo "PID is $PID"
このスクリプトは、バックグラウンドプロセスであっても、リーフパッドプロセスが終了するまで閉じかっこを通過し続けません。
どうしてこれなの?関数からバックグラウンドプロセスを起動することはできますか?
回答:
この関数は戻りますが、バックグラウンドジョブを作成したが、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
コンソールに表示されます。
n>&-
ここn
で、ファイル記述子です。
/dev/null
、プロセスがstdoutを書き込もうとしても、それが1
無効なFDである場合、/へのリダイレクトはI / Oエラーにつながりません。したがって、投稿の用語は間違っており、実際のbashプログラミングではありません。(実際には、FD 1を0に複製すると、stdinがで開かれたファイル記述子にO_RDONLY
なり、プロセスが読み取りを試みたときに(望ましいバイト数ではなく)エラーが発生する可能性があります。例wc >/dev/null 0>&1
->wc: standard input: Bad file descriptor
exec <&- >&- <>/dev/null >&0
stdin / outをかなり徹底的に処理します。zsh
少なくとも違いは、multiosが設定されているときに、同じ記述子ですべてのオープンを自動的に連結することで異なります。