geoffroy-aubry/supervisor

监控脚本执行,记录标准输出、标准错误和退出码,并带时间戳,确保在启动、成功、警告或错误时发送电子邮件通知。

v1.8.1 2015-05-04 22:58 UTC

This package is not auto-updated.

Last update: 2024-09-28 13:58:11 UTC


README

最新稳定版本 构建状态  代码覆盖率估算: 87% (553 of 638 lines).

监控脚本执行,记录 stdoutstderr 和退出码,并带时间戳,确保在启动、成功、警告或错误时发送电子邮件通知……以及许多其他功能。

技术 : Supervisor 在 Bash 中实现,只有单元测试是用 PHP 编写的。

支持操作系统 : Debian/Ubuntu Linux、FreeBSD/OS X。

目录

功能

通用

  • 监控脚本执行,记录 stdoutstderr 和退出码
  • stdout 的每一行前添加百秒级的时间戳。
  • 执行 ID 唯一标识每次脚本执行。用于:supervisor.info.logsupervisor.error.log<script>_<exec_id>.info.log<script>_<exec_id>.error.log
  • 可以阻止并行脚本执行 (仅限于 Debian/Ubuntu Linux)。如果执行时间过长,则很有用……
  • 可以指定一个配置文件来加载,除了默认配置文件之外(覆盖)。
  • 完全可配置的标签系统允许执行脚本通过 stdout 动态指定警告、mailto、邮件附件、触发器等。
  • 自动日志存档机制。
  • 显示过去几天内 Supervisor 活动的摘要,包括每天以及每个被监控脚本的最终状态。
  • 处理 CSV 输出,在配置文件中定义字段分隔符、字段定界符和要监视的字段数量。
  • 添加适当的信号处理和中断:现在将 SIGHUPSIGINTSIGQUITSIGTERM 传递给被监控脚本。

通知

  • 确保在以下事件(可配置)时发送电子邮件通知:启动、成功、警告或错误。捕获退出码、致命错误、异常等……
  • 所有邮件都包含执行脚本的 stdoutstderr 内容,以 Gzip 附件的形式提供。
  • 邮件可完全自定义。只需在命令行中提供您的文件即可。
  • 可以在命令行中将多个外部参数注入到自定义电子邮件中。
  • Supervisor 本身由另一个进程监控,使用指数退避算法按分钟增量发送关键电子邮件通知。

人体工程学

  • 在监控期间,除了所有日志文件外,Supervisor 还实时显示被监控脚本的输出、警告和错误,添加时间戳,同时保留颜色和缩进。还会打印所有日志文件的名称。

代码质量

  • 使用以下指令执行 Bash 代码
    • set -o nounset:在执行参数扩展时,将未设置的变量和参数(除了特殊参数@*)视为错误。错误信息将被写入标准错误,非交互式shell将退出。
    • set -o pipefail:管道的返回值是最后(最右侧)退出状态非零的命令的值,如果所有命令都成功退出,则为零。
  • 通过PHPUnit(通过PHP包装器)进行了大量的单元测试,覆盖了几乎整个应用程序。

需求

  • Bash v4(2009)及以上版本

  • mutt,用于发送邮件通知(使用apt-get install muttbrew 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]

Help on command prompt

文本版本
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命令:'…'
  • 用户脚本返回的任何非空代码

成功执行

如果且仅当stderr为空、退出状态为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'

输出

Successful output

如果配置文件中将SUPERVISOR_MAIL_SEND_ON_STARTUP设置为1

Mail on startup

请注意,除了脚本参数外,Supervisor还添加了两个参数

  • 唯一的执行ID
  • 记录脚本stderr的文件名

如果配置文件中将SUPERVISOR_MAIL_SEND_ON_SUCCESS设置为1

Mail on success

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

请注意,颜色被去除,但缩进被保留。

错误

如果stderr不为空或退出状态不为0,则执行以错误状态结束。

PHP致命错误

我们将监视一个抛出致命错误的PHP脚本

<?php

undefined_fct();

输出

Error output

如果配置文件中将SUPERVISOR_MAIL_SEND_ON_ERROR设置为1

Mail on error

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

其他错误

以下提供的脚本以错误状态结束。

需要注意的是,当stderr不为空而退出状态为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 stderr

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_WARNING1

Mail on error

请注意,警告将与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

输出示例

Example of lock

发送的邮件示例

Example of sent e-mail

自定义邮件

待文档

被 Supervisor 监控

待文档

存档

将所有早于<min-days>的supervisor日志归档为Gzip格式。

Archiving

监控

检查supervisor的错误日志文件是否为空。如果不为空,则使用指数退避算法以分钟递增发送关键电子邮件通知。文件supervisor.info.logsupervisor.error.log将以Gzip格式附加。

通常通过cron作业每分钟调用一次

* * * * * <user> /path/to/supervisor.sh --conf=<conf-file> --monitor

通过单元测试生成的邮件

Critical error

摘要

显示过去<max-nb-days>天内supervisor活动的摘要,包括每天和每个监督脚本的最终状态。还将此摘要通过电子邮件发送到SUPERVISOR_MAIL_TO列表。

Summary

安装

  1. 移动到您希望存储源和克隆存储库的目录

    $ git clone https://github.com/geoffroy-aubry/Supervisor.git
  2. 您应该在stable分支上。如果不是,请将您的克隆切换到该分支

    $ cd Supervisor && git checkout stable
  3. 创建您自己的配置文件并对其进行适配

    $ cp conf/supervisor-dist.sh conf/supervisor.sh

    注意:文件conf/supervisor-dist.sh始终被加载。然后加载带--conf选项指定的可选配置文件(覆盖)。但如果找不到选项--conf,则如果存在,则加载conf/supervisor.sh

  4. 如果您必须监督产生CSV输出的脚本,那么请安装Awk CSV解析器组件

  5. 您可以为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%(638行中的553行)。

需要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