2013-07-19 94 views
3

在這個腳本 工作,我們有一個腳本trap.sh爲什麼陷阱沒有在管道

#!/bin/bash 
trap "echo trapped" EXIT 
exit 0 

和test.sh.如果test.sh就像

#!/bin/bash 
. trap.sh 

#!/bin/bash 
./trap.sh | : 

補漏工程

但如果test.sh就像

#!/bin/bash 
. trap.sh | : 

陷阱沒有工作。

有人知道這是爲什麼嗎?

+0

是否有任何腳本運行,使得工作目錄(cwd)不在腳本的位置? – wallyk

+0

@wallyk不,它不在腳本的位置。 – dspjm

回答

0

在管道的左手側的命令運行在子shell:

exit | grep 

出口SIGTRAP似乎不被傳播到子shell。

trap 'echo T >&2' EXIT ; (exit) # Nothing. 
+0

我注意到了子殼問題。但是當我們打電話時。 trap.sh | :,我認爲我們在子shell中調用trap.sh,並且子shell調用trap,當子shell退出時,應該調用陷阱調用,就像我們調用./trap.sh | :。我不明白爲什麼會有不同的結果。 – dspjm

1

更好(從trap.sh標準輸出無法:顯示),以. trap.sh|cat改變你的測試命令。但即使那樣也沒有輸出,所以你是對的:陷阱沒有奏效。這必須是bash中的一個錯誤,並且應該向維護者報告。

有趣的是,當我們echo $$從劇本trap.sh裏面,我們看到,它是由執行整個管道. trap.sh|cat,矛盾手動的聲明同一個shell執行:管道中的每個命令都作爲執行單獨的過程(即在一個子殼中)。這是一個謬論,請參閱評論。也許這與一些優化有關,以最小化子shell創建,但這只是猜測。

+1

'$$'總是評估爲父shell的進程ID,即使子進程在不同的進程中執行。 – chepner

+0

+1,因爲我認爲這可能是一個錯誤。我用'touch trap.fired'取代了echo,以確保這不是標準輸出剛剛在某處丟失的問題。用'。 trap.sh | :',文件沒有被創建。 – chepner

+0

儘管bash手冊指出:_ $擴展爲shell_的進程ID,您顯然是正確的,在這種情況下,'$$'評估爲父shell的進程ID。感謝您的評論,我發現了shell變量* BASHPID *,手冊中提到:_展開到當前bash進程的進程ID。這在某些情況下與$$不同,例如不需要bash重新初始化的子殼。實際上,'echo $ BASHPID'顯示不同的值。 – Armali

1

我修改了trap.sh以包含xtrace選項。

#!/bin/bash 
set -x 
trap 'echo trapped' EXIT 
exit 0 

運行trap.sh作爲腳本生成

〜$ ./trap.sh |貓 +陷阱 '回聲被困' EXIT +退出0 +回聲被困 被困

採購它首先,然而產生

~ $ . trap.sh | cat 
++ trap 'echo trapped' EXIT 
++ exit 0 

這表明trap在更深的子shell被執行(爲什麼,我不知道),並且陷阱本身從未被執行(我在第二個實驗中通過將文件整合到陷阱中而不是僅回顯來證實,以防在繼承標準輸出時出現問題;文件是從未碰過)。

我的猜測是,不知何故EXIT信號被前正在執行的source命令基於來自trap命令的手冊頁說明這句話被忽略,:忽略在 進入

信號到外殼不能被困或重置。

因此,執行trap命令,但陷阱本身從未註冊,因此不會觸發。