while
bash
내 스크립트에는 처음과 5초 간격으로 서로 다른 작업을 수행하도록 되어 있는 루프가 있습니다 . 이전 루프가 완료되도록 허용합니다. 5초 간격은 함수에 의해 do_different
설정된 전역 변수로 표시됩니다 heartbeat
. 또 다른 문제는 일반 while
루프가 알 수 없는 시간 내에 완료된다는 것입니다( RANDOM
아래 스크립트에서 단순화됨). 사용은 cron
옵션이 아니며 무작위 프로세스 타이밍도 아닙니다.
성공하지 못한 채 파이프 및 프로세스 대체를 사용해 보았습니다. 전체 스크립트를 리팩터링할 수 있습니다.
#!/bin/bash
function heartbeat {
do_different=true
while sleep 5s
do
do_different=true
done
}
heartbeat &
while true
do
if $do_different
then
echo 'Something different'
do_different=false
i=0
else
# process of random duration; not important
r=$(( 1 + RANDOM % 3 ))
sleep "${r}s"
i=$((i + r))
echo "$i"
fi
done
답변1
첫째, 명확하지 않은 경우 문제의 스크립트는 heartbeat
하위 프로세스에서 실행되므로 상위 셸 메모리의 셸 변수를 변경할 수 없기 때문에 실패합니다.
OP가 하려는 정신에 더 가까운 접근 방식은 다음과 같습니다.
#!/bin/bash
trap 'do_different=true' USR1
heartbeat() {
while sleep 5
do # If the parent process has gone away, the child should terminate.
kill -USR1 "$$" || exit
done
}
heartbeat &
heartbeat_pid=$!
trap 'kill "$heartbeat_pid"' 0
do_different=true
while true
do
if "$do_different"
then
echo 'Something different'
do_different=false
i=0
else
# process of random duration; not important
r=$(( 1 + RANDOM % 3 ))
sleep "$r"
i=$((i + r))
echo "$i"
fi
done
수정된 프로세스는 heartbeat
SIGUSR1 신호를 기본(부모) 셸 프로세스로 보냅니다. 이 신호와 SIGUSR2는 사용자/애플리케이션 사용을 위해 예약되어 있으며 시스템에서 생성되어서는 안 됩니다. 이 trap
명령을 사용하면 쉘 스크립트가 신호를 캡처할 수 있습니다. 이 trap 'do_different=true' USR1
명령은 SIGUSR1 신호(5초마다 도착)를 포착하고 do_different
신호가 발생할 때 플래그를 설정하도록 쉘에 지시합니다.
heartbeat_pid
분명히 자식 프로세스의 프로세스 ID(PID)입니다 heartbeat
. 이 명령은 trap 'kill "$heartbeat_pid"' 0
스크립트가 종료되었음을 나타내는 가짜 신호 0이 "수신"될 때 어떤 일이 발생하는지 정의합니다. Shell이 문에 "떠난 후 집에가는 길에 식료품을 가져가는 것을 잊지 마세요"라고 적힌 스티커 메모를 붙이는 것과 같다고 생각하십시오. exit
이 작업 은 스크립트가 끝에 도달하거나 명령문을 실행하거나(이 스크립트에서는 무한 루프이기 때문에 두 가지 모두 발생하지 않음) 인터럽트 신호(SIGINT, +에 의해 생성됨)에 의해 종료되는 경우CtrlCheartbeat
답변2
이 date
유틸리티를 사용하여 현재 시간을 초 단위로 가져옵니다.
#!/bin/bash
lastTime=-5
while true
do
currentTime=$(date +%s)
elapsedTime=$((currentTime - lastTime))
if [[ $elapsedTime -ge 5 ]]
then
echo 'Something different'
lastTime=$currentTime
i=0
else
# process of random duration; not important
r=$(( 1 + RANDOM % 3 ))
sleep ${r}s
i=$((i + r))
echo $i
fi
done
편집: lastTime
처음에 "다른 작업을 수행"하도록 초기 값을 변경했습니다.
답변3
이것은 내가 지금 실행하고 있는 코드입니다.페이유의 답변일부 수정 사항이 있습니다.
#!/bin/bash
t_lastdue=$(date --date='5seconds ago' +%s)
while true
do
t_now=$(date +%s)
t_elapsed=$((t_now - t_lastdue))
if [ $t_elapsed -ge 5 ]
then
echo 'Something different'
t_lastdue=$((t_lastdue + 5))
i=0
else
# process of random duration; not important
r=$(( 1 + RANDOM % 3 ))
sleep "${r}s"
i=$((i + r))
echo "$i"
fi
done
답변4
어쨌든 그것을 사용하고 있으므로 bash
다음을 사용해야 합니다 $SECONDS
.
#!/bin/bash
while [ "$SECONDS" -lt 5 ] || {
SECONDS=$((i=0))
echo Something different
};do sleep "$((r=(1+RANDOM)%3))"
echo "$((i+=r))"
done
에서 man bash
:
$SECONDS
- 이 변수는 쉘이 시작된 이후의 시간(초)으로 확장됩니다. 이 변수에 할당하면 카운트가 할당된 값으로 재설정되고 확장된 값은 할당된 값에 할당 이후의 초 수를 더한 값이 됩니다.
아래와 같은 방법그리고다루다경향:
S=SECONDS
while [ "$(($S<5||(i=0*($S-=5))))" -ne 0 ] ||
echo Something different
do sleep "$((r=(1+RANDOM)%3))"
echo "$((i+=r))"
done