Временные журналы программ, управляемых супервизором
Я использую 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, поэтому все строки имели бы такую же метку времени журнала