【问题标题】:Is it possible to autoflush STDOUT/STDERR with no TTY?是否可以在没有 TTY 的情况下自动刷新 STDOUT/STDERR?
【发布时间】:2017-01-27 17:53:45
【问题描述】:

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

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

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

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

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

编辑:

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

env $BENV script -qec "$BATCH $OPT" -af $FILE

这需要早于 2010 年的 util-linux 支持 -e 标志以进行返回代码处理(不幸的是,对于 2005 年的 RHEL5 来说,我不是这种情况,有关详细信息,请参阅 commit)。

【问题讨论】:

标签: linux bash


【解决方案1】:

添加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" "$@"

【讨论】:

  • 好点,但我目前使用coreutils 5.97-34.el5_8.1 卡在 RHEL5 上。那里没有stdbuf。 :( 是否有任何其他实用程序,也许可以设置 TTY?
  • @S.T.A.L.K.E.R.让您快速而肮脏的stdbuf -o0 仿真。 (假设你至少有 gcc)
  • 感谢您的帮助!我已经在旁边编译了unbuf.c,现在我正在尝试像这样启动批处理:env LD_PRELOAD="$tmpd/unbuf.so" $BENV setsid $BATCH $OPT &gt;&gt; $FILE 2&gt;&amp;1。但这无济于事,我仍然丢失了这些日志。你知道我做错了吗?
  • 在这个小慢写器上测试(int main() { uint i=0; for(;;){ printf("%u\n", i++); usleep(0.5*1000000); } } 编译为 a.out 并在 $PWD 中使用 unbuf.so,`env LD_PRELOAD=$PWD/unbuf.so setsid ./a.out > out ` 对我有用(=允许我 tail -f out 并实时观看其内容)。不幸的是,如果您的 $BATCH 程序不使用 stdio 或对其输出做一些特殊的事情,那么除非它有自己的,否则您就不走运了禁用缓冲的选项。
  • 批处理是用 PERL 编写的。我发现我可以通过在 PERL 中手动调用 STDOUT-&gt;flush(); 来解决这个问题,但我想没有通用的解决方案可以解决所有语言(C、C++、Python、Perl 等)的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-31
  • 2019-10-22
  • 2017-07-06
  • 2020-05-28
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多