GNU 타임 아웃과 동등한 POSIX? 시간이 너무 오래 걸리면 생략

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

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


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



답변

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

  • 백그라운드 프로세스 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