[英]How to redirect output of background bash pipeline in real time
我有一個長時間運行的 bash 腳本(就像一個守護進程),它可能會向 stdout 和 stderr 發出 output。
我有這些要求:
這是我到目前為止所取得的成就:
myscript="script_name"
log_file="/tmp/blabla"
prepend_info() {
xargs -d '\n' printf "$(date +'%b %d %T') $HOSTNAME $myscript: %s\n"
}
script -q -c "$myscript" /dev/null 2>&1 | prepend_info > "$log_file" 2>&1 &
問題是日志文件僅在我的腳本終止后才被填充,但我想在它運行時看到 output。
如果我刪除|& prepend_info
它會按預期工作,但我也需要將這些附加信息添加到日志文件中。
似乎 pipe 僅在第一個命令終止后才執行。
有沒有辦法修改后台腳本的 output 並在運行時將其重定向到文件中?
我需要盡可能兼容,只能使用簡單的bash命令。 例如,我不能使用ts
,因為它並不總是可用,而且我不僅需要時間戳,還需要其他信息。
更新:到目前為止我找到的唯一解決方案(它解決了所有問題,也解決了日期問題)如下。
myscript="script_name"
log_file="/tmp/blabla"
exec_script() {
rm -f "$log_file"
local out_log=<($myscript 2>&1)
while read -r line; do
echo "$(date +'%b %d %T') $HOSTNAME $myscript: $line" >> $log_file
done < "$out_log"
}
exec_script &
如果有人有更好的解決方案,我會洗耳恭聽。
我想了解我的代碼片段哪里錯了
請記住使用 shellcheck 檢查您的腳本。 $myscript
和$log_file
沒有被引用。 另請參閱https://wiki.bash-hackers.org/scripting/obsolete - 您正在使用function NAME()
,只需使用NAME()
,不應同時使用|&
和>&
。
管道中的命令是完全緩沖的,在您的情況下,它會在命令終止時刷新 output,因為緩沖區足夠大。 script_name
和tr
都是完全緩沖的,這在您的命令到達xargs
之前提供了很大的緩沖。
tr '\n' '\0' | xargs -0
tr '\n' '\0' | xargs -0
聽起來很奇怪。 為什么將零的換行符更改為使用零? 從一開始就使用換行符xargs -d '\n'
。
此外,命令替換會在運行xargs
之前擴展,因此$(date +'%b %d %T')
將擴展一次到xargs
開始之前的日期,而不是當前行已寫入的時間。
在 Bash 中, $HOSTNAME
比$(hostname)
快。
此外, tr
output 始終是全緩沖的,因為tr
程序本身使用全緩沖算法。 Sooo .. 不要使用tr
。
有沒有辦法修改后台腳本的 output 並在運行時將其重定向到文件中?
關於如何為命令 output 添加前綴,在 .net 上有很多很多解決方案,例如https://unix.stackexchange.com/questions/26728/prepending-a-timestamp-to-each-line-of-output -來自命令, https://unix.stackexchange.com/questions/592215/best-way-to-prefix-output-of-a-command-and-check-its-return-value 。
主觀上,最好不要使用 shell,而編寫一個 python 腳本,它將subprocess.popen
命令並通過讀取文件描述符來實現你想要的。 這樣性能就可以接受了。
使用 bash 4.2+,您可以避免使用printf '%(... )T'
和全局變量SECONDS
在每行輸入中分叉date
命令
#!/bin/bash
myscript="script_name"
log_file="/tmp/blabla"
SECONDS=$(command -p awk 'BEGIN{srand();print srand()}')
{
"$my_script" 2>&1 |
while IFS='' read -r line
do
printf '%(%b %d %T)T %s %s: %s\n' "$SECONDS" "$HOSTNAME" "$myscript" "$line"
done > "$log_file" 2>&1
} &
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.