2016-08-12 36 views
1

我對將信號轉發到具有陷阱的子進程感到困惑。說我有兩個腳本:bash trap''vs陷阱函數傳遞信號

a.sh

#!/bin/bash 

# print the process id 
echo $$ 

cleanup() { 
    rv=$? 
    echo "cleaning up $rv" 
    exit 
} 

sleep 5 
trap '' SIGTERM # trap cleanup SIGTERM 
echo 'cant stop wont stop' 
./b.sh 
echo 'can stop will stop' 
trap - SIGTERM 
sleep 4 
echo 'done' 

b.sh

#!/bin/bash 
sleep 4; 
echo 'b done' 

如果我執行a.sh,然後從另一個窗口殺死kill -- -PGID進程組中,SIGTERM被忽略並沒有傳遞給b.sh。但是如果我做trap cleanup SIGTERM,SIGTERM通過並終止b.sh。爲什麼我的陷阱在一種情況下傳遞信號而不是另一種?

回答

1

這很有趣。引用man 7 signal

通過fork(2)創建的子級繼承其父級信號處置副本。在execve(2)期間,被處理信號的處置被重置爲默認值;被忽略的信號的配置保持不變。

對於您的情況,由於處於同一個進程組,因此孩子總是收到TERM。問題是,它是如何處理的。

當父母忽略TERM,按照上面的規則,孩子也是如此,所以孩子生存下來。當父母捕獲TERM時,孩子的處理程序將被重置,並且它將作爲默認操作而死亡。

1

trap man page

陷阱[動作條件...]

如果動作是空( 「」),如果它出現的殼應忽略每個指定的條件。當你執行TRAP '' SIGTERM

因此,SIGTERM條件被忽略。嘗試使用空格值,看看它是否有效:

sleep 5 
trap ' ' SIGTERM # Note the space (' ')!! 

echo 'cant stop wont stop' 
./b.sh 

echo 'can stop will stop' 
trap - SIGTERM 

sleep 4 
echo 'done'