Php supervisord管理的程序的时间戳日志

Php supervisord管理的程序的时间戳日志,php,bash,supervisord,Php,Bash,Supervisord,我正在使用supervisord管理一个需要在后台运行的php程序。该程序将事件记录到一个文件worker\u log。在我正在使用的supervisord.conf中配置它非常简单: stderr_logfile=/var/log/supervisord/worker_log; 但是,我希望写入日志的事件能够给自己加上时间戳。我对php程序没有控制权,所以装饰它的日志不是一个选项。我想我要做的是注释掉上面的日志配置,并通过supervisor命令配置中的命令行管道装饰程序: command=

我正在使用supervisord管理一个需要在后台运行的php程序。该程序将事件记录到一个文件
worker\u 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
执行得很好,但在这种配置中,它的报告被抑制。因此,它当然不会添加时间戳


是否有人对此有足够的了解,可以就如何实现为工作程序的输出添加时间戳的目标提供指导?

您可以编写一个专用的包装器脚本,在调用工作程序代码之前将过滤器附加到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上测试过)。

以前的答案(来自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计算和替换的,因此所有行都具有相同的日志时间戳。Edit:我想我将把它留在这里。确切地说,这种方法不起作用,因为sed命令只是永久地使用它的startup
date
输出,所以时间戳是不正确的


实现这一点的另一种方法是将原始命令放在
bash-c“command here”
的引号中,这与您最初的尝试非常接近

command=bash -c 'php /www/myapp/worker.php 2>&1 | sed "s/^/`date` /" >> /var/log/supervisord/worker_log';
注意:我从
切换到
>
,因为我倾向于保留这些日志,并通过
logrotate
规则管理日志文件

对于更一般的情况,您可能还需要设置您的环境,这有点不合时宜,但至少需要在一个位置进行检查。玩具示例:
bash-c“source~/setup.bash&&php/www/myapp/worker.php 2>&1 | sed…>/your/logfile/path.log”


(免责声明:鉴于我对这个答案还不存在的轻微惊讶,我会毫不奇怪地知道这是一种糟糕的做事方式)

我今天要尝试一下!这是一个非常好的建议,尽管承认有一层代码是不幸的。这不会在致命错误消息前加上时间戳,这会跳过所有用户区代码,直接转到“将消息输出到STDERR并死亡”@Stampy是的,这是致命错误的本质,因为任何错误处理程序都无法捕获这些错误=(不过,可能是关机处理程序可以工作……可能是命令参数不支持管道吗?或者可能是run释放终端时的命令,而supervisord不支持该命令?为什么不只是
perl-ne'打印标量(localtime)。“..$\u'
?或者可能是
perl-mpoix=strftime-ne”打印strftime(“%F%t”,localtime)“,$”
也可以。我更喜欢我给出的格式,但这是每个口味的问题