To create `/var/run/h2o/` directory using systemd-tmpfiles

h2oをインストールするansibleのタスクを書いた。ついでにh2oの実行ユーザーをh2oユーザーにしてみた(デフォルトはnobody)。しかし、h2oの起動に失敗する。

ログ見ると/var/run/h2oディレクトリへ書き込みできなくて起動失敗している。

  • h2oインストール時(?)に/var/run/h2oが作成される(nobody:nobodyで)
  • h2o起動直後h2oユーザーで/var/run/h2o以下にpidファイルを作成しようとするが、オーナーがnobodyなので作成失敗→起動失敗

という流れ。

予めディレクトリを作成するタスク書けば良いと思ったけど微妙感が…。h2oの起動スクリプトをいじるのも、h2oアップデート時元に戻されそうだしダメそう。

そこで何かいい方法がないか探した所、systemdにsystemd-tmpfilesというものがあった!

これはその名の通り、systemdのテンポラリなファイルを管理できる。/etc/tmpfiles.d/h2o.confのように、/etc/tmpfiles.d以下に定義ファイルを置く。

中身は以下。

D /var/run/h2o 0755 h2o h2o - -

Type Path Mode UID GID Age Argumentというフォーマットで書く。

今回AgeとArgumentは使わないので-にしてある。Ageはそのファイル/ディレクトリが削除される時間を指定できるっぽい。Argumentはシンボリックリンク指定したりできるらしい…。(よく調べてない)

定義したディレクトリを作成するには、以下のコマンドを実行する。

sudo systemd-tmpfiles --create

こういう「デフォルトと異なるファイルを定義したい」場合の使い方としてありなのかはよく知らない。。

それで、ansibleのタスク書いたはいいんだけどどうも1回目はh2o起動に失敗し、2回目以降は成功するという事態になった。なんでだ!と思ったらnotifyの実行順はhandlerに書かれた順だった!!これ罠だった。

h2oのnotifyがsystemd-tmpfilesの前にあったからsystemd-tmpfiles実行する前にh2o起動しようとして、1回目は必ず失敗するようになってた。

systemd-tmpfilesのnotifyをh2o起動のnotofyより前に書いて解決…。この辺の依存関係はchefの方が便利だね。

task/main.yml

- name: user-h2o exist
  user: name=h2o state=present createhome=no
  tags: [users,h2o]

- name: h2o tmpfile is exist
  copy: src="tmpfiles-h2o.conf" dest="/etc/tmpfiles.d/h2o.conf" owner=root group=root mode=0644
  notify:
    - create tmpfiles
  tags: h2o

- name: add h2o yum repository
  get_url: url=http://download.opensuse.org/repositories/home:funzoneq/CentOS_7/home:funzoneq.repo dest=/etc/yum.repos.d/
  tags: h2o

- name: h2o is installed
  yum: pkg=h2o state=installed
  tags: h2o

- name: h2o is configured
  notify:
    - restart h2o
  copy: src="h2o.conf" dest="/etc/h2o/h2o.conf" owner=root group=root mode=0644
  tags: h2o

- name: h2o is runnning and enabled
  service: name=h2o state=running enabled=yes
  tags: h2o

handlers/main.yml

- name: create tmpfiles
  shell: systemd-tmpfiles --create

- name: restart h2o
  service: name=h2o state=restarted