Bash

在 tee 輸出中註入字元串

  • March 7, 2019

我正在使用管道在 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,因為我經常有空輸出,我不想記錄。

如何讓第二個發球檯等待第一個發球檯完成?

如果我理解正確,您想用一個標記記錄 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字節的行,但我不確定。

鑑於順序和原子性限制,我建議將日誌記錄到單獨的文件中,在這種情況下您不需要前綴。

引用自:https://unix.stackexchange.com/questions/504707