Почему мой демон 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) Второй подход заключается в использовании $|, для которого при установке значения non- ноль делает текущий дескриптор файла (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