pslaboが試したことの記録

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

はてなダイヤリー時代はカテゴリ分けが適当だったのですが、これはそのうち直します。


シェルスクリプトで OS によらず時刻をミリ秒単位で取得したい

シェルスクリプトで何かの処理を実行する際に、その実行にかかった時間を秒単位で計測したい場合は次のように実行することができます。

dt_start=$( date +"%s" )
何かの処理
dt_end=$( date +"%s" )

elapsed=$((dt_end - dt_start))
echo ${elapsed}

それでは、今度はミリ秒単位で計測しようと思って次のように実行してみると、Linux では問題なく計測できますが、macOS では意図通りに動作しません。

dt_start=$( date +"%s%3N" )
何かの処理
dt_end=$( date +"%s%3N" )

elapsed=$(( dt_end - dt_start ))
echo ${elapsed}

この理由は、macOS の date コマンドでは "%N" をサポートしていないためです。Linux では次のように結果を返しますが、

$ date +"%s%3N"
1613896343808

同じことを macOS で実行すると、こうなってしまいます。

$ date +"%s%3N"
1613896453N

このため、別の方法での解決策を考えてみたのですが、perl の Times::Hires を用いればミリ秒単位の時刻を取得できることに気づきました。具体的には次のように実行します。

$ perl -MTime::HiRes -e 'printf("%.0f\n",Time::HiRes::time()*1000)'
1613896697373

したがって、macOS のときだけ上記のように実行したいと考えた場合は、uname の値が Darwin の場合だけ perl を用いるように実装すれば良いでしょう。ただし RHEL, CentOS, Ubuntu でも perl はインストール済みのことが多いと思いますので、環境によらず、この方法でミリ秒単位の時刻を取得できると考えて良いでしょう。

今回の例を上記の方法で書き直すと、次のようになります。

dt_start=$( perl -MTime::HiRes -e 'printf("%.0f\n",Time::HiRes::time()*1000)' )
何かの処理
dt_end=$( perl -MTime::HiRes -e 'printf("%.0f\n",Time::HiRes::time()*1000)' )

elapsed=$((dt_end - dt_start))
echo ${elapsed}