dbuf和类似工具的情况下解缓冲旧版正在运行的二进制文件的std

dbuf和类似工具的情况下解缓冲旧版正在运行的二进制文件的std

本文介绍了如何在没有stdbuf和类似工具的情况下解缓冲旧版正在运行的二进制文件的stdout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

然后从监视脚本中

cat apipe

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

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.

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

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?

我无权访问我要运行的命令的源代码.这是旧版二进制文件.

I do not have access to the source code of the command I am trying to run. It is a legacy binary.

推荐答案

如果您无权访问stdbuf,则可以对其进行模拟并使用手动取消缓冲stdout gdb(假设您显然可以访问gdb).

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).

让我们看一下stdbuf的实际运行方式. stdbuf GNU coreutils命令基本上只注入LD_PRELOAD环境变量>>. (这不重要,但为了记录起见,选项是通过_STDBUF_E/_STDBUF_I/_STDBUF_O env vars传递的.)

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.)

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

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).

setvbuf的声明在stdio.h中,可用于man 3 setvbuf:

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);

mode的值是:_IONBF_IOLBF_IOFBF,如stdio.h中所定义.我们只对非缓冲模式感兴趣:_IONBF.它的值为2(您可以检查/usr/include/stdio.h).

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).

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

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

setvbuf(stdout, NULL, _IONBF, 0)

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

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)"

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

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

我们可以将这个简单的Python程序与缓冲的标准输出(如果未通过-u调用且未设置PYTHONUNBUFFERED调用)一起使用,writer.py:

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)

运行:

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

观察到没有任何输出出现,直到我们运行:

and observe no output appears until we run:

$ sudo ./unbuffer-stdout.sh "$(pgrep -f writer.py)"

这篇关于如何在没有stdbuf和类似工具的情况下解缓冲旧版正在运行的二进制文件的stdout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 14:15