Bash

將 stderr 發送到管道中的不同接收器

  • May 7, 2018

現在我有這個:

echo "$run_test" | bash 2>&1 | prepend "r2g-test:" "yellow";

這樣做是將“r2g-test:”添加到 stdout/stderr 的每一行。因為我將標準錯誤發送到標準輸出,所以prepend程序不知道區別,因為它都是標準輸入。

有什麼方法可以將 stderr 發送到不同的prepend實例,也許是tee

也許是這樣的?

echo "$run_test" | bash 2> $(prepend 'r2g-test:' 'red') | prepend 'r2g-test:' 'yellow';

這可能工作,與程序替換:

bash 2> >(prepend 'r2g-test:' 'red')

但到目前為止,stderr 從未出現在終端中

首先,讓我們創建一個run_test同時生成 std​​out 和 stderr 的程序:

$ run_test() { while sleep 0.2; do echo "Out $((++c))"; echo "err$c">&2; done; }

現在,讓我們將 stdout 和 stderr 發送到不同的過濾器。由於我沒有prepend安裝,我將sed用於相同的目的:

$ exec 3>&2; { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

這個怎麼運作

  • exec 3>&2

這將創建文件描述符 3 作為 stderr 的副本。

  • run_test | sed 's/^/stdout: /'

這將執行run_teststdout:添加到標準輸出的開頭。

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3

2>&將 stderr 重定向到 stdout,以便 stderr 進入下一個管道。 1>&3將 stdout 重定向到 stderr 以便它出現在終端上。

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'

最後一個管道擷取 run_test 的標準錯誤(現在是標準輸出)並將stderr:其添加到它的前面。

使用程序替換

$ run_test > >(sed 's/^/stdout: /') 2> >(stdbuf -oL sed 's/^/stderr: /' >&2)
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

以上使用stdbuf是 Linux 上的標準。對於其他作業系統,需要尋找類似的命令。

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