2013-07-23 1 views
10

Używam superwizji do zarządzania programem php, który musi działać w tle. Ten program rejestruje zdarzenia w pliku worker_log. Jest to dość proste, aby skonfigurować to w supervisord.conf Używam:Logi z datowaniem programów zarządzanych przez supervisord

stderr_logfile=/var/log/supervisord/worker_log; 

Jednakże chciałbym dla zdarzenia są zapisywane w dzienniku na timestamp siebie. Nie mam kontroli nad programem php, więc dekorowanie jego logu nie jest opcją. Pomyślałem, że to, co robię jest wykomentuj powyższą konfigurację rejestrowania i ozdobić program rurami wiersza polecenia w konfiguracji poleceń przełożonego:

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

Po uruchomieniu tej komendy ręcznie wydaje się działać prawidłowo. Jednak superwizor wydaje się jakoś uniemożliwić mu prawidłowe funkcjonowanie i nie jestem w stanie powiedzieć jak. worker.php wykonuje dobrze, ale raportowanie w tej konfiguracji jest stłumione. I z tego powodu oczywiście nie dodaje znacznika czasu.

Czy ktoś ma wystarczającą wiedzę na ten temat, aby dostarczyć wskazówek, jak osiągnąć cel, jakim jest znacznik czasu dla wyników pracownika?

+0

Czy prawdopodobne jest, że parametr polecenia nie obsługuje potoku? Lub może być poleceniem, gdy run jest zwalnianiem terminala, który superwizor nie obsługuje? –

Odpowiedz

7

Można napisać skrypt dedykowany otoki, które przywiązują filtra do stderr przed wywołaniem kodu pracownika:

// 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, jeśli nie usunąć filtr powoduje błąd segmentacji (przynajmniej , testowane na 5.4).

+0

Mam zamiar wypróbować to już dziś! To naprawdę dobra sugestia, choć oczywiście warstwa kodu, która jest niefortunna. –

+0

To przyzwyczajenie znaczników czasu do krytycznego komunikatu o błędzie, to pomija cały kod pola użytkownika i przechodzi bezpośrednio do "wyprowadzenia wiadomości do STDERR i umrzeć" – StampyCode

+0

@Stampy Tak, to niestety natura fatalnych błędów, ponieważ nie można ich złapać z jakimkolwiek błędem handler = (chociaż, może działacz zamykający mógłby działać ... –

4

poprzednia odpowiedź (z Jacka) jest poprawna, ponieważ potrzebna jest kolejna warstwa kodu do sygnatury czasowej każdej linii. Ta jedna linijka w perlu osiągnie ten sam wynik:

perl -ne '@timeparts=localtime(); printf("%04d/%02d/%02d %02d:%02d:%02d %s",$timeparts[5]+1900,$timeparts[4]+1,@timeparts[3,2,1,0], $_);' 

Użyj tego zamiast skryptu sed.

Jeden problem z podejściem próbowano nie działa to, że data jest obliczany i podstawiony przez powłokę w punkcie, że polecenie sed został wywołany więc wszystkie linie będą miały ten sam znacznik czasu dziennika

+0

Dlaczego nie tylko 'perl -ne 'print skalar (localtime).". $ _' '? A może' perl -mPOSIX = strftime -ne 'print strftime ("% F% T", czas lokalny), $ _; '' – Otheus

+0

To też może działać. Preferuję format, który dałem, ale to kwestia per smaku – Nick