一个坑爹的问题,有关mysql与重定向

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
南浦月
帖子: 197
注册时间: 2011-07-24 23:34
系统: archlinux
联系:

一个坑爹的问题,有关mysql与重定向

#1

帖子 南浦月 » 2014-04-03 10:40

嗯,我实在不能用一句话描述这个问题,所以标题就只能这样了。

具体问题是,假如我有如下代码:

代码: 全选

for i in {1..5}; do
  echo "select md5($i);";
  sleep 5;
done |\
mysql -u<user> -p<passwd> --skip-column-name
在终端直接运行这些代码,我会每隔5秒钟得到一个输出。

但是如果我在最后加了重定向,就像这样:

代码: 全选

for i in {1..10}; do
  echo "select md5($i);";
  sleep 5;
done |\
mysql -u<user> -p<passwd> --skip-column-name > output.txt
那么在前整段代码运行完毕前,output.txt这个文件里没有任何内容,运行完毕后,所有输出一起出现了!

这个问题该怎么解释呢?
还有如果我想在重定向后也像没有重定向时一样每隔5秒就向output.txt输出一行结果该怎么办?

这个问题困扰我好久了,我觉得应该是mysql的问题。

求解答啊,先谢过大家了。
jackysc
帖子: 51
注册时间: 2006-12-29 20:45

Re: 一个坑爹的问题,有关mysql与重定向

#2

帖子 jackysc » 2014-04-04 12:00

代码: 全选

for i in {1..10}; do
  echo "select md5($i);";
  sleep 5;
  mysql -u<user> -p<passwd> --skip-column-name >> output.txt
done

你这样试试.....
只用一个> 每次都会清空里面的内容的..
头像
南浦月
帖子: 197
注册时间: 2011-07-24 23:34
系统: archlinux
联系:

Re: 一个坑爹的问题,有关mysql与重定向

#3

帖子 南浦月 » 2014-04-05 23:29

jackysc 写了:

代码: 全选

for i in {1..10}; do
  echo "select md5($i);";
  sleep 5;
  mysql -u<user> -p<passwd> --skip-column-name >> output.txt
done

你这样试试.....
只用一个> 每次都会清空里面的内容的..
谢谢, 但是这样不是我想要的结果,酱紫每次循环都会fork一个子进程。
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 一个坑爹的问题,有关mysql与重定向

#4

帖子 astolia » 2014-04-12 23:43

应该是mysql的输出缓冲区导致的,在终端里显示的话,由于终端是行缓冲的,遇到换行能自动作flush操作,重定向到文件后,默认是全缓冲,只有达到EOF或缓冲区满了才会自动flush。缓冲区默认一般是4096字节,那10次的输出应该不够长

这缓冲区也没啥问题,如果你非要每次输出都能即时反映到文件内容中,要么你去改mysql的源码,用setvbuf把缓冲区弄小点,要么用下面这个hack:
创建一个以下内容的C源代码hack.c

代码: 全选

#include <stdio.h>
void _init(){
    setvbuf(stdout, NULL, _IOLBF, 0);
}
编译成一个hack.so动态链接库

代码: 全选

gcc -fPIC -c hack.c
ld -shared -lc -o hack.so hack.o
强制让mysql加载这个动态链接库

代码: 全选

for i in {1..10}; do
  echo "select md5($i);";
  sleep 5;
done |\
LD_PRELOAD=./hack.so mysql -u<user> -p<passwd> --skip-column-name > output.txt
回复