我正在 Centos 6 上使用管道通过 bash 实现一些功能。在这些管道中,我想将数据导出到日志文件中,但这些数据来自管道中的不同管道,我想通过注入标签来区分它们在每个日志行之前。更准确地说,我想做以下事情:
COMMAND1 | (create a line in the log file like: "command1: " + output of the command) | COMMAND2 ...
经过大量研究后,我得出以下观点:
COMMAND1 | tee >(ifne echo -n "command1: " >> out.log) | tee -a out.log | COMMAND2
这有效但有一个问题。第二个tee
首先写入文件,然后写入第一个tee
。所以我得到:
(output of command 1)
command1:
代替
command1: (output of command 1)
我怀疑ifne
延迟足以使第二个tee
在第一个之前执行。如果我删除它ifne
,它就可以正常工作。问题是我需要ifne
,因为我经常有空输出,我不想记录它。
如何让第二个发球台等待第一个发球台完成?
答案1
如果我理解正确的话,您希望使用一个标记来记录 COMMAND1 的输出,表明它来自 COMMAND1。这是一种方法:
COMMAND1 | tee >(sed 's/^/command1: /' >>out.log) | COMMAND2
注意:
- 这会将
command1:
标记放在每行的开头,而不仅仅是第一行的开头,我认为这是可取的,但不是您似乎想要做的。 command1
不得包含任何 sed 特殊字符(否则需要用反斜杠保护)。- 由于
out.log
打开是为了追加,所以即使多个命令并行输出到同一个日志文件,也不会有输出重叠的风险。 - 由于
out.log
在此片段中仅打开一次,因此所有行都将按顺序排列。 现在坏消息是:如果您并行多次登录到同一个文件,则不能保证这些行会按所需的顺序出现。例如,
echo hello | tee >(sed 's/^/command1: /' >>out.log) | tr a-z A-Z | tee >(sed 's/^/command2: /' >>out.log)
command2: HELLO
可能会在 之前登录command1: HELLO
。- 如果并行多次记录到同一个文件,并且一行内容太长,则来自不同实例的行可能会散布。我认为常见的 sed 实现将通过小于
PIPE_BUF
字节长,但我不确定。
考虑到排序和原子性限制,我建议记录到单独的文件,在这种情况下您不需要前缀。