Временные журналы программ, управляемых супервизором

Я использую supervisord для управления php-программой, которая должна работать в фоновом режиме. Эта программа регистрирует события в файле worker_log. Это достаточно просто, чтобы настроить его в supervisord.conf, который я использую:

stderr_logfile=/var/log/supervisord/worker_log;

Тем не менее, я хотел бы, чтобы события записывались в журнал в timestamp самостоятельно. Я не контролирую программу php, поэтому ее оформление не является вариантом. Я подумал, что я бы сделал это, прокомментировав приведенную выше конфигурацию регистрации и украсив программу через команды командной строки в конфигурации диспетчера диспетчера:

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

При запуске этой команды вручную это работает нормально. Однако супервизор как-то мешает ему нормально функционировать, и я не могу сказать, как это сделать. worker.php работает отлично, но в этой конфигурации он отключается. И, из-за этого, он, конечно, не добавляет отметки времени.

Кто-нибудь знает об этом, чтобы дать указания о том, как выполнить задачу временного штампа рабочего вывода?

Ответ 1

Вы можете написать выделенную оболочку script, которая будет прикреплять фильтр к 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);

Btw, если вы не удаляете фильтр, он вызывает ошибку сегментации (по крайней мере, проверен на 5.4).

Ответ 2

предыдущий ответ (от Джека) правилен тем, что вам нужен еще один уровень кода для отметки времени каждой строки. Этот однострочный слой в 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 script.

Одна из проблем, с которыми вы пытались работать, не работала, так это то, что дата вычисляется и заменяется оболочкой в ​​точке, в которой была вызвана команда sed, поэтому все строки имели бы такую ​​же метку времени журнала