Ответ 1
Try:
use IO::Handle;
$fh->autoflush;
Это было фактически опубликовано как способ автоматической очистки в раннем вопросе моего вопроса, в котором говорилось о общепризнанном плохом способе достижения этого: -)
У меня есть Perl script, который добавляет новую строку к существующему файлу каждые 3 секунды. Кроме того, есть приложение С++, которое читает из этого файла.
Проблема в том, что приложение начинает читать файл после завершения script, и дескриптор файла закрыт. Чтобы этого избежать, я хочу, чтобы флеш после каждой строки добавлял, но я новичок в Perl и не знаю, как это сделать.
Try:
use IO::Handle;
$fh->autoflush;
Это было фактически опубликовано как способ автоматической очистки в раннем вопросе моего вопроса, в котором говорилось о общепризнанном плохом способе достижения этого: -)
TL/DR: используйте IO::Handle
и метод flush
, например:
use IO::Handle;
$myfile->flush();
Во-первых, вам нужно решить, как "покраснеть" вам это нужно. Может быть довольно много слоев буферизации:
Внутренний буфер Perl в дескрипторе файла. Другие программы не могут видеть данные, пока они не покинут этот буфер.
Буферизация уровня файловой системы "грязных" блоков файлов. Другие программы все еще могут видеть эти изменения, они кажутся "написанными", но они будут потеряны, если ОС или машина сработает.
Буферная запись записи на уровне диска. ОС думает, что они записаны на диск, но на самом деле диск хранит их в энергозависимой памяти на диске. Если ОС выйдет из строя, данные не будут потеряны, но если сбой питания произойдет, возможно, если диск не сможет записать его первым. Это большая проблема с дешевыми потребительскими SSD.
Это становится еще более сложным, когда задействованы SAN, удаленные файловые системы, RAID-контроллеры и т.д. Если вы пишете через каналы, там также должен быть рассмотрен буфер для труб.
Если вы просто хотите очистить буфер Perl, вы можете close
создать файл, print
строку, содержащую "\n"
(так как она кажется, что Perl flushes на символах новой строки) или использовать метод IO::Handle
flush
.
Вы также можете использовать perl faq использовать binmode
или играть с $|
, чтобы сделать файл дескриптором небуферизованным. Это не то же самое, что сброс буферизованной дескриптора, поскольку в очереди с буферизацией записывается то, что выполнение одного флеша имеет гораздо более низкую стоимость исполнения, чем запись в небуферизованный дескриптор.
Если вы хотите сбросить буфер обратной записи файловой системы, вам нужно использовать системный вызов типа fsync()
, откройте файл в режиме O_DATASYNC
или используйте один из многочисленных других параметров. Это мучительно сложно, о чем свидетельствует тот факт, что PostgreSQL имеет свой собственный инструмент для тестирования методов синхронизации файлов.
Если вы хотите убедиться, что это действительно, честно говоря, честно на жестком диске в постоянном хранилище, вы должны очистить его до файловой системы в своей программе. Вам также необходимо настроить контроллер жесткого диска/SSD/RAID/SAN/все, что действительно нужно, когда запрашивает ОС. Это может быть на удивление сложным и довольно специфичным для ОС/аппаратного обеспечения. "plug-pull" тестирование настоятельно рекомендуется, чтобы убедиться, что вы действительно поняли его.
От 'man perlfaq5':
$old_fh = select(OUTPUT_HANDLE);
$| = 1;
select($old_fh);
Если вы просто хотите сбросить stdout, вы можете просто сделать:
$| = 1;
Но проверьте FAQ для получения подробной информации о модуле, который дает вам более удобную абстракцию, например IO::Handle
.
Все решения, предлагающие установку autoflush, игнорируют основной факт, что большинство современных ОС являются буферизацией ввода-вывода файлов независимо от того, что делает Perl.
Только возможность принудительного использования данных на диске заключается в закрытии файла.
Я пойман в ловушку с той же дилеммой, где у нас есть проблема с вращением записываемого журнала.
Вот статья об этом в PerlDoc: Как сбросить/удалить буфером дескриптор выходного файла? Почему я должен это делать?
Два решения:
$|
IO::Handle
или один из его подклассов.Чтобы автоматически очистить вывод, вы можете установить autoflush/ $|
, как описано другими, прежде чем вы будете выводить на дескриптор файла.
Если вы уже вышли в дескриптор файла и должны убедиться, что он попадает в физический файл, вам нужно использовать методы IO:: Handle flush
и sync
.
Вот ответ, реальный ответ.
STOP, поддерживающий дескриптор открытого файла для этого файла в течение всего процесса.
START абстрагирование операции с файлом-добавлением в подраздел, который открывает файл в режиме добавления, записывает на него, закрывает его.
#appends a new line to the existing file
sub append_new_line{
my $linedata = shift;
open my $fh, '>>', $fnm or die $!; # $fnm is file-lexical or something
print $fh $linedata,"\n"; # flavor to taste
close $fh;
}
процесс наблюдения за файлом встретит закрытый файл, который будет изменяться всякий раз, когда вызывается функция.
Альтернативным подходом было бы использовать named pipe между вашей программой Perl script и С++, вместо файла, re в настоящее время используется.
У меня была та же проблема с единственной разницей в написании одного и того же файла снова и снова с новым контентом. Эта ассоциация "$ | = 1" и autoflush работала для меня:
open (MYFILE, '>', '/internet/web-sites/trot/templates/xml_queries/test.xml');
$| = 1; # Before writing!
print MYFILE "$thisCardReadingContentTemplate\n\n";
close (MYFILE);
MYFILE->autoflush(1); # After writing!
Удачи. Н