为什么在RHEL5或RHEL6上从管道读取数据时,read -t
不会超时?
这是我在RHEL系统上从管道读取数据时无法超时的示例:
tail -f logfile.log | grep 'something' | read -t 3 variable
如果我没记错的话,
read -t 3
应该在三秒后超时?非常感谢!ChrisGNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
cat | sleep 5
五秒钟后,管道将会被中断,因为sleep
命令已经结束,但是cat
命令会一直运行直到你按下回车键。
在你的情况下,也就是说,直到grep产生结果,即使超时了,你的命令也会继续运行。
read -t 3 variable < <( tail -f logfile.log | grep "something" )
variable
值,需要将其设为可见。请确认此操作是否按预期超时。
read
作为固定时间后退出管道的方式,因此不必担心variable
的范围。但是,grep
可能会在超时时找到匹配项,但由于其自身的内部缓冲而未打印出来。您可以使用--line-buffered
选项禁用它(至少在GNU grep
中)。tail -f logfile.log | grep --line-buffered "something" | read -t 3
如果可用,另一个选择是使用timeout
命令代替read
:
timeout 3 tail -f logfile.log | grep -q --line-buffered "something"
tail
,并像通常一样使用grep
的退出状态。read
会退出,但始终带有代码142-即使grep
实际上找到了它应该找到的内容。 - Chrisgrep --line-buffered
,这样 grep
可以在找到匹配项时立即输出。 - chepner我现在没有 RHEL 服务器来测试你的脚本,但我敢打赌 read 正确地在超时时退出并按预期工作。尝试运行:
grep 'something' | strace bash -c "read -t 3 variable"
而且你可以确认这一点。
read
在 read(0, 0x7fff306fc50f, 1) = ? ERESTARTSYS (To be restarted) --- SIGALRM (Alarm clock) @ 0 (0) ---
后退出,但进程仍然挂起。 - Chris
variable
只会在执行read
命令的子shell中设置,对吧?你的bash
版本没有lastpipe
选项,无法使管道的最后一个命令在当前shell中执行。 - chepner