在這個腳本 工作,我們有一個腳本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 | :
陷阱沒有工作。
有人知道這是爲什麼嗎?
在這個腳本 工作,我們有一個腳本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 | :
陷阱沒有工作。
有人知道這是爲什麼嗎?
在管道的左手側的命令運行在子shell:
exit | grep
出口SIGTRAP似乎不被傳播到子shell。
trap 'echo T >&2' EXIT ; (exit) # Nothing.
我注意到了子殼問題。但是當我們打電話時。 trap.sh | :,我認爲我們在子shell中調用trap.sh,並且子shell調用trap,當子shell退出時,應該調用陷阱調用,就像我們調用./trap.sh | :。我不明白爲什麼會有不同的結果。 – dspjm
更好(從trap.sh
標準輸出無法:
顯示),以. trap.sh|cat
改變你的測試命令。但即使那樣也沒有輸出,所以你是對的:陷阱沒有奏效。這必須是bash中的一個錯誤,並且應該向維護者報告。
有趣的是,當我們echo $$
從劇本trap.sh裏面,我們看到,它是由執行整個管道. trap.sh|cat
,矛盾手動的聲明同一個shell執行:管道中的每個命令都作爲執行單獨的過程(即在一個子殼中)。這是一個謬論,請參閱評論。也許這與一些優化有關,以最小化子shell創建,但這只是猜測。
'$$'總是評估爲父shell的進程ID,即使子進程在不同的進程中執行。 – chepner
+1,因爲我認爲這可能是一個錯誤。我用'touch trap.fired'取代了echo,以確保這不是標準輸出剛剛在某處丟失的問題。用'。 trap.sh | :',文件沒有被創建。 – chepner
儘管bash手冊指出:_ $擴展爲shell_的進程ID,您顯然是正確的,在這種情況下,'$$'評估爲父shell的進程ID。感謝您的評論,我發現了shell變量* BASHPID *,手冊中提到:_展開到當前bash進程的進程ID。這在某些情況下與$$不同,例如不需要bash重新初始化的子殼。實際上,'echo $ BASHPID'顯示不同的值。 – Armali
我修改了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
命令,但陷阱本身從未註冊,因此不會觸發。
是否有任何腳本運行,使得工作目錄(cwd)不在腳本的位置? – wallyk
@wallyk不,它不在腳本的位置。 – dspjm