12

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

stderr_logfile=/var/log/supervisord/worker_log;

但是,我希望写入日志的事件能够为自己添加时间戳。我无法控制 php 程序,因此不能选择装饰它的日志。我想我要做的是注释掉上面的日志配置,并通过主管命令配置中的命令行管道装饰程序:

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

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

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

4

3 回答 3

8

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

// 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 上测试过)。

于 2013-07-25T02:29:57.767 回答
4

先前的答案(来自杰克)是正确的,因为您需要另一层代码来为每一行加上时间戳。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 计算并替换的,因此所有行都将具有相同的日志时间戳

于 2013-07-27T14:24:09.043 回答
0

编辑:我想我会把它留在这里。确切地说,这种方法不起作用,因为 sed 命令只是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"

(免责声明:鉴于我对这个答案尚不存在感到有点惊讶,得知这是一种糟糕的做事方式,我不会感到惊讶)

于 2020-09-12T03:32:46.380 回答