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

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

표준 출력에서 ​​많은 출력을 생성하는 장기 실행 명령이 있습니다. 예를 들어, 지난 3일 또는 지난 1GB만 보존하고(행이 중간에 잘리지 않도록) 가능하다면 파일 블록을 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크론 작업 설정, 규칙 지정, 프로세스 일시 중지 등이 필요하지 않은 더 간단한 것을 찾고 있습니다.

답변1

당신은 당신이 원하는 것을 얻을 수 있습니다파이프라인 로그, 이는 "실행 중인 프로세스의 로그를 외부 신호에 응답하는 중간체를 통해 회전하거나 지울 수 있도록 허용합니다." 예를 들면 다음과 같습니다.

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

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

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

하지만 cron과 같은 것을 사용하여 설정해야 합니다. 그러나 문제가 있습니다. 참고하세요 gzip spew.log.1. 이는 -x로그 회전 후에 명령이 실행되기 때문입니다. 따라서 spew.log.1.gzgzip을 수행하고 이후에 파일을 이동하는 짧은 스크립트를 작성하고 이를 명령으로 사용하지 않는 한 -x덮어쓸 때마다 추가 문제가 발생합니다.

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

그 목적은 다음과 같습니다.텍스트-z출력; 잠재적인 null 바이트가 있는 경우 0을 다른 것으로 바꾸는 --를 사용해야 합니다 . 이는 구현을 단순화하기 위한 절충안입니다.

답변2

댄 번스타인의다중 로그파일 설명자를 통해 콘센트를 제공하면서 그렇게 하는 것이 분명히 가능합니다. 또는 대부분의 경우일 수도 있습니다.! 프로세서원하는 대로 차이점을 구성하세요. 20M/1G 크기 사양에는 약간의 부정 행위가 필요할 수 있지만 16M이 각 로그의 외부 한계인 것처럼 보입니다. 다음의 대부분은 위 링크에서 복사+붙여넣기를 선택하는 것입니다. 단, 해당 링크는 최신 행 일치 항목만 포함하는 추가 파일을 유지하는 행별 타임스탬프와 같은 다른 옵션도 자세히 설명합니다.무늬그리고 더.

상호 작용

 multilog script

...스크립트다양한 매개변수로 구성됩니다. 각 매개변수는 작업을 지정합니다. 각 입력 줄에 대해 이러한 작업을 순차적으로 수행합니다.

라인 선택

각 행은 처음에 선택됩니다. 그 행동...

-pattern

...패턴이 행과 일치하는 경우 행을 선택 취소합니다. 그 행동...

+pattern

다음과 같은 경우 행을 선택하세요.무늬행과 일치합니다.

...무늬별과 별이 아닌 문자열입니다. 동일한 순서로 일치하는 모든 별표 및 별표가 아닌 문자로 구성된 모든 문자열 연결과 일치합니다. 별이 아닌 사람들은 자신과 일치합니다. 패턴 끝 앞의 별표는 패턴의 다음 문자를 포함하지 않는 모든 문자열과 일치합니다. 패턴 끝에 있는 별표는 모든 문자열과 일치합니다.

로그 자동 순환

만약에목차점이나 슬래시로 시작한 다음...

 dir

...선택한 각 행을 다음 이름의 로그에 추가합니다.목차. 만약에목차존재하지 않는 경우 multilog작성하십시오.

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

  1. 목차특정 개수의 오래된 로그 파일이 포함된 디렉터리입니다. 로그 파일의 이름은 다음과 같습니다.현재의multilog및 작업을 추적하는 데 사용되는 기타 파일입니다.

  2. 각 이전 로그 파일의 이름은 다음으로 끝납니다.@, 파일이 완료된 정확한 타임스탬프를 표시하고 다음 코드 중 하나로 끝납니다.

    • .에스: 이 파일은 완전히 처리되어 디스크에 안전하게 기록되었습니다.
    • .유: 이 파일은 중단 당시 생성되었습니다. 잘렸을 수도 있습니다. 아직 처리되지 않았습니다.

그 행동...

 ssize

...이후 최대 파일 크기 설정목차행동. multilog결정할 것이다현재의그렇다면 충분히 크다현재의가지다크기바이트.( multilog또한 최대 파일 크기의 2000바이트 이내에서 개행 문자가 보이면 current가 충분히 큰 것으로 판단합니다. 라인 경계에서 로그 파일을 완성하려고 시도합니다.)4096에서 16777215 사이여야 합니다. 기본 최대 파일 크기는 99999입니다.

0.75 이상: multilog받은 경우경보신호를 보내면 즉시 결정됩니다.현재의그렇다면 충분히 크다현재의비어 있지 않습니다.

(참고: 원하는 경우 지정된 간격으로 전송 zsh schedule하도록 내장 기능을 쉽게 설득할 수 있을 것으로 생각됩니다.)ALRM

그 행동...

 nnum

...후속 로그 파일 수 설정목차행동. 이름을 바꾼 후현재의, multilog네가 본다면일련번호또는 더 많은 오래된 로그 파일을 사용하면 타임스탬프가 가장 작은 오래된 로그 파일이 삭제됩니다.일련번호2개 이상이어야 합니다. 기본 로그 파일 수는 10입니다.

그 행동...

 !processor

...다음 작업을 위해 프로세서를 설정합니다.목차행동. multilog먹일 수 있다현재의통과하다프로세서출력을 대신 이전 로그 파일로 저장합니다.현재의. multilog프로세서가 설명자 5에 쓴 모든 출력은 프로세서가 다음 로그 파일에서 실행될 때 설명자 4에서 저장되고 읽을 수 있게 됩니다. 신뢰성을 위해,프로세서출력을 생성하는 동안 문제가 발생하면 0이 아닌 값으로 종료해야 합니다. multilog그런 다음 다시 실행됩니다. 실행중이니 참고하세요프로세서프로그램이 입력을 제공하지 못하게 할 수 있습니다 multilog.

답변3

다음은 귀하가 요청한 것과 같은 작업을 수행하도록 수정된 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)

답변4

systemd가 있는 Linux에서는 루트 권한이 있으면 전용통나무예. LogNamespace=유닛 파일에 있어야 합니다.

/etc/systemd/[email protected]:

[Journal]
Storage=volatile
RuntimeMaxUse=20M

/etc/systemd/system/myprogram.service:

[Unit]
Description=My Test Service
[Service]
ExecStart=/home/myuser/myprogram
LogNamespace=myprogram
User=myuser

_

systemctl daemon-reload
systemctl start myprogram
journalctl --namespace=myprogram --follow

바라보다https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html#Journal%20Namespaces

관련 정보