English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Pythonのプロセス管理ツールsupervisorの使用ガイド

SupervisorはPythonに基づいたプロセス管理ツールで、Unix上でのみ実行できます。-Likeのシステム上では、つまりWindows上で実行できないです。Supervisorの公式版は現在、Python上でのみ実行できます。 2.4 の以上のバージョンですが、まだPython上で実行できません。 3 上,ただし既にPythonがあります 3 の移植版 supervisor-py3k

什么情况下我们需要进程管理呢?就是执行一些需要以守护进程方式执行的程序,比如一个后台任务,我最常用的是用来启动和管理基于 Tornado 写的 Web 程序。

除此之外,Supervisor 还能很友好的管理程序在命令行上输出的日志,可以将日志重定向到自定义的日志文件中,还能按文件大小对日志进行分割。

Supervisor 有两个主要的组成部分:

  1. supervisord,运行 Supervisor 时会启动一个进程 supervisord,它负责启动所管理的进程,并将所管理的进程作为自己的子进程来启动,而且可以在所管理的进程出现崩溃时自动重启。
  2. supervisorctl,是命令行管理工具,可以用来执行 stop、start、restart 等命令,来对这些子进程进行管理。

安装

sudo pip install supervisor

创建配置文件

echo_supervisord_conf > /etc/supervisord.conf

如果出现没有权限的问题,可以使用这条命令

sudo su - root -c "echo_supervisord_conf > /etc/supervisord.conf"

配置文件说明

想要了解怎么配置需要管理的进程,只要打开 supervisord.conf 就可以了,里面有很详细的注释信息。

打开配置文件

vim /etc/supervisord.conf

默认的配置文件是下面这样的,但是这里有个坑需要注意,supervisord.pid 以及 supervisor.sock 是放在 /tmp 目录下,但是 /tmp 目录是存放临时文件,里面的文件是会被 Linux 系统删除的,一旦这些文件丢失,就无法再通过 supervisorctl 来执行 restart 和 stop 命令了,将只会得到 unix:///tmp/supervisor.sock 不存在的错误 。

[unix_http_server]
;file=/tmp/supervisor.sock  ; (the path to the socket file)
;変更します /var/run ディレクトリ、システムによって削除されないようにします
file=/var/run/supervisor.sock  ; (the path to the socket file)
;chmod=0700         ; socket file mode (default 0700)
;chown=nobody:nogroup    ; socket file uid:gid owner
;username=user       ; (デフォルトはユーザー名なし(オープンサーバー))
;password=123        ; (デフォルトはパスワードなし(オープンサーバー))
;[inet_http_server]     ; inet (TCP) サーバーはデフォルトで無効
;port=127.0.0.1:9001    ; (ip_address:port specifier, *:port for ;all iface)
;username=user       ; (デフォルトはユーザー名なし(オープンサーバー))
;password=123        ; (デフォルトはパスワードなし(オープンサーバー))
...
[supervisord]
;logfile=/tmp/supervisord.log ; (メインログファイル;デフォルト $CWD/supervisord.log)
;変更します /var/log ディレクトリ、システムによって削除されないようにします
logfile=/var/log/supervisor/supervisord.log ; (メインログファイル;デフォルト $CWD/supervisord.log)
logfile_maxbytes=50MB    ; (メインログファイルの最大バイト数 b4 rotation;デフォルト 50MB)
logfile_backups=10      ; (メインログファイルのリローテーションバックアップの数;デフォルト 10)
loglevel=info        ; (ログレベル;デフォルト info; その他: debug,warn,trace)
;pidfile=/tmp/supervisord.pid ; (supervisord pidfile;デフォルト supervisord.pid)
;変更します /var/run ディレクトリ、システムによって削除されないようにします
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;デフォルト supervisord.pid)
...
;supervisordの起動ユーザーを設定します。一般的には、rootユーザーで起動することは避け、本当にそのようにする必要がある場合は除けりません
;user=chrism         ; (デフォルトは現在のユーザー、rootの場合には必要,デフォルト)
...
[supervisorctl]
; 必ず 'unix_http_server' 内の設定と一致する必要があります
;serverurl=unix:///tmp/supervisor.sock;ユニックスOCKETを使用します:// ユニックスOCKETのURL
;変更します /var/run ディレクトリ、システムによって削除されないようにします
serverurl=unix:///var/run/supervisor.sock;ユニックスOCKETを使用します:// ユニックスOCKETのURL
;serverurl=http://127.0.0.1:9001 ; http:を使用する// inetソケットを指定するURL
;username=chris       ; 設定されている場合、http_usernameと同じであるべきです
;password=123        ; 設定されている場合、http_passwordと同じであるべきです
...

デフォルトでは、プロセスのログファイルは50MB に達した場合、分割が行われ、最大で保留されます10ファイル、もちろんこれらの設定は各プロセスごとに個別に設定することもできます。

権限問題

設定ファイルを設定した後、上記の設定ファイルで追加されたフォルダーを作成する必要があります。起動ユーザー user が指定されている場合、ここでは oxygen を例にしますが、関連するファイルの権限問題、特にログファイルに注意してください。そうしないと、権限がないエラーが発生します。例えば、起動ユーザー oxygen を設定して supervisord を起動すると、エラーが発生します

エラー: HTTP サーバーを開くことができません: socket.error が errno.EACCES で報告されました (13)

上記の設定ファイルのために /var/run フォルダーには、supervisord の起動ユーザー oxygen に書き込み権限が付与されていません。/var/runフォルダーは実際にはリンクされている /runが実行されないため、以下のように修正します /runの権限

sudo chmod 777 /run

これは少し単純で強引ですが、上記の設定ファイルの .sock、.pid などのファイルを他のフォルダーに移動し、適切な権限を確保することも考慮できます。一般的には、rootユーザーでsupervisordプロセスを起動し、その管理するプロセスで必要に応じて特定のユーザーでこれらのプロセスを起動することができます。

ブラウザを使用して管理

supervisorは、ブラウザを使用してプロセスを管理する方法も提供しています。以下の行をコメントアウトするだけで良いです。

;[inet_http_server]     ; inet (TCP) サーバーはデフォルトで無効
;port=127.0.0.1:9001    ; (ip_address:port specifier, *:port for ;all iface)
;username=user       ; (デフォルトはユーザー名なし(オープンサーバー))
;password=123        ; (デフォルトはパスワードなし(オープンサーバー))
[supervisorctl]
...
;serverurl=http://127.0.0.1:9001 ; http:を使用する// inetソケットを指定するURL
;username=chris       ; 設定されている場合、http_usernameと同じであるべきです
;password=123        ; 設定されている場合、http_passwordと同じであるべきです

 

includeの使用

設定ファイルの最後に、[include]の設定項目があります。Nginxのように、特定のフォルダー内のすべての設定ファイルをincludeすることができます。これにより、各プロセスまたは関連するいくつかのプロセスの設定をそれぞれのファイルに分けて書くことができます。

[include]
files = /etc/supervisord.d/*.ini

プロセスの設定例

以下は簡単な例です

; プロセスの名前を設定します。supervisorctlを使ってプロセスを管理する場合は、このプロセス名を使用する必要があります
[program:your_program_name] 
command=python server.py --port=9000
;numprocs=1         ; デフォルトは1
;process_name=%(program_name)s  ; デフォルトは %(program_name)s、つまり [program:x] の x
directory=/home/python/tornado_server ; commandを実行する前に、作業ディレクトリに切り替えます
user=oxygen         ; このプロセスを起動するために oxygen ユーザーを使用
; プログラムがクラッシュした場合に自動的に再起動します。再起動回数は制限されています。デフォルトは3回
autorestart=true      
redirect_stderr=true    ; 出力のログをリダイレクト
stdout_logfile = /var/log/supervisord/tornado_server.log
loglevel=info

ログレベルを設定

loglevel はログのレベルを指定します。Pythonの print 文を使って出力されるログは、ログファイルに記録されません。Pythonの logging モジュールを使って指定されたレベルのログを出力する必要があります。

複数のプロセス

公式ドキュメントの定義によると、[program:x] は実際には同じ特徴や同種のプロセスグループを表しており、つまり [program:x] は複数のプロセスを起動できるという意味です。このプロセスグループのメンバーは numprocs と process_name の二つのパラメータで決定されます。この文が何を意味しているのか、この例を見てみましょう。

; プロセスの名前を設定します。supervisorctlを使ってプロセスを管理する場合は、このプロセス名を使用する必要があります
[program:foo] 
; command ここで python 式を使って各プロセスに異なるパラメータを渡すことができます
command=python server.py --port=90%(process_num)02d
directory=/home/python/tornado_server ; commandを実行する前に、作業ディレクトリに切り替えます
; numprocs が1、process_name の表現式中は必ず process_num を含めて異なるプロセスを区別する必要があります
numprocs=2          
process_name=%(program_name)s_%(process_num)02d; 
user=oxygen         ; このプロセスを起動するために oxygen ユーザーを使用
autorestart=true      ; プログラムがクラッシュした場合に自動的に再起動
redirect_stderr=true    ; 出力のログをリダイレクト
stdout_logfile = /var/log/supervisord/tornado_server.log
loglevel=info

この例では、process_name が foo:foo_0 の二つのプロセスが起動されます1 そして foo:foo_02この方法により、[program:x] 設定項目を使って非常に似たプロセスを一組起動することができます。

さらに二つの設定項目を紹介します stopasgroup と killasgroup

; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发送给该进程的子进程。如果这个配置项为 true,那么也隐含 killasgroup 为 true。例如在 Debug 模式使用 Flask 时,Flask 不会将接收到的 stop 信号也传递给它的子进程,因此就需要设置这个配置项。

stopasgroup=false       ; 向 UNIX 进程发送停止信号 
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发送给该进程的子进程。如果这个程序使用了 python 的 multiprocessing 时,就能自动停止它的子线程。
killasgroup=false       ; 发送 SIGKILL 到 UNIX 进程组(默认 false)

更详细的配置示例,可以参考以下内容,官方文档在此处

;[program:theprogramname]
;command=/bin/cat       ; 程序(相对路径使用 PATH,可以接受参数)
;process_name=%(program_name)s ; process_name 表达式(默认 %(program_name)s)
;numprocs=1          ; 要启动的进程副本数(默认) 1)
;directory=/tmp        ; 执行前的当前工作目录(默认无 cwd)
;umask=022           ; 进程的 umask(默认 None)
;priority=999         ; 相対的なスタート優先度(デフォルト) 999)
;autostart=true        ; 在 supervisord 启动时启动(默认:true)
;autorestart=unexpected    ; 是否/何时重启(默认:意外)
;startsecs=1          ; 必须保持运行的时间(默认) 1)
;startretries=3        ;シリアルスタート失敗の最大数 (デフォルト 3)
;exitcodes=0,2         ;プロセスの'期待される'終了コード (デフォルト 0,2)
;stopsignal=QUIT ; プロセスを殺すために使用されるシグナル (デフォルト TERM)
;stopwaitsecs=10        ;待機する最大秒数 b4 SIGKILL (デフォルト 10)
;stopasgroup=false ; UNIXプロセスグループに停止シグナルを送信する (デフォルト false)
;killasgroup=false ; UNIXプロセスグループにSIGKILL (デフォルト false)
;user=chrism ; プログラムを実行するUNIXアカウントにsetuidする
;redirect_stderr=true ; procのstderrをstdoutにリダイレクトする (デフォルト false)
;stdout_logfile=/a/path ; stdoutログパス, NONE は無し; デフォルト AUTO
;stdout_logfile_maxbytes=1MB ; 最大ログファイルバイト数 b4 rotation (デフォルト 50MB)
;stdout_logfile_backups=10   ; stdoutログファイルのバックアップ数 (デフォルト 10)
;stdout_capture_maxbytes=1MB  ; 'capturemode' におけるバイト数(デフォルト 0)
;stdout_events_enabled=false ; stdout書き込み時にイベントを発行する (デフォルト false)
;stderr_logfile=/a/path ; stderrログパス, NONE は無し; デフォルト AUTO
;stderr_logfile_maxbytes=1MB ; 最大ログファイルバイト数 b4 rotation (デフォルト 50MB)
;stderr_logfile_backups=10   ; # of stderr logfile backups(デフォルト) 10)
;stderr_capture_maxbytes=1MB  ; 'capturemode' におけるバイト数(デフォルト 0)
;stderr_events_enabled=false  ; stderrの書き込みにイベントを発行(デフォルト false)
;environment=A="1",B="2"    ; プロセス環境の追加(デフォルトでは追加なし)
;serverurl=AUTO        ; serverurlの計算をオーバーライド(childutils)

複数のプロセスをグループごとに管理します。

Supervisor はまた、別のプロセスグループの管理方法も提供しており、この方法では supervisorctl コマンドを使ってプロセスグループを管理できます。[program:x] のプロセスグループとは異なり、ここではプロセスは個々の [program:x] です。

[group:thegroupname]
programs=progname1,progname2 ; 各のは [program:x] 定義の 'x' を指します。
; priority=999         ; 相対的なスタート優先度(デフォルト) 999)

上記の設定を追加した後は、progname1 progname2 のプロセス名は thegroupname:progname に変わります。1 と thegroupname:progname2 以降はこの名前を使ってプロセスを管理する必要があります。それ以前は progname ではなく、the groupname:progname でした。1。

以降、supervisorctl stop thegroupname: で progname を同時に終了できます。1 progname2、supervisorctl stop thegroupname:prognameを実行します。1 progname を終了することができます。1。supervisorctlのコマンドは後で説明します。

supervisord の起動

supervisord コマンドを実行すると、supervisord プロセスが起動し、設定ファイルで指定したプロセスも対応して起動します。

# 使用默认的配置文件 /etc/supervisord.conf
supervisord
# 明确指定配置文件
supervisord -c /etc/supervisord.conf
# 使用 user 用户启动 supervisord
supervisord -u user

更多参数请参考文档

supervisorctl 命令介绍

# 停止某一个进程,program_name 为 [program:x] 里的 x
supervisorctl stop program_name
# 启动某个进程
supervisorctl start program_name
# 重启某个进程
supervisorctl restart program_name
# 结束所有属于名为 groupworker 这个分组的进程 (start,restart 同理)
supervisorctl stop groupworker:
# 结束 groupworker:name1 这个进程 (start,restart 同理)
supervisorctl stop groupworker:name1
# 停止全部进程,注:start、restart、stop 都不会载入最新的配置文件
supervisorctl stop all
# 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程
supervisorctl reload
# 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启
supervisorctl update

注意:显示用 stop 停止掉的进程,用 reload 或者 update 都不会自动重启。也可以参考这里

开机自动启动 Supervisord

Supervisord 默认情况下并没有被安装成服务,它本身也是一个进程。官方已经给出了脚本可以将 Supervisord 安装成服务,可以参考这里查看各种操作系统的安装脚本,但是我用官方这里给的 Ubuntu 脚本却无法运行。

安装方法可以参考 serverfault 上的回答。

比如我是 Ubuntu 系统,可以这么安装,这里选择了另外一个脚本

# 下载脚本
sudo su - root -c "sudo curl https://gist.githubusercontent.com/howthebodyworks/176149/raw/d60b505a585dda836fadecca8f6b03884153196b/supervisord.sh > /etc/init.d/supervisord"
# このスクリプトを実行可能に設定
sudo chmod +x /etc/init.d/supervisord
# 起動時に自動的に実行するように設定
sudo update-rc.d supervisord defaults
# 正常に動作しているか確認
service supervisord stop
service supervisord start

注意:このスクリプトをダウンロードした後は、私たちの設定と一致しているか確認してください。例えば、デフォルトの設定ファイルパス、pidファイルパスなど、異なる場合は変更が必要です

実際には、Linuxが起動する際に実行されるため、簡単な方法があります /etc/rc.localに含まれるスクリプトに、ここで実行コマンドを追加するだけで良い

# Ubuntuの場合、以下の内容を追加
/usr/local/bin/supervisord -c /etc/supervisord.conf
# Centosの場合、以下の内容を追加
/usr/bin/supervisord -c /etc/supervisord.conf

以下の内容はexitコマンドの前に追加する必要があり、rc.localスクリプトの実行時にはPATH環境変数が完全に初期化されていないため、絶対パスを使用する必要があります

追加前に、ターミナルでコマンドが正常に実行できるかテストしてください。supervisordが見つからない場合は、以下のコマンドを使用して見つけることができます

sudo find / -name supervisord

声明:本文の内容はインターネットから取得しており、著作権者に帰属します。インターネットユーザーにより自発的に貢献し、アップロードされたコンテンツであり、本サイトは所有権を有しておらず、編集も行われていません。著作権侵害を疑う内容があれば、メールを送信してください:notice#oldtoolbag.com(メール送信時は、#を@に変更してください)で通報し、関連証拠を提供してください。一旦確認が取れましたら、本サイトは即座に侵害疑いのコンテンツを削除します。

おすすめ