이 답변 에 에 명령 줄 명령 일정한 시간이 지나면 명령을 자동-죽일
bash 명령 줄에서 장기 실행 명령을 시간 초과하는 단선 방법을 제안합니다.
( /path/to/slow command with options ) & sleep 5 ; kill $!
그러나 지정된 “장기 실행”명령이 시간 초과보다 일찍 완료 될 수 있습니다. ( “일반적으로 오래 실행되지만 때로는 빠른”명령 또는 재미를 위해 tlrbsf라고하자 .)
따라서이 멋진 1- 라이너 방식에는 몇 가지 문제가 있습니다. 첫째,는 sleep
조건부가 아니므로 시퀀스가 완료되는 데 걸리는 시간에 바람직하지 않은 하한을 설정합니다. tlrbsf 명령이 2 초 안에 완료 될 때 수면을 위해 30 ~ 2m 또는 5m를 고려하십시오 . 둘째, kill
는 무조건적이므로이 순서는 실행 중이 아닌 프로세스를 종료시키고 그 과정에서 우회를 시도합니다.
그래서…
일반적으로 오래 실행되지만 가끔 빠른 ( “tlrbsf” ) 명령 을 시간 초과 하는 방법이 있습니까?
- bash 구현이 있습니다 (다른 질문에는 이미 Perl 및 C 답변이 있습니다)
- 두 가지의 이전에 종료됩니다 : tlrbsf의 프로그램 종료 또는 제한 시간 경과
- 존재하지 않거나 실행되지 않는 프로세스를 종료하지 않습니다 (또는 선택적 으로 나쁜 종료에 대해 불평 하지 않습니다 )
- 1- 라이너 일 필요는 없습니다
- Cygwin 또는 Linux에서 실행할 수 있습니다
… 그리고 보너스 포인트의 경우, tlrbsf 명령의 stdin / stdout / stderr가 원래의 위치 와 동일하게 리디렉션 될 수 있도록 포 그라운드에서 tlrbsf 명령을 실행하고 백그라운드 에서 ‘sleep’또는 추가 프로세스를 실행합니다. 직접 실행?
그렇다면 코드를 공유하십시오. 그렇지 않은 경우 이유를 설명하십시오.
앞서 언급 한 예제를 해킹하려고 잠시 시간을 보냈지 만 bash 기술의 한계에 도달했습니다.
답변
나는 이것이 당신이 요구하는 정확하게라고 생각합니다.
http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3
#!/bin/bash
#
# The Bash shell script executes a command with a time-out.
# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
# is blocked, then the subsequent SIGKILL (9) terminates it.
#
# Based on the Bash documentation example.
# Hello Chet,
# please find attached a "little easier" :-) to comprehend
# time-out example. If you find it suitable, feel free to include
# anywhere: the very same logic as in the original examples/scripts, a
# little more transparent implementation to my taste.
#
# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>
scriptName="${0##*/}"
declare -i DEFAULT_TIMEOUT=9
declare -i DEFAULT_INTERVAL=1
declare -i DEFAULT_DELAY=1
# Timeout.
declare -i timeout=DEFAULT_TIMEOUT
# Interval between checks if the process is still alive.
declare -i interval=DEFAULT_INTERVAL
# Delay between posting the SIGTERM signal and destroying the process by SIGKILL.
declare -i delay=DEFAULT_DELAY
function printUsage() {
cat <<EOF
Synopsis
$scriptName [-t timeout] [-i interval] [-d delay] command
Execute a command with a time-out.
Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM
signal is blocked, then the subsequent SIGKILL (9) terminates it.
-t timeout
Number of seconds to wait for command completion.
Default value: $DEFAULT_TIMEOUT seconds.
-i interval
Interval between checks if the process is still alive.
Positive integer, default value: $DEFAULT_INTERVAL seconds.
-d delay
Delay between posting the SIGTERM signal and destroying the
process by SIGKILL. Default value: $DEFAULT_DELAY seconds.
As of today, Bash does not support floating point arithmetic (sleep does),
therefore all delay/time values must be integers.
EOF
}
# Options.
while getopts ":t:i:d:" option; do
case "$option" in
t) timeout=$OPTARG ;;
i) interval=$OPTARG ;;
d) delay=$OPTARG ;;
*) printUsage; exit 1 ;;
esac
done
shift $((OPTIND - 1))
# $# should be at least 1 (the command to execute), however it may be strictly
# greater than 1 if the command itself has options.
if (($# == 0 || interval <= 0)); then
printUsage
exit 1
fi
# kill -0 pid Exit code indicates if a signal may be sent to $pid process.
(
((t = timeout))
while ((t > 0)); do
sleep $interval
kill -0 $$ || exit 0
((t -= interval))
done
# Be nice, post SIGTERM first.
# The 'exit 0' below will be executed if any preceeding command fails.
kill -s SIGTERM $$ && kill -0 $$ || exit 0
sleep $delay
kill -s SIGKILL $$
) 2> /dev/null &
exec "$@"
답변
아마도 timeout
coreutils 에서 명령을 찾고있을 것입니다 . coreutils의 일부이므로 기술적으로 C 솔루션이지만 여전히 coreutils입니다. info timeout
상세 사항은. 예를 들면 다음과 같습니다.
timeout 5 /path/to/slow/command with options
답변
이 솔루션은 bash 모니터 모드에 관계없이 작동합니다. 적절한 신호를 사용하여 your_command를 종료 할 수 있습니다
#!/bin/sh
( your_command ) & pid=$!
( sleep $TIMEOUT && kill -HUP $pid ) 2>/dev/null & watcher=$!
wait $pid 2>/dev/null && pkill -HUP -P $watcher
감시자는 제한 시간이 초과되면 your_command를 종료합니다. 스크립트는 느린 작업을 기다렸다가 감시자를 종료합니다. 참고 wait
다른 쉘의 자식 프로세스 작동하지 않습니다.
예 :
- your_command가 2 초 이상 실행되어 종료되었습니다
your_command가 중단되었습니다
( sleep 20 ) & pid=$!
( sleep 2 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
echo "your_command finished"
pkill -HUP -P $watcher
wait $watcher
else
echo "your_command interrupted"
fi
- your_command가 시간 초과되기 전에 완료되었습니다 (20 초).
your_command 완료
( sleep 2 ) & pid=$!
( sleep 20 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
echo "your_command finished"
pkill -HUP -P $watcher
wait $watcher
else
echo "your_command interrupted"
fi
답변
당신은 간다 :
timeout --signal=SIGINT 10 /path/to/slow command with options
당신은 변경 될 수 있습니다 SIGINT
그리고 10
당신이 원하는대로)
답변
이 작업을 전적으로 bash 4.3
또는 그 이상으로 수행 할 수 있습니다 .
_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; r=$?; kill -9 `jobs -p`; exit $r; ) }
- 예:
_timeout 5 longrunning_command args
- 예:
{ _timeout 5 producer || echo KABOOM $?; } | consumer
- 예:
producer | { _timeout 5 consumer1; consumer2; }
-
예:
{ while date; do sleep .3; done; } | _timeout 5 cat | less
-
Bash 4.3 필요
wait -n
- 명령이 종료 된 경우 137을 제공하고 그렇지 않으면 명령의 리턴 값을 제공합니다.
- 파이프에 사용됩니다. (여기서는 전경으로 갈 필요가 없습니다!)
- 내부 쉘 명령 또는 기능에서도 작동합니다.
- 서브 쉘에서 실행되므로 현재 쉘로 변수를 내보낼 수 없습니다. 죄송합니다.
리턴 코드가 필요하지 않은 경우, 더 간단하게 만들 수 있습니다.
_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; kill -9 `jobs -p`; ) }
노트:
-
엄밀히 말하면
;
in은 필요하지 않지만 상황에; )
더 일관성이; }
있습니다. 그리고set +b
아마도 아마 빠져있을 수도 있지만 미안보다 안전합니다. -
--forground
(아마도)를 제외하고 모든 변형timeout
지원을 구현할 수 있습니다 .--preserve-status
그래도 조금 어렵습니다. 이것은 독자를위한 연습으로 남겨둔다;)
이 레시피는 쉘에서 “자연스럽게”사용할 수 있습니다 (와 마찬가지로 flock fd
).
(
set +b
sleep 20 &
{
YOUR SHELL CODE HERE
} &
wait -n
kill `jobs -p`
)
그러나 위에서 설명한대로 환경 변수를 자연스럽게 둘러싸는 쉘로 다시 내보낼 수 없습니다.
편집하다:
실제 예 : 시간 __git_ps1
이 너무 오래 걸리면 시간이 초과 됩니다 (SSHFS 링크 속도가 느린 경우).
eval "__orig$(declare -f __git_ps1)" && __git_ps1() { ( git() { _timeout 0.3 /usr/bin/git "$@"; }; _timeout 0.3 __orig__git_ps1 "$@"; ) }
편집 2 : 버그 수정. 나는 그것이 exit 137
필요하지 않고 _timeout
동시에 신뢰할 수 없다는 것을 알았 습니다.
Edit3 : git
다이 하드이므로 만족스럽게 작동하려면 이중 트릭이 필요합니다.
Edit4 : 실제 GIT 예제 _
에서 처음으로 a 를 잊었습니다 _timeout
.
답변
나는 적어도 데비안 패키지를 가지고있는 “timelimit”를 선호합니다.
http://devel.ringlet.net/sysutils/timelimit/
프로세스를 종료 할 때 무언가를 인쇄하기 때문에 coreutils “timeout”보다 조금 더 좋고 기본적으로 일정 시간 후에 SIGKILL을 보냅니다.
답변
slowcommand
1 초 후 시간 초과하려면
timeout 1 slowcommand || echo "I failed, perhaps due to time out"
자체적 인 이유로 명령이 시간 종료되었는지 또는 실패했는지 판별하려면 상태 코드가 124인지 확인하십시오.
# ping for 3 seconds, but timeout after only 1 second
timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process Timed Out!'
else
echo 'Process did not timeout. Something else went wrong.'
fi
exit $EXIT_STATUS
종료 상태가 124 인 timeout
경우 명령으로 인해 시간 종료되었는지 또는 자체 내부 시간 초과 논리로 인해 명령 자체가 종료 된 후 124로 리턴 되는지 여부를 알 수 없습니다 . 두 경우 모두 안전하게 가정 할 수 있습니다. 그러나 어떤 종류의 시간 초과가 발생했습니다.