Bash
防止殼叉的壽命比它的啟動器長?
如果我有一個像這樣的 Bash 腳本:
function repeat { while :; do echo repeating; sleep 1 done } repeat & echo running once
running once
列印一次,但repeat
’s fork 永遠存在,無休止地列印。在創建它的腳本退出後,我應該如何防止
repeat
繼續執行?我想也許顯式地實例化一個新的
bash -c
解釋器會迫使它退出,因為它的父程序已經消失了,但我猜孤兒程序被init
PID 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
但是你最好不要有另一個具有該名稱的重要程序,否則它也會被刪除。
- 我想知道,當創建它們的腳本(或程序)退出時,是否有更好或可接受的方法來處理分叉 shell 中的後台作業?
- 如果沒有比盲目地
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