内部スクリプトから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

しかし、これはあまり良くなく、他のほとんどのシェルに移植可能ではなく、文書化されていない(信頼できない)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

おすすめ記事