要求:使用python脚本,开启一个子进程并实时读取并解析其打印(printf())的字符串。
首先用linux shell脚本来做试验,
写一个echo-test.sh,循环输出,内容如下:
#!/bin/sh
while :;do
echo "status:A"
echo "status:B"
echo "status:C"
echo "status:D"
echo "status:E"
echo "status:V"
echo "status:F"
sleep 1
done
单独执行echo-test.sh效果:
$ ./echo-test.sh
status:A
status:B
status:C
status:D
status:E
status:V
status:F
status:A
status:B
status:C
status:D
status:E
status:V
status:F
status:A
status:B
status:C
status:D
status:E
status:V
status:F
^C
再写一个python脚本rdstdout.py,读取并分析echo-test.sh的输出:
import time
from subprocess import *
p=Popen("./echo-test.sh",shell=True,stdout=PIPE)
data=p.stdout.readline()
while data:
if "status:V" in data:
print time.time()
print data
elif "status:A" in data:
print time.time()
print data
data=p.stdout.readline()
执行下rdstdout.py,
$ python rdstdout.py
1517467252.54
status:A
1517467252.54
status:V
1517467253.54
status:A
1517467253.54
status:V
1517467254.54
status:A
1517467254.54
status:V
^CTraceback (most recent call last):
File "rdstdout.py", line 14, in
data=p.stdout.readline()
KeyboardInterrupt
方法可行,初战告捷!
修改rdstdout.py,
p=Popen("./echo-test.sh",shell=True,stdout=PIPE) --->
p=Popen("./gps_test.sh 9600",shell=True,stdout=PIPE)
gps_test 读取并解析gsp module输出的数据,定位成功输出status:A,未定位输出status:V.
单独执行gps_test,输出结果,
$ ./gps_test 9600
status:V
total sat:0
status:V
total sat:0status:V
total sat:0^C
但执行rdstdout.py,看不到任何输出,按键盘退出程序才看到输出信息。
修改p=Popen("./gps_test.sh 9600",shell=True,stdout=PIPE) --->
p=Popen("ping www.baidu.com",shell=True,stdout=PIPE),
可以即时获取ping输出的数据。怀疑到printf()有个缓冲,需要在其后加一句fflush(stdout); 这样修改编译出新的gps_test,执行python rdstdout.py可以即时获取gps_test输出的数据,
执行 objdump -T /bin/ping |grep fflush
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 fflush
可以看到ping程序也用到了fflush,应该也是用了类似方法吧。不过需要在每个线程的printf()后都要加上fflush(stdout),比较繁琐,可以在执行主线程printf()前加一句setbuf(stdout, NULL), stdout就没有buffer可用,每个线程的printf()数据都可以即时获取。
当然也可以用fprintf(stderr,... 代替printf(),也可以解决问题。
这些办法的共同点就是都需要修改gps_test的源码,如果没有源码,这些办法就不好用了,可以考虑用API hook的方法,具体就不在这里讨论了。