Bash Unix:如何在不使用sleep命令的情况下暂停进程

时间:2015-09-06 16:00:05

标签: bash unix sleep

您好我试图暂停执行一个进程,以便用户在5秒后才能进行多次输入。我尝试使用sleep但是sleep只是停止然后执行用户在进程处于睡眠状态时运行的所有输入,我不希望在程序休眠时读取任何输入。

我想要的例子:聊天机器人 输入1:嗨 输出:"程序回复" 输入2(在5秒之前):"什么是新的" - 没有输出 - 输入3(已经过了5秒):"你好吗" 输出:我很好。

sleep命令的作用示例: 输入1." hi" 输出"嘿" 输入2(在5秒之前):"什么是新的" - 没有输出 - 等待 输入3:"你好吗" 输出:"并不多是新的" 输出:"我很好"

3 个答案:

答案 0 :(得分:1)

您可以在5秒钟后读取并丢弃用户的输入

# 1. 
read -p "prompt 1: " first_thing

sleep 4

# this reads and ignores whatever the user has typed during the sleep
while read -t 1 _garbage; do :; done

# 2.
read -p "prompt 2: " next_thing
如果没有任何内容可读,

read s -t 1选项超时为一秒。

测试

  1. 带输入

    $ read -p "prompt 1: " first_thing; sleep 4; while read -t 1 _garbage; do :;done ; read -p "prompt 2: " next_thing
    prompt 1: foo
    bar
    baz
    prompt 2: qux
    $ echo $first_thing $next_thing 
    foo qux
    
  2. no" extra"在第二次读取之前输入 - 进程没有"挂起"等待输入

    $ read -p "prompt 1: " first_thing; sleep 4; while read -t 1 _garbage; do :;done ; read -p "prompt 2: " next_thing
    prompt 1: hello
    prompt 2: world
    $ echo $first_thing $next_thing 
    hello world
    

答案 1 :(得分:1)

这绝非易事,您需要更具体地说明您希望脚本如何响应键盘输入。

没有办法锁定"键盘;用户可以在他们认为合适时继续打孔。如果您满足于要回显的键,但您希望忽略输入,则可以执行以下操作:

# Beware! Read the entire answer; don't just use this command
timeout 5 bash -c 'while :;do read -s -d ""; done'

timeout实用程序运行命令,在指定的秒数过后将其终止;指定的数字可以是小数。 read命令周围的循环是必要的,因为只要按下Enter键,read就会终止; while :; do是"永远循环的标准习语"。

timeout命令是Gnu coreutils的一部分。如果你没有它,也许是因为你使用的是BSD衍生物,你可能会找到替代品。有一个FreeBSD命令,可能在其他BSD上可用,包括Mac OS X,称为timelimit;我相信正确的调用是将timeout 5替换为timelimit -t 5 -s9,但我没有任何简单的测试方法。

您需要让read命令立即实际读取输入,而不是等到按下Enter键。否则,在read终止后,下一个命令仍然可以使用键入的输入。

有几种方法可以做到这一点。一种是使用-n 1标志使read在每个字符后返回;另一个是使用-d ""将输入字符的结尾设置为NUL,这具有将读取放入一次一个字符模式的副作用。

此外,您可能希望抑制在读取循环中按下的键的回声。你可以通过在-s命令中添加read标志来做到这一点,但是这样做会产生副作用,即将终端留在"没有回声" read命令中断时的模式。 [注1]

不幸的是,您可能会发现终端设置已永久更改,因为当read命令导致timeout被杀时,它没有机会恢复终端设置。因此,您最终会得到一个不会回显的终端,不会处理退格和其他行编辑命令,并且不会在其他问题中使用Ctrl-D。

要避免此问题,您需要保存并恢复终端设置。您可以使用stty命令执行此操作,如下所示:

# Save the terminal settings
saved=$(stty -g)
# Ignore input for 5 seconds, suppressing echo  
timeout 5 bash -c 'while :;do read -s -d ""; done'
# Restore the terminal settings
stty "$saved"
  1. 如果您不抑制回声,您会发现输入提示可能与忽略的输入显示在同一行。您可以通过输出"回车/擦除到行尾来避免这种情况。提示前的控制序列:

    tput cr; tput el; read -p "Give me some input: "
    

答案 2 :(得分:0)

@glenn的答案是一个很好的答案! 也许你前面不知道你要睡多久(你在打电话 其他一些功能)。 当您只想刷新输入队列时,可以尝试类似的方法:

echo "What is your name?"
read name
echo "Please be quiet for 5 seconds"
sleep 5

smalltime=0.000001
read -t ${smalltime} -s garbage
while [ -n "${garbage}" ]; do
   echo "Flushing $garbage"
   read -t ${smalltime} -s garbage
done

echo "Hello ${name}, please say something else"
read y
echo "You said $y"