Loading
BLOG 開発者ブログ

2024年9月30日

libfaketimeによる時間設定のチートシート

こんにちは。クラウドソリューショングループのkaneko.kです。
「サーバの時間を切り替えてテストしたい。」
そんな要件に直面したことはありますでしょうか。
現案件ではまさに1年間に2回だけだけ動く処理がありますので、それがちゃんと予定日時に動くかどうかをテストする必要があります。
今まではサーバ内の時刻を手で書き換えてテストしていたのですが、サービスのコンテナ化に伴ってより柔軟で確実な方法を模索しようかと。
今回はそんな希望を叶えるlibfaketimeでの細かい設定話をしていきます。

0. 対象者

本記事ではlibfaketimeで、より細かい設定をしたい人に向けた記事です。
初期導入や基礎的な設定項目については他の方にお任せすることとします。
また、本記事は、バージョン 0.9.10:2024/09/9時点での公式ReadMeを基に記載しています。
より詳細で正確な設定内容は公式を確認するようにお願いします

1.各種時間設定

1.0. チートシート

No. 設定内容 フォーマット
1.1 絶対日を指定する FAKETIME=”YYYY-MM-DD hh:mm:ss”
1.2 開始日時を指定する FAKETIME=”@YYYY-MM-DD hh:mm:ss”
1.3 相対的(オフセット)時間を設定する FAKETIME=”±<n>[y | d | h | m]”
1.3.1 より高度な時間指定(小数点指定) 例)FAKETIME=”+1.5h”  # FAKETIME=”+90m”と同値
1.3.2 より高度な時間指定(倍速指定) FAKETIME=”±<n>y x<q>”  # q:小数点も設定可能
1.4 faketimeラッパーを使用した設定 例)faketime ‘YYYY-MM-DD hh:mm:ss‘ /your/command/here # dateコマンド表記でも設定可能

1.1. 絶対日を指定する

常にこの日この時間を返すようにしたいというのであれば下記のように環境変数を設定すれば可能です。
FAKETIME="YYYY-MM-DD hh:mm:ss"

⚠️注意!!

可能な限りこの後説明する開始日時の指定か相対的(オフセット)時間設定を使うようにした方が良いとのことです。
絶対日時を指定することで「経過時間を測定するプログラム」が機能しなくなる恐れがあります。

1.2. 開始日時を指定する

特定の日時から進むように設定したい場合は日時の前に@をつければOKです。
FAKETIME="@YYYY-MM-DD hh:mm:ss"
ちなみにこちらは、呼び出しをしたプロセスが別の子プロセスを起動すると、指定した開始日時でリセットされてしまうようなので、
子プロセス生成でリセットされたくない場合は
FAKETIME_DONT_RESET=1
を環境変数に設定しましょう。
例)
LD_PRELOAD=src/libfaketime.so.1 FAKETIME="@2000-01-01 11:12:13" \ 
		/bin/bash -c 'while [ $SECONDS -lt 5 ]; do date; sleep 1; done'
上記のようにFAKETIME_DONT_RESETを設定しない場合は、
「dete」プロセスが起動するたびにリセットがかかるため、常に「2000-01-01 11:12:13」が返ります。
LD_PRELOAD=src/libfaketime.so.1 FAKETIME="@2000-01-01 11:12:13" \ 
		FAKETIME_DONT_RESET=1 \
		bin/bash -c 'while [ $SECONDS -lt 5 ]; do date; sleep 1; done'
  こちらのようにFAKETIME_DONT_RESETを設定した場合はリセットされませんので、時間が増加していきます。

1.3. 相対的(オフセット)時間を設定する

○○日後や〇〇時間前といったように「今」を起点とした相対的な時間で設定することができます。
例)

10日後:

FAKETIME="+14d"

5分前 :

FAKETIME="-5m"
ちなみに、設定できる単位は下記のように紐づけされています。
・年:y
・日:d
・時:h
・分:m
※ 「週」や「月」はうるう年の処理等が関わってくるため、正確に設定したい場合はfaketime ラッパーまたは GNU date コマンドのいずれかを使用する必要があります

1.3.1 より高度な時間指定(小数点指定)

Version0.8以降では時間オプションに小数点を利用できるようになったようです。
例)
FAKETIME="+90m"
FAKETIME="+1.5h"
のように表記できます。

1.3.2 より高度な時間指定(倍速指定)

「時間の進みを2倍にしてより短い間で検証したい」や逆に「時間の進みを遅くして検証したい」といった場合は下記のように設定することで時間の進みを調整することができます

・1年後に設定しつつ、2倍速に:

FAKETIME="+1y x2"

・1年後に設定しつつ、1/2倍速に:

FAKETIME="+1y x0.5"

・時刻はそのままに2倍速:

FAKETIME="+0 x2"
⚠️注意!!
オフセットの設定なしに、倍速設定はできませんので、”x2″のような書き方はせず”+0 x2″と設定する必要があります
また、倍速ではなく「2秒ずつ進めたい」という場合は
FAKETIME=”+1y i2.0″
のように”i”を指定することで設定できます。

1.4. faketimeラッパーを使用した設定

libfaketimeは「faketime」というコマンドを提供しており、設定の手間を省くことができます。
また、deteコマンドの表記ルールにも対応しているため、自然言語的な設定も可能です。
例)
faketime 'last Friday 5 pm' /your/command/here  # 先週の金曜日午後5時で右記のコマンドを実行
faketime '2018-12-24 08:15:42' /bin/date        # 2018-12-24 08:15:42でdateコマンドを実行
ちなみに、 ‘last Friday 5 pm’ のような「自然言語的設定」についてはGNU dateコマンドに定められている表記に従って設定できます

2. 最後に

今回は時間の設定方法についてまとめてみました。
このほかにも
・独立したプロセス間での「仮想設定時間」の共有
・経過時間や呼び出し回数による制限設定
・プロセスごとのlibfaketimeの有効設定
・外部プロセス生成
・…etc
といったようにプロセスに対して細かな設定が用意されています
ただし、予期せぬ副作用をもたらすものが多いため、設定する場合は公式をしっかりと読みましょう。
本記事で「特定のタイミングでしか発火しないプロセスのテスト方法」で困っている人が一人でも救えたら幸いです。


	            
kaneko.kのブログ