Есть ли инструмент, который прозрачно объединяет zcat и cat?

71

При обработке файлов журналов, некоторые из них в конечном итоге, как gzipped файлы, logrotateа другие нет. Поэтому, когда вы пытаетесь что-то вроде этого:

$ zcat *

в итоге вы получите командную строку, zcat xyz.log xyz.log.1 xyz.log.2.gz xyz.log.3.gzа затем:

gzip: xyz.log: not in gzip format

Есть ли инструмент, который будет принимать волшебные байты, аналогично тому, как fileработает, и использовать zcatили в catзависимости от результата, чтобы я мог, например, направить вывод grep?

NB: я знаю, что могу написать сценарий, но я спрашиваю, есть ли уже инструмент.

0xC0000022L
источник

Ответы:

41

zless

Жаль zcat, что в libz есть API, который поддерживает прозрачное чтение как сжатых, так и несжатых файлов. Но страница руководства говорит, что zcatэто эквивалентно gunzip -c.

sourcejedi
источник
Спасибо за эту альтернативу. Я мог бы подумать об этом, не так ли? ;) ... Ну что ж. Найдите, +1 и примите (также потому, что у вас меньше повторений, чем у другого отвечающего).
0xC0000022L
Удивительно. Мне очень помогло, я использовал сценарий оболочки для решения этой проблемы в течение многих лет ... или ужасный сценарий perl ... объединение разрешения журнала, используемое awstats ... теперь я знаю этот удивительный инструмент. Благодарю.
Лучано Андресс Мартини
99

Попробуйте это с помощью -fили --force:

zcat -f -- *

Так zcatкак это простой скрипт, который запускается

exec gzip -cd "$@"

с длинными вариантами, которые будут переводить в

exec gzip --stdout --decompress "$@"

и согласно man gzip(подчеркните мое):

-f --force
      Принудительное сжатие или распаковка, даже если файл имеет несколько ссылок
      или соответствующий файл уже существует, или если сжатые данные
      читать или писать в терминал. Если входные данные не в формате
      распознается gzip, и если также указана опция --stdout, скопируйте
      входные данные без изменений в стандартный вывод: пусть zcat ведет себя как cat .

Также:

так что я могу передать вывод, grepнапример,

Вы можете использовать zgrepдля этого:

zgrep -- PATTERN *

хотя см. комментарий Стефана ниже.

don_crissti
источник
1
Спасибо, это интересная альтернатива zlessрешению. Ницца и +1.
0xC0000022L
6
Обратите внимание, что оба zlessи zgrepявляются сценариями, которые вызывают gzip -cdfq(то есть zcat -fq).
Стефан Шазелас
9

Я использую точно для той же цели:

{ cat /var/log/messages ; zcat /var/log/messages*.gz ; }| grep something | grep "something else" ....
Васю
источник
Мне нравится этот подход, потому что он требует меньше всего времени на обучение коллег. Если сообщения журнала имеют временную метку в удобной для сортировки временной метке, это особенно полезно.
Thomas L Holaday
Отличный подход. Благодарю.
Милош Чаконович
7

Для ztools (zcat, zgrep, ..) существует встроенная замена zutils, которая объединяет все инструменты декомпрессии независимо от серверной части. Таким образом, с помощью одной и той же команды вы можете прозрачно читать обычные, lzma, gzipped, xz файлы.

Он доступен в Debian Wheezy или новее, вероятно, в Redhat / Centos.

Страница проекта находится здесь nongnu.org

Сообщение в блоге, объясняющее использование утилиты здесь ( noone.org )

aseques
источник
3

Это прекрасно работает в RHEL 5.x, где zcat - бинарный файл. Сбой в RHEL 6.x (и Ubuntu 12.x), где zcat - это скрипт. Это используется для работы в порядке.

Я бы вообще не использовал zcat, но zgrep также не будет правильно обрабатывать несжатые файлы.

Питер Лоус
источник
2

Открывается как сжатый, так и несжатый, в хронологическом порядке.

ls -v syslog* | tac | xargs zcat -f | less
Райан
источник
Это дает неправильный порядок с более чем десятью файлами журнала (syslog.10.gz ...)
Ванни
Хороший улов. -v должно это исправить.
Райан
ls -rvчтобы избежать tac. Для файлов журналов, less $(ls -rv syslog*)с вашим установленным LESSOPENenv var правильно работает. Вы можете выполнять поиск по файлам, esc-nчтобы найти следующее совпадение, игнорируя границы файлов.
Питер Кордес
С zsh:zcat -f syslog*(nOn)
Стефан
Это не сработает, если у вас настроено вращение журнала на следующий день
cjbarth
1

Как насчет обертки?

$ cat xcat.sh 
#!/bin/bash

for i in $@;do 
        [ ! -z "$(file -i $i | grep "gzip")" ] && zcat $i || cat $i
done

$ bash xcat.sh plain.txt gzipped_text.gz
маскировка
источник
0

Скопируйте и вставьте (или поместите в конец ~/.bashrcфайла) эту функцию bash :

logs() { zcat -f $(ls -rv "$1"*) | less; }

Теперь вы можете ввести, например , logs /var/log/syslogили , logs /var/log/nginx/access.logчтобы увидеть все те системный журнал или Nginx лог сообщений от старых к новым с менее .

Затем вы можете искать что-то набрав /somethingи нажав nдля следующего .

Ванни
источник
0

Существует прекрасный Perl-скрипт, который точно делает это. Это logresolvemerge.pl из проекта awstats: http://www.awstats.org/docs/awstats_tools.html

Logresolvemerge позволяет получить один уникальный выходной файл журнала, отсортированный по дате, построенный из определенных источников:

  • Он может читать несколько входных файлов журнала
  • Он может читать файлы журнала .gz / .bz2

    Вывод находится на STDOUT, так что вы можете использовать его в дополнительных процессах.

  • Даниэль Андерсен
    источник
    0

    Основываясь на ответе @ Ryan, следующее получит все отсортированные файлы, отсортированные по алфавиту, затем получит текущий файл, разархивирует его, если необходимо, и lessих:

    cat <(ls mylog.log-* | sort) <(ls mylog.log) | xargs zcat -f | less

    или если вы хотите получить их все в виде непрерывного потока, вы можете tailих и, необязательно, направить в другой процесс

    cat <(ls mylog.log-* | sort | xargs zcat -f) <(tail -f -n +0 mylog.log)

    Я должен отметить, что это предназначено для журналов, которые чередуются ежедневно с датой, добавленной в конец файла. Если ваши журналы регистрируют нас в другом формате, вам придется изменить первую часть catзаявления, чтобы она соответствовала вашим требованиям .

    cjbarth
    источник