파일에 가장 최근 n줄의 출력만 유지합니다.

파일에 가장 최근 n줄의 출력만 유지합니다.

분할 오류로 인해 주기적으로 충돌이 발생하는 컴퓨팅 클러스터에서 프로그램을 실행하고 있으므로 자세한 디버그 출력을 유지하여 원인을 진단하고 싶습니다. 그러나 프로그램은 충돌 없이 여러 시간 동안 실행될 수 있으므로 전체 출력을 파일로 리디렉션하는 경우 srun my-program-binary > output.log 2>&1로그 파일이 너무 커서 클러스터의 디스크 할당량을 초과하게 됩니다. 가장 최근 n 라인의 출력(예: 약 1000 라인)만 필요하므로 실행 중인 출력 버퍼를 유지하고 향후 참조를 위해 특정 시간의 최신 부분만 유지하는 방법이 있는지 궁금합니다.

클러스터에 설치할 수 있는 항목이 제한되어 있으므로 비표준 패키지가 필요하지 않은 솔루션이 필요합니다.이 솔루션마지막 부분을 유지하기 위해 파일이 생성될 때까지 기다릴 수 없기 때문에 제 경우에는 작동하지 않습니다. 특정 길이/메모리 크기를 초과하지 않는 실행 버퍼를 유지해야 합니다. 이런 일을 하는 방법을 아는 사람이 있나요?

답변1

bash, wc및 가 있는 경우 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

메모리가 1000개 정도의 행을 수용할 수 있는 경우 한 가지 접근 방식은 문제가 발생할 때까지 메모리에 행을 버퍼링하는 것입니다.

#!/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 소켓이나 웹 API를 사용하여 좋든 나쁘든 로그 출력을 다른 곳으로 보낼 수도 있습니다.

멀티플렉서

예를 들어 터미널 멀티플렉서는 tmux제한된 롤백을 제공합니다. 간단히 아래 작업을 실행 tmux한 다음 버퍼 롤백을 사용하여 설정될 때까지 로그의 마지막 몇 줄이 무엇인지 확인할 수 있습니다 history-limit.

set-option -g history-limit 1000

관련 정보