30 秒无用户输入后终止脚本?
Terminate script after 30 seconds of no user input?
我正在尝试创建一个简单的 Bash 脚本,该脚本在等待用户输入 10 秒后终止。如果用户输入某些内容,计时器将重置,10 秒规则再次适用。我正在使用 trap 来确保我的程序可以退出的唯一两种方式是:
- 我输入“停止”
- 用户未输入 10 秒
我尝试使用类似的东西:
{
sleep 10s
kill $$
} &
但是按下Ctrl-C后,10秒后程序并没有停止。它会无限期地继续下去。
您可以使用 read
的超时选项。但请注意,当用户按下某个键时,这不会重置,只有当他们按回车键完成输入时才会重置。
read -t 10 userinput || exit 1
如果您使用 set -e
,则可以省略 || exit 1
。
read
可能因为其他原因而失败,所以你可以专门测试超时。超时错误代码大于 128。
read -t 10 userinput || { (($?>128)) && exit 1; }
或
if ! read -t 10 userinput && (($? > 128)); then
echo 'you timed out' >&2
exit 1
fi
如果 read
失败,您可能仍想退出。但是测试超时错误代码允许您打印相关的错误消息。
read有超时参数,可以使用:
read -t 30 answer
POSIX TTY 线路规程提供了这样一个功能:一个可配置的计时器,只要输入到达就会重置,并在超时时终止 read()
操作。当 TTY 处于原始模式时(例如来自串行线路),此计时器通常用于生成更大的读取。
这个 proof-of-concept 解决方案中有一些棘手的事情。它处理 Ctrl-Z 暂停在读取期间工作的要求,并重置计时器:
#!/bin/sh
# save the TTY settings, to restore later
# this should ideally be done in an exit/interrupt trap.
saved_tty=$(stty -g)
# initialize some variables
resumed= # flag indicating Ctrl-Z resume
biginput= # total input collected
littleinput= # input from one read operation
# function to set a special TTY mode, and set the resumed flag
set_tty_mode()
{
# turn of canonical mode; set up 10 second timer (100 x 0.1s)
# min 0 means read a minimum of 0 bytes, allowing timer to work
stty -icanon min 0 time 100
# setting this flag plays a role when this function is called
# as the SIGCONT interrupt handler.
resumed=y
}
# switch to above TTY mode
set_tty_mode
# when the SIGCONT signal goes off, indicating we resumed from Ctrl-Z
# suspend, call set_tty_mode. This is because when we are suspended,
# the shell, e.g. Bash, messes with the TTY settings.
trap set_tty_mode CONT
# no we loop, reading into the littleinput variable.
while true ; do
resumed= # clear the flag
read littleinput # read input
biginput="$biginput$littleinput" # accumulate
[ $resumed ] || break # terminate loop, unless SIGCONT happened
done
printf "read: [%s]\n" "$biginput"
stty $saved_tty
我正在尝试创建一个简单的 Bash 脚本,该脚本在等待用户输入 10 秒后终止。如果用户输入某些内容,计时器将重置,10 秒规则再次适用。我正在使用 trap 来确保我的程序可以退出的唯一两种方式是:
- 我输入“停止”
- 用户未输入 10 秒
我尝试使用类似的东西:
{
sleep 10s
kill $$
} &
但是按下Ctrl-C后,10秒后程序并没有停止。它会无限期地继续下去。
您可以使用 read
的超时选项。但请注意,当用户按下某个键时,这不会重置,只有当他们按回车键完成输入时才会重置。
read -t 10 userinput || exit 1
如果您使用 set -e
,则可以省略 || exit 1
。
read
可能因为其他原因而失败,所以你可以专门测试超时。超时错误代码大于 128。
read -t 10 userinput || { (($?>128)) && exit 1; }
或
if ! read -t 10 userinput && (($? > 128)); then
echo 'you timed out' >&2
exit 1
fi
如果 read
失败,您可能仍想退出。但是测试超时错误代码允许您打印相关的错误消息。
read有超时参数,可以使用:
read -t 30 answer
POSIX TTY 线路规程提供了这样一个功能:一个可配置的计时器,只要输入到达就会重置,并在超时时终止 read()
操作。当 TTY 处于原始模式时(例如来自串行线路),此计时器通常用于生成更大的读取。
这个 proof-of-concept 解决方案中有一些棘手的事情。它处理 Ctrl-Z 暂停在读取期间工作的要求,并重置计时器:
#!/bin/sh
# save the TTY settings, to restore later
# this should ideally be done in an exit/interrupt trap.
saved_tty=$(stty -g)
# initialize some variables
resumed= # flag indicating Ctrl-Z resume
biginput= # total input collected
littleinput= # input from one read operation
# function to set a special TTY mode, and set the resumed flag
set_tty_mode()
{
# turn of canonical mode; set up 10 second timer (100 x 0.1s)
# min 0 means read a minimum of 0 bytes, allowing timer to work
stty -icanon min 0 time 100
# setting this flag plays a role when this function is called
# as the SIGCONT interrupt handler.
resumed=y
}
# switch to above TTY mode
set_tty_mode
# when the SIGCONT signal goes off, indicating we resumed from Ctrl-Z
# suspend, call set_tty_mode. This is because when we are suspended,
# the shell, e.g. Bash, messes with the TTY settings.
trap set_tty_mode CONT
# no we loop, reading into the littleinput variable.
while true ; do
resumed= # clear the flag
read littleinput # read input
biginput="$biginput$littleinput" # accumulate
[ $resumed ] || break # terminate loop, unless SIGCONT happened
done
printf "read: [%s]\n" "$biginput"
stty $saved_tty