Lendo um arquivo incrementalmente [duplicado]

0

Eu tenho requisito onde eu preciso ler parte do arquivo que foi atualizado a partir da última leitura. Quero dizer, se eu li o arquivo da última vez em 2016-07-26T01: 30 e depois eu quero correr novamente em 2016-07-26T02: 30, onde 100 registros são atualizados no arquivo, então eu preciso ler apenas esses 100 registros em vez disso de arquivo inteiro.

O formato do arquivo é:

[2016-07-26T16:26:31.953-04:00] [AnalyticProviderServices0] [ERROR] [] [oracle.EPMOHPS] [tid: 17] [userId: <anonymous>] [ecid: 0000LGXnLUEComOpyg4EyW1N4iIi000002,1:28342] [APP: APS#11.1.2.0] Unable to resolve 'jdbc.EPMSystemRegistry'. Resolved 'jdbc'[[
[2016-07-26T16:26:31.954-04:00] [AnalyticProviderServices0] [WARNING] [] [oracle.EPMOHPS] [tid: 17] [userId: <anonymous>] [ecid: 0000LGXnLUEComOpyg4EyW1N4iIi000002,1:28342] [APP: APS#11.1.2.0] Failure while getting the active Essbase node for cluster [SWESSPROD1]. Runtime Provider Services Error: [Unable to resolve 'jdbc.EPMSystemRegistry'. Resolved 'jdbc']
    
por Naresh 26.07.2016 / 22:30

3 respostas

2

Existe um utilitário de linha de comando (de 2003) chamado Re-Tail ou "varejo", que faz a leitura de arquivo de log incremental toda vez que você executa o programa no arquivo de log.

Isso é ótimo para tarefas agendadas que são executadas a cada hora, por exemplo.

Re-Tail salva o estado em um "arquivo de deslocamento"; para cada arquivo em que você o executar, ele armazenará o último número da linha e também o texto que estava naquele número de linha.

Na próxima vez que você executar o programa, ele tentará procurar o número da linha armazenada e comparar o conteúdo. Se houver uma correspondência, ela exibirá o restante do arquivo, começando na seguinte linha. Se houver menos linhas no arquivo no disco ou se o conteúdo da linha não corresponder, presume-se que o arquivo tenha sido removido ou girado; nesse caso, ele será reiniciado a partir da primeira linha.

Por fim, o varejo atualizará o número da linha e o conteúdo salvos.

O software está em: link

Quando executo varejo como root, gosto de colocar o estado salvo em / var / lib / retail. Por exemplo, em uma máquina, executo varejo a cada hora para criar um relatório sobre logins de SSH, usando um script que contém a seguinte linha de comando:

/usr/local/bin/retail -p /var/lib/retail/ /var/log/secure >"$tempfile"

Boa sorte!

    
por 25.07.2017 / 11:29
1
#!/bin/bash

logfile="$1"

test -f "$logfile" || exit 1

lastline="$( basename "$logfile" )-last"

if [ -f "$lastline" ]; then
    place=$( <"$lastline" )
else
    place=1
fi

tmpfile="$( mktemp )"
trap 'rm -f "$tmpfile"' EXIT

sed -n -e "$place,\$p" -e '$=' "$logfile" |
tee "$tmpfile" |
tail -n 1 >"$lastline"

sed '$d' "$tmpfile"

Esse pequeno script pegará um arquivo de log na linha de comando e mostrará todas as linhas adicionadas desde a última vez que você usou o script. Ele não entende a rotação do arquivo de log em sua forma atual , então você precisaria remover manualmente o arquivo ...-last que ele cria no diretório atual se o log for girado.

O que faz:

Quando executado pela primeira vez, ele usa sed para gerar todas as linhas do arquivo de registro fornecido para um arquivo temporário, seguido pelo número da linha da última linha. Esse número também é armazenado em um arquivo no diretório atual com o mesmo nome do arquivo de log, com o sufixo -last . O arquivo temporário, sem a última linha contendo o número da linha, é então enviado para o terminal (canalize a saída do script para less , se desejar). Quando o script sai, o arquivo temporário é removido.

Quando executado novamente, o número da linha é lido do arquivo ...-last no diretório atual e o conteúdo do arquivo de log é processado desse número e para o final de maneira semelhante à anterior.

Se nenhuma saída tiver sido feita no arquivo de log entre as execuções desse script. A última linha do arquivo de log será exibida.

Executando:

$ bash script.sh /var/log/system.log
[lots of output]

$ ls system*
system.log-last

$ cat system.log-last
14758

$ bash script.sh /var/log/system.log
[a few lines of output,
 with the first line being the same as the last of the previous run]

$ cat system.log-last
14768
    
por 27.07.2016 / 13:53
1

Você pode deixar o arquivo aberto:

exec 3< file
cat <&3

sleep 3600

echo After one hour, these records were added:
cat <&3

Isso significa que tem que ser o mesmo processo invocando aqueles cat s uma hora a mais.

Se os horários de acesso estiverem ativados no sistema de arquivos e seu script for a única coisa que lê esse arquivo, você também poderá ler as linhas cujo registro de data e hora posteriores ao último horário de acesso. Em um sistema GNU:

awk -v last_access="$(find file -prune -printf %AFT%AT)" '
   $0 > last_access' < file

Isso assume que o -04:00 no arquivo de log corresponde ao atual deslocamento do fuso horário.

Outra abordagem é gravar a posição atual do arquivo em algum lugar, como em file.pos :

{
   if [ -e file.pos ]; then
     pos=$(cat file.pos)
   else
     pos=0
   fi
   tail -c +"$((pos+1))"
   perl -le 'print tell STDIN' > file.pos
} < file

Ou com ksh93

{
   if [ -e file.pos ]; then
     pos=$(<file.pos)
   else
     pos=0
   fi
   cat <#((pos))
   exec <#((pos=CUR))
   echo "$pos" > file.pos
} < file

Ou com zsh :

zmodload zsh/system    
{
   if [ -e file.pos ]; then
     pos=$(<file.pos)
   else
     pos=0
   fi
   sysseek $pos
   cat
   echo "$((systell(0)))" > file.pos
} < file
    
por 27.07.2016 / 14:33

Tags