Bash

防止殼叉的壽命比它的啟動器長?

  • October 30, 2018

如果我有一個像這樣的 Bash 腳本:

function repeat {
   while :; do
       echo repeating; sleep 1
   done
}
repeat &
echo running once

running once列印一次,但repeat’s fork 永遠存在,無休止地列印。

在創建它的腳本退出後,我應該如何防止repeat繼續執行?

我想也許顯式地實例化一個新的bash -c解釋器會迫使它退出,因為它的父程序已經消失了,但我猜孤兒程序被initPID 1 採用。

使用另一個文件對此進行測試:

# repeat.bash
while :; do echo repeating; sleep 1; done

# fork.bash
bash -c "./repeat.bash & echo an exiting command"

執行./fork.bash仍然會導致repeat.bash永遠在後台繼續執行。

簡單而懶惰的解決方案是將行添加到fork.bash

pkill repeat.bash

但是你最好不要有另一個具有該名稱的重要程序,否則它也會被刪除。

  1. 我想知道,當創建它們的腳本(或程序)退出時,是否有更好或可接受的方法來處理分叉 shell 中的後台作業?
  2. 如果沒有比盲目地pkilling使用相同名稱的所有程序更好的方法,那麼應該如何處理與網路伺服器之類的東西一起執行的重複作業以退出?我想避免cron工作,因為腳本位於git儲存庫中,並且程式碼應該是自包含的,而無需更改/etc/.

這會在腳本退出之前殺死後台程序:

trap '[ "$pid" ] && kill "$pid"' EXIT

function repeat {
   while :; do
       echo repeating; sleep 1
   done
}
repeat &
pid=$!
echo running once

這個怎麼運作

  • trap '[ "$pid" ] && kill "$pid"' EXIT

這就形成了一個陷阱。每當腳本即將退出時,將執行單引號中的命令。該命令檢查是否pid已為 shell 變數分配了非空值。如果有,則與之關聯的程序將pid被終止。

  • pid=$!

這將前面後台命令 ( repeat &) 的程序 ID 保存在 shell 變數pid中。

改進

正如帕特里克在評論中指出的那樣,腳本有可能在後台程序啟動設置pid變數之前被終止。我們可以使用以下程式碼處理這種情況:

my_exit() {
   [ "$racing" ] && pid=$!
   [ "$pid" ] && kill "$pid"
}
trap my_exit EXIT

function repeat {
   while :; do
       echo repeating; sleep 1
   done
}

racing=Y
repeat &
pid=$!
racing=

echo running once

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