如何在Supervisord管理的进程中获取配置属性并实现日志拆分?
问题1:如何在Supervisord所管理的进程中获取其配置属性?
嘿,其实Supervisord会自动把进程的配置信息通过环境变量传递给它管理的子进程,你直接在Python代码里读取这些环境变量就可以拿到想要的配置啦!
这些环境变量都是以SUPERVISOR_开头的,对应你配置里的各个字段:
SUPERVISOR_PROGRAM_NAME:就是你配置里program:后面的名称(比如你的例子里是automate_test_sessions_bigquery)SUPERVISOR_COMMAND:启动进程的完整命令(对应配置里的command字段)SUPERVISOR_STDOUT_LOGFILE:标准输出日志的路径(对应stdout_logfile)SUPERVISOR_STDERR_LOGFILE:标准错误日志的路径(对应stderr_logfile)SUPERVISOR_NUMPROCS:进程的数量(对应numprocs)
给你个Python代码示例,直接用就行:
import os # 获取当前程序名 program_name = os.environ.get('SUPERVISOR_PROGRAM_NAME') # 获取stdout日志路径 stdout_log_path = os.environ.get('SUPERVISOR_STDOUT_LOGFILE') # 获取stderr日志路径 stderr_log_path = os.environ.get('SUPERVISOR_STDERR_LOGFILE') # 获取启动命令 start_command = os.environ.get('SUPERVISOR_COMMAND')
如果你需要更全的配置信息,也可以通过Supervisord的XML-RPC接口查询,但这个需要你的进程能访问到Supervisord的RPC服务(一般是UNIX socket或者TCP端口),不过大多数场景下,读环境变量已经足够方便啦!
问题2:如何让Python2.7的logger分别将普通日志和error日志写入Supervisord配置的对应文件?
其实我更推荐你利用Supervisord本身的日志重定向能力,而不是手动拆分流——因为Supervisord本来就会把进程的stdout和stderr分别写到你配置的a.out.log和a.err.log里,你只需要让Python的logger把普通日志输出到stdout,错误日志输出到stderr就行,这样既简单又不容易出问题。
先给你看这种推荐方式的代码:
import logging import sys # 初始化logger logger = logging.getLogger('automate_test_logger') logger.setLevel(logging.DEBUG) # 清空默认的handler,避免重复输出 logger.handlers = [] # 配置普通日志输出到stdout stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setLevel(logging.INFO) # 处理INFO及以下的日志(可根据需求调整) # 设置日志格式,你可以根据自己的需要修改 log_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') stdout_handler.setFormatter(log_formatter) # 配置错误日志输出到stderr stderr_handler = logging.StreamHandler(sys.stderr) stderr_handler.setLevel(logging.ERROR) # 只处理ERROR及以上的日志 stderr_handler.setFormatter(log_formatter) # 把handler添加到logger logger.addHandler(stdout_handler) logger.addHandler(stderr_handler) # 测试一下 logger.info('这是一条普通日志,会被Supervisord写到a.out.log') logger.error('这是一条错误日志,会被Supervisord写到a.err.log')
如果你确实需要手动让logger直接写入指定文件(不依赖Supervisord的重定向),那也可以这么做:
import logging logger = logging.getLogger('automate_test_logger') logger.setLevel(logging.DEBUG) logger.handlers = [] # 创建普通日志的文件handler stdout_file_handler = logging.FileHandler('/tmp/a.out.log') stdout_file_handler.setLevel(logging.INFO) log_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') stdout_file_handler.setFormatter(log_formatter) # 创建错误日志的文件handler stderr_file_handler = logging.FileHandler('/tmp/a.err.log') stderr_file_handler.setLevel(logging.ERROR) stderr_file_handler.setFormatter(log_formatter) logger.addHandler(stdout_file_handler) logger.addHandler(stderr_file_handler)
不过这里要注意几个坑:
- 要确保你的Python进程有写入
/tmp目录的权限,不然日志写不进去 - 如果你同时用了
logging.basicConfig,一定要先清空logger的默认handler,不然会出现重复日志 - 手动写文件的话,后期如果修改Supervisord的日志路径,你还要同步修改代码,不如第一种方式灵活
内容的提问来源于stack exchange,提问作者kawadhiya21
相关产品推荐
相关产品推荐

