블록 버퍼링 없이 표준 출력을 압축하는 방법

블록 버퍼링 없이 표준 출력을 압축하는 방법

나는 이것을 시도했다

myprogram | gzip > /var/log/mylog.log

제가 이해한 바에 따르면 로그 파일은 전체 gzip 청크(32kB인 것 같습니다)가 생성될 때만 기록됩니다. 이로 인해 디스크에 쓸 때 상당한 대기 시간이 발생할 수 있습니다. 시스템이 충돌하면 로그의 마지막 부분이 손실됩니다.

바이트가 도착하자마자 압축하고 쓰는 gzip의 대안이 있습니까? 블록 기반이 아닌 바이트 스트림 기반의 압축 알고리즘도 있는 것 같은데 그런 도구가 있는지는 찾아볼 수 없습니다.

답변1

제가 이해한 바에 따르면 로그 파일은 전체 gzip 청크(32kB인 것 같습니다)가 생성될 때만 기록됩니다.

음, 압축기의 임무는 많은 비트를 취하고 더 적은 비트를 생성하는 것입니다. 따라서 일부 블록별 작업은 기본적으로 고유합니다. 마지막으로 Lempel-Ziv와 유사한 모든 것(gzip과 같지만 대부분의 다른 압축기와 유사)은 코드북에서 기호를 찾는 작업을 수행합니다. 코드북과의 일치가 완료될 때까지 기호가 발견되었는지 여부를 알 수 있습니다.

이는 코드북의 주기적인 재설정과 결합되어 상대적으로 고정된 블록 길이를 가져옵니다. (예: gzip에서는 블록 크기를 선택할 수 없습니다. 블록 크기 선택은 gzip 압축 방법에 내재되어 있습니다.)

  • gzip다음보다 약간 덜 오래된 것을 사용할 수 있습니다. 어쩌면 xz이것이 --flush-timeout당신이 정말로 찾고 있는 것일 수도 있습니다.

  • 32kB가 "많은 로그"로 보인다면 압축이 전혀 필요하지 않은 것일까요? 실제로 logrotate와 같은 메커니즘은 정확히 이 경로를 따릅니다. 즉, 몇 메가바이트마다 새 로그로 전환하고(최신 컴퓨터에는 데이터가 많지 않음) 오래된 파일만 압축합니다.

  • 또한 평균 파일 시스템 및 블록 장치 계층 버퍼는 32kB보다 훨씬 큽니다. 파일 시스템을 fsync 마운트 모드로 유지해야 하며, 그럼에도 불구하고 저장 장치의 물리적 블록이 실제로 항상 저장 매체에 플러시되면 Smaller가 4kB(또는 그 배수)가 될 수 있다는 점을 잊지 마십시오. 성능에 심각한 영향을 미칠 수 있습니다.

답변2

많은 솔루션이 있으며 대부분 자체 압축 도구를 작성해야 합니다(더 자주 작성하도록 설정 - Lempel-Ziv 기반 도구는 스트림에 쓸 수 있지만 전체 바이트 쓰기로만 제한됩니다. LZ 스트림은 일반적으로 다른 비트 길이 마커이므로 8비트 경계에 있지는 않지만 여전히 부분 바이트인 끝에 있는 부분을 제외하고 언제든지 압축된 모든 것을 쓸 수 있습니다. 그러나 이는 다소 고통스러운 방법이다.

더 간단한 접근 방식이지만 2개의 "부분"이 필요합니다.

myprogram | split -u -l 1M -d /var/log/myprogram.log

이렇게 하면 항상 최신 상태를 유지하고 1MB를 초과하지 않는 일련의 로그 파일이 생성됩니다.

그런 다음 프로그램을 사용하여 새 로그 파일이 더 이상 열리지 않는 시기를 모니터링하고 압축한 다음 삭제할 수 있습니다.

최신 로그 정보는 항상 즉시 사용할 수 있으며 로그 파일은 1MB보다 크지 않습니다. gzip은 "오래된" 파일을 삭제하기 전에 항상 압축을 완료하므로 로그 정보가 손실되지 않습니다.

#!/bin/sh

while true; do
  for file in /var/log/myprogram.log*[^z]; do
    proc_count=$(lsof -t "$file" | wc -l)
    if (( $proc_count == 0 )); then
      gzip "$file"
    fi
  done
  sleep 1
done

가장 좋은 해결책은 두 가지 작업을 모두 수행하는 프로그램이 될 것입니다. 귀하의 게시물을 찾았고 동일한 것을 원하기 때문에 이를 작성할 수 있습니다.

관련 정보