LoginSignup
6
6

More than 5 years have passed since last update.

node.jsのWebアプリケーションをUpstartでサービス化する

Posted at

Upstartの記事に需要はあまりないと思いますが・・・

systemdが盛り上がってきている今どきUpstartの記事に需要はほとんどない気がしますが結構困ったので書いておきます。対象OSがCentOS6.6なんですよ・・・
だからupstartのバージョンもやたらと低いのでした。

# initctl --version
initctl (upstart 0.6.5)

やりたいこと

upstartからnpm startでexpressなどで作ったWebアプリケーションを起動したいのです。
しかもrootユーザーとしてではなく、実行ユーザー指定で。

expressで作ったアプリ
/home/vagrant/myapp (owner=vagrant ,group=vagrant)
├── app.js
├── bin
│   └── www
├── node_modules
├── package.json
├── public
├── routes
└── views
package.json
{
  "name": "myapp",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "jade": "~1.11.0",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0"
  }
}

結論

/etc/init/myapp.conf
start on [2345]
stop on [!2345]

chdir /home/vagrant/myapp

script
  source /etc/profile
  exec su --session-command "NODE_ENV=staging $NVM_BIN/npm start" vagrant
end script
$ sudo initctl start myapp
myapp start/running, process 22083

$ ps -ef | grep node
root     22083     1  0 23:25 ?        00:00:00 su --session-command NODE_ENV=staging /opt/nvm/versions/node/v0.12.7/bin/npm start vagrant
vagrant  22225 22218  4 23:25 ?        00:00:00 node ./bin/www

何に詰まったのか

1. nvmを使っている、PATHが通っていない

まず困ったのがnpmコマンドの場所です。
普通にターミナルから使うときはnvm use v0.12.7とするので下記のようにパスが通っているのですが

$ which npm
/opt/nvm/versions/node/v0.12.7/bin/npm

upstartから実行する際はパスが通っていないのでnpmコマンドのフルパスを指定する必要があります。
nvmを使っているのでv0.12.7の箇所をベタに書きたくありません。
nvmでuseされているnodeの場所は環境変数$NVM_BINに入っていますが、upstartから実行する場合は環境変数もすっからかんです。

で、何をやったのかというと、

/etc/profile.d/nvm.sh
source /opt/nvm/nvm.sh
nvm use v0.12.7

こうして、myapp.confのscriptでsource /etc/profileとしました。
これで環境変数$NVM_BINが使えます。

2. upstartのバージョンが1.4未満なのでsetuidが使えずsuコマンドで起動ユーザー指定

su -c "$NVM_BIN/npm start vagrant" これでいいだろと思っていたのでうが動かず…これにかなり悩みました。

なんでダメだったかというと、

$ man su

       -c, --command=COMMAND
              pass a single COMMAND to the shell with -c

       --session-command=COMMAND
              pass a single COMMAND to the shell with -c and do not create a new session
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^

ここのせいでした。 -c でコマンド実行するとシェルセッションが新たに作られると。このせいでUpstartがsuを実行するが、Upstartから見るとsuコマンドの実行プロセスがすぐ終わってしまったように見えるようだ。

しかし、この--session-commandオプションってあまり見たことが無い・・・。手元のUbuntu14.04のsuには無いようだ。CentOS6独特なのか?

http://qiita.com/bundai223/items/3ffdde28f5acbe4ea903 の記事だと-cオプションでやってるんだけどなぁ。

ちなみに、sudo でやった場合は、

$ sudo -u vagrant $NVM_BIN/npm start

> myapp@0.0.0 start /home/vagrant/myapp
> node ./bin/www

sh: node: コマンドが見つかりません

こんな感じで、pakcage.json のstartに書かれているnode のパスが解決できないという…

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6