GNU 타임 아웃과 동등한 POSIX?


14

GNU coreutils timeout명령은 특정 스크립팅 상황에 매우 편리하여 명령이 빠르게 실행되면 명령 출력을 사용하고 시간이 너무 오래 걸리면 생략 할 수 있습니다.

timeoutPOSIX 지정 유틸리티 만 사용 하는 기본 동작을 어떻게 추정 할 수 있습니까?


(나는의 조합을 포함 할 수있다 생각하고 wait, sleep, kill및 그 밖의 무엇, 그러나 아마 내가 쉽게 접근 방식을 누락 알고있는 사람.)


3
쉘 스크립트에서 시간 초과를 참조하십시오 . 그러나 POSIX 이전 시스템으로의 이식성을 요청했으며 백그라운드 프로세스와 관련된 일부 솔루션이 제외하는 stdin 및 stdout을 보존해야한다는 요구 사항 때문에이를 복제본으로 간주하지 않습니다.
Gilles 'SO- 악한 중지'

command & pid=$! ; sleep 5 && kill $pid
Pandya

1
@Pandya는 경미한 경합 조건을 도입하지 않습니다. 여기서 command빠르게 완료 pid되면 kill명령이 실행 되기 전에 다른 프로세스가 시작될 가능성 이 적습니까? 나는 프로덕션 코드에서 그것을 원하지 않을 것입니다 ....
와일드 카드

해결하려는 근본적인 문제에 대해 더 자세히 설명해 주시겠습니까? 왜 timeout프로그램을 컴파일 하고 사용하지 않습니까?
James Youngman

2
@JamesYoungman, 이식성에 대한 스크립트 작성에 익숙하지 않은 것 같습니다 . POSIX 호환 (또는 POSIX 지정) 방식으로 무언가를 요청하는 것은 이식성 이 있다는 것을 의미 합니다. 바이너리로 소스 코드를 컴파일하는 것은 단호하게 이식 할 수 없습니다, 그리고 기업 보안 정책에 따라, 당신은 설치 컴파일러가 없을 수 있습니다 전혀 프로덕션 서버에 있습니다.
와일드 카드

답변:


2

내 접근 방식은 다음과 같습니다.

  • 백그라운드 프로세스 1로 명령 실행

  • 백그라운드 프로세스 2로 "워치 독 타이머"실행

  • 상위 쉘에서 종료 신호를 트랩하도록 핸들러 설정

  • 두 프로세스가 완료 될 때까지 기다리십시오. 먼저 종료되는 프로세스는 종료 신호를 부모에게 보냅니다.

  • 부모의 트랩 처리기는 작업 제어를 통해 두 백그라운드 프로세스를 모두 종료합니다 (이들 중 하나는 이미 정의에 의해 종료되었지만 PID를 사용하지 않기 때문에 해당 종료는 무해합니다. 아래 참조).

나는 시스템 PID 대신에 죽일 백그라운드 프로세스를 식별하기 위해 쉘의 작업 제어 ID (이 쉘 인스턴스 내에서 모호하지 않을 것임)를 사용하여 주석에서 해결 된 가능한 경쟁 조건을 피하려고했습니다.

#!/bin/sh

TIMEOUT=$1
COMMAND='sleep 5'

function cleanup {
    echo "SIGTERM trap"
    kill %1 %2
}

trap cleanup SIGTERM

($COMMAND; echo "Command completed"; kill $$) &
(sleep $TIMEOUT; echo "Timeout expired"; kill $$) &

wait
echo "End of execution"

결과 : TIMEOUT=10(워치 독 전에 명령이 종료 됨) :

$ ./timeout.sh 10
Command completed
SIGTERM trap
End of execution

에 대한 결과 TIMEOUT=1(워치 독이 명령 전에 종료 됨) :

$ ./timeout.sh 1
Timeout expired
SIGTERM trap
End of execution

에 대한 결과 TIMEOUT=5(워치 독과 명령이 "거의"동시에 종료 됨) :

./tst.sh 5
Timeout expired
Command completed
SIGTERM trap
End of execution

(a) 기능 정의가 있어야 cleanup() { ...; }하고 (b) 작업 제어가 POSIX에 의해 지정되지 않은 bash 기능 이기 때문에 이것은 POSIX를 준수 하지 않습니다 (ksh 및 기타 기능도 있음). 그래도 멋진 스크립트!
와일드 카드

당신은 또한 더 나은과 함께 할 수 timeout="$1"; shift(exec "$@"; echo "Command completed"; kill $$)인수 목록을 재-wordsplitting보다는.
와일드 카드
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.