node.js with nvm with systemd
先のこたつ記事の補足というか何というか
サラッと Hubot を常駐と書きましたが、当然そのサービスの自動起動には systemd を使いたいですね? 使いたいですね? 使いましょう。
systemd 氏は実行ユーザーなんかも指定できるわけですが、環境変数の設定までは面倒を見てくれないので、そのへんをやっていく必要があります。
nvm でインストールしたお好きなバージョンの node で Unit ファイルを書くと、おおよそ次のような感じになります。
[Unit] Description=Hoge Requires=network.target After=network.target [Service] Type=simple WorkingDirectory=/path/to/application User=<user> Environment=ENV=production ExecStart=/home/<user>/.nvm/versions/node/<version>/bin/node <mainfile>.js [Install] WantedBy=multi-user.target
kotatsubot の場合は次のようになっています。
/etc/systemd/system/kotatsubot.service
[Unit] Description=KotatsuBot Requires=network.target After=network.target [Service] Type=simple WorkingDirectory=/home/kotatsu/kotatsubot User=kotatsu Restart=always RestartSec=10 Environment=PATH=/home/kotatsu/.nvm/versions/node/v6.9.1/bin HUBOT_SLACK_TOKEN=hogehoge ExecStart=/home/kotatsu/kotatsubot/bin/hubot --name kotatsubot -a slack -l kotatsu [Install] WantedBy=multi-user.target
Note that, ExecStart の1つめの実行ファイル名に記述できるのはフルパスのみです。$PATH も見てくれないし変数も展開してくれない。甘えるな。.js はフルパスじゃなくて良いの だって WorkingDirectory してるから
/usr/local/nvm
なんかにシステムワイドに nvm をインストールしている場合もほぼ同じ方法が取れるはずです。
この方法だと nvm の設定によらずバージョンが固定されてしまうじゃないかという議論*1はあるのですが、僕はむしろ実行バージョンが固定されない方がヤなのでこの方法をとっています。あと ExecStart からラッパースクリプト呼ぶの好きじゃないんですよね(原理主義)。bin/hubot
だってラッパーじゃないかと言われると返す言葉がありませんが。
なんなら bin/hubot
に1行 . /home/user/.nvm/nvm.sh
と書き足すのもいいかと思います。
以上、よき systemd ライフを。