How to unbuffer stdout of legacy running binary without stdbuf and similar tools

微笑、不失礼 提交于 2019-11-29 07:58:15

If you don't have access to stdbuf, you might as well simulate it and unbuffer the stdout manually with gdb (assuming obviously you have access to gdb).

Let's take a look at how stdbuf actually operates. The stdbuf GNU coreutils command basically only injects libstdbuf in the user program by setting LD_PRELOAD environment variable. (Irrelevant, but for the record, options are passed via _STDBUF_E/_STDBUF_I/_STDBUF_O env vars.)

Then, when the libstdbuf is run, it calls setvbuf libc function (which in turn executes the underlaying syscall) on appropriate file descriptors (stdin/stdout/stderr), with the appropriate mode (fully buffered, line buffered, or unbuffered).

Declaration for setvbuf is in stdio.h, available with man 3 setvbuf:

#include <stdio.h>

int setvbuf(FILE *stream, char *buf, int mode, size_t size);

Values for mode are: _IONBF, _IOLBF, _IOFBF, as defined in stdio.h. We are here only interested in the unbuffered mode: _IONBF. It has a value of 2 (you can check your /usr/include/stdio.h).

Unbuffer script

So, to unbuffer a stdout for some process, we just need to call:

setvbuf(stdout, NULL, _IONBF, 0)

We can easily do that with gdb. Let's make a script we can call, unbuffer-stdout.sh:

#!/bin/bash
# usage: unbuffer-stdout.sh PID

gdb --pid "$1" -ex "call setvbuf(stdout, 0, 2, 0)" --batch

Then, we can call it like:

$ ./unbuffer-stdout.sh "$(pgrep -f my-program-name)"

(You'll probably need sudo to run it as root.)

Testing

We can use this simple Python program with buffered standard output (if not called with -u, and with unset PYTHONUNBUFFERED), writer.py:

#!/usr/bin/python
import sys, time

while True:
    sys.stdout.write("output")
    time.sleep(0.5)

Run it with:

$ ./writer.py >/tmp/output &
$ tailf /tmp/output

and observe no output appears until we run:

$ sudo ./unbuffer-stdout.sh "$(pgrep -f writer.py)"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!