抱歉,我無法弄清楚以下內容有什么問題。當我在腳本中按 ctrl-c 時,陷阱起作用,但在執行腳本源代碼時不起作用。
示例(test2.sh):
#!/bin/bash
ctrl_c()
{
echo "user canceled."
}
trap ctrl_c INT
sleep 500
trap - INT
發生以下情況:
[root@localhost ~]# ./test2
^Cuser canceled.
[root@localhost ~]# . test2
^C
這是 RHEL 7、Bash 4.2,但同樣的問題也發生在其他 Linux 發行版和 Bash 4.4 中。
請幫忙。謝謝!
uj5u.com熱心網友回復:
我似乎記得互動式 shell(這是你做陷阱的地方,因為你是在獲取它而不是異步運行它)對SIGINT. 他們自己捕獲它,以便可以中斷程序控制呼叫。
我懷疑這妨礙了你正在嘗試做的事情。
更新:只是有一個看看bash手冊頁,該SIGNALS段有一點點模糊的,但它確實似乎證實了我的記憶重新在互動shell特殊處理。
信號
當
bash是互動式時,在沒有任何陷阱的情況下,它會忽略SIGTERM(這樣kill 0不會殺死互動式 shell),并被SIGINT捕獲和處理(這樣wait內置函式是可中斷的)。在所有情況下,bash忽略SIGQUIT.
uj5u.com熱心網友回復:
所以這就是我如何解決我的問題。也許這不是最好或最優雅的方式,但它似乎作業得很好。
訣竅是在后臺任務(子行程)中運行該程序,然后等待該行程完成。當后臺行程 ($!) 正在運行時,trap INT 將作業并進行清理。因為我需要獲取一些命令,所以我將它們寫入一個檔案,然后在主腳本中 source 執行這些檔案。然而,這些檔案在 Ctrl-C 時被清除,因此腳本結束。
例如:
# scan.sh
scan.sh, not sourced. Aborting...
# source scan.sh
[|] Working...^C
scan.sh: waiting for process 22390 to terminate...
scan.sh: user canceled.
[1] Interrupt doit $f_menu $f_alias
我沒有找到消除“中斷”訊息的可行解決方案,但這并不是真正的問題。
#!/bin/bash
....
# Preliminary options and environment.
save_monitor=$(set o | grep -w monitor)
set o monitor # Turn off monitor mode.
save_history=$(set o | grep -w history)
set o history # Turn off command line history.
save_extglob=$(shopt -p extglob)
shopt -s extglob
f_menu=/tmp/1_$$
f_alias=/tmp/2_$$
iam=scan.sh
cleanup()
{ # Requires $1 (f_menu) $2 (f_alias) args.
# Restore shell the previous shell environment.
unset i f_pid f_menu f_alias aver iam list aname line sourced
unset spinner doit cleanup ctrl_c
trap - INT
\rm -f $1 $2 # Don't use rm alias.
eval "$save_extglob"
eval "$save_monitor"
eval "$save_history"
unset save_extglob save_history save_monitor
}
# Exit if the script was not sourced.
$(return >/dev/null 2>&1) && sourced=1 || unset sourced
[[ "$sourced" ]] || { echo; echo "$iam, not sourced. Aborting..."; exit 1; }
ctrl_c()
{ # Requried: f_pid f_quit
# Optional: f_menu $f_alias
kill -TERM $f_pid
while (( f_pid )); do
echo; echo "$iam: waiting for process $f_pid to terminate..."
sleep 2
[[ $(kill -0 $f_pid 2>&-) ]] || f_pid=
done
echo "$iam: user canceled."
cleanup $f_menu $f_alias
}
trap ctrl_c INT
spinner()
{
# Optional: $1
local disp
disp='|/-\'
while kill -0 $! 2>&-; do
printf " [%c] %s..." "$disp" "$1"
disp=${disp#?}${disp%%???}
sleep .1
printf "\r"
done
}
doit()
{
# Requires $1 (f_menu) $2 (f_alias) args.
.....
}
echo
doit $f_menu $f_alias &
f_pid=$!; spinner "Working"; wait $f_pid
# Following will no longer work after user hit control-c.
source $f_alias 2>&-
cleanup $f_menu $f_alias 2>&-
# end
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/323962.html
標籤:猛击
