geoffroy-aubry / supervisor
监控脚本执行,记录标准输出、标准错误和退出代码,并添加时间戳,确保在开始、成功、警告或错误时发送电子邮件通知。
Requires
Requires (Dev)
- php: >=5.3.3
- geoffroy-aubry/helpers: 1.*
- phpunit/phpunit: >=3.7
README
估计代码覆盖率: 87% (553 of 638 lines).
监控脚本执行,记录 stdout
、stderr
和退出代码,并添加时间戳,确保在启动、成功、警告或错误时发送电子邮件通知……以及其他许多功能。
技术 : Supervisor 使用 Bash,只有单元测试使用 PHP。
支持的操作系统 : Debian/Ubuntu Linux,FreeBSD/OS X。
目录
功能
通用
- 监控脚本执行,记录
stdout
、stderr
和退出代码 - 在
stdout
的每一行前加上秒级的时间戳。 - 执行 ID 唯一标识每次脚本执行。用于:
supervisor.info.log
、supervisor.error.log
、<script>_<exec_id>.info.log
和<script>_<exec_id>.error.log
。 - 可以阻止并行脚本执行 (仅限 Debian/Ubuntu Linux)。如果执行时间过长,这很有用……
- 可以指定一个配置文件来加载(覆盖默认配置文件)。
- 完全可配置的标签系统,允许执行脚本通过
stdout
动态指定警告、mailto、邮件附件、发起者等。 - 自动日志存档机制。
- 显示过去几天内 Supervisor 的活动摘要,包括每天每个被监控脚本的最终状态。
- 处理 CSV 输出,配置文件中定义了字段分隔符、字段封装符和要监视的字段数量。
- 添加适当的信号处理和中断:
SIGHUP
、SIGINT
、SIGQUIT
和SIGTERM
现在已传输到被监控脚本。
通知
- 确保在以下事件(可配置)上发送电子邮件通知:启动、成功、警告或错误。捕获退出代码、致命错误、异常……
- 所有邮件都包含执行的脚本
stdout
和stderr
的内容,以 Gzip 附件形式提供。 - 邮件可以完全自定义。只需在命令行上提供你的文件。
- 可以在命令行上将多个外部参数注入到自定义电子邮件中。
- Supervisor 本身由另一个进程监控,使用指数退避算法在分钟递增中发送关键电子邮件通知。
人体工程学
- 在监控期间,除了所有日志文件外,Supervisor 还实时显示被监控脚本的输出、警告和错误,添加时间戳,并尊重颜色和缩进。还打印所有日志文件名称。
代码质量
- 使用以下指令执行的Bash代码
set -o nounset
:当执行参数扩展时,将未设置变量和其他参数(除了特殊参数@
或*
)视为错误。错误信息将被写入标准错误,非交互式shell将退出。set -o pipefail
:管道的返回值是最后(最右边)退出状态非零的命令的返回值,或者如果管道中的所有命令都成功退出,则为零。
- 大量单元测试(通过PHPUnit通过PHP包装器)覆盖了几乎整个应用程序。
需求
-
Bash v4(2009)及以上版本
-
mutt,用于发送邮件通知(
apt-get install mutt
或brew install mutt
) -
单元测试需要PHP >= 5.3.3和Xdebug
-
仅限FreeBSD/OS X,您需要安装以下GNU工具
$ brew install coreutils $ brew install gnu-sed $ brew install gawk
在Debian/Ubuntu Linux和FreeBSD/OS X上进行了测试。
使用
命令提示符帮助
由
$ supervisor.sh [-h|--help]
文本版本
Description
Oversee script execution, recording stdout, stderr and exit code with timestamping,
and ensure email notifications will be sent (on start, success, warning or error).
Usage
supervisor [OPTION]… <script-path> [<script-parameters>]
supervisor [-c <conf-file>] --archive=<min-days>
supervisor [-c <conf-file>] --monitor
supervisor [-c <conf-file>] --summarize
Options
--archive=<min-days>
Archive in Gzip supervisor's logs older than <min-days>.
-c <conf-file>, --conf=<conf-file>
Specify a configuration file to load in addition to the default one,
namely '/conf/supervisor-dist.sh'.
--customized-mails=<file>
Path to a Bash script customizing sent mails by redefining some of
the sendMailOn[Init|Success|Warning|Error]() functions.
See --param option.
--exec-id=<string>
Allow to force execution id, used in mails and name of logs.
By default: YYYYMMDDHHIISS_XXXXX, where X are random digits.
--extra-param-mode=[only-value|with-name|none]
Two extra parameters are added to the end of <script-parameters>: a unique
execution ID and name of file recording script's stderr. with-name mode prefixes
values with '--exec-id=' and '--error-log-file=' respectively.
By default: only-value.
-h, --help
Display this help.
--mail-instigator=<email>
Specify who executed the supervisor.
--mail-to=<email>
Add a new recipient's email address. Multiple --mail-to options may be used.
--monitor
Check whether supervisor's error log file is empty. If not, then send critical
email notifications using an exponential backoff algorithm in minute increments.
Typically called every minute with a cron job:
* * * * * <user> /path/to/supervisor.sh --conf=<conf-file> --monitor
-p <key>=<value>, --param=<key>=<value>
Allow to inject multiple external parameters into customized emails.
Assign the value <value> to the Bash variable $EXT_<key>.
See --customized-mails option.
--summarize=<max-nb-days>
Display a summary of supervisor's activity during last <max-nb-days> days,
including final status per day and per supervised script.
Also send this summary by email.
<script-path>
Executable script to oversee.
<script-parameters>
Optional oversaw script's parameters.
Exit status
0 if and only if no error
65 Missing script name!
66 Script '…' not found!
67 Script '…' is not executable!
68 Exit code changed from 0 to 68 due to errors.
69 Another instance of '…' is still running with supervisor!
71 Customized mails file not found: '…'
72 Invalid Mutt command: '…'
xxx Any code not null returned by user script
退出状态
退出状态列表
0
如果且仅如果没有错误65
缺少脚本名称!66
脚本 '…' 未找到!67
脚本 '…' 不可执行!68
由于错误,退出代码从0更改为68。69
'…' 的另一个实例仍在运行中,带有supervisor!71
找不到自定义邮件文件:'…'72
无效的mutt命令:'…'- 用户脚本返回的非空代码
成功执行
如果且仅当标准错误为空、退出状态为0
且没有警告时,执行成功。
一个简短的例子,这里在Bash中,但无论语言如何
#!/usr/bin/env bash echo Title: echo -e '\033[0;30m┆\033[0m \033[1;32mgreen level 1' echo -e '\033[0;30m┆\033[0m \033[0;30m┆\033[0m \033[1;33myellow level 2' echo 'END'
输出
如果配置文件中将SUPERVISOR_MAIL_SEND_ON_STARTUP
设置为1
请注意,Supervisor除了脚本参数外,还添加了两个参数
- 唯一的执行ID
- 记录脚本
stderr
的文件名
如果配置文件中将SUPERVISOR_MAIL_SEND_ON_SUCCESS
设置为1
supervisor.info.log.20131006223705_01765.gz
附件的内容
2013-10-06 22:37:05 58cs;20131006223705_01765;/usr/local/lib/supervisor/tests/resources/bash_colored_simple.sh;START
2013-10-06 22:37:05 78cs;20131006223705_01765;/usr/local/lib/supervisor/tests/resources/bash_colored_simple.sh;OK
bash_colored_simple.sh.20131006223705_01765.info.log.gz
附件的内容
2013-10-06 22:37:05 58cs;[SUPERVISOR] START
2013-10-06 22:37:05 74cs;Title:
2013-10-06 22:37:05 75cs;┆ green level 1
2013-10-06 22:37:05 76cs;┆ ┆ yellow level 2
2013-10-06 22:37:05 77cs;END
2013-10-06 22:37:05 78cs;[SUPERVISOR] OK
请注意,颜色已被删除,但缩进被保留。
错误
如果标准错误不为空或退出状态与0
不同,则执行将以错误状态结束。
PHP致命错误
我们将观察一个抛出致命错误的PHP脚本
<?php undefined_fct();
输出
如果配置文件中将SUPERVISOR_MAIL_SEND_ON_ERROR
设置为1
supervisor.info.log.20131006223703_01618.gz
附件的内容
2013-10-06 22:37:03 42cs;20131006223703_01618;/usr/local/lib/supervisor/tests/resources/php_fatal_error.php;START
2013-10-06 22:37:03 59cs;20131006223703_01618;/usr/local/lib/supervisor/tests/resources/php_fatal_error.php;ERROR
php_fatal_error.php.20131006223703_01618.info.log.gz
附件的内容
2013-10-06 22:37:03 42cs;[SUPERVISOR] START
2013-10-06 22:37:03 59cs;[SUPERVISOR] ERROR
php_fatal_error.php.20131006223703_01618.error.log.gz
附件的内容
PHP Fatal error: Call to undefined function undefined_fct() in /usr/local/lib/supervisor/tests/resources/php_fatal_error.php on line 4
PHP Stack trace:
PHP 1. {main}() /usr/local/lib/supervisor/tests/resources/php_fatal_error.php:0
[SUPERVISOR] Exit code not null: 255
其他错误
同样,下面提供的脚本以错误状态结束。
请注意,当标准错误非空而退出状态为0
时,Supervisor将退出状态从0
更改为68
(参见退出状态)。
PHP通知
tests/resources/php_notice.php
的内容
<?php $a = $b;
结果在php_notice.php.[…].error.log.gz
附件中
PHP Notice: Undefined variable: b in /usr/local/lib/supervisor/tests/resources/php_notice.php on line 4
PHP Stack trace:
PHP 1. {main}() /usr/local/lib/supervisor/tests/resources/php_notice.php:0
[SUPERVISOR] Exit code changed from 0 to 68 due to errors.
PHP异常
tests/resources/php_exception.php
的内容
<?php throw new RuntimeException("It's an error!\n", 42);
结果在php_exception.php.[…].error.log.gz
附件中
PHP Fatal error: Uncaught exception 'RuntimeException' with message 'It's an error!
' in /usr/local/lib/supervisor/tests/resources/php_exception.php:4
Stack trace:
#0 {main}
thrown in /usr/local/lib/supervisor/tests/resources/php_exception.php on line 4
[SUPERVISOR] Exit code not null: 255
PHP标准错误
tests/resources/php_stderr.php
的内容
<?php // file_put_contents('php://stderr', "It's an error!\n"); // or: fwrite(STDERR, "It's an error!\n");
结果在php_stderr.php.[…].error.log.gz
附件中
It's an error!
[SUPERVISOR] Exit code changed from 0 to 68 due to errors.
退出非空
tests/resources/bash_exit_not_null.sh
的内容
#!/usr/bin/env bash exit 42
结果在bash_exit_not_null.sh.[…].error.log.gz
附件中
[SUPERVISOR] Exit code not null: 42
标签
标签允许用户脚本将一些信息发送到supervisor。
标签是方括号之间的字符串——例如:[warning]
——用于受监督脚本的输出。标签必须位于行的开头或仅由制表符——由SUPERVISOR_LOG_TABULATION
定义——或空格 precede——标签必须占用整行。
警告
如果成功执行的脚本输出中包含警告标记,则其状态将从 成功 变更为 警告。
默认配置:SUPERVISOR_WARNING_TAG='[WARNING]'
。
如果配置文件中 SUPERVISOR_MAIL_SEND_ON_WARNING
设置为 1
请注意,警告将与上下文2行一起列出。
调试跟踪
默认情况下,带有调试标记的消息在Supervisor的输出中是隐藏的(但仍然存在于 <script>_<exec_id>.info.log
中)。将 SUPERVISOR_SHOW_DEBUG_MSG
设置为 1
以显示它们。
默认配置
SUPERVISOR_DEBUG_TAG='[DEBUG]'
SUPERVISOR_SHOW_DEBUG_MSG=0
与电子邮件相关的标记
默认配置
SUPERVISOR_MAILTO_TAG='[MAILTO]'
SUPERVISOR_MAIL_ATTACHMENT_TAG='[MAIL_ATTACHMENT]'
待文档
锁
有时需要确保脚本只执行一次。为此,请在配置文件中将 SUPERVISOR_LOCK_SCRIPT
设置为 1。仅适用于Debian/Ubuntu Linux,否则请留为 0。
# Lock script against parallel run (0|1)
SUPERVISOR_LOCK_SCRIPT=1
输出示例
发送的邮件示例
自定义邮件
待文档
被监控的 Supervisor
待文档
存档
将所有早于 <min-days>
天的Supervisor日志存档为Gzip格式。
监控
检查Supervisor的错误日志文件是否为空。如果不为空,则使用指数退避算法以分钟为单位发送关键电子邮件通知。将 supervisor.info.log
和 supervisor.error.log
文件以Gzip格式附加。
通常每分钟由cron作业调用一次
* * * * * <user> /path/to/supervisor.sh --conf=<conf-file> --monitor
单元测试生成的邮件
总结
显示最近 <max-nb-days>
天内Supervisor的活动摘要,包括每天以及每个受监督脚本的最终状态。还将此摘要通过电子邮件发送到 SUPERVISOR_MAIL_TO
列表。
安装
-
移动到您想要存储源代码和克隆存储库的目录
$ git clone https://github.com/geoffroy-aubry/Supervisor.git
-
您应该在
stable
分支上。如果不是,切换您的克隆到该分支$ cd Supervisor && git checkout stable
-
创建自己的配置文件并修改它
$ cp conf/supervisor-dist.sh conf/supervisor.sh
注意:文件
conf/supervisor-dist.sh
总是会被加载。然后加载带有--conf
选项指定的可选配置文件(覆盖)。但如果找不到--conf
选项,则如果存在,则加载conf/supervisor.sh
。 -
如果您必须监督生成CSV输出的脚本,则安装 Awk CSV解析器 组件
-
手动
-
查看Awk CSV解析器
README.md
的安装部分。 -
然后更新
/conf/supervisor.sh
中的SUPERVISOR_CSV_PARSER
常量SUPERVISOR_CSV_PARSER="/path/to/csv-parser.awk"
-
-
通过 composer (需要PHP >= 5.3.3)
$ composer install # or $ php composer.phar install
有关安装composer的更多信息,请参阅 https://getcomposer.org.cn/doc/00-intro.md#installation-nix。
-
-
您可以为
supervisor.sh
创建一个符号链接$ sudo ln -s /path/to/src/supervisor.sh /usr/local/bin/supervisor
它已准备好使用
$ supervisor --help
版权与许可
根据GNU Lesser General Public License v3 (LGPL版本3)授权。有关详细信息,请参阅 LICENSE 文件。
变更日志
有关详细信息,请参阅 CHANGELOG 文件。
持续集成
代码覆盖率估计: 87% (553 of 638 lines).
需要PHP >= 5.3.3和Xdebug。
创建自己的配置文件并修改它
$ cp conf/phpunit-dist.php conf/phpunit.php
使用 PHPUnit 运行单元测试
$ vendor/bin/phpunit --configuration conf/phpunit-dist.xml
在FreeBSD/OS X上,您必须排除有关独占执行(SUPERVISOR_LOCK_SCRIPT
)的测试
$ vendor/bin/phpunit --configuration conf/phpunit-dist.xml
Git 分支模型
开发所使用的git分支模型是twgit
工具所描述和辅助的模型:https://github.com/Twenga/twgit。