如何在没有stdbuf和类似工具的情况下解除传统运行二进制文件的stdout

The*_*ser 4 bash buffer pipe petalinux

我想监视我将要开始的程序的实时输出.我试图通过将程序的输出重定向到管道,然后从监视脚本中读取管道来实现此目的.

./program >> apipe
Run Code Online (Sandbox Code Playgroud)

然后从监控脚本

cat apipe
Run Code Online (Sandbox Code Playgroud)

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

我已经尝试了另一个平台上的脚本,其中unbuffer可用,它可以正常工作.

我可以用任何方式配置这个缓冲区,或使用另一个二进制文件来重定向?

编辑:我无法访问我尝试运行的命令的源代码.它是传统的二进制文件.

ran*_*mir 5

如果您没有访问stdbuf,你还不如模拟它和非缓冲的stdout手动gdb(假设很明显,你可以访问gdb).

我们来看看stdbuf实际运作情况.的stdbufGNU的coreutils命令基本上只注入libstdbuf在用户程序通过设置LD_PRELOAD环境变量.(不相关,但为了记录,选项通过_STDBUF_E/ _STDBUF_I/ _STDBUF_Oenv vars 传递.)

然后,当libstdbuf运行时,它setvbuf在适当的文件描述符(stdin/ stdout/ stderr)上调用libc函数(进而执行底层系统调用),具有适当的模式(完全缓冲,行缓冲或无缓冲).

宣言setvbufstdio.h,可提供man 3 setvbuf:

#include <stdio.h>

int setvbuf(FILE *stream, char *buf, int mode, size_t size);
Run Code Online (Sandbox Code Playgroud)

对于价值观mode是:_IONBF,_IOLBF,_IOFBF,中定义stdio.h.我们这里只对无缓冲模式感兴趣:_IONBF.它的值为2(你可以查看你的/usr/include/stdio.h).

Unbuffer脚本

所以,要stdout为某个进程取消缓冲,我们只需要调用:

setvbuf(stdout, NULL, _IONBF, 0)
Run Code Online (Sandbox Code Playgroud)

我们可以轻松地做到这一点gdb.让我们制作一个我们可以调用的脚本unbuffer-stdout.sh:

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

gdb --pid "$1" -ex "call setvbuf(stdout, 0, 2, 0)" --batch
Run Code Online (Sandbox Code Playgroud)

然后,我们可以这样称呼:

$ ./unbuffer-stdout.sh "$(pgrep -f my-program-name)"
Run Code Online (Sandbox Code Playgroud)

(您可能需要sudo将其作为root.)

测试

我们可以用这个简单的Python程序与缓冲标准输出(如果不叫-u,并与未设置PYTHONUNBUFFERED)writer.py:

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

while True:
    sys.stdout.write("output")
    time.sleep(0.5)
Run Code Online (Sandbox Code Playgroud)

运行它:

$ ./writer.py >/tmp/output &
$ tailf /tmp/output
Run Code Online (Sandbox Code Playgroud)

并且在我们运行之前观察没有输出:

$ sudo ./unbuffer-stdout.sh "$(pgrep -f writer.py)"
Run Code Online (Sandbox Code Playgroud)