Bash在子shell中殺死
在子shell中殺死sleep
在 bash 中,我觀察到 如果我從子外殼開始,呼叫
kill
睡眠程序*不會殺死它。*你能幫我理解為什麼嗎?function foo () { # Start a loop with `sleep` in the background while true; do >&2 echo looping sleep 5 done & # Wait for user input, then kill the "sleep" loop loop_id=$! read -p 'press enter' DUMMY kill $loop_id } echo $(foo) # Call foo within a subshell echo "DONE"
可能會發生兩種截然不同的事情,具體取決於最後一行是否使用子shell
- 使用 subshell 呼叫
echo $(foo)
,如果我按 enter 來滿足read
呼叫,那麼腳本直到結束後才會終止sleep
。foo
如果我只使用而不是呼叫該函式$(foo)
,那麼腳本會在我按下輸入後立即終止。我真的在這個玩具範例上,但在我的實際工作中,我想將標準輸出從
foo
一個 shell 變數中擷取,所以我想盡快殺死子 shell。有沒有辦法讓我實現目標的兩個部分?
當您使用命令替換
$(foo)
時,shell 需要等待,直到收到命令替換的所有輸入。您正在執行的sleep
文件描述符(可能是管道)的副本連接到 shell 讀取命令替換輸出的位置。(我也很確定它將給出執行循環$!
的 shell 的 PID ,而不是它的內部。)while``sleep
考慮例如這個腳本:
foo() { sleep 5 & echo foo } tmp=$(foo) echo end.
執行它需要 5 秒。
但是將
sleep
行更改為sleep 5 > /dev/null &
,現在腳本立即返回,因為sleep
不再連接到命令替換。請注意,後台睡眠仍將在後台執行,直到超時。你只是不太可能注意到它。請注意,這是特定於命令替換的,而不僅僅是任何子shell 環境。(
(foo)
也將是一個子shell,但應該類似於{ foo; }
, 或只是foo
在這裡。)