1

Существует несколько z-утилит (zless , zcat), которые могут прозрачно читать содержимое zip-файла.

Можно ли добавить в сжатый файл журнала (в любом формате, не обязательно gzip)?

Я хочу что-то вроде следующего (ztee - мнимая утилита с интересующей функциональностью):

echo "[ $( date ) ] message" | ztee -a file.log.gz

1 ответ1

3

Да, но это бесполезно.


Некоторые форматы сжатых файлов, в том числе используемые gzip , bzip2 и xz , изначально поддерживают конкатенацию. (Это может потребовать явного согласия при использовании низкоуровневых API, но декомпрессоры командной строки принимают его по умолчанию.)

echo "test 1" | gzip >> log.txt.gz
echo "test 2" | gzip >> log.txt.gz
echo "test 3" | tee >(gzip >> log.txt.gz)
echo "test 4" | (tee /dev/fd/3 | gzip >> log.txt.gz) 3>&1
zcat log.txt.gz

(Обратите внимание, что, например, zcat буквально просто оболочка для шеллскрипта для gunzip ...)

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

$ dmesg > test.log
$ cat test.log | gzip > test-single.log.gz
$ cat test.log | while read -r line; do
                     echo "$line" | gzip
                 done > test-concat.log.gz
$ du -h test*
500K     test-concat.log.gz
416K     test.log
64K      test-single.log.gz

Насколько мне известно, нет инструмента, который бы поддерживал загрузку существующих заголовков сжатых файлов и использовал бы их для сжатия новых данных. Для этого вам нужно будет запустить постоянный процесс gzip и периодически передавать его логи через stdin. Например:

#!/bin/bash

# open a subprocess (the bash equivalent of 'popen')
coproc LOG { gzip >> log.txt.gz; }

echo "doing stuff" >&${LOG[1]}
echo "doing more stuff" >&${LOG[1]}
echo "still doing stuff" >&${LOG[1]}

# close its stdin to finish compression
exec {LOG[1]}>&-

В "стандартной" оболочке вы можете добиться того же, используя именованные каналы, или даже более просто перенаправить весь скрипт через gzip . (Просто напечатайте одно и то же сообщение один раз в stdout и один раз в stderr, и вы получите свою tee .)


Дополнительная информация о сцеплении сжатых потоков:

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .