TL;DR
動機
Packerを使い、プロビジョニングにAnsibleを使ってVMイメージを作成してみたが、必ずしもそのイメージは自分や日本サイドだけが使うものでなくオフショア開発メンバーにも利用してもらいたいのでタイムゾーン設定は埋め込みたくない。ここだけ外だしにし環境により変更したいなぁと言うのが動機。
方法
事前にPacker+Ansible(ここでは触れない)でboxがビルドされてるとして、その先、タイムゾーン設定は動的に行う。
この記事では例示用にVagrant Cloudにあるboxをそのまま利用する。当然世界中の人たちが利用するものだからUTCで作られたCentOS7, Debian, Ubuntu の公式イメージを利用。
timedatectl コマンド
Red Hat Enterprise Linux > 7 > システム管理者のガイド > 第3章 日付と時刻の設定
timedatectl ユーティリティーは、systemd システムおよびサービスマネージャーの一部として配布されており、システムクロック設定を確認および変更できます。このツールを使用すると、現在の日付および時間の変更、タイムゾーンの設定、リモートサーバーとシステムクロックとの自動同期の有効化が可能になります。
こちらは、Red Hat系/Debian系などSystemdを利用した最近のディストリビューションなら利用可能。いくつかのQiitaなどの記事には/etc/timezone
を手で変更する手法があるが、今はこちらの利用が良いのではないだろうか?(あくまでもベアメタルやVMでの話、Dockerの場合は通常は変更しない?よね)
$ sudo timedatectl set-timezone Asia/Tokyo
Vagrant Shell Provisioner
とりあえず、inlineで一行追加で固定でタイムゾーンの設定はできる。
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
config.vm.provision "shell", inline: "timedatectl set-timezone Asia/Tokyo"
end
このままだとVagrantfileを書き換えてもらう必要あり。
Rubyでのタイムゾーンの扱い
Vagrantfile自体はRubyなのでホストOSの現在のタイムゾーンを取得する方法がないか?残念ながらTime.now.zone
ではJST
,PDT
,IST
などは取得できるがAsia/Tokyo
の様な形式では取得できない(RailsのActiveSupportなら扱えそうだが…)。
環境変数から
シェル環境ではタイムゾーンの環境変数としてTZ
が利用される。
$ date
2020年 4月 8日 水曜日 21時54分13秒 JST
$ TZ="UTC" date
2020年 4月 8日 水曜日 12時54分19秒 UTC
$ TZ="America/Los_Angeles" date
2020年 4月 8日 水曜日 05時54分24秒 PDT
この値をRubyから利用する。TZ環境変数がない場合としてUTC
にするため三項演算子で、
$ TZ="Asia/Tokyo" ruby -e 'p ENV["TZ"] ? ENV["TZ"] : "UTC"'
"Asia/Tokyo"
$ ruby -e 'p ENV["TZ"] ? ENV["TZ"] : "UTC"'
"UTC"
完成
これらを組み合わせて出来上がったVagrantfileがこちら
Vagrant.configure("2") do |config|
config.vm.box = "centos/7"
#config.vm.box = "debian/buster64"
#config.vm.box = "ubuntu/bionic64"
config.vm.provision "shell" do |sh|
timezone = ENV['TZ'] ? ENV['TZ'] : "UTC"
sh.inline = "timedatectl set-timezone $1"
sh.args = timezone
end
end
実際に利用すると、
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'centos/7'...
...
...
==> default: Running provisioner: shell...
default: Running: inline script
$ vagrant ssh
[vagrant@localhost ~]$ date
Wed Apr 8 13:10:42 UTC 2020
[vagrant@localhost ~]$ exit
$ TZ="Asia/Tokyo" vagrant provision
==> default: Running provisioner: shell...
default: Running: inline script
$ vagrant ssh
Last login: Wed Apr 8 22:10:40 2020 from 10.0.2.2
[vagrant@localhost ~]$ date
Wed Apr 8 22:11:31 JST 2020
TZ
環境変数を恒久的に設定するなら.bash_profile
などでexportしておけば、ホストOSとゲストOSで同じタイムゾーンになる。