web-dev-qa-db-ja.com

対話型コマンドから「tee」で終わるパイプラインに渡された出力のバッファーを解除するにはどうすればよいですか?

インタラクティブコマンドのトラブルシューティングを行っています。

  • そのコマンドが生成するので、(block-bufferedの代わりに)バッファリングされていない、またはラインバッファリングされた元のカラーリングで画面に出力された出力を参照してください
  • teeのようなものを使用して、このコマンドの出力を同時にファイルにリダイレクトし、保持します。つまり、文字化けしない(たとえば、処理する代わりにrawで ANSIエスケープシーケンス を渡すなど)正しく)—この結果のログファイルの色。 (この設定の一部はおそらく不可能であることを理解しているため、次の設定に置き換えます。)
  • teeまたはそのようなものを使用して、このコマンドの出力を同時にファイルにリダイレクトします
  • 実行時に問題のコマンドによって色分けされた出力を表示します
  • 結果のログを ANSIエスケープシーケンス —で汚染しません。つまり、端末に表示した後でbeforeログファイルに保存します。

通常、tee -aは、ここでログに記録しようとしているのと同じ種類のコマンドからの出力を使用してこれを行いますが、someteeで終わるパイプラインでヒットした奇妙なコーナーケースは、この通常の賢明な動作を妨害しているようです。私はビットを調べて、誰かが以前に同様の問題を抱えているかどうかを確認し、その解決策を考え出しましたが、すべての関連資料私はこれを浚うことができました:

しかし、これらのリソースはどれもquite十分なヒントを提供していないので、私はそれらを使用して、私が何をしているかに沿って何かをコブルすることができると思うlike—最後に、自分が生成するのに必要なログを、できる人に送信することができますgleanもちろん、彼らからの何か。
unbuffer-とscriptベースの提案にいくつかのバリエーションを試してみた私がすでに熟読していて、この質問を書き始める前にstdbufを少し検討することを検討していたが、まだ最後の質問に取り掛かっていません。 OS X v10.11.6「El Capitan」で/usr/bin/bashを使用しています。私がトラブルシューティングしようとしているコマンドはHOMEBREW_BUILD_FROM_SOURCE=1 brew upgrade -vd --build-from-source mailutilsです。ここで、brewHomebrewパッケージマネージャー であり、ソースからビルドしようとしているMailutilsのバージョンとアップグレードしようとしているのはv3.3(現在はv3.2です)ですが、完全にdeeplyに切り替えると、differentコマンドalsoは、パイプラインの一部として使用されると、ブロックバッファー出力を生成します(私が理解している場合正しくanyシェルコマンド、私が見たように、パイプラインを設定すると、それ自体でブロックバッファリングが発生する可能性があることを述べましたが、ここでは私の問題を解決できません。ここでキャプチャしようとしているログに関して、私が求める結果を達成するために使用できるツールはどれですか?

6
RandomDSdevel
_#!/usr/bin/env expect
package require Tcl 8.5
if {[llength $argv] == 0} {
    puts stderr "Usage: $argv0 logfile command \[cmd-args ..]"
    exit 1
}
set ::argv [lassign $::argv thelogfile]
log_file $thelogfile
spawn -noecho {*}$argv
interact
_

interactを使用すると、生成されたコマンドをいじることができますが、すべてを(expect(1)に文書化されている_log_file_のデフォルトです)追加する必要があります。使用例:

_$ rm out
$ ./yointeract out sh
$ echo hi
hi
$ printf "\033[10Ghi\n"
         hi
$ exit
$ xxd out
00000000: 2420 6563 686f 2068 690d 0a68 690d 0a24  $ echo hi..hi..$
00000010: 2070 7269 6e74 6620 225c 3033 335b 3130   printf "\033[10
00000020: 4768 695c 6e22 0d0a 1b5b 3130 4768 690d  Ghi\n"...[10Ghi.
00000030: 0a24 2065 7869 740d 0a                   .$ exit..
$ 
_

追伸これは多かれ少なかれautoexpect(1)プログラムと同じで、少なくともexpect(1)に同梱または同梱されています

1
thrig

@EliahKaganとのチャットで複数のセッションを行った後、彼が私を思いついたのは次のとおりです。

まず、次の前提条件を収集します。

  • 記録する標準出力とエラーを明らかに実行するコマンド。以下では、これを"$COMMAND"と呼びます。
  • ログを追加するファイル(このように、コメントを上部に残して、それらのログを生成したものを示すことができます。少なくとも、それが私が文書化する傾向がある方法です。)以下では、これを参照します"$LOG_FILE"として。
  • 比較的最近のバージョンのインストール PerlnotPerl6、これがない場合not以前のメインラインリリースと互換性がありません)。
  • @ -dewtellによって 彼の回答 から この他のUnix&Linux Stack Exchangeの質問 に渡されたPerlスクリプトの実行可能なコピー。以下では、これを"$RM_ANSI_ESC_SEQS_SCRIPT"と呼びます。
  • moreutils のインストール(sponge用)。

"$PATH"を変更して、シェル(bashを使用していますが、これらの手順をほとんどまたはまったく変更せずに、ここで概説されている手順に完全に適している場合もあります)がPerlとmoreutilsを見つけられるようにします。この回答で参照されている他のコマンドであるscriptは、少なくとも私のようなマシンでOS X/macOSの比較的最近のバージョンを実行している場合は、システムですでに使用可能になっているはずです。そうでない場合、または何らかの理由で別のソースから新しいバージョンをインストールする場合は、修正して実行するか、今すぐ実行してください。
次に、次のコマンドを順番に実行します。

script -aq "$LOG_FILE" "$COMMAND" # Add the `k` option, either separately or as part of the group of short options already given to this command, if you want to log user input as well.  
"$RM_ANSI_ESC_SEQS_SCRIPT" "$LOG_FILE" | sponge "$LOG_FILE"

scriptコマンドのバージョンによっては、構文が異なることにも注意してください。 指定されたものはOS X/macOS用 なので、必要に応じて調整します。それはさておき、それで終わりです。ただし、これをすべて1つのパイプラインにまとめる方法がさらに存在する可能性があることを付け加えておきますが、これを書いている時点では、それを理解することができませんでした。どうすればよいかを示す追加のコメントや回答も歓迎します。

1
RandomDSdevel