gpt4 book ai didi

linux - 是否可以在没有 TTY 的情况下自动刷新 STDOUT/STDERR?

转载 作者:太空狗 更新时间:2023-10-29 11:17:34 25 4
gpt4 key购买 nike

我有一个名为批处理启动器的 bash 脚本在工作。它负责启动和报告各个批处理的状态。批处理的启动是这样完成的:

env $BENV setsid $BATCH $OPT >> $FILE 2>&1

几个月前,我遇到了一个问题,其中一个带有 fork 子项的批处理在 PGID 上发送了一个终止信号,最终终止了该批处理和批处理启动器,这是一个很大的禁忌。我对这个问题的解决方案是添加 setsid 部分(因为 bash 不允许 setpgrp),这会创建一个新 session 并因此创建一个新的 PGID。

现在我有另一个问题。同样讨厌的批处理有 fork 的 child ,除了 child 在他们的工作完成之前不会写任何日志。在调查这个问题之后,我找到了原因 here - setsid 产生了一个没有 TTY 的进程,在这种情况下,子进程的任何输出都不会在每个换行符上自动刷新,而是在最后刷新一次就在流关闭之前。这意味着如果一个 child 死于错误,缓冲区中的日志将永远消失,证明任何调试都是不可能的。

有没有办法告诉 setsid 自动刷新 STDOUT/STDERR 输出流?谷歌搜索没有得到任何结果,此时我唯一的解决方案是用支持 setpgrp 的语言(如 PERL 或 C)重写批处理启动器,这需要 QA 进行大量测试。

编辑:

小提示,问题可以通过以下方式解决:

env $BENV 脚本 -qec "$BATCH $OPT"-af $FILE

这需要 util-linux 早于 2010 来支持 -e 返回代码处理的标志(不幸的是,我使用 2005 年的 RHEL5 时情况并非如此,请参阅 commit了解详情)。

最佳答案

添加 stdbuf -o0(无缓冲,或 stdbuf -oL 行缓冲)

env $BENV setsid stdbuf -o0 $BATCH $OPT >> $FILE 2>&1

应该可以解决问题(只要通过 libc 的 stdio 和 libc 动态链接的 $BATCH 缓冲区(默认))。

编辑:

这是一个快速的'n'dirty stdbuf -o0 模拟:

#!/bin/sh -e
trap 'rm -rf "$tmpd"' EXIT HUP INT QUIT TERM
tmpd=$(mktemp -d)
cat > "$tmpd/unbuf.c" <<EOF
#include <stdio.h>
__attribute__((constructor))
static void unbuffer(void){ setvbuf(stdout, 0, _IONBF, 0); }
EOF
gcc "$tmpd/unbuf.c" -o "$tmpd/unbuf.so" -fpic -shared
LD_PRELOAD="$tmpd/unbuf.so" "$@"

关于linux - 是否可以在没有 TTY 的情况下自动刷新 STDOUT/STDERR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41900132/

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