通过strace查看一个进程的标准输出内容

线上某个业务java进程出了一些麻烦,去诊断的时候发现jstack无法输出,可能是jdk或os版本的问题。这时还可以尝试一下kill -3,它默认会输出到进程的标准输出。如果不幸这个进程的标准输出被重定向到了 /dev/null 或者重定向到某个文件,但却因为很多其他日志也在大量的输出,导致日志文件过大,要从中找出线程栈相关的日志,还要耗点时间;这个时候,可以通过strace来跟踪一个进程的标准输入。

strace输出的信息需要一些处理,可以通过管道与其他命令组合(通过-o参数或-ff参数)

这里 -o 参数后边是一个字符串表示输出文件,如果字符串开头是一个"|"会被strace识别为管道

$ strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $pid -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"

或者 -ff 参数,用管道与其他命令组合,注意strace的错误输出也要重定向

$ strace -ff -e trace=write -e write=1,2 -s 1024 -q -p $pid 2>&1 | cut -c11-60 | sed -e 's/ //g' | xxd -r -p

不过这两种方式都遇到一个问题,因为buffer的问题导致管道后边的命令没能完全处理strace跟踪到的数据(要等到后续的数据塞满buffer),有点像grep需要--line-buffer解决缓冲区问题,但不知道这里有什么方式,尝试过stdbuf也没有解决。最后只能分两步,先把strace的内容输出到文件,然后再对内容解析:

$ strace -f -e trace=write -e write=1,2 -q -p $pid  -o /tmp/slog

$ grep " |" /tmp/slog | cut -c11-60 | sed -e 's/ //g' | xxd -r -p

通过strace查看一个进程的标准输出内容》上有1条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注