將輸出從腳本內部重定向到 less

將輸出從腳本內部重定向到 less

我可以使用以下命令將腳本的輸出從腳本內部重定向到日誌檔案exec

#!/bin/bash
exec > stdout.log 2>&1
echo hello world

是否可以將輸出重定向到less而不是檔案?我試過

#!/bin/bash
exec > >(less) 2>&1

# output some text
for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done

但這以一種奇怪的方式失敗了......可見的提示較少,但您最終回到了終端。

我想將其設定為腳本的開頭(因此它可以是有條件的,取決於參數、tty 等)。

答案1

您應該讓腳本等待less子進程,否則您的腳本將在其之前終止,並且less會突然發現自己位於前台進程組之外,無法再從終端讀取命令或恢復終端設定。

另外,為了防止less永遠等待輸入結束,您的腳本應該關閉它的管道。

把所有這些放在一起:

exec > >(less) 2>&1
trap 'exec >&- 2>&-; wait' EXIT
# >&- 2>&- => close stdout and stderr => cause EOF on less' stdin

seq 1 50000
# the rest of your script

但這不是很好,不能移植到大多數其他 shell,並且依賴 bash 的未記錄(且不可靠)行為:wait如果您的腳本中有多個腳本exec > >(...),則該方法將無法正常工作,並且它還會等待其他背景進程以 開始&


更好的想法是讓腳本呼叫自身,使用環境變數來避免無限遞歸:

if [ ! "$CALLED_MYSELF" ]; then
    set -o pipefail # supported in bash, but not in all the shells  
    CALLED_MYSELF=1 "$0" "$@" 2>&1 | less
    exit
fi

seq 1 50000
# the rest of your script

答案2

試試這個(不含線exec):

for (( i=1; i <= 500; i++ )); do echo "hello world $i"; done | less

(更新)

如果您想包含整個腳本,可以將腳本包裝為{ ... }

#!/bin/bash
{
# output some text
for (( i=1; i <= 500; i++)) do echo "hello world $i"; done

# whatever output you want...

} | less

相關內容