Bash
將 stderr 發送到管道中的不同接收器
現在我有這個:
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
同時生成 stdout 和 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_test
並stdout:
添加到標準輸出的開頭。
{ 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 上的標準。對於其他作業系統,需要尋找類似的命令。