10GBを超えるログファイルを表示するには?

10GBを超えるログファイルを表示するには?

私が考えた方法は:

  1. 現場をリアルタイムで再現できれば。使用

    tail -f application.log | tee /tmp/tailed_log

しかし、リアルタイムでシーンを再現できるかどうかはわかりません。

  1. グレブログ

    grep -i 'string_to_search" application.log > /tmp/greppedLOG

問題は、「string_to_search」が存在しない行をスキップしたことです。スキップする他の文字列も重要です。

私はこれを試していませんが、これはうまくいくかもしれません。

grep -i "string_to_search || string_to_not_skip" application.log > /tmp/greppedLOG

私が言ったように、いくつかの文字列を省略すると、問題全体が混乱します。したがって、他の解決策が見つからない場合は、そうする可能性が最も高くなりますが、満足できません。

  1. 別の方法は、n行をgrepすることです。

    grep -A5000 "string_to_search" application.log > /tmp/greppedLOG

問題は、特定のユーザーのログがどれだけ長いかわからないことです。これは信頼できる方法ではありません。

  1. 私がやったもう一つの方法は、大容量ログファイルを分割することでした。

    split -n 20 application.log /tmp/smallfile

しかし、先輩同僚も費用がかかるプロセスなので、こうしてはいけないと助言することもあります。時々、私たちが管理しているサーバーにスペースが足りなくなることがありますが、このような状況でログファイルを分割するとサーバーがダウンすることがあります。

  1. 私が考えるのに効果があると思われるもう1つのアプローチは、ある期間のログを別の期間にインポートすることです。私はこれを試していないが、https://unix.stackexchange.com/a/751676/569181、動作します。
LC_ALL=C awk -v beg=10:00:00 -v end=13:00:00 '
  match($0, /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/) {
    t = substr($0, RSTART, 8)
    if (t >= end) selected = 0
    else if (t >= beg) selected = 1
  }
  selected'

問題は、顧客が取引を行うときは常に時間がないということです。しかし、時にはログをチェックして、顧客が取引をした時間を知ることができます。

別の考えが頭の中に浮かんでいました。

df -H出力のデフォルトパーティションが85%を超える場合は、ファイルを分割しないでください。分割コマンドを入力しても。エイリアスとスクリプトが必要だと思います。

ログを圧縮してggrepを実行することもスペース分割と同じであるため、役に立ちません。

他におすすめしていただけるものはありますか?より良い解決策はありますか?それでも技術的な問題ですか?それとも私たちの顧客の問題ですか?私はこの状況が本当に苦しいです。

答え1

このスクリプトは、テキストファイルを特定の数の部分に分割し、テキスト行が複数の部分に分割されるのを防ぎます。一度に1つのセクションに十分なスペースがある場合に使用できます。最後から始めて、ソースファイルの一部をコピーし、ソースファイルを切り取ってスペースを解放するように動作します。したがって、1.8GBファイルと0.5GBの空き容量がある場合は、4つのセクションを使用する必要があります(または出力ファイルを小さくするにはそれ以上)。最後の部分はコピーする必要がないので、名前を変更するだけです。分割後、ソースファイルはもう存在しません(とにかくスペースはありません)。

主な部分は、セクションサイズのみを設定するawkスクリプト(Bashでパッケージ化されています)です(ニューラインと一致するようにセクション調整を含む)。 system() 関数を使用して dd、truncate、および mv を呼び出して、すべての重い操作を実行します。

$ bash --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
$ awk --version
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)
$ dd --version
dd (coreutils) 8.28
$ truncate --version
truncate (GNU coreutils) 8.28

スクリプトは1〜4個のパラメータを使用します。

./splitBig Source nSect Dest Debug

Source: is the filename of the file to be split into sections.

nSect: is the number of sections required (default 10).

Dest: is a printf() format used to generate the names of the sections.
Default is Source.%.3d, which appends serial numbers (from .001 up) to the source name.
Section numbers correspond to the original order of the source file.

Debug: generates some diagnostics (default is none).

テスト結果:

$ mkdir TestDir
$ cd TestDir
$ 
$ cp /home/paul/leipzig1M.txt ./
$ ls -s -l
total 126608
126608 -rw-rw-r-- 1 paul paul 129644797 Aug 27 15:54 leipzig1M.txt
$ 
$ time ../splitBig leipzig1M.txt 5

real    0m0.780s
user    0m0.045s
sys 0m0.727s
$ ls -s -l
total 126620
25324 -rw-rw-r-- 1 paul paul 25928991 Aug 27 15:56 leipzig1M.txt.001
25324 -rw-rw-r-- 1 paul paul 25929019 Aug 27 15:56 leipzig1M.txt.002
25324 -rw-rw-r-- 1 paul paul 25928954 Aug 27 15:56 leipzig1M.txt.003
25324 -rw-rw-r-- 1 paul paul 25928977 Aug 27 15:56 leipzig1M.txt.004
25324 -rw-rw-r-- 1 paul paul 25928856 Aug 27 15:56 leipzig1M.txt.005
$ 
$ rm lei*
$ cp /home/paul/leipzig1M.txt ./
$ ls -s -l
total 126608
126608 -rw-rw-r-- 1 paul paul 129644797 Aug 27 15:57 leipzig1M.txt
$ time ../splitBig leipzig1M.txt 3 "Tuesday.%1d.log" 1
.... Section   3 ....
#.. findNl: dd bs=8192 count=1 if="leipzig1M.txt" skip=86429864 iflag=skip_bytes status=none
#.. system: dd bs=128M if="leipzig1M.txt" skip=86430023 iflag=skip_bytes of="Tuesday.3.log" status=none
#.. system: truncate -s 86430023 "leipzig1M.txt"
.... Section   2 ....
#.. findNl: dd bs=8192 count=1 if="leipzig1M.txt" skip=43214932 iflag=skip_bytes status=none
#.. system: dd bs=128M if="leipzig1M.txt" skip=43214997 iflag=skip_bytes of="Tuesday.2.log" status=none
#.. system: truncate -s 43214997 "leipzig1M.txt"
.... Section   1 ....
#.. system: mv "leipzig1M.txt" "Tuesday.1.log"

real    0m0.628s
user    0m0.025s
sys 0m0.591s
$ ls -s -l
total 126612
42204 -rw-rw-r-- 1 paul paul 43214997 Aug 27 15:58 Tuesday.1.log
42204 -rw-rw-r-- 1 paul paul 43215026 Aug 27 15:58 Tuesday.2.log
42204 -rw-rw-r-- 1 paul paul 43214774 Aug 27 15:58 Tuesday.3.log
$ 

スクリプト:

#! /bin/bash --

LC_ALL="C"

splitFile () {  #:: (inFile, Pieces, outFmt, Debug)

    local inFile="${1}" Pieces="${2}" outFmt="${3}" Debug="${4}"

    local Awk='
BEGIN {
    SQ = "\042"; szLine = 8192; szFile = "128M";
    fmtLine = "dd bs=%d count=1 if=%s skip=%d iflag=skip_bytes status=none";
    fmtFile = "dd bs=%s if=%s skip=%d iflag=skip_bytes of=%s status=none";
    fmtClip = "truncate -s %d %s";
    fmtName = "mv %s %s";
}

function findNl (fIn, Seek, Local, cmd, lth, txt) {

    cmd = sprintf (fmtLine, szLine, SQ fIn SQ, Seek);
    if (Db) printf ("#.. findNl: %s\n", cmd);
    cmd | getline txt; close (cmd);
    lth = length (txt);
    if (lth == szLine) printf ("#### Line at %d will be split\n", Seek);
    return ((lth == szLine) ? Seek : Seek + lth + 1);
}

function Split (fIn, Size, Pieces, fmtOut, Local, n, seek, cmd) {

    for (n = Pieces; n > 1; n--) {
        if (Db) printf (".... Section %3d ....\n", n);
        seek = int (Size * ((n - 1) / Pieces));
        seek = findNl( fIn, seek);
        cmd = sprintf (fmtFile, szFile, SQ fIn SQ, seek,
            SQ sprintf (outFmt, n) SQ);
        if (Db) printf ("#.. system: %s\n", cmd);
        system (cmd);
        cmd = sprintf (fmtClip, seek, SQ fIn SQ);
        if (Db) printf ("#.. system: %s\n", cmd);
        system (cmd);
    }
    if (Db) printf (".... Section %3d ....\n", n);
    cmd = sprintf (fmtName, SQ fIn SQ, SQ sprintf (outFmt, n) SQ);
    if (Db) printf ("#.. system: %s\n", cmd);
    system (cmd);
}

{ Split( inFile, $1, Pieces, outFmt); }
'
    stat -L -c "%s" "${inFile}" | awk -v inFile="${inFile}" \
        -v Pieces="${Pieces}" -v outFmt="${outFmt}" \
        -v Db="${Debug}" -f <( printf '%s' "${Awk}" )
}

#### Script body starts here.

    splitFile "${1}" "${2:-10}" "${3:-${1}.%.3d}" "${4}"

答え2

あなたが何を達成したいのかは全く明確ではありません。私が知っている限り、質問した内容は質問のタイトルに「10GBを超えるログファイルを表示するには?「そして質問自体には、正しいと思う自分の考えやアイデアだけが含まれています。

だから私が見つけることができる唯一の質問に答えるための1つのオプションはポケットベルを使うことです。less

less 10GBlogfile

文書(man less)には、最終的に使用できるキーがリストされており、文書を起動したら、それを使用してhヘルプ(キーと関連タスクのリスト)を取得できます。最初はG最後の行に移動し、カーソルキー(PageUp、PageDownを含む)が移動して/RE文字列を検索し、次の/前nN一致を検索しqてポケットベルを終了します。

答え3

すでに試してみましたが、split -n 20 これについて考えたことがありますか?split -n 20 --filter 'grep <whatever> or something' これにより、ソースファイルがコンポーネントに分割され、目的のコマンドに個別にパイプされます。

分割費用はそれほど高くないはずです。特に分割する場合には、基本的split --bytes=100Mには単一でseekあり、読み取り/書き込みです。しかし、UTF-8などの可変長エンコーディングをどのように処理するのかはわかりません。データがASCIIであることを知っていれば、完全に安全です。そうでなければ、同様のことをする方が良いでしょうsplit --line-bytes=<size>。ただし、これを行うと、より多くのデータを解析する必要があるため、費用がかかる可能性があります。

答え4

ログからエラーを抽出して分析したいようです。この質問に対する普遍的な答えはありません。ログファイルの特定のパターンに関連するイベントを分離する方法は、ログファイルの構造とそれを生成したエントリの性質によって完全に異なります。

特定のユーザーのログがどれくらい持続するかわかりません。

明示的(ユーザー名)または暗黙的な(セッションID、プロセスID、IPアドレス)識別子はありますか?そうでない場合は、1つが必要なように聞こえ、ログファイルを何度も繰り返して次のことを行う必要があります。

  1. エラーインスタンス、タイムスタンプ、ユーザー識別子の識別
  2. エラーではなく周辺イベントをキャプチャ

関連情報