Журналы временных меток программ, управляемых супервайзером
Я использую 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
работает нормально, но в этой конфигурации отчеты подавляются. И из-за этого он, конечно, не добавляет метку времени.
Знает ли кто-нибудь достаточно об этом, чтобы дать рекомендации о том, как достичь цели отметка времени на выходе работника?
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).
Предыдущий ответ (от Джека) верен в том, что вам нужен еще один слой кода для отметки времени каждой строки. Этот однострочный текст на 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, поэтому все строки имели бы одинаковую временную метку журнала