«Утечки» в linux

Вы можете использовать команду tee для перенаправления вывода вашего скрипта в stdout и файл.

Следующая команда выведет содержимое файла f1.txt в файл f2.txt, а также в stdout (консоль).

cat f1.txt | tee f2.txt

Для получения дополнительной информации о tee проверьте tee manpage

11
08.12.2018, 20:06
1 ответ

Самый простой способ - пропустить некоторую программу, которая устанавливает неблокирующий вывод. Вот простой perl oneliner (который вы можете сохранить как leakybuffer ), который выполняет следующие действия:

чтобы ваш a | b становится:

a | perl -MFcntl -e \
    'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { print }' | b

то, что делает, это чтение ввода и запись на вывод (то же самое, что и cat (1) ), но вывод не блокируется - это означает, что если запись не удалась, он вернет ошибку и потеряете данные, но процесс будет продолжен со следующей строки ввода, поскольку мы удобно игнорируем ошибку. Процесс имеет линейную буферизацию, как вы хотели, но см. Предостережение ниже.

вы можете проверить, например:

seq 1 500000 | perl -w -MFcntl -e \
    'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { print }' | \
    while read a; do echo $a; done > output

вы получите файл вывода с потерянными строками (точный вывод зависит от скорости вашей оболочки и т. Д.) Следующим образом:

12768
12769
12770
12771
12772
12773
127775610
75611
75612
75613

вы видите, где оболочка потеряла строки после 12773 , но это также аномалия - в perl не хватило буфера для 12774 \ n , но было для 1277 , поэтому он написал только это - и поэтому следующий номер 75610 не начинается в начале строки, что делает его немного некрасивым.

Это можно улучшить, если perl обнаружит, когда запись не завершилась полностью, а затем попытается очистить оставшуюся часть строки, игнорируя входящие новые строки, но это значительно усложнит сценарий perl, поэтому оставлено как упражнение для заинтересованного читателя :)

Обновление (для двоичных файлов): Если вы не обрабатываете строки, завершаемые новой строкой (например, файлы журналов или аналогичные), вам нужно немного изменить команду, или perl будет потреблять большой объем памяти (в зависимости от того, как часто символы новой строки появляются во вводе):

perl -w -MFcntl -e 'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (read STDIN, $_, 4096) { print }' 

он будет работать правильно и для двоичных файлов (без использования дополнительной памяти).

Update2 - более удобный вывод текстового файла: Избегание буферов вывода ( syswrite вместо print ):

seq 1 500000 | perl -w -MFcntl -e \
    'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { syswrite STDOUT,$_ }' | \
    while read a; do echo $a; done > output

, похоже, устраняет проблемы с "объединенным lines "для меня:

12766
12767
12768
16384
16385
16386

(Примечание: можно проверить, на каких строках был вырезан вывод, с помощью: perl -ne '$ c ++; next if $ c == $ _; print" $ c $ _ "; $ c = $ _ 'output oneliner)

14
27.01.2020, 19:58

Теги

Похожие вопросы