Разбор gzipped файла журнала построчно внутри файла tar gzipped
У меня есть следующая структура для файлов журнала:
/var/log/2013-12-24.tar.gz
Этот файл имеет:
2013-12-24/{00,01,02...23}.log.gz
файлы
Мне нужно проанализировать эти файлы, используя Python,
без извлечения каких-либо файлов на диске ИЛИ памяти
Какие-либо предложения?
2 ответа
Это невозможно с .tar.gz
и вот почему.
Для того, чтобы создать .tar.gz
файл, вы должны tar
это первый, чтобы создать сингл .tar
файл, а затем gzip
результат.
.tar
файл МОЖНО сканировать, не читая целиком, но он хорошо работает, только если члены tar
архив относительно большой. Это потому что tar
НЕ имеет заголовка, в котором перечислены все члены в одном компактном месте. Каждый элемент архива имеет 512-байтовый дескриптор, чем показывает, где находится следующий. С большими членами архива вы можете относительно быстро найти произвольное содержимое на диске, но вам придется lseek()
много раз.
Но, как только вы подаете заявку gzip
на вершине .tar
это, в основном, делает невозможным быстрое получение списка всех участников архива, и тем более, что их содержимое фактически не распаковывается. Вы вынуждены распаковать весь архив, чтобы просто получить список всех его членов.
Обратите внимание, что точно такая же проблема существует для популярных .tar.bz2
или же .tar.xz
форматы.
Вы можете исправить это с помощью zip
формат. zip
имеет большое преимущество перед .tar.gz
потому что он имеет компактный индекс, который перечисляет все члены архива в одном месте, и это позволяет быстро читать этот список и извлекать только те файлы, которые вам нужны, без необходимости извлекать (gunzip) весь архив, который .tar.gz
страдает от.
Я нашел решение. Я просто дам это здесь для справки:
import subprocess
file_name = /var/log/2013-06-10.tar.gz
gzip_data = subprocess.Popen(["tar", "-Oxf", file_name], stdout=subprocess.PIPE)
data = subprocess.Popen(["zcat"], stdin=gzip_data.stdout, stdout=subprocess.PIPE)
for line in data.stdout:
do_my_process_on(line)