데이터 손실 없이 시스템 로그를 더 작은 파일로 나누는 방법

데이터 손실 없이 시스템 로그를 더 작은 파일로 나누는 방법

syslog여기서는 파일을 더 작은 덩어리로 분할 하려고 합니다 . 이를 위해 다음 스크립트를 사용합니다.

#!/bin/bash
date=$(date +%Y%m%d_%H%M)
 
cp /path/to/sys.log /path/to/chuck/file.log
cat /dev/null > /path/to/sys.log

cp /path/to/chuck/file.log /path/to/chuck/file_"$date".log
cat /dev/null > /path/to/chuck/file.log

스크립트는 5분마다 실행되며 이를 syslog더 작은 로그로 나누어 추가 처리에 사용합니다. 문제는 원본 파일과 청크 파일
에 일부 기록이 누락되어 있다는 것입니다. syslog이 문제를 해결할 방법이 있나요?

여기서 청크 파일은 약 2GB입니다. syslog성장하고 있습니다.

답변1

경고하다:이것은 작은 최대 크기와 imfile입력 모듈이 있었기 때문에 버전 8.2002에서는 완벽하게 작동하지 않았습니다. 일부 데이터는 로그 파일에서 손실되지만 문서에서는 일반적으로 작은 버퍼 크기는 지원되지 않는다고 경고합니다.


rsyslog를 사용하는 경우 로그 파일이 특정 크기를 초과할 때 회전하는 기본 제공 메커니즘을 제공합니다. 당신은 단지 채널, 파일 이름, 최대 크기 및 크기가 초과된 경우 실행할 스크립트 이름을 지정합니다. 그 다음에 사용 파일 이름 대신 필터의 채널 이름입니다.

예를 들어, /home/me/rotatescript파일이 작성된 50Mibytes를 초과할 때 스크립트를 실행 하려면 /var/log/mylog다음과 같은 이름의 채널을 생성하십시오 mylogrotatechan.

$outchannel mylogrotatechan,/var/log/mylog,52428800,/home/me/rotatescript

그리고 *.* /var/log/mylog로 교체

*.* :omfile:$mylogrotatechan

문서화되지 않은 RainerScript 구문을 사용하는 최신 소스(2023년 1월)에는 테스트 스크립트도 있습니다.

action(type="omfile" file="/var/log/mylog" rotation.sizeLimit="52428800"
       rotation.sizeLimitCommand="/home/me/rotatescript")

일반적인 스크립트는 다음과 같습니다.

#!/bin/bash
mv /var/log/mylog /var/log/mylog.$(date +%Y%m%d.%H%M%S)

답변2

나는 Perl을 사용할 것이다.파일::꼬리이 목적을 위해(나는 모니터링해야 하는 거의 모든 것, 즉 연속 테일 로그 파일에 사용합니다).

#!/usr/bin/perl

# File::Tail need to be installed from a distro package e.g. 'apt
# install libfile-tail-perl' on debian, ubuntu, mint etc or from
# CPAN https://metacpan.org/pod/File::Tail
# BTW, File::Tail has several useful options, run `man File::Tail`
# for details.
use File::Tail;

# These two need to be installed from a distro package e.g. 'apt
# install libtimedate-perl' on debian, ubuntu, mint etc or from
# CPAN https://metacpan.org/release/TimeDate
use Date::Parse;
use Date::Format;

# These two modules are included with perl
use File::Basename;
use Scalar::Util qw(openhandle);

use strict;

# $logfile is hard-coded here, but you can get it from the command line
# e.g. with something as simple as `my $logfile = shift` or use one of
# the command-line option processing modules like Getopt::Std or
# Getopt::Long
my $logfile = '/var/log/syslog';

# the output dir is hard-coded here to `chunk/` in the current dir.
# set it to whatever you want, or get it from the command line.
my $basename = './chunk/' . basename($logfile);

# open a handle to the log file.  File::Tail will automatically
# re-open the log file if it gets rotated and re-created.
my $logref=tie(*LOG,"File::Tail", (name => $logfile, tail => -1));

my ($d, $t, $t2, $outfile, $chunk);

while(<LOG>) {
  # Example of handling two different common rsyslog logfile date
  # formats.  Adjust the regex(es) to suit YOUR log file.
  if (/^([[:alpha:]]{3} \d+ \d\d:\d\d):/i) {
    # Jul 25 00:00:02 ....
    $d = $1;
  } elsif (/^(\d{4}[ T]\d\d:\d\d):/) {
    # 2023-07-25T00:00:01.737457+10:00 ....
    $d = $1;
  } else {
    die "Couldn't find a known date format in:\n$_";
  };
  $t = str2time($d);

  if ($t - $t2 >= 300) {
    close($chunk) if openhandle($chunk);
    # Alternatively, you could run your chunk processing
    # program from here:
    # (this is really basic & untested but it should work...but
    # there are better ways of handling child processes.)
    # if (openhandle($chunk)) {
    #   close($chunk);
    #
    #   $SIG{CHLD} = "IGNORE";
    #   fork;
    #   exec("myprogram", $outfile) or
    #     warn "Couldn't exec 'myprogram $outfile'\n";
    # };


    $t2 = $t;
    $d = time2str("%Y%m%d_%H%M", $t);
    $outfile = "${basename}_$d";

    # Ignore output files that already exist, so that we can
    # just re-run this script if it gets killed for some reason.
    if (! -e $outfile) {
      print "opening new output file $outfile\n";
      open($chunk, ">", $outfile) or
        die "couldn't open $outfile for write: $!\n";
    }
  };

  print $chunk $_ if openhandle($chunk);
}

예를 들어 비슷한 이름으로 저장하고 split-log-5min.pl실행 가능하게 만든 chmod +x split-log-5min.pl다음 실행하세요. 로그 파일이 종료될 때까지(예: Ctrl-C 또는 를 사용하여 kill) 또는 쓰기 위해 출력 파일을 열려고 시도하는 동안 오류가 발생할 때까지 로그 파일의 데이터를 계속 실행하고 처리합니다 .

/var/log/syslog의 발췌 부분에서 이 명령을 실행했고 결과적으로 ./chunk수많은 5분 분량의 청크가 포함된 디렉터리가 생겼습니다.

$ ls chunk/
syslog_20230725_0000  syslog_20230725_0519  syslog_20230725_1037
syslog_20230725_0007  syslog_20230725_0525  syslog_20230725_1043
syslog_20230725_0013  syslog_20230725_0531  syslog_20230725_1049
syslog_20230725_0019  syslog_20230725_0537  syslog_20230725_1055
[...many more deleted]
syslog_20230725_0455  syslog_20230725_1013  syslog_20230725_1531
syslog_20230725_0501  syslog_20230725_1019  syslog_20230725_1537
syslog_20230725_0507  syslog_20230725_1025
syslog_20230725_0513  syslog_20230725_1031

그런데, 5분 단위로 처리하는 내용에 따라 해당 단위를 별도의 파일에 복사하지 않고도 이 스크립트에서 처리할 수 있습니다. 예를 들어 파일에 쓰는 대신 각 줄을 배열에 추가한 다음 5분마다 배열을 처리하고 지웁니다.

관련 정보