명령의 출력을 링 버퍼에 저장


16

stdout에서 많은 출력을 생성하는 장기 실행 명령이 있습니다. 예를 들어 마지막 3 일 또는 마지막 기가 바이트 (가운데 절단 선을 피함) 만 가능하고 가능한 경우 20MiB보다 크지 않은 파일 청크를 유지할 수 있기를 원합니다. 각 파일 청크에는 숫자 접미사 또는 타임 스탬프가 지정됩니다.

다음과 같은 것 :

my-cmd | magic-command --output-file-template=my-cmd-%t \
                       --keep-bytes=1G \
                       --keep-time=3d \
                       --max-chunk-size=20M \
                       --compress=xz

쓸 것이다 :

my-cmd-2014-09-05T10:04:23Z

20M에 도달하면 압축하여 새 파일을 여는 등의 작업을 수행하며 잠시 후 가장 오래된 파일을 삭제하기 시작합니다.

그러한 명령이 있습니까?

logrotate다른 응용 프로그램에서 작성한 파일을 관리하는 기능을 알고 있지만 크론 작업을 설정하고 규칙을 지정하고 프로세스를 일시 중단하지 않아도되는 더 간단한 것을 찾고 있습니다.


"기비 바이트"란 무엇입니까?
Peter Mortensen

답변:


6

pipelog 를 통해 원하는 것을 얻을 수 있습니다. "실행중인 프로세스의 로그를 외부 신호에 응답하는 중간체를 통해 파이프하여 회전하거나 지울 수 있습니다":

spewstuff | pipelog spew.log -p /tmp/spewpipe.pid -x "gzip spew.log.1"

그런 다음에서 pid를 얻을 수 있습니다 /tmp/spewpipe.pid.

kill -s USR1 $(</tmp/spewpipe.pid)

그러나 당신은 cron 또는 무언가로 설정해야합니다. 그러나 여기에는 한 가지 문제점이 있습니다. 통지 I- gzip spew.log.1이것은 -x로그가 회전 된 후 명령이 실행 되기 때문 입니다. 따라서 spew.log.1.gzgzip을 수행하고 파일을 나중에 이동하기 위해 짧은 스크립트를 작성하고 -x명령 으로 사용하지 않는 한 매번 덮어 쓰기 문제가 발생 합니다 .

전체 공개 : 나는 이것을 썼으므로 물론 완벽하게 작동 합니다 . ;) 버전 0.2의 경우 압축 옵션 또는 더 나은 방법을 염두에 두겠습니다 (의도 된 목적 -x은 다소 다르지만 위와 같이 작동합니다). 또한 자동 롤오버는 좋은 생각입니다 ... 첫 번째 버전은 필요하지 않은 기능을 추가하려는 유혹에 저항했기 때문에 의도적으로 최소화되었습니다 (결국 크론 작업을 설정하는 것은 그리 어렵지 않습니다).

이를 위해 의도 있습니다 텍스트 출력; 잠재적 인 null 바이트가있는 경우 -z-를 0으로 대체 해야합니다 . 이는 구현을 단순화하기위한 절충안이었습니다.


감사. pipelog-0.3;-) 를 기대하고 있습니다. metacpan.org/release/File-Write-Rotate 도 발견 했습니다 . 크론 작업은 파일 크기를 기준으로 회전하는 데별로 도움이되지 않습니다.
Stéphane Chazelas

크기를 기준으로 회전!?! 출력을 플러시 상태로 유지하므로 파일을 주기적으로 통계 할 수 있습니다.
goldilocks

그런 식으로 (내 질문 요구 사항에서와 같이) 크기를 20M 미만으로 유지할 수 없었습니다.
Stéphane Chazelas

다른 것은 거의 텍스트 일뿐입니다 (마지막 단락을 추가했습니다).
goldilocks

4

Dan Bernstein의 멀티 로그 는 분명히이 작업을 수행 할 수 있습니다. 또는 아마도 대부분의 경우, 파일 디스크립터를 통해 ! processor 에 콘센트를 제공하여 원하는대로 차이를 만들 수 있습니다.하지만 20M / 1G 크기 사양은 16M이 로그 당 외부 한계. 다음은 대부분 위의 링크에서 복사 + 붙여 넣기를 선택하는 것입니다. 그러나 링크에는 라인 당 타임 스탬프, 가장 최근의 라인 매칭 패턴 만 포함하는 다른 파일을 유지하는 등의 다른 옵션도 자세히 설명 되어 있습니다. .

상호 작용

 multilog script

... 스크립트 는 여러 개의 인수로 구성됩니다. 각 인수는 하나의 동작을 지정합니다. 조치는 각 입력 행에 대해 순서대로 수행됩니다.

라인 선택

각 줄이 처음에 선택됩니다. 행동 ...

-pattern

... 패턴이 선과 일치하면 선을 선택 해제합니다. 행동 ...

+pattern

패턴 이 선과 일치하면 선을 선택합니다 .

... 패턴 은 별과 별이 아닌 문자열입니다. 모든 별과 비 별이 일치하는 문자열을 동일한 순서로 연결합니다. 별이 아닌 별은 그 자체와 일치합니다. 패턴 끝 앞의 별은 패턴에 다음 문자가 포함되지 않은 문자열과 일치합니다. 패턴 끝의 별은 모든 문자열과 일치합니다.

자동 회전 로그

경우 디렉토리 또는 점으로 시작되면 다음 작업을 슬래시 ...

 dir

... 선택한 각 줄을 dir 이라는 로그에 추가합니다 . 경우 디렉토리가 존재하지 않는 multilog파일을 작성합니다.

로그 형식은 다음과 같습니다.

  1. dir 은 몇 개의 오래된 로그 파일, current 라는 로그 파일 및 multilog작업을 추적 하기위한 기타 파일을 포함하는 디렉토리 입니다.

  2. 각 이전 로그 파일의 이름은 @로 시작 하여 파일이 완료된 시간을 나타내는 정확한 타임 스탬프를 유지하고 다음 코드 중 하나로 끝납니다.

    • .s :이 파일은 완전히 처리되어 안전하게 디스크에 기록됩니다.
    • .u :이 파일은 정전시 작성되었습니다. 잘 렸을 수 있습니다. 처리되지 않았습니다.

행동 ...

 ssize

... 이후의 dir 조치에 대한 최대 파일 크기를 설정합니다 . multilog그 결정합니다 현재하는 경우 큰 충분한 전류크기 바이트. ( multilog최대 파일 크기의 2000 바이트 내에 줄 바꿈이 표시되면 현재가 충분히 큰 것으로 결정합니다. 로그 파일을 줄 경계에서 마무리하려고 시도합니다.) 크기 는 4096과 16777215 사이 여야합니다 . 기본 최대 파일 크기는 99999입니다.

버전 0.75 이상에서 다음과 같은 경우는 multilog수신 ALRM의 신호를 즉시 그 결정 전류가 있는 경우, 큰 충분한 전류가 비어 있지 않은 것입니다.

(참고 : 필요한 경우 zsh schedule내장 ALRM을 지정된 간격 으로 보내도록 쉽게 설득 할 수 있다고 생각합니다 .)

행동 ...

 nnum

... 이후의 dir 조치에 대한 로그 파일 수를 설정합니다 . current로 이름을 바꾼 후 오래된 로그 파일 multilognum 개 이상 이면 타임 스탬프가 가장 작은 오래된 로그 파일을 제거합니다. num 은 2 이상이어야합니다. 기본 로그 파일 수는 10입니다.

행동 ...

 !processor

... 이후의 dir 동작을 위한 프로세서를 설정합니다 . 프로세서를 통해 전류multilog공급하고 current 대신 current 로그 파일로 출력을 저장합니다 . 또한 프로세서가 디스크립터 5에 쓰는 출력을 저장하고 다음 로그 파일에서 프로세서를 실행할 때 디스크립터 4에서 해당 출력을 읽을 수있게합니다. 안정성을 위해 프로세서 는 출력 작성에 문제가있는 경우 0이 아닌 값을 종료해야합니다. 그런 다음 다시 실행합니다. 실행중인 프로세서 는에 대한 모든 프로그램 공급 입력을 차단할 수 있습니다 .multilogmultilogmultilog


2

거대한 코드 조각을 작성하지 않는 근사치까지 내가 찾을 수있는 가장 좋은 것은이 zsh코드입니다.

autoload zmv
mycmd |
  while head -c20M > mycmd.log && [ -s mycmd.log ]; do
    zmv -f '(mycmd.log)(|.(<->))(|.gz)(#qnOn)' '$1.$(($3+1))$4'
    {rm -f mycmd.log.1 mycmd.log.50.gz; (gzip&) > mycmd.log.1.gz} < mycmd.log.1
  done

최대 51 20MiB 큰 파일로 분할 및 회전합니다.


아마도 ... 루프 마운트? btrfs로 장착 할 수도 있습니다 compress-force=zlib.
mikeserv

2

다음은 요청한 것과 같은 작업을 수행하는 해킹 된 Python 스크립트입니다.

#!/bin/sh
''':'
exec python "$0" "$@"
'''

KEEP = 10
MAX_SIZE = 1024 # bytes
LOG_BASE_NAME = 'log'

from sys import stdin
from subprocess import call

log_num = 0
log_size = 0
log_name = LOG_BASE_NAME + '.' + str(log_num)
log_fh = open(log_name, 'w', 1)

while True:
        line = stdin.readline()
        if len(line) == 0:
                log_fh.close()
                call(['gzip', '-f', log_name])
                break
        log_fh.write(line)
        log_size += len(line)
        if log_size >= MAX_SIZE:
                log_fh.close()
                call(['gzip', '-f', log_name])
                if log_num < KEEP:
                        log_num += 1
                else:
                        log_num = 0
                log_size = 0
                log_name = LOG_BASE_NAME + '.' + str(log_num)
                log_fh = open(log_name, 'w', 1)

1
또는 hashbang exec을 사용하는 대신 파이썬을 첫 번째 로 사용하는 쉘 스크립트로 사용해야 할 이유가 있습니까? pythonenv python
peterph 2014 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.