无法将多个 shell 语句重定向到命名管道
Posted
技术标签:
【中文标题】无法将多个 shell 语句重定向到命名管道【英文标题】:Can't redirect multiple shell statements to named pipe 【发布时间】:2013-11-12 20:17:55 【问题描述】:观察当我一个接一个地发出两个命令时会发生什么,而不是在一行中,用分号分隔:
制作管道并启动电影:
$ mkfifo pipe1
$ tail -f /dev/null > pipe1 &
$ cat pipe1 | omxplayer /path/to/video.mp4
退出试验 1:
$ echo -n q > pipe1; # Exits movie, but omxplayer hangs
$ echo > pipe1; # Completes exit process
退出试验 2:
$ echo -n q > pipe1; echo > pipe1 # Does nothing
退出试验 3:
$ echo -n q > pipe1; sleep 1; echo > pipe1 # Works just like trial 1
有人可以解释为什么试验 2 什么都不做。另外,有没有更好的方法通过命名管道发出退出命令,不需要两个echo
语句?
【问题讨论】:
如果您的目标是运行两个输出到 FIFO 的命令而不关闭它们之间的 FIFO,则可以轻松解决: foo; bar; >pipe
。但是,从您描述的行为来看,听起来 omxplayer 可能要求您关闭 FIFO。
...顺便说一下,echo -n
不是 POSIX 标准(echo -E
也不是)。最好使用printf
。
【参考方案1】:
如果 fifo 上的最后一个写入器死了,而读取器检查了 fifo,它会看到一个文件结尾。如果在阅读器检查之前再次有新的写入器,则阅读器看不到文件结尾。我猜你的阅读器(omxplayer)会检查文件结尾。
从读者omxplayer
的角度来说:它看到了
"q" EOF ... <LF> EOF
"q"
(EOF
可能没有被omxplayer
看到) <LF> EOF
"q" EOF ... <LF> EOF
会发生什么完全取决于omxplayer
的处理方式,而不是你自己、操作系统或你的 shell 搞砸了。
【讨论】:
谢谢,但我不太理解你的意思:last writer, fifo dies, new writer before reader checks , 文件结束...基本上所有内容 =P 您的echo
命令写入管道,即fifo。由于它们是由您的 shell 作为子进程运行的单独命令,因此它们终止(死亡)。读者是omxplayer
,他正在检查fifo中是否有可用数据。
哦,您的意思是输入的输入速度可能快于它们的处理速度?
不是真的;我想这只是omxplayer
如何处理其输入的问题。我猜该程序涉及一些超时,它会根据您输入的时间改变其行为。【参考方案2】:
我怀疑以某种方式涉及缓冲。 (1) 和 (3) 都在 q
和换行之间提供了一段相对较长的时间,停止电影但直到读完一整行才退出。在 (2) 中,q
和换行非常接近,以至于 omxplayer
可能只是忽略了整个字符串。 echo q > pipe1
(类似于(2),但更快)有什么作用?
【讨论】:
echo q > pipe1
不起作用(因此为什么我转向echo -n q > pipe1
...基本上我在破解我不理解的东西)
是的,我也不清楚omxplayer
对标准输入做了什么,你必须阻止echo
发送换行符。尝试cat -u pipe1 | omxplayer /path/to/video.mp4
,这将禁用缓冲,并且可能在您按下q
后允许omxplayer
退出,而无需后续echo > pipe1
。
哦,我认为原因是 omxplayer 只支持一次击键(即你按q
而不是q
和ENTER
)
没有缓冲,至少在用户空间中没有,因为涉及多个写入进程。【参考方案3】:
omxplayer
是对其(命令)输入有点挑剔。它不喜欢以换行符 '\n'
终止的命令(例如 q
)。 将换行符作为命令的一部分 ('q''\n'
) 会错误地处理它,从而导致未知命令(而只有 'q'
作为有效命令存在)。因此,当echo
-ing 命令到omxplayer
时,-n
选项是必需的。
除了omxplayer
的这种“错误处理”之外,在使用cat pipe1 | cat
时可以看到相同的行为。在杀死 second cat
之后,它是最后一个(或第一个跟随)echo
终止 first cat
。
【讨论】:
请不要在回答中提问。为他们提出一个新问题,或获得足够的声誉以先发表评论。以上是关于无法将多个 shell 语句重定向到命名管道的主要内容,如果未能解决你的问题,请参考以下文章