쉘 스크립트에서 주어진 줄을 출력 한 후 프로그램을 종료하십시오.


15

배경:

컴퓨터 생물학 소프트웨어에 대한 테스트 스크립트를 작성 중입니다. 테스트중인 소프트웨어를 실행하는 데 며칠 또는 몇 주가 걸릴 수 있으므로 시스템 충돌 또는 정전시 복구 기능이 내장되어 있습니다.

복구 시스템을 테스트하는 방법을 찾으려고합니다. 특히, 프로그램을 제어 된 방식으로 "충돌"시키는 방법을 알 수 없습니다. 어떻게 든 SIGKILL 명령의 타이밍을 일정 시간 후에 실행하려고 생각했습니다. 테스트 케이스가 매번 동일한 속도로 실행되는 것을 보장하지 않기 때문에 (적어도 공유 환경에서 실행) 로그를 원하는 출력과 비교하는 것은 어려울 수 있습니다.

이 소프트웨어는 분석의 각 섹션마다 한 줄씩 인쇄합니다.

질문:

프로그램에서 출력을 캡처하고 주어진 라인 / 라인 수가 프로그램에 의해 출력 될 때 프로그램을 죽이는 좋은 / 우아한 방법이 있는지 궁금합니다 (쉘 스크립트)?


1
특정 시간에 프로그램을 중지해야하는 이유는 무엇입니까? 출력 버퍼링으로 인해 확인중인 텍스트를 출력 한 후 프로그램이 오래 종료 될 수 있습니다.
stardt

@stardt 테스트 결과를보다 잘 제어하고 재현 할 수 있도록 특정 시간에 프로그램을 중지하고 싶었습니다. 나는 지금 이것에 대한 길을 찾았습니다. 프로그램을 수동으로 한 번만 종료 한 다음 복구 코드 만 테스트합니다. 모든 복구 시도는 같은 시점에서 시작됩니다. 나는 그것이 어떻게 결국 충돌하는지가 아니라 어떻게 회복되는지 테스트하고있다 :)
Paul

답변:


7

이와 같은 래퍼 스크립트는 표준 방식입니다. 스크립트는 백그라운드에서 프로그램을 실행 한 다음 루프를 수행하여 매분마다 로그 파일에서 문자열을 확인합니다. 문자열이 발견되면 백그라운드 프로그램이 종료되고 스크립트가 종료됩니다.

command="prog -foo -whatever"
log="prog.log"
match="this is the what i want to match"

$command > "$log" 2>&1 &
pid=$!

while sleep 60
do
    if fgrep --quiet "$match" "$log"
    then
        kill $pid
        exit 0
    fi
done

15

프로그램이 SIGPIPE (기본 조치)에서 종료되면 출력을 판독기로 파이프하여 해당 행을 읽을 때 종료됩니다.

그래서 그것은 간단 할 수 있습니다

$ program | sed -e '/Suitable text from the line/q'

기본 출력 사용을 억제하려면

$ program | sed -n -e '/Suitable text from the line/q'

마찬가지로 특정 수의 라인 이후에 멈추기를 원한다면 sed 대신 head를 사용할 수 있습니다.

$ program | head -n$NUMBER_OF_LINES_TO_STOP_AFTER

킬 (kill)이 발생하는 정확한 시간 않습니다 stardt로 터미널의 버퍼링 동작에 의존는 코멘트에 제안합니다.


-1. 여기에 심각한 결함이 있습니다. 프로그램은 종료 된 후 (깨진) 파이프에 쓰려고 할 때만 sed종료됩니다. OP는 "이 소프트웨어는 완료된 각 분석 섹션마다 한 줄을 인쇄합니다"라고 말합니다. 프로그램이 하나의 추가 섹션을 완료한다는 의미 일 수 있습니다! 개념 증명 : { echo 1; sleep 3; >&2 echo peekaboo; sleep 3; echo 2; } | sed -e '/1/q'. 이 답변을 참조하십시오 . 가능한 해결 방법 : ( program & ) | sed -e '/Suitable text from the line/q'; killall program. 귀하의 답변에 결함이 있음을 알리십시오. 나는 하향식 투표를 취소 할 것입니다.
Kamil Maciorowski

흠 ... 사실. 그리고 버퍼링 문제는 개선해도 신뢰할 수 없게 만듭니다 (물론 여기서 보는 모든 솔루션에 영향을 미칩니다). 가능한 경우 신호 인프라를 사용하고 싶지만 언젠가는 우아함을 잃기 시작합니다. 아마도 전체를 긁어내는 것이 좋습니다.
dmckee --- 전 사회자 고양이

7

dmckee의 답변에 대한 대안으로 옵션이 있는 grep명령 -m(예 : 이 매뉴얼 페이지 참조 ) 명령을 사용할 수도 있습니다.

compbio | grep -m 1 "Text to match"

텍스트와 일치하는 한 줄이 발견되면 중지하거나

compbio | grep -v -m 10 "Text to match"

주어진 텍스트와 일치하지 않는 10 줄을 기다립니다.


3

expect(1)프로그램의 표준 출력을보고 일부 패턴에 대해 사전 정의 된 동작을 실행할 수 있습니다 .

#!/usr/bin/env expect

spawn your-program -foo -bar 
expect "I want this text" { close }

또는 다른 스크립트에 임베드하기위한 하나의 라이너 :

expect -c "spawn your-program -foo -bar; expect \"I want this text\" { close }"

주의 expect명령은 기본적으로 모든 OS와 함께 제공되지 않습니다. 설치해야 할 수도 있습니다.


이것은 좋은 해결책입니다. set timeout -1무한 시간 초과를 설정하는 것이 좋습니다 . 그렇지 않으면 모두 expect기본 10 초 시간 초과로 닫힙니다 .
pepper_chico

1

"while"문을 사용할 수 있습니다.

소프트웨어 (또는 해당 로그)의 출력을 파이프 한 다음 새 줄마다 조건부 테스트를 수행 한 다음 kill -KILL을 실행해야합니다. 예를 들어 (/ var / log / messages를 로그 파일로 테스트) :

tail -f /var/log/messages | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

또는 소프트웨어로 직접 :

./biosoftware | while read line; do test "$line" = "THE LINE YOU WANT TO MATCH" && kill PIDTOKILL; done

로그 경로 / 응용 프로그램 이름, 일치하는 줄 및 죽일 PID를 교체해야합니다 (killall을 사용할 수도 있음).

소프트웨어와 함께 행운을 빌어 요

휴고,

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.