Журналы временных меток программ, управляемых супервайзером


Я использую 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;

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

Знает ли кто-нибудь достаточно об этом, чтобы дать рекомендации о том, как достичь цели отметка времени на выходе работника?

Author: Nathaniel Ford, 2013-07-23

2 answers

Вы можете написать специальный скрипт-оболочку, который прикрепит фильтр к 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
Author: Ja͢ck, 2013-07-25 02:29:57

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

 4
Author: Nick, 2013-07-27 14:24:09