4

我想监视将要启动的程序的实时输出。我试图通过将程序的输出重定向到管道然后从监视脚本中读取管道来做到这一点。

./program >> apipe

然后从监控脚本

cat apipe

但是,由于 >> 中的缓冲区,没有输出。无论如何我可以禁用这个缓冲区?我在准系统嵌入式系统 (petalinux) 上运行,因此我无法访问 unbuffer、脚本或 stdbuf 来帮助我。

我已经在另一个可以使用 unbuffer 的平台上尝试了这些脚本,它可以按我的预期工作。

有什么办法可以配置这个缓冲区,或者使用另一个二进制文件来重定向?

编辑:我无权访问我尝试运行的命令的源代码。它是一个遗留的二进制文件。

4

1 回答 1

5

如果您无权访问stdbuf,则不妨模拟它并手动取消缓冲stdoutgdb(假设显然您可以访问gdb)。

让我们来看看stdbuf实际是如何操作的。stdbufGNU coreutils 命令基本上只通过设置环境变量注入用户程序libstdbufLD_PRELOAD(无关紧要,但为了记录,选项是通过_STDBUF_E// env vars 传递的。_STDBUF_I_STDBUF_O

然后,当libstdbuf运行时,它以适当的模式(完全缓冲、行缓冲或无缓冲)在适当的文件描述符 ( / / ) 上调用setvbuflibc 函数(依次执行底层系统调用)。stdinstdoutstderr

声明为setvbufin 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, 和 unset调用PYTHONUNBUFFEREDwriter.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)"
于 2017-08-02T14:34:56.807 回答