Shell-Script
sh shell:將輸出重定向到終端和腳本內的文件
如何從腳本內部將 stdout 和 stderr 重定向到文件和終端。
#!/bin/sh LOG_FILE="/tmp/abc.log" exec &> >(tee -a $LOG_FILE) echo "Start" echo "Hi" 1>&2 echo "End"
我找到了上面的腳本。但是這個腳本只適用於 bash。使用 sh shell 會出現以下錯誤:
./abc.sh: 5: Syntax error: redirection unexpected (expecting word)
我想要一個同時適用於 sh 和 bash shell 的腳本。
是的,
&>
是一個bash
運算符(現在也支持zsh
, 雖然zsh
總是有>&
相同的 like incsh
),和>(...)
一個ksh
運算符(現在也支持zsh
andbash
),也不是sh
運算符。那個不帶引號的 $LOG_FILE 在這裡你顯然不想要 split+glob ,使它成為 zsh 語法(在不帶引號的擴展時不隱式執行 split+glob 的那些 shell 中唯一的一個,儘管在 中zsh
,你只是這樣做exec >&1 > $LOG_FILE 2>&1
)。在
sh
語法中,您可以執行以下操作:#! /bin/sh - LOG_FILE="/tmp/abc.log" { # your script here } 2>&1 | tee -- "$LOG_FILE"
或者把所有東西都放在一個函式中:
#! /bin/sh - LOG_FILE="/tmp/abc.log" main() { # your script here } main "$@" 2>&1 | tee -- "$LOG_FILE"
在任何情況下,這種方法和您的
zsh
-style 方法最終都會在與在標準輸出上打開的相同資源上列印錯誤消息。因此,如果有人這樣做your-script > out 2> err
,err
將是空的,並且out
將包含正常輸出和錯誤。為確保保留輸出和錯誤的原始目標,您可以改為:
{ { main "$@" 3>&- | tee -a -- "$LOG_FILE" >&3 3>&- } 2>&1 | tee -a -- "$LOG_FILE" >&2 3>&- } 3> "$LOG_FILE" 3>&1
(未經測試)。