web-dev-qa-db-ja.com

完了したターミナルコマンドからの以前のすべての出力を確認するにはどうすればよいですか?

予想よりも多くの出力をターミナルに出力するコマンドをgnomeターミナルで実行しました。出力全体を読みたいのですが、端末のスクロールが最初に達する前に停止します。

端末プロファイル設定を変更して無制限のスクロールを有効にしたり、出力をファイルにパイプしたりできることを理解しています。ただし、これらすべての一般的な解決策はfuture出力に適用されます。

すでに実行されたコマンドの完全な端末出力を表示するにはどうすればよいですか?

編集:大丈夫、それはできません。みんなありがとう!

3
JonahHuron

私の経験では、コメントのコンセンサスは正しいです-端末のバッファを超えると、そのデータは失われます(または、メモリ内にまだ上書きされていない可能性があります)-このため、さかのぼってバッファサイズを増やすことはできません。

この答えは、コメント、答え、そしておそらくあなたの状況に対するやり過ぎの間のどこかの境界線です。それはあなたの状況に対処するかもしれない提案されたアプローチです-特に手遅れになるまでログが必要かどうかわからないという問題(非因果的な問題は難しいです)が、それはあなたの質問への直接の答えではありません。

いずれにせよ、コメントするには長すぎました。このアプローチを実装するために必要なすべてのコードを明示的にリストしているわけではありません。これは主に、実行する必要のある実装上の決定が多数あるためです。より詳細な情報が必要な場合は、提供させていただきます。

Scriptを扱うのは決して楽しいことではありません

まず、scriptユーティリティは、バッファサイズを増やすことなくデータの損失を防ぐための「一時的なギャップ」として提案されています(無制限に設定するとセキュリティに影響します)。 TLCを必要とするユーティリティがあったとしたら、それはscriptです。そして再び、カーネルチームによって開発されました。あなたがそうするようにそれを読んでください。

scriptは、その価値よりも問題が多いことがよくあり(後処理して半人間が読めるようにするなど)、代わりに単純化された方法を使用してstdout、stdin、stderrをログに記録し始めました。ある意味では、これはスクリプトを再作成していますが、ハードコードされたscriptロギング設定に翻弄されるのではなく、完全に制御できます。

このアプローチは、シェルセッションに比較的シームレスに統合できます。まれに、ターミナルバッファがオーバーフローした場合、それらの内容を含む一時ファイルが作成されます。ロギングを「クリーン」に保つために、対処しなければならないハウスキーピング手順がいくつかあります。さらに、同じセキュリティ問題(すべての端末出力のログ)がデフォルトで存在します。ただし、ログを暗号化する簡単な方法があります。

3つの基本的な手順があります。

  1. Stdout(および必要に応じてstderr)をファイルと端末に分割するようにリダイレクトを構成します。この例は単純にして、stdinやstderrをファイルに送信しないようにしていますが、stdoutリダイレクトの例を理解していれば、残りは簡単です。
  2. シェルが開かれるたびにこのロギングが開始されるように.bashrcを構成します。
  3. 特定のシェルが閉じているときに、bash組み込みTRAPを使用してユーザーコードを呼び出し、セッションログを終了します(ファイルを削除したり、アーカイブしたりできます)。

このアプローチを使用すると、特定のシェルセッションの履歴全体を確認できる目に見えないセーフティネットが効果的に得られます(リダイレクトした内容に基づいて、stdoutのみを表示することを簡単にします)。あなたがそれを必要としないとき、あなたはそれがそこにあることさえ知らないはずです。

詳細

1.リダイレクトを構成する

次のコードスニペットは、ログファイルを指すファイル記述子3を作成します。 stdoutは3にリダイレクトされ、teeを使用して、そのストリームをターミナルに分割して戻します(stdoutと同等)。 stderrを同じコマンド/ログファイルに簡単に追加したり、別のファイルにパイプしたり、そのまま(ログなし)のままにすることができます。

logFile=$(mktemp -u)
exec 3>&1 1> >(tee $logFile >&3)
  • このログファイルは、スクリプトによって生成されたものよりもはるかにクリーンであることがわかります。不要なことが多いバックスペース、ラインフィード、その他の特殊文字は保存されません。

  • LogFileを暗号化する場合は、 openssl を介してteeコマンドの後にパイプステージを追加することで、かなり簡単に行うことができます。

2.ログ生成を自動化する

.bashrcに、上記と同じコードを追加します。新しいシェルが作成されるたびに、そのセッションに固有のログファイルが作成されます。

export logFile=$(mktemp -u)
exec 3>&1 1> >(tee $logFile >&3)
echo "Current session is being logged in $logFile"

3.シェルが閉じているときにログを自動的に閉じる

セッションの終了時にログファイルを削除する場合は、bashの組み込みのtrap関数を使用してセッションの終了を検出し、関数を呼び出してログファイルをアドレス指定することができます(これも.bashrc)。

trap closeLog EXIT

closeLog () {
  rm -f "$logFile" >/dev/null 2>&1
}

セッションロギングのクリーンアップは、さまざまな方法で処理できます。このアプローチは、シェルが「終了」信号をトラップすることによって閉じているときに呼び出されます。この時点で、ログファイルを削除したり、移動したり、名前を変更したり、その他の方法でログファイルをクリーンアップしたりできます。また、TRAPではなくcronジョブでログファイルをクリーンアップすることもできます(この方法を使用する場合、/ tmpディレクトリに構成済みのクリーンアップタスクがない場合は、定期的なクリーンアップタスクをお勧めします。 bashシェルがクラッシュすると、EXITトラップはトリガーされません)。

サブシェルの取り扱いに関する注意

興味深い状況はサブシェルで発展します。既存のシェルの上に新しいインタラクティブシェルを開くと、新しいログが作成され、すべてが正常に動作します。そのシェルが終了すると(親に戻る)、そのファイルへのログオンが再開されます。これにもっときれいに対処したい場合-おそらくサブシェルの共通ログ(インタラクティブまたはその他)を維持する場合でも、ネストされたサブシェルにいることを(.bashrcで)検出し、親のログファイルにリダイレクトする必要があります新しいものを作成します。また、終了時に「trap」呼び出しが親のログファイルを削除しないように、サブシェルにいるかどうかを確認する必要もあります。ネストされたシェルレベルは、シェルスタックの「深さ」を格納するbash環境変数SHLVLから取得できます。

ログを「クリーン」に保つための注意:

Stdinをログファイルにリダイレクトすると、スクリプトユーティリティが生成するのと同じ不要なアーティファクトが多数発生します。これは、リダイレクトとファイルの間にフィルターステージ(sed/grepなど)を追加することで対処できます。ログに記録したくないものを削除する正規表現を作成するだけです。完全にクリーンアップするには、かなり詳細な処理が必要です(おそらく、ファイルに書き込む前に新しい各行をバッファリングし、クリーンアップしてから書き込みます)。そうしないと、バックスペースが「ゴミ」または意図されたタイミングを知るのが難しくなります。

2
Argonauts