쉘 스크립팅에 타임 아웃을 도입하는 방법은 무엇입니까?


35

루프가있는 쉘 스크립트를 실행하고 싶지 않으며 영원히 원하지 않는 곳으로 갈 수 있습니다. 따라서 전체 스크립트에 대한 시간 초과를 소개해야합니다.

SuSE에서 전체 셸 스크립트에 타임 아웃을 어떻게 도입 할 수 있습니까?


4
이것은 매우 모호한 질문입니다. 어떤 종류의 타임 아웃에 대해 자세히 설명해 주시겠습니까? 전체 스크립트에서 시간 초과를 원하십니까, 단일 기능 또는 명령에서 시간 초과를 원하십니까? 무엇을하려고합니까?
팀 케네디

@ TimKennedy : 더 나아지기를 바랍니다.
Radek

1
참고 쉘 스크립트에서 타이밍 (I 때문에 내 이동성 요구 사항의 그것을 중복을 고려하지 않는 등 제외 도구 timeoutexpect)
질 'SO-정지되는 악'

답변:


30

GNU timeout를 사용할 수없는 경우 사용할 수 있습니다 expect(Mac OS X, BSD, ... 일반적으로 기본적으로 GNU 도구 및 유틸리티는 없음).

################################################################################
# Executes command with a timeout
# Params:
#   $1 timeout in seconds
#   $2 command
# Returns 1 if timed out 0 otherwise
timeout() {

    time=$1

    # start the command in a subshell to avoid problem with pipes
    # (spawn accepts one command)
    command="/bin/sh -c \"$2\""

    expect -c "set echo \"-noecho\"; set timeout $time; spawn -noecho $command; expect timeout { exit 1 } eof { exit 0 }"    

    if [ $? = 1 ] ; then
        echo "Timeout after ${time} seconds"
    fi

}

편집 예 :

timeout 10 "ls ${HOME}"

좋아 보인다 화면에서 실행 된 명령의 출력을 어떻게 볼 수 있습니까?
Radek

안녕하세요, stdout이 다른 곳으로 리디렉션되지 않기 때문에 출력이 표시되어야합니다. 사용법에 대한 예를 추가했습니다. 필자의 경우 홈 디렉토리의 내용을 예상대로 인쇄합니다. 어떤 명령이 출력을 인쇄하지 않습니까?
Matteo

나는 그것을 제대로 부르지 않았다. 잘 작동합니다! 고맙습니다. 시간 초과 후 초 수만 출력하지 않습니다.
Radek

@Radek 죄송합니다.
Matteo

1
GNU 시간 초과를 사용하는 경우 시간 초과 timeout의 경우 자체 반환 상태 는 124이고 그렇지 않으면 명령의 반환 상태입니다 (Tim Kennedy의 답변에 언급되어 있음).
QuasarDonkey

15

명확하게 해 주셔서 감사합니다.

당신이 한 일을 수행하는 가장 쉬운 방법 timeout은 GNU Coreutils 패키지 의 명령 과 같은 래퍼 내에서 루프로 스크립트를 실행하는 것 입니다.

root@coraid-sp:~# timeout --help            
Usage: timeout [OPTION] DURATION COMMAND [ARG]...
   or: timeout [OPTION]
Start COMMAND, and kill it if still running after DURATION.

Mandatory arguments to long options are mandatory for short options too.
  -k, --kill-after=DURATION
                   also send a KILL signal if COMMAND is still running
                   this long after the initial signal was sent.
  -s, --signal=SIGNAL
                   specify the signal to be sent on timeout.
                   SIGNAL may be a name like 'HUP' or a number.
                   See `kill -l` for a list of signals
      --help     display this help and exit
      --version  output version information and exit

DURATION is an integer with an optional suffix:
`s' for seconds(the default), `m' for minutes, `h' for hours or `d' for days.

If the command times out, then exit with status 124.  Otherwise, exit
with the status of COMMAND.  If no signal is specified, send the TERM
signal upon timeout.  The TERM signal kills any process that does not
block or catch that signal.  For other processes, it may be necessary to
use the KILL (9) signal, since this signal cannot be caught.

Report timeout bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
For complete documentation, run: info coreutils 'timeout invocation'

결국, 쉘에 내장되어 있지 않은 자신 만의 타임 아웃 함수를 작성하는 것보다 훨씬 쉽습니다.


gtimeout설치 (OSX) 에서 호출 되었기 때문에이 설치가 설치되었음을 즉시 알 수 없었습니다 .
Joshua Goldberg

7

스크립트 내에서 워치 독 프로세스를 시작하여 너무 오래 실행되는 경우 부모를 종료하십시오. 예:

# watchdog process
mainpid=$$
(sleep 5; kill $mainpid) &
watchdogpid=$!

# rest of script
while :
do
   ...stuff...
done
kill $watchdogpid

이 스크립트는 5 초 후에 워치 독에 의해 종료됩니다.


6
그러나 매번 시간 초과를 기다려야합니다. 예를 들어 스크립트가 훨씬 짧아도 스크립트는 항상 5 초 동안 실행됩니다. 또한 워치 독의 PID를 저장하고 마지막에 종료해야합니다.
Matteo

@Matteo Fair 충분히. 추가되었습니다.
Kyle Jones

1
... 작업이 수행하는 작업에 따라 그보다 더 복잡 할 수 있습니다. 참조 쉘 스크립트에서 타이밍
질 'SO-정지 존재 악마'를

또한 읽기 : 얼마나 오래 PID를 고유 간주 될 수 stackoverflow.com/questions/11323410/linux-pid-recycling
플로리안 카스텔란

3

도 있습니다 cratimeout마틴 Cracauer에 의해.

# cf. http://www.cons.org/cracauer/software.html
# usage: cratimeout timeout_in_msec cmd args
cratimeout 5000 sleep 600
cratimeout 5000 tail -f /dev/null
cratimeout 5000 sh -c 'while sleep 1; do date; done'

2
#!/bin/sh

# Execute a command with a timeout

if [ "$#" -lt "2" ]; then
echo "Usage:   `basename $0` timeout_in_seconds command" >&2
echo "Example: `basename $0` 2 sleep 3 || echo timeout" >&2
exit 1
fi

cleanup()
{
trap - ALRM               #reset handler to default
kill -ALRM $a 2>/dev/null #stop timer subshell if running
kill $! 2>/dev/null &&    #kill last job
  exit 124                #exit with 124 if it was running
}

watchit()
{
trap "cleanup" ALRM
sleep $1& wait
kill -ALRM $$
}

watchit $1& a=$!         #start the timeout
shift                    #first param was timeout for sleep
trap "cleanup" ALRM INT  #cleanup after timeout
"$@"& wait $!; RET=$?    #start the job wait for it and save its return value
kill -ALRM $a            #send ALRM signal to watchit
wait $a                  #wait for watchit to finish cleanup
exit $RET                #return the value

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