意外と知られていない?シェルスクリプトで1秒未満のsleep(wait)が使える

Bash

はじめに

今回紹介する機能が利用できる環境、利用できない環境があるかと思います。
(逆に利用できる環境のほうが少ないかもしれないです ^^;)

シェルスクリプトで1秒未満のsleep (wait処理といったほうがよい?) を行う方法について紹介します。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ head -n 2 /etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

$ date --version | head -n 2
date (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.

sleep に小数を指定するだけ

ブログネタがなかったのでひねり出したというのが正直なところですね。

1秒未満の sleep 処理を行う方法、それは sleep コマンドの引数に小数を指定する」 だけです。

なんか昔は小数指定できなかった気がしたんですけどね。
数年前に0.1秒ごとにポーリングする機能を実現する際に使ってみたらいけました。

$ sleep 0.5; echo ok
ok

上記のコマンドは 「0.5秒待ってから "ok" という文字を出力する処理」ですが、本当に0.5秒waitしたのかわからないですね。

開始時間と終了時間の差 を出力して確認してみます。

date +%s%3N というコマンドでミリ秒を取得できる ので、これを利用します。

$ S=$(date +%s%3N); sleep 0.5; E=$(date +%s%3N); echo $((E - S))
510

$ S=$(date +%s%3N); sleep 0.7; E=$(date +%s%3N); echo $((E - S))
714

$ S=$(date +%s%3N); sleep 1.1; E=$(date +%s%3N); echo $((E - S))
1115

もちろん多少の誤差はありますが、 sleep コマンドに指定した時間が小数の場合でも、その時間waitしているようです。

0.1以下の値をしてした場合はどうなるの?

更に興味がわきました。

0.1よりも小さい小数値を指定した場合はどうなるのでしょう?

試してみました。

$ S=$(date +%s%3N); sleep 0.09; E=$(date +%s%3N); echo $((E - S))
104

$ S=$(date +%s%3N); sleep 0.05; E=$(date +%s%3N); echo $((E - S))
67

$ S=$(date +%s%3N); sleep 0.02; E=$(date +%s%3N); echo $((E - S))
34

date / echo / sleep コマンド実行のオーバヘッドが随分影響していそうですが、 0.1以下の数値を指定しても解釈してくれているようです

ひとこと

試しにMac環境の sleep ( /bin/sleep )でも試してみましたが、利用できました。

ただ、過去には小数は指定できなかった気がしていて、環境に依存しそうな機能なので注意が必要です。

Bash