수신하는 애플리케이션을 종료하지 않고 Linux tee 명령을 종료하는 방법

수신하는 애플리케이션을 종료하지 않고 Linux tee 명령을 종료하는 방법

Linux 시스템의 전원이 켜질 때마다 실행되는 bash 스크립트가 있습니다. 나는 다음과 같이 시작합니다.

( /mnt/apps/start.sh 2>&1 | tee /tmp/nginx/debug_log.log ) &

시작한 후 내 창에서 tee 명령을 볼 수 있습니다.메모출력은 아래와 같습니다.

$ ps | grep tee
  418 root       0:02 tee /tmp/nginx/debug_log.log
3557 root       0:00 grep tee

로그 크기를 모니터링하는 기능이 있습니다산란하고 죽인다로그가 특정 크기에 도달하면 다음 명령을 실행합니다.

monitor_debug_log_size() {
                ## Monitor the file size of the debug log to make sure it does not get too big
                while true; do
                                cecho r "CHECKING DEBUG LOG SIZE... "
                                debugLogSizeBytes=$(stat -c%s "/tmp/nginx/debug_log.log")
                                cecho r "DEBUG LOG SIZE: $debugLogSizeBytes"
                                if [ $((debugLogSizeBytes)) -gt 100000 ]; then
                                                cecho r "DEBUG LOG HAS GROWN TO LARGE... "
                                                sleep 3
                                                #rm -rf /tmp/nginx/debug_log.log 1>/dev/null 2>/dev/null
                                                kill -9 `pgrep -f tee`
                                fi
                                sleep 30
                done
}

놀랍게도 살해당함명령은 start.sh 인스턴스를 통해서도 종료됩니다. 왜 이런거야? 어떻게 끝낼 수 있어?명령을 실행했는데 start.sh가 계속 실행되나요? 감사해요.

답변1

종료 되면 tee주어진 명령은 더 많은 출력 쓰기를 시도할 때까지 계속 실행됩니다. 그런 다음 판독기가 없는 파이프에 쓰기를 시도하면 SIGPIPE(대부분의 시스템에서 13개)를 수신합니다.

SIGPIPE를 포착하도록 스크립트를 수정하고 적절한 조치(예: 출력 쓰기 중지)를 취하면 티가 종료된 후에도 계속할 수 있습니다.


죽이는 것보다 낫다tee 그래도,logrotate단순화를 위해 options 와 함께 사용됩니다 copytruncate.

견적으로 이동logrotate(8):

copytruncate

이전 로그 파일을 이동하고 새 로그 파일을 생성하도록 선택하는 대신 복사본을 생성한 후 원본 로그 파일을 자릅니다. 일부 프로그램에서 로그 파일을 닫으라고 지시할 수 없어 이전 로그 파일에 영원히 계속해서 쓸(추가) 수 있는 경우에 사용할 수 있습니다. 파일 복사와 자르기 사이의 시간 간격은 매우 짧으므로 일부 로깅 데이터가 손실될 수 있습니다. 이 옵션을 사용하면 이전 로그 파일이 그대로 유지되므로 만들기 옵션이 적용되지 않습니다.

답변2

이유를 설명해라"

간단히 말해서: 쓰기가 실패하는 경우아니요프로그램이 종료되고 (기본적으로) 혼란스러워집니다. 생각해 보십시오 . 필요한 10개 행을 가져와서 계속 진행한 후에 하드 드라이브의 나머지 부분을 검색하면서 계속 실행하고 find . | head -n 10싶지는 않을 것입니다 .findhead

더 나은 방법: 레코더 내부 회전

tee전혀 사용되지 않는 다음 예를 고려하십시오 .

#!/usr/bin/env bash

file=${1:-debug.log}                     # filename as 1st argument
max_size=${2:-100000}                    # max size as 2nd argument
size=$(stat --format=%s -- "$file") || exit  # Use GNU stat to retrieve size
exec >>"$file"                           # Open file for append

while IFS= read -r line; do              # read a line from stdin
  size=$(( size + ${#line} + 1 ))        # add line's length + 1 to our counter
  if (( size > max_size )); then         # and if it exceeds our maximum...
    mv -- "$file" "$file.old"            # ...rename the file away...
    exec >"$file"                        # ...and reopen a new file as stdout
    size=0                               # ...resetting our size counter
  fi
  printf '%s\n' "$line"                  # regardless, append to our current stdout
done

다음과 같이 실행하는 경우:

/mnt/apps/start.sh 2>&1 | above-script /tmp/nginx/debug_log

...파일을 추가하는 것으로 시작하고 내용이 100KB를 초과하면 /tmp/nginx/debug_log파일 이름을 바꿉니다 . /tmp/nginx/debug_log.old로거 자체가 회전을 수행하므로 회전이 발생하는 동안 파이프 손상, 오류 및 데이터 손실 창이 없습니다. 모든 라인은 한 파일 또는 다른 파일에 기록됩니다.

물론 이를 네이티브 bash에서 구현하는 것은 비효율적이지만 위의 내용은 예시입니다.위의 논리를 구현할 수 있는 프로그램이 많이 있습니다. 고려하다:

  • svlogd, Runit 제품군의 서비스 로거입니다.
  • s6-log, skanet 제품군의 적극적으로 유지 관리되는 대안입니다.
  • multilog프로세스 감독 및 모니터링 도구 제품군의 창시자인 DJB Daemontools에서 제공됩니다.

관련 정보