Supervisorのインストールで起動スクリプトを書きたくなかったのでRPMから抽出して利用した話

f:id:akase244:20170928112758j:plain

こんにちは、エンジニアの @akase244 です。

プロセス管理ツールのSupervisorをAmazon Linux(version 2017.03)上にインストールする機会があったので、その際のインストールメモをザザッとまとめました。

インストール方法の種類

Amazon LinuxでSupervisorをインストールする方法は以下のようにいくつかあります。

  • yumコマンド(EPELリポジトリ)の場合
    • $ sudo yum --enablerepo=epel install supervisor
  • easy_installコマンドの場合
    • $ sudo easy_install supervisor
  • pipコマンドの場合
    • $ sudo pip install supervisor

2系と3系の違い

yumコマンドでのインストールは楽(といってもAmazon LinuxでインストールするとPythonのバージョンの問題でちょっとしたハマりどころがあるのでこの辺を参考にするとよいでしょう)ですが、yumでインストールされる2系とeasy_install/pipでインストールされる3系では、supervisorctlでの起動方法やオプションに違いがあります。

2系のsupervisorctlコマンドのオプション

$ supervisorctl help

Documented commands (type help <topic>):
========================================
EOF    exit  maintail  quit    restart   start   stop
clear  help  open      reload  shutdown  status  tail

2系のsupervisorctlコマンドによる起動時の指定方法

$ supervisorctl help start
start <processname>         Start a process.
start <processname> <processname> Start multiple processes
start all             Start all processes
  When all processes are started, they are started in
  priority order (see config file)

3系のsupervisorctlコマンドのオプション(2系と比較すると rereadupdate といったオプションが増えています)

$ supervisorctl help

default commands (type help <topic>):
=====================================
add    exit      open  reload  restart   start   tail
avail  fg        pid   remove  shutdown  status  update
clear  maintail  quit  reread  signal    stop    version

3系のsupervisorctlコマンドによる起動時の指定方法(2系と比較すると「start <gname>:*」の指定が増えています)

$ supervisorctl help start
start <name>        Start a process
start <gname>:*     Start all processes in a group
start <name> <name>   Start multiple processes or groups
start all     Start all processes

easy_installコマンドによるインストール手順

今回SupervisorをインストールするきっかけになったのはLaravelのQueueをプロセス監視したかったからなんですが、Laravelのドキュメントに「start <gname>:*」形式の設定例が記載されているため、ここではeasy_installコマンドを使って3系のSupervisorをインストールする手順を示します。

$ sudo easy_install supervisor
Searching for supervisor
Reading https://pypi.python.org/simple/supervisor/
Best match: supervisor 3.3.3
Downloading https://pypi.python.org/packages/31/7e/788fc6566211e77c395ea272058eb71299c65cc5e55b6214d479c6c2ec9a/supervisor-3.3.3.tar.gz#md5=0fe86dfec4e5c5d98324d24c4cf944bd
Processing supervisor-3.3.3.tar.gz
Writing /tmp/easy_install-z4eOFY/supervisor-3.3.3/setup.cfg
Running supervisor-3.3.3/setup.py -q bdist_egg --dist-dir /tmp/easy_install-z4eOFY/supervisor-3.3.3/egg-dist-tmp-lxgmqh
warning: no previously-included files matching '*' found under directory 'docs/.build'
creating /usr/local/lib/python2.7/site-packages/supervisor-3.3.3-py2.7.egg
Extracting supervisor-3.3.3-py2.7.egg to /usr/local/lib/python2.7/site-packages
Adding supervisor 3.3.3 to easy-install.pth file
Installing echo_supervisord_conf script to /usr/local/bin
Installing pidproxy script to /usr/local/bin
Installing supervisorctl script to /usr/local/bin
Installing supervisord script to /usr/local/bin

Installed /usr/local/lib/python2.7/site-packages/supervisor-3.3.3-py2.7.egg
Processing dependencies for supervisor
Searching for meld3>=0.6.5
Reading https://pypi.python.org/simple/meld3/
Best match: meld3 1.0.2
Downloading https://pypi.python.org/packages/45/a0/317c6422b26c12fe0161e936fc35f36552069ba8e6f7ecbd99bbffe32a5f/meld3-1.0.2.tar.gz#md5=3ccc78cd79cffd63a751ad7684c02c91
Processing meld3-1.0.2.tar.gz
Writing /tmp/easy_install-Eg0YVq/meld3-1.0.2/setup.cfg
Running meld3-1.0.2/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Eg0YVq/meld3-1.0.2/egg-dist-tmp-1evpS3
zip_safe flag not set; analyzing archive contents...
Moving meld3-1.0.2-py2.7.egg to /usr/local/lib/python2.7/site-packages
Adding meld3 1.0.2 to easy-install.pth file

Installed /usr/local/lib/python2.7/site-packages/meld3-1.0.2-py2.7.egg
Finished processing dependencies for supervisor

バージョンの確認

$ supervisord --version
3.3.3

インストールパスについて

↑のインストール手順を眺めてみると、実行結果に以下のようなインストールパスの記述が見つけられます。

Installing echo_supervisord_conf script to /usr/local/bin
Installing pidproxy script to /usr/local/bin
Installing supervisorctl script to /usr/local/bin
Installing supervisord script to /usr/local/bin

どうやら、Amazon Linuxのバージョンによって、インストールパスが「/usr/bin」や「/usr/local/bin」になるようです。

easy_installコマンドのオプションに「--script-dir (-s)」というのがあり、helpを確認すると「install scripts to DIR」との説明があるので、このオプションを試してみたところどうにもうまくいかず、「/usr/bin」にインストールできませんでした。

なので、今回は「/usr/bin」配下にシンボリックリンクを貼ることにしました。

$ cd /usr/bin
$ sudo ln -s /usr/local/bin/echo_supervisord_conf .
$ sudo ln -s /usr/local/bin/pidproxy .
$ sudo ln -s /usr/local/bin/supervisorctl .
$ sudo ln -s /usr/local/bin/supervisord .

Supervisorの設定ファイル(supervisord.conf)の準備

Supervisorの設定ファイルを出力してくれるecho_supervisord_confという便利なコマンドがあるので、これを使って /etc/supervisord.conf として作成します。

$ sudo sh -c "echo_supervisord_conf > /etc/supervisord.conf"

なぜパスを決め打ちで /etc/supervisord.conf として作成するかというと、ドキュメントにも書いてありますが、Supervisorの起動時に以下の順に supervisord.conf を検索し読み込むためです。なので、 /etc/supervisord.conf を作成しておけば自動的に設定ファイルが読み込まれるという訳です。(起動時に設定ファイルのパスを指定する「-c」オプションについては後ほど説明します)

  1. カレントの作業ディレクトリ/supervisord.conf
  2. カレントの作業ディレクトリ/etc/supervisord.conf
  3. /etc/supervisord.conf
  4. /etc/supervisor/supervisord.conf (バージョン3.3.0以降)
  5. ../etc/supervisord.conf
  6. ../supervisord.conf

起動スクリプトをRPMから抽出

さて、ようやく本題です。

起動スクリプトについては、Supervisorのリポジトリに準備されているので、これを使ってもよいのですが、今回はRPMから抽出する方法を試してみました。

RPMからファイルを取り出すにはrpm2cpioコマンドでRPMをcpio形式にし、さらにcpioコマンドで出力することでできます。

$ cd ~
$ mkdir supervisor_rpm
$ cd supervisor_rpm
$ curl -LO https://dl.fedoraproject.org/pub/epel/6/x86_64/supervisor-2.1-9.el6.noarch.rpm
$ mkdir rpm_files
$ cd rpm_files
$ rpm2cpio ../supervisor-2.1-9.el6.noarch.rpm | cpio -id
$ cd ~
$ sudo cp supervisor_rpm/rpm_files/etc/rc.d/init.d/supervisord /etc/init.d/

起動スクリプトの中身を見てみると、chkconfigが以下のような設定になっているので、起動する順番やランレベルについては適宜設定してください。

# chkconfig:    - 95 04

↑のchkconfigの設定から分かるようにランレベルが指定されていないので、 /etc/init.d/supervisord を何も修正せずに利用する場合は、以下のように手動で自動起動のランレベルを設定する必要があります。

$ sudo chkconfig --add supervisord
$ sudo chkconfig --level 345 supervisord on
$ sudo chkconfig --list supervisord
supervisord     0:off  1:off  2:off  3:on   4:on   5:on   6:off

ちなみに、Supervisorのリポジトリに準備されている起動スクリプトでは、以下のような設定になっているので、 sudo chkconfig --add supervisord するだけで、ランレベル3、4、5の場合に自動で起動するはずです。

# chkconfig:    345 83 04

起動スクリプトでのSupervisorの起動

$ sudo service supervisord start
supervisord を起動中: /usr/local/lib/python2.7/site-packages/supervisor-3.3.3-py2.7.egg/supervisor/options.py:298: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
  'Supervisord is running as root and it is searching '
                                                           [  OK  ]
$ sudo service supervisord status
supervisord (pid 2934) を実行中...

起動時の警告表示が気になる場合は、記載されているとおり起動スクリプトのstartのところに「-c」オプションを追加して設定ファイルのパスを渡してあげるとよいです。

$ sudo vim /etc/init.d/supervisord

変更前
start() {
        echo -n $"Starting supervisord: "
        daemon supervisord

変更後
start() {
        echo -n $"Starting supervisord: "
        daemon supervisord -c "/etc/supervisord.conf"

警告が表示されなくなりました。

$ sudo service supervisord restart
supervisord を停止中:                                      [  OK  ]
supervisord を起動中:                                      [  OK  ]

まとめ

ということで、Supervisorのインストールを例に取りながら、RPMからファイルを抽出する方法を説明しました。
今回の例のように、起動スクリプトが提供されていない場合などはRPMから取り出すと(必ずしもそのまま使えるとは限りませんが)準備する手間が省けるのでよいのではないでしょうか。