Bash
當“選擇”循環執行時,Bash 忽略 SIGINT 陷阱
當我將“陷阱”與選擇循環結合使用時,即當我嘗試在顯示選項時按 CTRL+C 來突破時,它只會在終端中列印 ^C。如果我從腳本中刪除“陷阱”,它通常會退出,也就是說它會接受 CTRL+C。
我已經在兩種不同版本的 bash 上對此進行了測試(一種隨 CentOS 提供,另一種隨 Fedora 提供),我對 Fedora(4.4.23(1)-release)中的一個有問題。CentOS 附帶的 Bash 版本 4.2.46(2)-release 似乎工作正常。我還在本地終端和遠端(通過 ssh)上對此進行了測試。問題總是在 Fedora 方面。
我將發布程式碼以查看我在說什麼
這個不行:
#!/bin/bash trap exit SIGINT select opt in One Two Three; do break done
如果我要刪除整個 ’trap exit SIGINT’ 行,它將正常工作並接受 CTRL+C 沒有問題。
任何想法如何解決或繞過這個?
任何想法如何解決或繞過這個?
您可以通過打開posix模式來繞過它,或者使用
--posix
選項,或者暫時使用set -o posix
:set -o posix select opt in foo bar baz; do echo "opt=$opt" done set +o posix
有關此行為的解釋,您可以查看內置
zread()
函式使用的函式read
(也由 bash in 內部呼叫select
):while ((r = read (fd, buf, len)) < 0 && errno == EINTR) /* XXX - bash-5.0 */ /* We check executing_builtin and run traps here for backwards compatibility */ if (executing_builtin) check_signals_and_traps (); /* XXX - should it be check_signals()? */ else check_signals ();
由於某些特殊原因,
executing_builtin
僅在read
顯式呼叫內置函式時設置,而不是在由 呼叫時設置select
。這看起來很像一個錯誤,而不是故意的。在posix模式下執行時,信號將取消
read
內置。在這種情況下,zreadintr()
被呼叫,與 不同的是,在執行陷阱後zread()
不會重新呼叫中斷的系統呼叫。read(2)
見builtins/read.def
:if (unbuffered_read == 2) retval = posixly_correct ? zreadintr (fd, &c, 1) : zreadn (fd, &c, nchars - nr); else if (unbuffered_read) retval = posixly_correct ? zreadintr (fd, &c, 1) : zread (fd, &c, 1); else retval = posixly_correct ? zreadcintr (fd, &c) : zreadc (fd, &c);
read
有關 bash內置的“重新啟動”的更多詳細資訊,請點擊此處。