I want to monitor the realtime output of a program that I will start. I am trying to do this by redirecting the output of the program to a pipe and then reading the pipe from a monitoring script.
./program >> apipe
then from the monitoring script
cat apipe
However due to the buffer in >> there is no output. Anyway I can disable this buffer? I am running on a barebones embedded system (petalinux) so I don't have access to unbuffer, script, or stdbuf to help me out.
I have tried the scripts on another platform where unbuffer is available it works as I expect.
Any way I can configure this buffer, or use another binary to redirect?
Edit: I do not have access to the source code of the command I am trying to run. It is a legacy binary.
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)"
来源:https://stackoverflow.com/questions/45460998/how-to-unbuffer-stdout-of-legacy-running-binary-without-stdbuf-and-similar-tools