Existe uma ferramenta que combina zcat e cat de forma transparente?

71

Ao manipular arquivos de log, alguns acabam sendo arquivos compactados com gzip logrotatee outros não. Então, quando você tenta algo assim:

$ zcat *

você acaba com uma linha de comando como zcat xyz.log xyz.log.1 xyz.log.2.gz xyz.log.3.gze depois com:

gzip: xyz.log: not in gzip format

Existe uma ferramenta que retire os bytes mágicos, semelhante a como filefunciona, e use zcatou catdependendo do resultado para que eu possa canalizar a saída, greppor exemplo?

NB: Eu sei que posso criar um script, mas estou perguntando se já existe uma ferramenta disponível.

0xC0000022L
fonte

Respostas:

41

zless

Parece uma pena zcat, já que a libz possui uma API que suporta a leitura de arquivos compactados e descompactados de forma transparente. Mas a página de manual diz que zcaté equivalente a gunzip -c.

sourcejedi
fonte
Obrigado por esta alternativa. Eu poderia ter pensado nisso, não poderia? ;) ... Ah bem. Localize, marque com +1 e aceite (também porque você tem menos representantes do que o outro respondedor).
0xC0000022L
Surpreendente. Ajudou-me bastante, eu estava usando o shell script para resolver isso por anos ... ou um terrível script perl ... fusão de resolução de log, usada pelo awstats ... agora eu conheço essa ferramenta incrível. Obrigado.
Luciano Andress Martini
99

Experimente com -fou --force:

zcat -f -- *

Como zcaté apenas um script simples que roda

exec gzip -cd "$@"

com opções longas que se traduziriam em

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

e, de acordo com o man gzip(enfatize o meu):

-f --force
      Forçar compactação ou descompactação, mesmo se o arquivo tiver vários links
      ou o arquivo correspondente já existe, ou se os dados compactados forem
      lido ou gravado em um terminal. Se os dados de entrada não estiverem em um formato
      reconhecido pelo gzip e, se a opção --stdout também for fornecida, copie o
      insira dados sem alterar a saída padrão: deixe o zcat se comportar como gato .

Além disso:

para que eu possa canalizar a saída para, greppor exemplo

Você poderia usar zgreppara isso:

zgrep -- PATTERN *

embora veja o comentário de Stéphane abaixo.

don_crissti
fonte
11
Obrigado, essa é uma alternativa interessante para a zlesssolução. Agradável e +1.
0xC0000022L
6
Observe que ambos zlesse zgrepsão scripts que chamam gzip -cdfq(ou seja zcat -fq).
Stéphane Chazelas
9

Eu uso exatamente para o mesmo propósito:

{ cat /var/log/messages ; zcat /var/log/messages*.gz ; }| grep something | grep "something else" ....
Washuu
fonte
Gosto dessa abordagem porque exige menos tempo na educação de colegas de trabalho. Se as mensagens de log tiverem um carimbo de data / hora em um carimbo de data e hora de classificação, isso é especialmente útil.
Thomas L Holaday
Excelente abordagem. Obrigado.
Miloš Đakonović
7

Existe um substituto para o ztools (zcat, zgrep, ..) chamado zutils, que une todas as ferramentas de descompressão independentemente do back-end. Portanto, com o mesmo comando, você pode ler arquivos simples, lzma, gzipped, xz de forma transparente.

Está disponível no debian wheezy ou mais recente, provavelmente no redhat / centos também.

A página do projeto está aqui nongnu.org

Uma postagem no blog explicando o uso do utilitário aqui ( noone.org )

aseques
fonte
3

Isso funciona bem no RHEL 5.x, em que o zcat é um binário. Ele falha no RHEL 6.x (e Ubuntu 12.x), onde zcat é um script. Isso costumava funcionar bem.

Eu não usaria o zcat, mas o zgrep também não lidará adequadamente com arquivos não compactados.

Peter Laws
fonte
2

Abre ambos compactados e não compactados, em ordem cronológica.

ls -v syslog* | tac | xargs zcat -f | less
Ryan
fonte
Dá ordem errada com mais de dez arquivos de log (syslog.10.gz ...)
Vanni
Boa pegada. -v deve consertar isso.
Ryan
ls -rvpara evitar tac. Para arquivos de log, less $(ls -rv syslog*)com o seu LESSOPENenv var, o conjunto funciona corretamente. Você pode pesquisar nos arquivos esc-npara encontrar a próxima correspondência, ignorando os limites dos arquivos.
Peter Cordes
Com zsh:zcat -f syslog*(nOn)
Stéphane Chazelas
Isso não funciona se você tiver seu registro girar definido para comprimir o dia seguinte
cjbarth
1

E o invólucro?

$ 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
ConcealmEnt
fonte
0

Copie e cole (ou coloque no final do seu ~/.bashrcarquivo) esta função bash :

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

Agora você pode digitar, por exemplo, logs /var/log/syslogou logs /var/log/nginx/access.logpara ver todas as mensagens de log syslog ou nginx, da mais antiga para a mais nova, com menos .

Você pode então procurar algo digitação /somethinge bater npara o próximo .

Vanni
fonte
0

Existe um belo script perl exatamente fazendo isso. É logresolvemerge.pl do projeto awstats: http://www.awstats.org/docs/awstats_tools.html

O Logresolvemerge permite obter um arquivo de log de saída exclusivo, classificado na data, construído a partir de fontes específicas:

  • Pode ler vários arquivos de log de entrada
  • Ele pode ler arquivos de log .gz / .bz2

    A saída está em STDOUT, para que você possa utilizá-la bastante bem em processos adicionais.

  • Daniel Andersen
    fonte
    0

    Com base na resposta de @ Ryan, o seguinte fará com que todos os arquivos 'rolados' sejam classificados em ordem alfabética, depois obtenha o arquivo atual, descompacte-os, se necessário, e lesseles:

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

    ou, se você quiser obtê-los todos como um fluxo contínuo, poderá obtê- taillos e, opcionalmente, canalizar isso para outro processo

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

    Devo observar que isso foi projetado para logs rotacionados diariamente com a data anexada ao final do arquivo. Se seus logs nos apresentarem um formato diferente, você precisará modificar a primeira parte da catdeclaração para acomodar.

    cjbarth
    fonte