저는 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)
이건 제가 이해할 수 없는 일입니다... 사용법을 찾아봤지만 여전히 확신이 없습니다.
- 대신 스크립트를
kill -s PIPE "$!"
단축했습니다 .kill -13 $!
- 아직도 의 사용법이 헷갈립니다
{ } < <()
. 나에겐 외국어 같은 단어들인데...exec
삭제가 가능한가요 ? 안 쓰는 것과는 다른 것 같아요.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
. 위의 네 가지 질문에 대해 대략적으로 대답할 수 있습니다.
kill -15
이 명령을 추가했기 때문에 더 좋습니다timeout
.$!
응, pidtimeout
.tail -Fn 0 balabala.log
다음은 기본 번호 15를 사용하여 종료할 수 있는 하위 프로세스입니다.- 단지 프로세스 교체와 다중 프로세스 사용일 뿐입니다
{...}
.kill
1분 후에timeout
백그라운드에서 스스로 종료되기 때문에 무시할 수도 있습니다 . 따라서 이 명령은 : 없이도kill
여전히 허용됩니다sed /"$keywords"/q < <(exec timeout 1m tail -Fn 0 $log_file)
. 이 경우 항상 0을 반환합니다.- 그렇지 않은 것이 좋습니다. 명령을 실행하면 두 개의 상위 프로세스가 표시됩니다. 그런데 하고 나니 괜찮더라고요.
- 그 이유는 위의 "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
으로 종료됩니다 (실제로 발생해서는 안 됨).kill
tail
사용되면 pipefail
SIGPIPE에 의해 종료 상태가 종료되면서 종료됩니다 tail
(값이 141인 대부분의 쉘에 표시됨). || true
성공적인 종료 상태를 강제하기 위해 언제든지 a를 추가할 수 있습니다 .
또한보십시오:
답변2
내 생각에 여기서 일어나는 일은 경쟁 조건입니다. 종료로 인해 손상된 파이프 에 쓰려고 하는 SIGPIPE(보통 128+13=141 종료 상태에 해당하는 신호 13)를 수신하기 전에 추적된 PID가 종료되었는지 확인하고 인식 tail --pid=...
하십시오 . 이것tail
sed
수동단지 "프로세스가 종료된 직후 tail도 종료됩니다"라고만 나와 있으므로 확인이 자주 발생하지 않을 수 있습니다.
어쨌든 tail
SIGPIPE에 의해 종료된다면 이는 (보통) 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/bash
set -euxo pipefail
스크립트에 및 가 필요한 경우 bash
CentOS에서는 스크립트가 sh
에 연결 되지 않고 에 의해 실행되어야 합니다.bash