如果您无权访问stdbuf,您不妨模拟它并手动解除stdout 的缓冲 与gdb(假设您显然可以访问gdb) .
让我们来看看stdbuf 是如何实际操作的。 stdbuf GNU coreutils 命令基本上只通过设置LD_PRELOAD 环境变量在用户程序中注入libstdbuf。 (无关紧要,但为了记录,选项是通过_STDBUF_E/_STDBUF_I/_STDBUF_O env vars 传递的。)
然后,当 libstdbuf 运行时,它会在适当的文件描述符 (stdin/stdout/stderr) 上调用 setvbuf libc 函数(它依次执行底层系统调用),并使用适当的模式(完全缓冲、行缓冲或无缓冲)。
setvbuf 的声明在stdio.h 中,可通过man 3 setvbuf 获得:
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
mode 的值为:_IONBF、_IOLBF、_IOFBF,如stdio.h 中所定义。我们在这里只对无缓冲模式感兴趣:_IONBF。它的值为2(您可以查看您的/usr/include/stdio.h)。
解缓冲脚本
所以,要为某个进程取消缓冲 stdout,我们只需要调用:
setvbuf(stdout, NULL, _IONBF, 0)
我们可以通过gdb 轻松做到这一点。让我们编写一个可以调用的脚本,unbuffer-stdout.sh:
#!/bin/bash
# usage: unbuffer-stdout.sh PID
gdb --pid "$1" -ex "call setvbuf(stdout, 0, 2, 0)" --batch
那么,我们可以这样称呼它:
$ ./unbuffer-stdout.sh "$(pgrep -f my-program-name)"
(您可能需要sudo 以root 运行它。)
测试
我们可以使用这个带有缓冲标准输出的简单 Python 程序(如果没有使用 -u 调用,并且未设置 PYTHONUNBUFFERED),writer.py:
#!/usr/bin/python
import sys, time
while True:
sys.stdout.write("output")
time.sleep(0.5)
运行它:
$ ./writer.py >/tmp/output &
$ tailf /tmp/output
并观察在我们运行之前没有输出:
$ sudo ./unbuffer-stdout.sh "$(pgrep -f writer.py)"