【发布时间】:2018-10-31 07:59:40
【问题描述】:
这很可能属于 KISS(保持简单)原则,但我仍然很好奇并希望了解为什么我没有收到预期的结果。所以,我们开始...
我有一个 shell 脚本来捕获 STDOUT 和 STDERR 而不会干扰原始文件描述符。这是为了保留用户在终端上看到的原始输出顺序(参见下面的test.pl)。
不幸的是,我仅限于使用 sh,而不是 bash(但我欢迎示例),因为我是从另一个套件中调用它的,我可能希望将来在 cron 中使用它(我知道 cron 有 @ 987654323@环境变量)。
wrapper.sh 包含:
#!/bin/sh
stdout_and_stderr=$1
shift
command=$@
out="${TMPDIR:-/tmp}/out.$$"
err="${TMPDIR:-/tmp}/err.$$"
mkfifo ${out} ${err}
trap 'rm ${out} ${err}' EXIT
> ${stdout_and_stderr}
tee -a ${stdout_and_stderr} < ${out} &
tee -a ${stdout_and_stderr} < ${err} >&2 &
${command} >${out} 2>${err}
test.pl 包含:
#!/usr/bin/perl
print "1: stdout1\n";
print STDERR "2: stderr1\n";
print "3: stdout2\n";
在场景中:
sh wrapper.sh /tmp/xxx perl test.pl
STDOUT 包含:
1: stdout1
3: stdout2
STDERR 包含:
2: stderr1
到目前为止一切都很好......
/tmp/xxx 包含:
2: stderr1
1: stdout1
3: stdout2
但是,我期待 /tmp/xxx 包含:
1: stdout1
2: stderr1
3: stdout2
谁能向我解释为什么 STDOUT 和 STDERR 没有按照我预期的顺序附加/tmp/xxx?我的猜测是后台的tee 进程正在阻止/tmp/xxx 资源,因为它们具有相同的“目的地”。你会如何解决这个问题?
相关:How do I write stderr to a file while using "tee" with a pipe?
【问题讨论】:
-
无论你在这里做什么,如果
tees 中的一个被阻塞了一段时间(因为系统负载过重,或其他原因),通过它的数据也会被延迟。确实没有办法解决这个问题,因为进程的输出不包含可用于在另一端正确安排写入的排序或时间戳。