로그 유틸리티 키워드 검색 또는 시간 초과 추적

로그 유틸리티 키워드 검색 또는 시간 초과 추적

저는 Google에 액세스할 수 있는 특별한 방법을 사용하고 있습니다. 이제 페이지가 많이 달라졌습니다. 따라서 정상적으로 질문을 편집하고 답변에 댓글을 달 수 있습니다. 이전 토론을 더 삭제하고 요점을 정리했습니다.

스크립트가 다음 명령을 실행하는 키워드를 찾으면 테일링을 중지하고 0을 반환하고 싶습니다. 1분 후에도 키워드를 찾을 수 없으면 전체 스크립트가 중지되고 오류 코드가 반환됩니다. set -euxo pipefail꼭 필요해서 사용하고 있습니다 .

timeout 1m tail -Fn 0 --pid=$(ps -ef | grep "sed /$keywords" | grep -v grep | awk '{print $2}') $log_file | sed "/$keywords/q"

이전에 사용한 위 명령은 테스트할 때 제대로 연결되었습니다. 그러나 Jenkins에서는 키워드가 발견되면 "빌드 단계 '쉘 실행'이 빌드를 실패로 표시했습니다."를 반환하는 경우가 있습니다.

프로그램을 수동으로 다시 시작한 후 원인을 찾았습니다. 코드 141을 반환합니다. 그래서 코드를 확인해 보니 tail -f파이프라인과 관련이 있는 것으로 나타났습니다 |.http://www.pixelbeat.org/programming/sigpipe_handling.html.


내 목적을 위해 다른 질문의 명령을 수정했습니다. "tail -Fn 0 balabala.log"가 여전히 백그라운드에 남아 있고 몇 분 후에 사라지는 것을 제외하면 모든 것이 괜찮아 보입니다. 하지만 목표에 가장 가깝습니다.

{ sed /"$keywords"/q; kill -13 $!; } < <(exec timeout 1m tail -Fn 0 $log_file)

이건 제가 이해할 수 없는 일입니다... 사용법을 찾아봤지만 여전히 확신이 없습니다.

  1. 대신 스크립트를 kill -s PIPE "$!"단축했습니다 .kill -13 $!
  2. 아직도 의 사용법이 헷갈립니다 { } < <(). 나에겐 외국어 같은 단어들인데...
  3. exec삭제가 가능한가요 ? 안 쓰는 것과는 다른 것 같아요.
  4. tail이면에 문제가 있는 걸까요? 동시에 여러 프로그램을 시작하면 위험합니까?

Jenkins 로그는 다음과 같습니다.

......
+ keywords='cloud-service-notice has been started successfully'
+ log_file=/data/jars/logs/info.cloud-service-notice.log
+ cd /data/jars/cloud-service-notice
+ nohup java -jar /data/jars/cloud-service-notice/cloud-service-notice.jar --spring.profiles.active=test
+ sed '/cloud-service-notice has been started successfully/q'
++ exec timeout 1m tail -Fn 0 /data/jars/logs/info.cloud-service-notice.log
2019-07-02 10:31:12,544 [main] INFO  o.s.c.a.AnnotationConfigApplicationContext.prepareRefresh[588] - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@54a097cc: startup date [Tue Jul 02 10:31:12 CST 2019]; root of context hierarchy
......
2019-07-02 10:31:33,860 [main] INFO  c.enneagon.service.notice.NoticeApp.main[24] - cloud-service-notice has been started successfully
+ kill -13 20021
+ ssh web01 'cd /data/releases/cloud-service-notice/20190702-104108/.. &&' 'ls -1 | sort -r | awk '\''FNR > 20  {printf("rm -rf %s\n", $0);}'\'' | bash'
Finished: SUCCESS

프로세스 20021은 입니다 timeout 1m tail -Fn 0 balabala.log. 스크립트가 완료된 후에도 프로세스 20023이 tail -Fn 0 balabala.log여전히 존재하고 몇 분 후에 사라졌습니다.

[root@web01 scripts]# ps -ef | grep notice
root     20020     1 27 10:41 ?        00:01:07 java -jar /data/jars/cloud-service-notice/cloud-service-notice.jar --spring.profiles.active=test
root     20023     1  0 10:41 ?        00:00:00 tail -Fn 0 /data/jars/logs/info.cloud-service-notice.log
root     20461 18966  0 10:45 pts/1    00:00:00 grep --color=auto notice

이 명령으로 내 질문에 대답하고 싶지만 확실하지 않습니다. 로컬 컴퓨터에서 테스트한 후 추가 테스트를 위해 프로덕션 환경에 배치했습니다.


많은 테스트 끝에 마침내 명령을 다음과 같이 변경했습니다.

{ sed /"$keywords"/q; kill $!; } < <(exec timeout 1m tail -Fn 0 $log_file)

-13방금 삭제했습니다. 그렇기 때문에 머무르는 것입니다 tail -Fn 0 balabala.log. 위의 네 가지 질문에 대해 대략적으로 대답할 수 있습니다.

  1. kill -15이 명령을 추가했기 때문에 더 좋습니다 timeout. $!응, pid timeout. tail -Fn 0 balabala.log다음은 기본 번호 15를 사용하여 종료할 수 있는 하위 프로세스입니다.
  2. 단지 프로세스 교체와 다중 프로세스 사용일 뿐입니다 {...}. kill1분 후에 timeout백그라운드에서 스스로 종료되기 때문에 무시할 수도 있습니다 . 따라서 이 명령은 : 없이도 kill여전히 허용됩니다 sed /"$keywords"/q < <(exec timeout 1m tail -Fn 0 $log_file). 이 경우 항상 0을 반환합니다.
  3. 그렇지 않은 것이 좋습니다. 명령을 실행하면 두 개의 상위 프로세스가 표시됩니다. 그런데 하고 나니 괜찮더라고요.
  4. 그 이유는 위의 "1"에 있습니다. timeout살해당했지만 tail남겨졌습니다.

답변1

다음을 수행할 수 있습니다.

sh -c 'echo "$$"; exec tail -f file' | (
  IFS= read -r pid
  timeout 60 sed "/$keyword/q"
  kill -s PIPE "$pid"
)

해당 옵션을 활성화하지 않으면 자체적으로 종료 되지 않는 한 종료 상태가 0 pipefail으로 종료됩니다 (실제로 발생해서는 안 됨).killtail

사용되면 pipefailSIGPIPE에 의해 종료 상태가 종료되면서 종료됩니다 tail(값이 141인 대부분의 쉘에 표시됨). || true성공적인 종료 상태를 강제하기 위해 언제든지 a를 추가할 수 있습니다 .

또한보십시오:

답변2

내 생각에 여기서 일어나는 일은 경쟁 조건입니다. 종료로 인해 손상된 파이프 에 쓰려고 하는 SIGPIPE(보통 128+13=141 종료 상태에 해당하는 신호 13)를 수신하기 전에 추적된 PID가 종료되었는지 확인하고 인식 tail --pid=...하십시오 . 이것tailsed수동단지 "프로세스가 종료된 직후 tail도 종료됩니다"라고만 나와 있으므로 확인이 자주 발생하지 않을 수 있습니다.

어쨌든 tailSIGPIPE에 의해 종료된다면 이는 (보통) sed원하는 라인을 얻었고 종료했다는 의미입니다.반품성공의 조건이 되십시오. if방지하기 위해 블록을 사용 set -e하고 종료 상태를 명시적으로 확인하여 정확히 동일하게 처리하는 것이 좋습니다 .

if timeout tail ... | sed ...; ret=$?; then
    : # do nothing, success
elif [ "$ret" != 141 ]  # not sigpipe, sed didn't quit, so failure
    exit "$ret"
fi

내레이터 : 스크립트 가 #/bin/bash. 이것이 없으면 스크립트는 sh를 사용하여 실행될 것이며 아마도 프로세스 대체를 사용하려고 하는 이유일 것입니다( 예#!#<(...)프로세스, 명령이 아니라 대체)는 구문 오류입니다. 주의 깊게 확인하십시오.

단일 라이너를 원한다고 말씀하셨지만, 복잡한 단일 라이너가 서비스 가능성 측면에서 항상 최선의 솔루션은 아닙니다. 수행 중인 작업을 더 쉽게 기록하려면 여러 줄을 사용하세요.

답변3

명령어를 찾았습니다. 세부 사항은 질문에 있습니다.

{ sed /"$keywords"/q; kill $!; } < <(exec timeout 1m tail -Fn 0 $log_file)

#!/bin/bashset -euxo pipefail스크립트에 및 가 필요한 경우 bashCentOS에서는 스크립트가 sh에 연결 되지 않고 에 의해 실행되어야 합니다.bash

관련 정보