Bash

在子shell中殺死sleep

  • September 21, 2021

在 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

  • 使用 subshel​​l 呼叫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在這裡。)

引用自:https://unix.stackexchange.com/questions/670041