2011年6月20日月曜日

Process.su と upstart

ruby で su (のようなことを)するメソッドを作った。

実際行うのは UID,EUID,GID,EGID の変更で、Process クラスメソッドとして追加

process_su.rb
def Process.su(file)
  fstat = File::Stat.new file
  if fstat.uid != uid
    self.gid = self.egid = fstat.gid
    self.uid = self.euid = fstat.uid
  end
end

この Process.su メソッドは引数としてファイル名を受け取る。やることは引数に与えられたファイルの uid を調べ、もしプロセスの uid と一致していなければプロセスの uid,euid,gid,egid をファイルのものにそろえる。

あるユーザが以下の ruby スクリプトファイルを普通に作成し実行した場合、ファイルのオーナーとプロセスのオーナーが同じなのでそのユーザーのプロセスが起動するだけである。

sleep.rb
require 'process_su'
Process.su __FILE__
sleep

次に root でこのスクリプトを実行すると root ではなく、スクリプトファイルオーナーのプロセスとして起動する。このスクリプトを upstart からキックすると好きなユーザーをオーナーにした sleep だけを行うデーモンを立てることができる。

この仕組みを使って Redmine を upstart で起動するようにしてみた。

/etc/init/redmine.conf
start on started postgres
stop on  stopping postgres

exec /usr/local/ruby-1.8.7/bin/ruby /home/shingo/Redmine/script/server -e production 2>> /home/shingo/Redmine/log/production.log

Ubuntu11 で初めて upstart を触ったが man 5 init を読むと便利な仕組みであることがわかった。上のように /etc/init/redmine.conf を書いておけば、postgres が起動したら redmine を上げるように、また postgres が止まる前に redmine をとめるようになどの指定ができる。.conf の拡張子をつけた設定ファイルを /etc/init/以下にファイルを入れておくだけでinit が読み込んでくれる。ファイルの変更も監視され適宜 init が新しい情報に基づいてプロセスの上げ下げをしてくれるようだ(二重起動もチェックしてくれる)。

もちろんこれだけでは駄目でRedmine の script/server の先頭に以下の2行を加える。
require 'process_su'
Process.su __FILE__

これで mongrel が自分のユーザー権限で動くようになる。加えて PostgreSQL の起動設定も必要(自分のところではソースからビルドしている)。以下のように /etc/init/postgres.conf を作る。 postgres.conf というファイル名にするとupstart 上の名前がpostgres になり、上記の redmine.conf にあるstart on started postgres が意味を持つようになる。

start on filesystem
stop on runlevel [016]

exec /usr/local/ruby-1.9.2/bin/ruby /home/shingo/PostgresData/postgres_startup

そして、これでキックしている postgres_startup も Process.su を使っている:
require 'process_su'

Process.su __FILE__

system '/usr/local/pgsql/bin/postgres -D /home/shingo/PostgresData > /dev/null 2>> /home/shingo/PostgresData/postgres.log'

sleep

最後に自分自身の為に備忘しておくと、redmine(rails) も postgres もdaemonize は upstart ( initctl )にお任せすること。これによって二重起動や停止、再起動などをすべて initctl 管理のもとで行うことができるようなにる。例えば
initctl stop postgres
とすれば redmine(rails) が止まったのち postgres が SIGINT で正常に終わってくれるし、もう一度
intctl start postgres
すればpostgres が上げてから redmnine を起動してくれる。

upstart 気に入ってしまった。

0 件のコメント:

コメントを投稿