12

私は現在、ターミナルに送られるすべてのものをキャプチャしてログファイルにスローするために以下を使用しています

exec 4<&1 5<&2 1>&2>&>(tee -a $LOG_FILE)

ただし、カラーエスケープコード/クラッターをログファイルに入れたくありません。だから私はこのようなものを持っています

exec 4<&1 5<&2 1>&2>&>(
    while read -u 0; do
        #to terminal
        echo "$REPLY"
        #to log file (color removed)
        echo "$REPLY" | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' >> $LOG_FILE
    done
    unset REPLY #tidy
)

readスクリプトの一部(例:echo -n "..."またprintfはなし)では理想的ではないキャリッジリターンを待機する場合を除きます\n


ジョナサンレフラーの答えへのフォローアップ:

サンプルスクリプトを考えるとtest.sh

#!/bin/bash

LOG_FILE="./test.log"
echo -n >$LOG_FILE

exec 4<&1 5<&2 1>&2>&>(tee -a >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > $LOG_FILE))


##### ##### #####
# Main

echo "starting execution"
printf "\n\n"

echo "color test:"
echo -e "\033[0;31mhello \033[0;32mworld\033[0m!"
printf "\n\n"

echo -e "\033[0;36mEnvironment:\033[0m\n  foo: cat\n  bar: dog\n  your wife: hot\n  fix: A/C"
echo -n "Before we get started. Is the above information correct?  "
read YES
echo -e "\n[READ] $YES" >> $LOG_FILE
YES=$(echo "$YES" | sed 's/^\s*//;s/\s*$//')
test ! "$(echo "$YES" | grep -iE '^y(es)?$')" && echo -e "\nExiting... :(" && exit
printf "\n\n"

#...some hundreds of lines of code later...

echo "Done!"


##### ##### #####
# End

exec 1<&4 4>&- 2<&5 5>&-

echo "Log File: $LOG_FILE"
  1. 端末への出力は期待どおりであり、ログファイルに必要なカラーエスケープコード/クラッターはありません。ただし、調べてみると、は表示されtest.logません[READ] ...(の21行目を参照test.sh)。

  2. [私の実際のbashスクリプトの]ログファイルにはLog File: ...、4および5 fdsを閉じた後でも、その最後に行が含まれています。sleep 12番目の前にaを置くことで問題を解決することができましたexec-競合状態またはfdshenanigansが原因であると思います。残念ながら、この問題を再現することはできませんが、test.sh誰かが持っているかもしれない憶測に興味があります。

4

6 に答える 6

6

stdinを並列プロセスに分散することは可能ですかでpee説明されているプログラムの使用を検討してください。これにより、実際の出力に色を送信し続けながら、sedスクリプトを介してログデータを送信できるようになります。

これの主な利点の1つは、「sedログ出力の1行に1回実行する」を削除することです。これは、パフォーマンスにとって本当に悪魔的なことです(実行されたプロセスの数に関しては、他に何もないとしても)。

于 2012-01-04T02:08:06.240 に答える
2

私はそれが完璧な解決策ではないことを知っていますが、cat -v目に見えない文字をのような\x1B目に見える形に変換するようになります^[[1;34m。出力は乱雑になりますが、少なくともasciiテキストになります。

于 2012-01-04T00:32:00.287 に答える
1

私はTERM=dumb、コマンドを実行する前に設定することで、このようなことを行うために使用します。これにより、タブ、CR、およびLFを除くすべての制御文字がほとんど削除されました。これがあなたの状況でうまくいくかどうかはわかりませんが、試してみる価値はあります。問題は、端末がダム端末であるため、端末にカラーエンコーディングが表示されないことです。

visまたはcat(特にパラメーター)のいずれかを試して-v、これらが何かを行うかどうかを確認することもできます。次のようにパイプラインに配置するだけです。

exec 4<&1 5<&2 1>&2>&>(tee -a | cat -v | $LOG_FILE)

ちなみに、ほとんどすべてのターミナルプログラムには、入力をキャプチャするオプションがあり、ほとんどの場合、入力をクリーンアップします。どのプラットフォームを使用していて、どのタイプのターミナルプログラムを使用していますか?

于 2012-01-04T02:25:27.927 に答える
0

そうでないscreen -Lか、scriptコマンドはこのexecループの代わりに実行可能なオプションである可能性がありますか?

于 2012-01-04T02:52:26.753 に答える
0

読み取りに-nオプションを使用してみることができます。改行を待つ代わりにn文字を読み込みます。1に設定できます。これにより、コードが実行される反復回数が増えますが、改行を待つことはありません。

男から:

-n NCHARS read returns after reading NCHARS characters rather than waiting for a complete line of input.

注:私はこれをテストしていません

于 2012-01-04T02:02:23.957 に答える
0

ANSIFilterを使用して、ANSIエスケープシーケンスでコンソール出力を削除または変換できます。

http://www.andre-simon.de/zip/download.html#ansifilterを参照してください

于 2012-01-04T02:09:44.577 に答える