我试图找出在终端不是活动窗口时使用键盘快捷键停止正在运行的脚本的最佳方法。
这让我了解了如何观察键盘事件cat /dev/input/eventX
(其中 X 是对应于击键事件的数字)
然后我了解了一个工具evtest
,该工具将一直运行,直到以人类可读的格式打印出事件(击键)为止。
这是我迄今为止管理的脚本,但它没有按预期工作。在完美的解决方案中,用户可以随时按 Key_Space 来停止脚本,但我认为这在这里不可能。所以我的解决方法是在循环开始时给他们 2 秒的窗口。
#!/bin/bash
exitCase='*type 1 (EV_KEY), code 57 (KEY_SPACE)*'
while [ true ] do
evtest /dev/input/eventX | read -s -t 2 line
if [ "$line" = "$exitCase" ]
then
echo caught event
exit 0
else
echo loop doing stuff
fi
done
问题是脚本将运行一次而不循环,是否有更好的方法来做到这一点?或者我如何调整我的脚本以循环,直到它看到与退出情况匹配的输入?
我认为另一个潜在的问题是一次击键会打印出多行,所以也许我需要一个evtest /dev/input/eventX | while read line
?但经过尝试后,我只能让它在事件上循环,而不是在等待事件时循环。
答案1
由于管道的右侧evtest | read line
在单独的子 shell 中运行(因此永远不会设置line
任何有用的内容),因此我预计您的测试会绝不是真的,并且脚本将无限期地运行。脚本中可能有未显示的代码?
无论如何,您不需要read
从evtest
.相反,您可以使用grep
(这也可以解决您在最后提到的“潜在问题”):
#!/bin/sh
exitCase='*type 1 (EV_KEY), code 57 (KEY_SPACE)*'
while true; do
if evtest /dev/input/eventX | grep -q -Fx -e "$exitCase"; then
echo caught event
break
else
echo loop doing stuff
fi
done
evtest
一旦生成了与 完全相同的行,就会跳出循环$exitCase
。-q
告诉grep
它保持安静的选项(我们只对退出状态感兴趣),我们-F
确保将grep
字符串$exitCase
与细绳而不是作为正则表达式,并且-x
我们需要整行匹配(没有子字符串,就好像字符串在开头和结尾都锚定一样)。
如果您想对grep
或施加超时evtest
,您可以使用timeout
GNU coreutils。