gpt4 book ai didi

linux - 即时输出重定向,在程序仍在运行时查看文件重定向输出

转载 作者:IT王子 更新时间:2023-10-29 00:06:15 27 4
gpt4 key购买 nike

如果我使用这样的命令:
./program >> a.txt &
,并且该程序是一个长时间运行的程序,那么我只能在程序结束后看到输出。这意味着在它真正停止计算之前,我无法知道计算是否进展顺利。我希望能够在程序运行时读取文件上的重定向输出。

这类似于打开一个文件,向其添加内容,然后在每次写入后将其关闭。如果文件仅在程序结束时关闭,则在程序结束之前无法读取其中的数据。我所知道的唯一重定向类似于在程序结束时关闭文件。

您可以使用这个小的 Python 脚本对其进行测试。语言无所谓。任何写入标准输出的程序都有同样的问题。

l = range(0,100000)
for i in l:
if i%1000==0:
print i
for j in l:
s = i + j

可以通过以下方式运行:
./python 程序.py >> a.txt &
然后 cat a.txt .. 只有在脚本完成计算后您才会得到结果。

最佳答案

来自 stdout manual page :

The stream stderr is unbuffered. The stream stdout is line-buffered when it points to a terminal. Partial lines will not appear until fflush(3) or exit(3) is called, or a new‐line is printed.

底线:除非输出是一个终端,否则您的程序将在默认情况下以全缓冲模式进行标准输出。这实质上意味着它将以大块的形式输出数据,而不是逐行输出,更不用说逐字符输出了。

解决此问题的方法:

  • 修正你的程序:如果你需要实时输出,你需要修正你的程序。在 C 中你可以使用 fflush(stdout) 在每个输出语句之后,或 setvbuf() 改变标准输出的缓冲模式。对于 Python,有 sys.stdout.flush()甚至一些建议 here .

  • 使用可以从 PTY 记录的实用程序,而不是直接的标准输出重定向。 GNU Screen可以为您做这件事:

    screen -d -m -L python test.py

    将是一个开始。这会将程序的输出记录到名为 screenlog.0 的文件中(或类似)在当前目录中,默认延迟 10 秒,您可以使用 screen连接到运行命令的 session 以提供输入或终止它。延迟和日志文件的名称可以在配置文件中更改,也可以在连接到后台 session 后手动更改。

编辑:

在大多数 Linux 系统上,还有第三种解决方法:您可以使用 LD_PRELOAD变量和一个预加载的库来覆盖 C 库的选择函数并使用它们来设置 stdout当您的程序调用这些函数时的缓冲模式。此方法可能有效,但它有许多缺点:

  • 它对静态可执行文件根本不起作用

  • 它很脆弱而且很丑。

  • 它对 SUID 可执行文件根本不起作用 - 动态加载器将拒绝读取 LD_PRELOAD出于安全原因加载此类可执行文件时的变量。

  • 它很脆弱而且很丑。

  • 它要求您找到并覆盖您的程序在初始设置 stdout 之后 调用的库函数。缓冲模式,最好是 before 任何输出。 getenv()是许多程序的不错选择,但不是全部。您可能必须重写常见的 I/O 函数,例如 printf()fwrite() - 如果到了紧要关头,你可能只需要覆盖所有控制缓冲模式的函数,并为 stdout 引入一个特殊条件。 .

  • 它很脆弱而且很丑。

  • 很难确保没有不受欢迎的副作用。要正确执行此操作,您必须确保只有 stdout受到影响,并且您的覆盖不会使程序的其余部分崩溃,例如stdout已关闭。

  • 我有没有提到它很脆弱而且很丑陋?

也就是说,这个过程相对简单。你放入一个 C 文件,例如linebufferedstdout.c替换函数:

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>


char *getenv(const char *s) {
static char *(*getenv_real)(const char *s) = NULL;

if (getenv_real == NULL) {
getenv_real = dlsym(RTLD_NEXT, "getenv");

setlinebuf(stdout);
}

return getenv_real(s);
}

然后将该文件编译为共享对象:

gcc -O2 -o linebufferedstdout.so -fpic -shared linebufferedstdout.c -ldl -lc

然后你设置LD_PRELOAD变量以将其与您的程序一起加载:

$ LD_PRELOAD=./linebufferedstdout.so python test.py | tee -a test.out 
0
1000
2000
3000
4000

如果你幸运的话,你的问题将得到解决,没有不幸的副作用。

您可以设置 LD_PRELOAD shell 中的库,如有必要,甚至在 /etc/ld.so.preload 中指定系统范围内的库(绝对推荐) .

关于linux - 即时输出重定向,在程序仍在运行时查看文件重定向输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5500515/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com