분할 오류로 인해 주기적으로 충돌이 발생하는 컴퓨팅 클러스터에서 프로그램을 실행하고 있으므로 자세한 디버그 출력을 유지하여 원인을 진단하고 싶습니다. 그러나 프로그램은 충돌 없이 여러 시간 동안 실행될 수 있으므로 전체 출력을 파일로 리디렉션하는 경우 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
프로세스가 종료되면 버퍼링된 로그 라인도 종료된다는 것입니다. 신호 처리는 이러한 극단적인 경우를 방지하는 데 도움이 될 수 있습니다. 주기적으로 디스크에 동기화하면 @buf
I/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