ファイルに最新のn行の出力のみを保持します。

ファイルに最新のn行の出力のみを保持します。

分割エラーが原因で定期的にクラッシュするコンピューティングクラスタでプログラムを実行しているので、詳細なデバッグ出力を維持して原因を診断したいと思います。ただし、プログラムは競合なしに複数時間実行される可能性があるため、出力全体をファイルにリダイレクトすると、ログファイルが大きすぎてsrun my-program-binary > output.log 2>&1クラスタのディスククォータを超えてしまいます。最新のn行の出力(約1000行)だけが必要なので、実行中の出力バッファを維持し、将来の参照のために特定の時間の最新部分だけを維持する方法があるかどうか疑問に思います。

クラスターにインストールできる項目は限られているため、非標準パッケージを必要としないソリューションが必要です。このソリューション最後の部分を維持するためにファイルが生成されるのを待つことができないため、私の場合は機能しません。特定の長さ/メモリサイズを超えない実行バッファを維持する必要があります。このようなことをする方法を知っている人はいますか?

答え1

bashwcおよびがある場合は、sed小さなスクリプトを使用できます。

#!/bin/bash

file=$1
nlines=$2

while read line ; do
    echo "$line" >> $file
    read clines _ <<< $(wc -l $file)
    if [[ clines -gt nlines ]] ; then
        n=$(( clines - nlines ))
        sed -i -e 1,${n}d $file
    fi
done

パイプで使用:srun my-program-binary 2>&1 | a_little_script output.log 1000

スクリプトは

  • 出力の各行を読み取り、my-program-binaryそれをoutput.logにエコーします。
  • Output.log の現在の行数を取得します。
  • それ以降の最初のn行を削除nlines

これにより、出力の最後のn行が常にログファイルに保持されます。メモリとCPUをほとんど使用しません。

答え2

メモリーが 1,000 行程度に対応できる場合、1 つのアプローチは問題が発生するまでメモリーに行をバッファリングすることです。

#!/usr/bin/env perl
# keepn - keep N lines of input in memory, and print them at exit
$0 = 'keepn';    # pkill(1) target (some OS do not honor this)
my $keep = shift // 1000;
my $okay = 1;
$SIG{$_} = sub { $okay = 0 } for qw(HUP INT PIPE TERM USR1);

my @buf;
while ( $okay and defined( my $line = readline ) ) {
    push @buf, $line;
    my $over = @buf - $keep;
    if ( $over > 0 ) { splice @buf, 0, $over }
}
END { print for @buf }

ここでの欠点は、keepnプロセスが終了するとバッファリングされたログ行も終了することです。信号処理は、これらの極端なケースを防ぐのに役立ちます。定期的にディスクに同期すると、@bufI / Oが増加しますが、いくつかのログ行があるかどうかを確認する方が良いですが、keepn信頼できない、または暴走しているメモリ不足キラーの対象にならないことを願っています。

srun my-program-binary 2>&1 | keepn 1000 > output

他の場所にログを送信する

別のオプションは、パイプを介してlogger(1)syslogデーモンに出力が必要な場所を処理させることです。ただし、これを行うにはsyslogデーモンまたはロギングフレームワークを制御する必要があります。これは、ログが他の場所に蓄積される可能性があり、より大きなディスククォータを使用する必要がある可能性があることを意味します。しかし、設定する方がはるかに複雑です。 TCPソケットまたはWeb APIを使用して、良いか悪いかをログ出力を別の場所に送信することもできます。

マルチプレクサ

たとえば、端末マルチプレクサはtmux制限されたロールバックを提供します。簡単に以下のタスクを実行しtmuxてから、バッファロールバックを使用して設定されるまで、ログの最後の数行が何であるかを確認できます history-limit

set-option -g history-limit 1000

関連情報