在 tee 输出中注入字符串

在 tee 输出中注入字符串

我正在 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字节长,但我不确定。

考虑到排序和原子性限制,我建议记录到单独的文件,在这种情况下您不需要前缀。

相关内容