Symfoware

Symfowareについての考察blog

PythonからSupervisorのXML-RPC APIに接続する

DebianにSupervisorをインストールしたことがあります。
SupervisorでPythonのスクリプトをデーモンプロセスとして動かす

ふとしたことから、XML-RPCのAPIがあることに気が付きました。
XML-RPC API Documentation

使い方を調べてみます。


APIの有効化



APIを使用するには、Webインターフェースを有効にする必要があります。
SupervisorのWebインターフェースを有効にする

設定ファイルを編集


# vi /etc/supervisor/supervisord.conf




ファイルの末尾に設定を追記します。


[inet_http_server]
port = 0.0.0.0:9001
username = user
password = P@ssw0rd



portは、「IPアドレス:ポート番号」の形式で指定。
usernameとpasswordの項目はオプションですので、設定しなくてもOKです。



復習として、ジョブの追加は、/etc/supervisor/conf.dに
xxx.confという名前のファイルを作成して指定します。

設定値は以下の通り。
[program:x] Section Settings

確認用に適当な設定を行い、task.confという名前で保存しました。

/etc/supervisor/conf.d/task.conf


[program:task]
command=/opt/daemon/task.py
process_name=%(program_name)s_%(process_num)02d
numprocs=1 ; ワーカーを1プロセス起動する
autostart=true ; supervisord起動時に自動的に起動する
autorestart=true ; プロセスが死んでも自動的に起動する
redirect_stderr=true




設定が終わったら、supervisorを再起動。


# service supervisor restart




http://192.168.1.101:9001/でこんな画面が表示されれば準備完了です。

581_01.png




XML-RPCによる通信



このサーバーにXML-RPC通信で接続してみます。
XML-RPC API Documentation

Pythonのサンプルが載ってるなんて最高と思っていたのですが、
よく考えたらSupervisor自身がPython製でしたね。


サンプルを動かしてみます。
※Python3では、xmlrpc.client.ServerProxyになります。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://192.168.1.101:9001/RPC2')
  4. print(server.supervisor.getState())




実行してみると、Supervisorのステータスが表示されました。


$ python sample.py
{'statename': 'RUNNING', 'statecode': 1}





server.system.listMethods()で使用可能なメソッドの一覧が表示されます。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://192.168.1.101:9001/RPC2')
  4. print(server.system.listMethods())






各メソッドの使い方を参照するには、methodHelpを実行します。
server.system.methodHelp('supervisor.shutdown')


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://192.168.1.101:9001/RPC2')
  4. print(server.system.methodHelp('supervisor.shutdown'))




$ python sample.py
Shut down the supervisor process

        @return boolean result always returns True unless error







ユーザー名、パスワードを指定した接続



サーバー側でユーザー名、パスワードを設定している場合は、URLに


http://[ユーザー名]:[パスワード]@[サーバーIP]:[ポート]/RPC2



のように指定します。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://user:P@ssw0rd@192.168.1.101:9001/RPC2')
  4. print(server.supervisor.getState())




/etc/supervisor/supervisord.confでこんな設定を行っている場合、


[inet_http_server]
port = 0.0.0.0:9001
username = user
password = P@ssw0rd




接続するためのプログラムはこのようになります。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://user:P@ssw0rd@192.168.1.101:9001/RPC2')
  4. print(server.supervisor.getState())







プロセスの操作



起動しているプロセスの情報を取得してみます。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://user:P@ssw0rd@192.168.1.101:9001/RPC2')
  4. print(server.supervisor.getProcessInfo('task:task_00'))




$ python sample.py
{'now': 1425565114, 'group': 'task', 'description': 'pid 3145, uptime 0:05:47',
'pid': 3145, 'stderr_logfile': '/var/log/supervisor/task_00-stderr---supervisor-fnh9PT.log',
'stop': 0, 'statename': 'RUNNING', 'start': 1425564767, 'state': 20,
'stdout_logfile': '/var/log/supervisor/task_00-stdout---supervisor-nKHUF_.log',
'logfile': '/var/log/supervisor/task_00-stdout---supervisor-nKHUF_.log',
'exitstatus': 0, 'spawnerr': '', 'name': 'task_00'}




ちょっとはまったのは、指定する名前は
[グループ名]:[プロセス名]
で指定することです。

グループ名は、設定ファイルで[program:(名称)]で指定した文字列。
プロセス名は、process_nameで指定した名前になります。


[program:task]
command=/opt/daemon/task.py
process_name=%(program_name)s_%(process_num)02d




stopProcessで、起動しているtask:task_00プロセスを停止してみます。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://user:P@ssw0rd@192.168.1.101:9001/RPC2')
  4. print(server.supervisor.stopProcess('task:task_00'))



停止しました。

581_02.png


startProcessで起動してみます。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://user:P@ssw0rd@192.168.1.101:9001/RPC2')
  4. print(server.supervisor.startProcess('task:task_00'))



これで起動してくれました。




プロセスの標準入力に文字列を送信



APIリファレンスを見ていると、sendProcessStdinというのを見つけました。
文字列をプロセスの標準入力に書き込んでくれるようです。

task.pyを修正。
受け取った文字列をファイルに出力します。


  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. import sys
  4. def main():
  5.     
  6.     while(True):
  7.         command = raw_input()
  8.         with open('/opt/daemon/test.log', 'a') as f:
  9.             f.write('recv:%s\n' % command)
  10. if __name__ == '__main__':
  11.     main()





文字列を送る側のプログラムはこんなかんじです。


  1. # -*- coding:utf-8 -*-
  2. import xmlrpclib
  3. server = xmlrpclib.ServerProxy('http://user:P@ssw0rd@192.168.1.101:9001/RPC2')
  4. server.supervisor.sendProcessStdin('task:task_00', u'hello\n')




ポイントは、送る文字列の最後に改行コードを指定することでしょうか。
これがないと、raw_inputに入力が渡されません。


実行してみると、所定のファイルに文字列が書き込まれました。

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2015/03/06(金) 00:20:22|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Supervisor 「taif -f」のリンクにPythonのprint出力が表示されない | ホーム | Ubuntu 14.40 CopyCmdを使用して、Copy.comにファイルのアップロート、ダウンロード>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1672-49cb7e75
この記事にトラックバックする(FC2ブログユーザー)