为什么我不能从 bash 中的 fifo 读取管道 sql 的结果?

Why can't I read the results of piped sql from a fifo in bash?

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

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

但非 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 的结果而不是让它出现在标准输出上?

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

重定向仅短暂起作用 - fifo 关闭,因此只有第一组 sql 发送到 fifo 被传递到 mysql。正如@poshi 所建议的那样,答案是使用 mysql--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