我编写的脚本将从服务器获取数据库名称列表,以便用户知道他们可以在下一个提示中输入哪些数据库:
echo "FETCHING DB NAMES... (^C to skip)"
ssh "$user@$SERV_A" "$remote_cmd" #returns space-delim db list
echo
printf "Which db do you want to import? >"
read db_name
#rest of script
用户看起来像这样:
FETCHING DB NAMES... (^C to skip)
db1 db2 personnel
Which db would you like to import? >
问题是获取这些数据库的时间可能需要1-10秒,具体取决于连接。如果用户已经知道数据库名称,这可能会令人沮丧。
当然,按下^C
作为提示符表示会终止整个脚本,而不仅仅是ssh进程。有没有办法可以编写脚本以便他们可以取消/跳过那个ssh进程?
提前谢谢。
编辑:它本身并不一定是^C
,实际上只是想让用户跳过正在运行的子进程。
答案 0 :(得分:2)
以下是使用trap
SIGQUIT
的可能方式(Ctrl + \
)
(对于此示例,我将您的ssh
命令替换为简单的sleep 5 ; echo "names"
来模拟ssh
的输出
#!/bin/bash
bashpid="$$"
trap "kill -9 "$bashpid"" SIGINT
echo "FETCHING DB NAMES... (^\ to skip)" # Fetching text
getdbnames () {
sleep 5 ; echo "names" # ssh command
}
dbnames="$({ getdbnames &
trap "kill -9 "$!"" SIGQUIT
wait
})" # uses trap and wait to handle Ctrl+\
trap "" SIGQUIT # Avoid accidental double Ctrl+\
if [[ -n "$dbnames" ]]; then # Only ask import if dbnames variable
printf "Which db do you want to import? >" # isn't empty, otherwise
read db_name # skip this whole
fi # section
echo "Rest of script"
还有很多其他方法,包括为输入循环读取语句,以及使用SIGCHLD和/或其他可能需要或不需要某些shell选项的内部组件。为了跳过一项任务,这可能是可靠的。
这也陷阱 ctrl + c 以确保它杀死整个脚本(有时脚本会产生你所追求的不需要的效果,有时玩SUBhell方法和陷阱可能导致它),所以这只是为了确保:
运行上面的脚本并按 Ctrl + C:
FETCHING DB NAMES... (^\ to skip) ^CKilled: 9
运行上面的脚本并按 Ctrl + \:
FETCHING DB NAMES... (^\ to skip) ^\Rest of script
运行上面的脚本并让它运行(成功的ssh
结果)
FETCHING DB NAMES... (^\ to skip) names Which db do you want to import? >
显然会有更多的精炼来调整它到你的确切环境,但样板就在那里。
答案 1 :(得分:2)
shell trap命令可用于暂时忽略^ C.
trap "" signalname
将忽略信号,trap - signalname
会将信号行为恢复为默认值。
在这里,我们忽略shell中的SIGINT,然后创建一个子shell,在其中SIGINT恢复其正常行为并运行ssh
。
在子shell中,ssh将响应^ C,但是父shell仍然忽略SIGINT,如果用户在ssh运行时键入^ C,则不会受到影响。
echo "FETCHING DB NAMES... (^C to skip)"
trap "" SIGINT # ignore ^C
# restore default ^C behavior in subshell,
# then run ssh to output space-delim db list
(trap - SIGINT; ssh "$user@$SERV_A" "$remote_cmd")
trap - SIGINT # restore default ^C behavior
echo
printf "Which db do you want to import? >"
read db_name
#rest of script