Linux 来自'的管道输出;超时';至';wc-l';失败
我试图计算给定时间段内的所有击键次数。 当前我的代码如下所示:Linux 来自'的管道输出;超时';至';wc-l';失败,linux,console,timeout,pipe,signals,Linux,Console,Timeout,Pipe,Signals,我试图计算给定时间段内的所有击键次数。 当前我的代码如下所示: $ timeout -s 9 10s xinput test 8 | wc -l $ xinput test 8 > output.log & sleep 10 && wc -l output.log && kill $! 这是回报 Killed 而不是预期的按键次数。 当我在没有管道的情况下运行timeout时,输出与预期的一样 $ timeout -s 9 20s xinput
$ timeout -s 9 10s xinput test 8 | wc -l
$ xinput test 8 > output.log & sleep 10 && wc -l output.log && kill $!
这是回报
Killed
而不是预期的按键次数。
当我在没有管道的情况下运行timeout时,输出与预期的一样
$ timeout -s 9 20s xinput test 8
key release 36
key press 42
key release 42
key press 26
key release 26
key press 28
key release 28
key press 38
key release 38
key press 46
key release 46
key press 31
key release 31
key press 41
key release 41
key press 26
key release 26
Killed
无论是更改信号还是添加参数--preserve status都无法解决此问题
我想知道为什么这不起作用。“超时”是否会以某种方式劫持标准输出
编辑:
然而,添加前景解决了我的问题。但我不明白为什么。它可以工作,因为这样,timeout命令不会杀死任何子进程,从而避免了wc来计算行数
$ timeout --foreground -s 15 10s xinput test 8 | wc -l
另一种方式是这样的:
$ timeout -s 9 10s xinput test 8 | wc -l
$ xinput test 8 > output.log & sleep 10 && wc -l output.log && kill $!
这样,您就不需要超时。第一部分将xinput的输出重定向到一个文件,并将命令发送到后台,然后休眠(等待文件接收到一些数据),在休眠完成后,我们运行wc并优雅地终止xinput后台命令。使用--foreground
,wc-l
只会看到一个EOF,因此它会打印行数
如果没有--前台
,wc-l
会被SIGKILL
杀死。(我用另一个终端的strace-p$(pidof-wc)
追踪它)
跟踪超时
本身,以查看有无--前台
时的不同功能:
除内存地址不同外:
在时间到期后,--front
只是杀死并等待(2)s它分叉的子对象(clone(2)
),然后通过正常的exit\u组(2)
系统调用退出
如果没有--前台
,它会
setpgid(0, 0) = 0
在用叉子叉孩子之前。在时间到期后,它kill()
s子对象,然后使用kill(0,SIGKILL)
杀死自己
从kill(2)
:
如果pid等于0,则sig被发送到调用进程的进程组中的每个进程
我忘记了信号语义的细节,我不知道为什么这解释了wc
接收SIGKILL
。根据pstree
,wc
和xinput
都是bash的孩子,而不是彼此的孩子。不过,进程是按照它们在管道中出现的顺序启动的
timeout(1)
手册页显示了关于--front
:“在此模式下,命令的子项不会超时”。这似乎包括管道中的后续元素。IDK如果shell可以安排管道的不同元素不在同一个进程组中以避免这种情况,或者什么。您的解决方案将所有按下的键存储在一个文件中的磁盘上。出于安全考虑,我不想那样。啊,好的。因此,超时似乎最适合您。