您当前的位置:首页 > 计算机 > 系统应用 > Linux

shell管道堵住

时间:01-26来源:作者:点击数:

背景#

起因是这样的,我们想开发一个小脚本,当cpu使用率过高时,使用jstack将java的线程栈保存下来,以便后面分析。

获取cpu使用率#

获取cpu使用率是比较容易的,使用vmstat就可以了,第15列id就是cpu空闲率,用100减一下,就是cpu使用率了。

于是,我使用如下命令获取了cpu使用率,发现能获取到,如下:

vmstat 1|awk '{print 100-$15}'

问题出现#

但当我在后面再加一个脚本读取cpu使用率时,却发现当cpu到90%以上时,脚本半天都没有输出,如下:

# 让一个核满载
stress --cpu 1

# cpu高时,自动jstack取线程栈
vmstat 1|awk '{print 100-$15}'|while read cpu; do [[ $cpu -gt 90 ]] && jstack `pgrep java`; done

我以为是我脚本的问题,于是把后面的脚本换成了cat,如下:

vmstat 1|awk '{print 100-$15}'|cat

发现还是没有输出,这就比较疑惑了,就好像最后那个管道被堵住了一样!

问题解决#

经过在网上一顿搜索,终于发现答案,原来是缓存的锅。当awk的输出目标是终端时,awk不会缓存数据立马输出,而当输出目标是文件或管道时,awk会缓存数据,到一定大小后再输出。

并且,在awk中可以使用fflush函数,让其立即输出,如下:

vmstat 1|awk '{print 100-$15; fflush()}'|cat

同样的,像grep, sed, python之类的命令,都有这样的问题,可如下避免:

grep --line-buffered
sed -u
python -u

另外,Linux专门提供了一个stdbuf命令,用来避免命令输出时缓存数据,用法如下:

stdbuf -o L grep

最后,我的小脚本修改如下,终于可以实现目标了。

vmstat 1|awk '{print 100-$15; fflush()}'|while read cpu; do [[ $cpu -gt 90 ]] && (jstack `pgrep java` > "$(date +'%FT%T')_stack.log"); done
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门