Bash에서 종료되지 않은 프로세스에 대한 시간 초과

Bash에서 종료되지 않은 프로세스에 대한 시간 초과

메인 스크립트가 실행 중이고 시간 제한 내에 완료되지 않으면 완료 여부에 따라 메인 스크립트에서 "뭔가를 수행하는" 두 번째 "느린 프로세스"를 시작하고 싶습니다. 참고: "느린 프로세스"가 시간 제한 이전에 완료되면 전체 시간 제한을 기다리고 싶지 않습니다.

"느린 프로세스"가 계속되어 성능에 대한 통계와 포렌식을 수집할 수 있기를 바랍니다.

나는 사용을 조사했다정지시키다, 그러나 완료되면 내 스크립트가 종료됩니다.

다음과 같은 단순화된 예를 가정해 보겠습니다.

메인 디렉토리

result=`timeout 3 ./slowprocess.sh`
if [ "$result" = "Complete" ]
then
 echo "Cool it completed, do stuff..."
else
 echo "It didn't complete, do something else..."
fi

느린 프로세스.sh

#!/bin/bash
start=`date +%s`
sleep 5
end=`date +%s`
total=`expr $end - $start`
echo $total >> /tmp/performance.log
echo "Complete"

여기서는 시간 초과를 사용하므로 스크립트가 종료되므로 아무 일도 일어나지 않습니다 /tmp/performance.log. 끝내고 싶지만 3초 안에 끝나지 않더라도 다음 단계로 넘어가고 slowprocess.sh싶습니다 .main.sh

답변1

ksh/bash/zsh 사용:

{
  (./slowprocess.sh >&3 3>&-; echo "$?") |
    if read -t 3 status; then
      echo "Cool it completed with status $status, do stuff..."
    else
      echo "It didn't complete, do something else..."
    fi
} 3>&1

( )에 대해 복원 할 수 있도록 원본 stdout을 fd 3( )에 복사하고 3>&1나머지 서브쉘의 stdout은 파이프로 이동합니다.slowprocess.sh>&3(...)read -t 3

또는 사용하려는 경우 timeout(여기서 GNU를 가정 timeout):

timeout --foreground 3 sh -c './slowprocess.sh;exit'

종료되는 것을 방지합니다 (이는 slowprocess.sh쉘 프로세스에서 마지막 명령을 실행하여 최적화된 구현에 ;exit필요합니다 ).sh

답변2

이는 유비쿼터스 쉘 도구만을 사용하는 솔루션입니다.

sleep이는 느린 프로세스를 포크하고 백그라운드에서 wait셸 내장 대기 외에 첫 번째 프로세스가 완료될 때까지 기다리면 쉽게 수행할 수 있습니다.모두첫 번째 작업뿐만 아니라 작업을 수행해야 합니다.

따라서 sleep느린 프로세스와 백그라운드에서 a를 분기하고 둘 다 파이프를 통해 상태를 보고하고 파이프에서 나오는 첫 번째 상태를 읽도록 합니다.

fifo=$(mktemp -u)  # if not on Linux, adapt to what your OS provides
mkfifo -m 600 "$fifo"
{ ./slowprocess.sh; echo z >"$fifo"; } &
sh -c 'sleep 3; echo a' >"$fifo" &
sleep_pgid=$!
read status <$fifo
case $status in
  a) echo "That process is taking a long time"; read ignored <$fifo;;
  z) echo "Done already"; kill -INT -$sleep_pgid;;
esac
rm "$fifo"

답변3

차단이 발생하더라도 slowprocess.sh백그라운드에서 수행될 수 있으므로 시간 초과 후에도 실행이 계속될 수 있습니다.

에 대한 매뉴얼 페이지를 참조하여 뒤에서 signal부터 사용할 수도 있습니다 .timeoutmain.shtimeout

timeout안내페이지 에서 발췌

`-s SIGNAL'
`--signal=SIGNAL'
     Send this SIGNAL to COMMAND on timeout, rather than the default
     `TERM' signal. SIGNAL may be a name like `HUP' or a number. Also
     see *Note Signal specifications::.

이 신호를 내부에서 잡아야 합니다 main.sh.

timeout다양한 유형의 실패에 대해서도 다양한 상태가 반환됩니다 . 다음을 활용할 수도 있습니다.

   Exit status:

     124 if COMMAND times out
     125 if `timeout' itself fails
     126 if COMMAND is found but cannot be invoked
     127 if COMMAND cannot be found
     the exit status of COMMAND otherwise

$?라인이 실행된 후 변수에 나타납니다 timeout ....

답변4

다음은 불필요한 작업 제어 출력을 생성하기는 하지만 매우 간단한 또 ​​다른 방법입니다. 백그라운드 프로세스 "sleep nnn"을 시작한 다음 "wait -n"을 사용하여 첫 번째 절전 프로세스와 모니터링 중인 프로세스를 기다립니다. 다음은 이 기술의 다소 서투른 예입니다(즉시 알림을 위해 "set -o 알림" 사용).

$ (for I in $(seq 10); do sleep 1; echo $I ; done) & \
more> J1=$! ; \
more> sleep 5 & \
more> J2=$! ; \
more> time wait -n $J1 $J2
[1] 288160
[2] 288161
1
2
3
4
[2]+  Done                    sleep 5

real    0m5.006s
user    0m0.002s
sys 0m0.004s
$ 5
6
7
8
9
10
[1]+  Done                    ( for I in $(seq 10);
do
sleep 1; echo $I;
done )
$

$ (for I in $(seq 3); do sleep 1; echo $I ; done) & \
more> J1=$! ; \
more> sleep 5 & \
more> J2=$! ; \
more> time wait -n $J1 $J2
[1] 288256
[2] 288257
1
2
3
[1]-  Done                    ( for I in $(seq 3);
do
sleep 1; echo $I;
done )

real    0m3.025s
user    0m0.004s
sys 0m0.015s
$ [2]+  Done                    sleep 5
$

관련 정보