问题 时间戳记由supervisord管理的程序日志


我正在使用supervisord来管理需要在后台运行的php程序。该程序将事件记录到文件中 worker_log。这很简单,可以在中进行配置 supervisord.conf 我在用着:

stderr_logfile=/var/log/supervisord/worker_log;

但是,我希望写入日志的事件能够自己加时间戳。我无法控制php程序,所以装饰它的日志不是一个选项。我想我要做的就是注释掉上面的日志记录配置,并通过supervisor命令配置中的命令行管道来装饰程序:

command=php /www/myapp/worker.php 2>&1 | sed "s/^/`date` /" > /var/log/supervisord/worker_log;

手动运行此命令时似乎工作正常。然而,supervisord似乎以某种方式阻止它正常运作,我无法告诉如何。 worker.php 表现良好,但在此配置中,它的报告被抑制。而且,正因为如此,它当然不会添加时间戳。

有没有人对此有足够的了解,为如何实现工人输出时间戳的目标提供指导?


7370
2017-07-23 01:32


起源

命令参数是否可能不支持管道?或者可能是运行时释放终端的命令,哪个supervisord不支持? - SSaikia_JtheRocker


答案:


您可以编写一个专用的包装器脚本,在调用您的工作器代码之前将过滤器附加到stderr:

// filter to prepend date/time on all stderr output
class eventdata_filter extends php_user_filter
{
    function filter($in, $out, &$consumed, $closing)
    {
        while (($bucket = stream_bucket_make_writeable($in))) {
            $bucket->data = date('c') . ' ' . $bucket->data;
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}

// register our custom filter    
stream_filter_register('eventdata', 'eventdata_filter');

// keep a reference to the attached filter
$filter = stream_filter_append(STDERR, 'eventdata', STREAM_FILTER_WRITE);

// isolate the worker from any variables in this scope, such as $filter
function run()
{
    include 'worker.php';
}

// run the worker
run();

// remove the filter
stream_filter_remove($filter);

顺便说一句,如果你不删除过滤器,它会导致分段错误(至少在5.4上测试)。


7
2017-07-25 02:29



我今天要试试这个!这是一个非常好的建议,虽然可以肯定是一层不幸的代码。 - Nathaniel Ford
这不会将时间戳添加到致命的错误消息中,这会跳过所有用户态代码并直接将消息输出到STDERR并死掉 - StampyCode
@Stampy是的,不幸的是致命错误的本质,因为那些不能被任何错误处理程序捕获=(但是,也许一个关机处理程序可以工作...... - Ja͢ck


之前的答案(来自Jack)是正确的,因为您需要另一层代码来为每一行添加时间戳。 perl中的这个单行将实现相同的结果:

perl -ne '@timeparts=localtime(); printf("%04d/%02d/%02d %02d:%02d:%02d %s",$timeparts[5]+1900,$timeparts[4]+1,@timeparts[3,2,1,0], $_);'

用它来代替sed脚本。

您尝试的方法无法解决的一个问题是日期是在调用sed命令时由shell计算并替换为shell,因此所有行都具有相同的日志时间戳


4
2017-07-27 14:24



为什么不呢 perl -ne 'print scalar(localtime)." ".$_' ?或者可能 perl -mPOSIX=strftime -ne 'print strftime("%F %T ",localtime),$_;' - Otheus
这也可行。我更喜欢我给出的格式,但这是一个每个品味的问题 - Nick