다음을 수행하여 bash에서 조건이 true가 될 때까지 기다릴 수 있다는 것을 알고 있습니다.
while true; do
test_condition && break
sleep 1
done
그러나 매 반복(수면)마다 1개의 하위 프로세스가 생성됩니다. 다음과 같이 하면 이러한 문제를 피할 수 있습니다.
while true; do
test_condition && break
done
하지만 CPU를 많이 사용합니다(Busy Waiting). 하위 프로세스와 바쁜 대기를 피하기 위해 다음과 같은 해결책을 생각해 냈지만 보기에 좋지 않습니다.
my_tmp_dir=$(mktemp -d --tmpdir=/tmp) # Create a unique tmp dir for the fifo.
mkfifo $my_tmp_dir/fifo # Create an empty fifo for sleep by read.
exec 3<> $my_tmp_dir/fifo # Open the fifo for reading and writing.
while true; do
test_condition && break
read -t 1 -u 3 var # Same as sleep 1, but without sub-process.
done
exec 3<&- # Closing the fifo.
rm $my_tmp_dir/fifo; rmdir $my_tmp_dir # Cleanup, could be done in a trap.
참고: 일반적인 경우 read -t 1 var
fifo는 stdin을 소비하므로 fifo 없이는 사용할 수 없으며 stdin이 터미널이나 파이프가 아니면 작동하지 않습니다.
보다 우아한 방법으로 하위 프로세스와 바쁜 대기를 피할 수 있나요?
답변1
bash
최신 버전(최소 v2)에서는 내장 기능을 런타임에 로드할 수 있습니다( enable -f filename commandname
. 이러한 로드 가능한 내장 기능 중 다수는 bash 소스와 함께 배포되며 sleep
그 안에 위치합니다. 물론, 가용성은 운영 체제마다(심지어 기계마다) 다를 수 있습니다. 예를 들어, openSUSE에서 이러한 내장 기능은 패키지를 통해 배포됩니다.bash-loadables
.
답변2
내부 루프에 많은 하위 프로세스를 만드는 것은 나쁜 일입니다. sleep
매초마다 하나의 프로세스를 생성하십시오. 괜찮아요
while ! test_condition; do
sleep 1
done
외부 프로세스를 정말로 피하고 싶다면 FIFO를 열어둘 필요가 없습니다.
my_tmpdir=$(mktemp -d)
trap 'rm -rf "$my_tmpdir"' 0
mkfifo "$my_tmpdir/f"
while ! test_condition; do
read -t 1 <>"$my_tmpdir/f"
done
답변3
나는 최근에 이것을 할 필요가 있었습니다. 나는 외부 프로그램을 호출하지 않고 bash를 영원히 잠들게 만드는 다음 함수를 생각해 냈습니다.
snore()
{
local IFS
[[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
{
# workaround for MacOS and similar systems
local fifo
fifo=$(mktemp -u)
mkfifo -m 700 "$fifo"
exec {_snore_fd}<>"$fifo"
rm "$fifo"
}
read ${1:+-t "$1"} -u $_snore_fd || :
}
참고: 이전에 매번 파일 설명자를 열고 닫는 버전을 게시했지만 일부 시스템에서는 초당 수백 번 이 작업을 수행하면 결국 작동이 중단되는 것을 발견했습니다. 따라서 새로운 솔루션은 함수 호출 간에 파일 설명자를 유지합니다. Bash는 어쨌든 종료 시 이를 정리합니다.
이는 /bin/sleep과 같이 호출할 수 있으며 요청한 시간 동안 절전 모드로 전환됩니다. 인수 없이 호출되면 영원히 중단됩니다.
snore 0.1 # sleeps for 0.1 seconds
snore 10 # sleeps for 10 seconds
snore # sleeps forever
답변4
또는 ksh93
은 내장 셸이므로 다른 옵션은 대신 이러한 셸을 사용하는 것 mksh
입니다 .sleep
bash
zsh
또한 주어진 100분의 1초 동안 휴면하는 zselect
내장 함수(loaded ) 도 있습니다 .zmodload zsh/zselect
zselect -t <n>