Защо моят perl демон не печата?

Отстранявам грешки в демон и се опитвам да използвам изрази print за извеждане на информация към терминала. Същността на моя код е:

#!/usr/bin/env perl

use strict;
use warnings;

use Readonly;

Readonly my $TIMEOUT => ...;

...

while (1) {

   print "DEBUG INFO";

   ...

   sleep $TIMEOUT;
}

Въпреки това няма изход, той се отпечатва на моя терминал. Защо е това?


person Iaan    schedule 20.09.2015    source източник
comment
STDOUT на демон обикновено е целенасочено насочен към някъде, различен от терминала. Как демонизирахте програмата?   -  person ikegami    schedule 21.09.2015


Отговори (1)


Резюме:

Използвайте $| = 1 или добавете нов ред, "\n" към разпечатката.

Обяснение:

Причината това да не се печата на терминала е, че perl буферира изхода за ефективност. След като буферът за печат бъде запълнен, той ще бъде изчистен и изходът ще се появи във вашия терминал. Може да е желателно да принудите да изчистите буфера, тъй като в зависимост от дължината на $TIMEOUT може да чакате значително време за извеждане!

Има два основни подхода за изчистване на буфера:

1) Тъй като печатате на вашия терминал, вашият файлов манипулатор най-вероятно е STDOUT. Всички манипулатори на файлове, прикачени към терминала, са по подразбиране в режим на буфериран ред и ние можем да изчистим буфера и да принудим изхода, като добавим знак за нов ред към вашия оператор print:

while (1) {
    print "DEBUG INFO\n";
    ...
    sleep $TIMEOUT;
 }

2) Вторият подход е да се използва $|, който, когато е зададен на не- нула прави текущия манипулатор на файла (STDOUT по подразбиране или последният, който е selected) горещ и принуждава незабавно изчистване на буфера. Следователно следното също ще принуди отпечатването на информацията за отстраняване на грешки:

$| = 1;
while (1) {
    print "DEBUG INFO";
    ...
    sleep $TIMEOUT;
}

Ако използването на синтаксис като този е объркващо, тогава може да помислите за:

use IO::Handle;
STDOUT->autoflush(1);

while (1) {
    print "DEBUG INFO";
    ...
    sleep $TIMEOUT;
}

В много примери на код, където се изисква незабавно изчистване на буфера, може да видите $|++, използван за нагряване на файлов манипулатор и незабавно изчистване на буфера, и --$|, за да направи файлов манипулатор студен и изключване на автоматичното промиване. Вижте тези два отговора за повече подробности:

Ако се интересувате да научите повече за perl буферите, тогава бих ви предложил да прочетете Страдание от буфериране, което дава страхотна представа защо имаме буфериране и обяснява как да го включваме и изключваме.

person Hayden    schedule 20.09.2015