2013-06-28 47 views
4

我有一個腳本,在後臺啓動另一個腳本,然後終止它。我期待孩子的腳本消失,但最終它仍然設法打印一些輸出。這裏是例子:如何用&(在bash中)製作過程並殺死它們?

腳本one.sh:

echo "this is one" 
./two.sh & 
sleep 1 
pid=$! 
kill $pid 
echo "this was one" 

腳本two.sh:

echo "this is two" 
./three.sh 
echo "this was two" 

腳本three.sh:

echo "this is three" 
sleep 5 
echo "this was three" 

我跑./one.sh它應該在後臺運行two.sh,然後運行three.sh,但不在後臺運行!輸出得到的是:

this is one 
this is two 
this is three 
this was one 
this was three 

不應該「這是三」未出現在輸出中,因爲three.sh沒有在後臺運行,並two.sh被one.sh終止?你能不能指出我的任何文檔,這些文檔描述了進程在不在後臺時的行爲以及在終止時會發生什麼?

非常感謝您的幫助!

回答

1

當你從bash腳本開始一個新的進程時,這基本上是通過fork()完成的。

新進程,稱爲子進程,與調用進程完全相同,稱爲父進程(除了可在man fork中找到的許多點)。

如果父母死亡,孩子成爲初始化進程的孩子。 然後,init進程在退出後收集孩子的返回代碼(收穫)的角色。所以當你殺死「兩個」時,「三個」不會被殺死,而只會得到一個不同的父母。這是後三名的原因。

的問題是從C點視圖這裏討論:How to make child process die after parent exits?

+0

init進程不會殺死孩子;它僅收集屍體(殭屍)的統計數據,以便殭屍不會無限制地積累。 –

+0

謝謝,我編輯了答案 – kamjagin

0

這似乎令人驚訝的原因是,人們所期望的TERM信號(從「殺」的默認值)傳播到換句話說,由two.sh接收的SIGTERM信號(信號#15)也會傳播到three.sh。然而,事實並非如此。 kill two.sh簡單地將three.sh留給init進程(處理ID 1)作爲它的新父進程,init在退出時會在three.sh之後清理。

隨着進程組的情況變得更加複雜,bash文檔討論瞭如何將鍵盤生成的信號發送到前臺進程組內的所有進程,通常是在沒有「&」的情況下運行管道。但是,這些問題不適用於示例腳本。

注意:在Unix中,不應在可執行腳本上使用「.sh」擴展名。請重點關注在第一行上放置正確的「#!/ bin/bash」或「#!/ bin/sh」。命令不應該在命令名中公開它們的實現語言,以免在實現語言改變時稍後留下錯誤的語言,但其他代碼已經依賴於原始的,現在不正確的擴展。

相關問題