Bash save/redirect 程序被杀死时的标准输出和标准错误

Bash save/redirect stdout and stderr when program is killed

当 ProgramA 被外部进程杀死(杀死:9)时,我无法重定向其输出(std/stderr)或将其保存到变量中。

程序A:

$ ./ProgramA arg1
  This is on stderr
  This is on stdout
  Killed: 9

无法保存到变量:

$ ProgramA_Output=`ProgramA arg1`
$ echo "$ProgramA_Output"

$

重定向到文件也不起作用:

$ ProgramA arg1 > output.txt
$ cat ./output.txt
$

有任何保存/重定向输出的线索吗?

这里最可能的直接原因是您的程序仅在输出到 TTY 时逐行刷新其缓冲区;因此,当重定向到一个文件或一个 FIFO 时,它在 SIGKILL 被传递时还没有刷新——并且由于 SIGKILL 不能被捕获或延迟,它没有机会在那个时候执行刷新。

如果您使用的是 GNU 平台,您可以使用 stdbuf 来默认修改此行为:

stdbuf -o0 ./ProgramA arg1 >output.txt

...或...

output=$(stdbuf -o0 ./ProgramA arg1)

因为你知道当输出到 tty 时它会刷新(因为当 运行 没有重定向时输出会立即显示),你也可以使用 unbufferexpect) 来模拟那个效果:

output=$(unbuffer ./ProgramA arg1)

但是,最可靠的做法是修改 ProgramA 的源代码,以便在每次要确保完成的写入后显式执行刷新操作——并且只使用 SIGKILL 当绝对需要时。 (通常的做法是使用 SIGTERM,等待相当长的时间,然后才求助于 SIGKILL)。