首页 > 解决方案 > 为什么我不能从 bash 中的 fifo 读取管道 sql 的结果?

问题描述

为什么/tmp/sql.log我尝试捕获通过fifo发送的sql的结果时为空:

fifo=/tmp/fifo.$$
mkfifo $fifo

tail -f $fifo | mysql -u root -N > /tmp/sql.log &
echo "SELECT IF(GET_LOCK('foo',1)=1,'Got lock', concat('Already locked by connection: ', IS_USED_LOCK('foo')));" >$fifo
# /tmp/sql.log is empty

但是 non-fifo 示例按预期写入:

echo "SELECT IF(GET_LOCK('foo',1)=1,'Got lock', concat('Already locked by connection: ', IS_USED_LOCK('foo')));" | mysql -u root -N > /tmp/sql.log
# /tmp/sql.log has result of mysql query

我知道命令是通过 fifo 发送的,因为如果我添加tee到尾部:

fifo=/tmp/fifo.$$
mkfifo $fifo

tail -f $fifo | tee >(mysql -u root -N) &
echo "SELECT IF(GET_LOCK('foo',1)=1,'Got lock', concat('Already locked by connection: ', IS_USED_LOCK('foo')));" >$fifo

我可以看到命令和 sql 的结果。如何捕获 sql 的结果而不是让它出现在标准输出上?

标签: mysqlbashfifo

解决方案


多哈。诀窍是保持简单。放弃tail并只使用重定向:

重定向只是短暂的工作 - fifo 被关闭,所以只有第一组 sql 发送到 fifo 被传递到mysql。正如@poshi 建议的那样,答案是使用mysql's--unbuffered选项。最终答案在这个答案下方(留给与我落入同一个坑的人)。

# This only works for the first set of sql - the fifo is closed 
# so more can't be sent later
fifo=/tmp/fifo.$$
mkfifo $fifo

mysql -u root -N < $fifo > /tmp/sql.log &
echo "SELECT IF(GET_LOCK('foo',1)=1,'Got lock', concat('Already locked by connection: ', IS_USED_LOCK('foo')));" >$fifo
# /tmp/sql.log has results of sql query

工作解决方案

用于tail保持 fifo 打开 &mysql--unbuffered选项以从中获取数据。

fifo=/tmp/fifo.$$
mkfifo $fifo

tail -f $fifo | mysql --unbuffered -u root -N > /tmp/sql.log &
echo "SELECT IF(GET_LOCK('foo',1)=1,'Got lock', concat('Already locked by connection: ', IS_USED_LOCK('foo')));" >$fifo
# sleep to prove that the fifo isn't closed for later queries
sleep 10
echo "SELECT CONNECTION_ID();" >$fifo
# /tmp/sql.log has results of both sql queries

推荐阅读