Mostrar o nome do arquivo no início de cada linha ao seguir vários arquivos de uma vez?


14

ao seguir vários arquivos de uma vez, como mostrado abaixo, existe alguma maneira de mostrar o nome do arquivo no início de cada linha?

tail -f one.log two.log

saída atual

==> one.log <==
contents of one.log here...
contents of one.log here...

==> two.log <==
contents of one.log here...
contents of two.log here..

Procurando algo como

one.log: contents of one.log here...
one.log: contents of one.log here...
two.log: contents of two.log here...
two.log: contents of two.log here...

Você pode olhar para a -vopção (detalhada) da cauda. Isso pode não corresponder exatamente à sua pergunta, mas é um começo.
Rahul

multitail pode fazer isso eu acho
Gilles 'SO parada sendo maus'

Respostas:


7
tail  -f ...your-files | 
    awk '/^==> / {a=substr($0, 5, length-8); next}
                 {print a":"$0}'

\ obrigado {don_cristti}


@don_crissti, obrigado! (1) um arquivo vs - não há mais vinho para o meu copo! (2) boa ideia. Começo a fazer algo assim, mas disse vagamente para mim mesmo: "ninguém fará arquivos-de-cauda com espaços" :) - Usarei suas excelentes sugestões.
JJoao

você pode explicar o comprimento-8? por que é 8 aqui, eu sei apenas 8 funciona.
Shicheng Guo

1
cauda -n 1 * .txt | awk '/ ^ ==> / {a = substr ($ 0, 5, comprimento-8); próximo} {imprima a, $ 1} '| awk '$ 2> 0 {if ($ 2! ~ / chrY /) imprime $ 1}' | xargs -I {} qsub {}
Shicheng Guo

@ShichengGuo, 8 = length ("==>") + length ("<==")
JJoao 25/17/17

1
surpreendentemente / surpreendentemente sua awksolução mágica joojoo funciona!
Trevor Boyd Smith

6

Resposta curta

O GNU Parallel possui um conjunto de boas opções que facilitam a execução de tais ações:

parallel --tagstring "{}:" --line-buffer tail -f {} ::: one.log two.log

A saída seria:

one.log: conteúdo de one.log aqui ...
one.log: conteúdo de one.log aqui ...
two.log: conteúdo de two.log aqui ...
two.log: conteúdo de two.log aqui ...

Mais explicações

  • A opção --tagstring=stridentifica cada linha de saída com a string str . Na parallel página do manual :
--tagstring str
                Marcar linhas com uma sequência. Cada linha de saída será anexada com
                str e TAB (\ t). str pode conter cadeias de substituição como {}.

                --tagstring é ignorado ao usar -u, --onall e --nonall.
  • Todas as ocorrências de {}serão substituídas pelos argumentos de paralelo que, nesse caso, são nomes de arquivos de log; ie one.loge two.log(todos os argumentos depois :::).

  • A opção --line-bufferé necessária porque a saída de um comando (por exemplo, tail -f one.logou tail -f two.log) seria impressa se esse comando fosse concluído. Como tail -faguardará o crescimento do arquivo, é necessário imprimir a saída on-line, o que o --line-bufferfará. Novamente na parallel página do manual :

--line-buffer (teste alfa)
                Saída do buffer em linha. --group manterá a saída
                juntos por um trabalho inteiro. --ungroup permite que a saída se misture com
                meia linha proveniente de um emprego e meia linha proveniente de
                outro trabalho. - line-buffer se encaixa entre estes dois: GNU paralelo
                imprimirá uma linha completa, mas permitirá misturar linhas de
                trabalhos diferentes.

2

Se tailnão for obrigatório, você pode usar greppara fazer isso:

grep "" *.log

Isso imprimirá o nome do arquivo como o prefixo de cada linha de saída.

A saída é interrompida se for *.logexpandida para apenas um arquivo. A respeito disso:

grep '' /dev/null *.log

Eu preciso mostrar o nome do arquivo na saída de tail -fnão grep.
mtk

@serenesat isso imprimiria todo o conteúdo dos arquivos, não? O OP foi pedir o nome do ficheiro a ser impresso quando for especificado cauda
rahul

você também pode fazer --with-filenameou -Hforçar sempre a pré-inclusão de nome de arquivo.
Trevor Boyd Smith

eu realmente amo essa resposta! faz exatamente o que é necessário com uma solução com 13 caracteres. em vez de awksolução complicada ou parallelque não está instalada.
Trevor Boyd Smith

O único problema é que, se seus arquivos de log tiverem 1 milhão de linhas. então o seu grep vai Spam 1 milhão de linhas para console (ou ssh over) ...
Trevor Boyd Smith

0

Minha idéia seria criar um único arquivo com logs mesclados de vários arquivos, como alguém sugerido aqui e anexar nomes de arquivos:

$ tail -f /var/log/syslog | sed -u -E 's,(^.+$),/var/log/syslog: \1,g' >> /tmp/LOG &&
$ tail -f /var/log/Xorg.0.log | sed -u -E 's,(^.+$),/var/log/Xorg.0.log: \1,g' >> /tmp/LOG &&
$ tail -f /tmp/LOG

0

Algo com xargse sedpoderia funcionar:

$ xargs -I% -P0 sh -c "tail -f % | sed s/^/%:/g" <<EOT
one.log
two.log
EOT
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.