Shell

在擷取 SIGINT 和類似情況時保留退出程式碼?

  • August 9, 2019

如果我使用http://linuxcommand.org/wss0160.php#traptrap上的描述來擷取 ctrl-c (或類似的)並在退出之前進行清理,那麼我將更改返回的退出程式碼。

現在這可能不會在現實世界中產生影響(例如,因為退出程式碼不可移植,而且在程序終止時預設退出程式碼中討論的並不總是明確的?)但我仍然想知道是否存在真的沒有辦法阻止這種情況並返回中斷腳本的預設錯誤程式碼嗎?

範例(在 bash 中,但我的問題不應被視為特定於 bash):

#!/bin/bash
trap 'echo EXIT;' EXIT
read -p 'If you ctrl-c me now my return code will be the default for SIGTERM. ' _
trap 'echo SIGINT; exit 1;' INT
read -p 'If you ctrl-c me now my return code will be 1. ' _

輸出:

$ ./test.sh # doing ctrl-c for 1st read
If you ctrl-c me now my return code will be the default for SIGTERM.
$ echo $?
130
$ ./test.sh # doing ctrl-c for 2nd read
If you ctrl-c me now my return code will be the default for SIGTERM.
If you ctrl-c me now my return code will be 1. SIGINT 
EXIT
$ echo $?
1

(編輯刪除以使其更符合 POSIX。)

(再次編輯以使其成為 bash 腳本,但我的問題不是特定於 shell 的。)

編輯為使用攜帶式“INT”進行陷阱,而不是使用非攜帶式“SIGINT”。

編輯刪除無用的花括號並添加潛在的解決方案。

更新:

我現在通過簡單地退出一些硬編碼的錯誤程式碼並擷取 EXIT 來解決它。這在某些系統上可能會出現問題,因為錯誤程式碼可能不同,或者 EXIT 陷阱不可能,但在我的情況下它已經足夠了。

trap cleanup EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM

實際上,中斷 bash 的內部read似乎與中斷 bash 執行的命令有點不同。通常,當您輸入trap,時$?,您可以保留它並以相同的值退出:

trap 'rc=$?; echo $rc SIGINT; exit $rc' INT
trap 'rc=$?; echo $rc EXIT; exit $rc' EXIT

如果您的腳本在執行類似命令sleep 甚至類似內置命令時被中斷wait,您將看到

130 SIGINT
130 EXIT

退出程式碼是 130。但是,對於read -p,它似乎$?是 0(無論如何在我的 bash 4.3.42 版本上)。


根據我發布的更改文件…(/usr/share/doc/bash/CHANGES),期間的信號處理read可能正在進行中

此版本 bash-4.3-alpha 與先前版本 bash-4.2-release 之間的更改。

  1. Bash 中的新功能

河。在 Posix 模式下,“讀取”可以被擷取信號中斷。執行陷阱處理程序後,read 返回 128+信號並丟棄任何部分讀取的輸入。

$?進入陷阱處理程序後,任何常用的信號退出程式碼都將可用:

sig_handler() {
   exit_status=$?  # Eg 130 for SIGINT, 128 + (2 == SIGINT)
   echo "Doing signal-specific up"
   exit "$exit_status"
}
trap sig_handler INT HUP TERM QUIT

如果有單獨的 EXIT 陷阱,您可以使用相同的方法:立即保持從信號處理程序(如果有)傳遞的退出狀態清理,然後返回保存的退出狀態。

引用自:https://unix.stackexchange.com/questions/235582