Como posso encontrar arquivos de log e arquivos de log perdidos não sendo rotacionados?

2

Eu tenho vários sistemas Linux executando vários aplicativos caseiros, alguns web apis, alguns dados de fundo, vários bancos de dados e coisas que eu nem encontrei ainda. Esses sistemas foram configurados por várias pessoas durante vários meses e ninguém sabe realmente como cada servidor é usado. Algumas das pessoas que criavam programas sobre estes eram estagiários ou contratados que partiram. Então, não sabemos como tudo está configurado.

Estou tentando descobrir quais arquivos de log estão sendo gravados, especialmente aqueles que estão sendo escritos em locais estranhos (ou seja, não em / var / log). Eu também estou tentando encontrar todos os arquivos de log não sendo girados, especialmente se eles estão crescendo rapidamente. Eu encontrei dois servidores na semana passada correndo contra o seu limite de disco e processos de falha. Meu objetivo é reconfigurar cada aplicativo para fazer algo sensato para o registro e, eventualmente, enviá-lo para uma pilha ELK, mas, por enquanto, só preciso descobrir o que tenho.

Então, para começar, estou tentando encontrar tudo o que é um arquivo de log. Isso é difícil se eles estão espalhados aleatoriamente no sistema. Alguns sob / home / someuser, um estava em / root, alguns em / tmp e um em / var / lib.

Meu primeiro pensamento para encontrar arquivos de log foi encontrar qualquer arquivo modificado recentemente. Veja esta resposta: link

Isso me deixa muito barulho embora. Bancos de dados mantêm as coisas em disco, então eles escrevem arquivos, as atualizações do sistema substituem os binários, então eles são modificados e os usuários modificam o material em suas casas.

Meu próximo pensamento foi encontrar pelo nome. A maioria dos arquivos de log termina com .log, mas outros não. Talvez alguns tenham "log" em algum lugar no nome do caminho. Veja esta resposta: link

Depois de ter uma lista de logs, posso verificar as regras do logrotate para encontrar algo correspondente. Isso deve ser fácil o suficiente para for e grep.

Alguém tem uma idéia melhor de como enumerar arquivos de log dispersos em um sistema Linux não documentado?

    
por Mnebuerquo 01.02.2018 / 17:26

2 respostas

3

Descobri que este é um problema interessante, por vários motivos:

  • Eu poderia entrar em um sistema semelhante e precisar lidar com o crescimento de arquivos / sistemas de arquivos
  • Reunir a lista de sistemas de arquivos "locais" não é simples
  • Determinar o crescimento requer várias verificações, com um atraso de tempo entre
  • Genericamente excluindo "diretórios de usuário" exigia alguns cuidados

Eu criei um script que, em alto nível, usa find para procurar arquivos não executáveis que foram modificados nos últimos sete dias; em seguida, ele dorme por um minuto e, em seguida, verifica novamente esses arquivos para ver se algum deles cresceu mais de 42 bytes.

Naturalmente, todos os números arbitrários são livremente editáveis em sua própria cópia do script:

  • quantidade de tempo para dormir (aguarde o crescimento do arquivo de log)
  • quantidade de crescimento para alertar sobre
  • quão recentemente modificados os arquivos devem ser

Eu pego a lista de sistemas de arquivos locais usando lsblk , pedindo para produzir uma lista, sem títulos , apenas dos pontos de montagem; porque essa saída inclui dispositivos de bloco que não são necessariamente montados (por exemplo, discos inteiros, áreas de troca, etc), eu então filto para pontos de montagem que contêm / .

Excluir diretórios caseiros parecia uma boa idéia, mas eu não queria supor que todos os diretórios home estivessem sob /home , então eu removi o UID_MIN de /etc/login.defs como o intervalo inicial para usuários "típicos", então use o awk para extrair os diretórios home de tais usuários de / etc / passwd. Esses diretórios base são excluídos do find .

Advertências

Eu queria usar find ... -print0 em combinação com readarray -t -d '' para capturar com segurança todos os nomes de arquivos, mas o readarray delimitado nulo requer uma versão bash recente (4.4-alpha ou posterior). Em vez disso, comprometi e usei find ... -print , com a ressalva de que qualquer nome de arquivo relevante que contivesse uma nova linha causaria erros.

O script não irá (durante qualquer execução) encontrar arquivos de log recém-criados ; ele reúne a lista inicial de arquivos de log em potencial e, em seguida, percorre a mesma lista para ver quais arquivos cresceram. Arquivos recém-criados só seriam capturados por uma execução subseqüente.

O script

#!/bin/bash

# files that grow by more than this much are interesting; in bytes per second; also, the answer to Life, the Universe, and Everything
rate=42

# how long we'll wait to account for file growth
sleeptime=60

function gethomedirs() (
  uidmin=$(awk '/^UID_MIN/ { print $2 }' < /etc/login.defs)
  awk -F: -v umin="$uidmin" '$3 >= umin { print $6 }' < /etc/passwd | sort -u
)

function findlogfiles {
  readarray -t homedirs < <(gethomedirs)

  if [ ${#homedirs[@]} -eq 0 ]
  then
    excludes=()
  elif [ ${#homedirs[@]} -eq 1 ]
  then
    excludes=("( -path ${homedirs[0]} ) -prune -o")
  else
    excludes=()
    excludes+=("(")
    excludes+=(" -path ${homedirs[0]}")
    for((i=1; i < ${#homedirs[@]}; i++))
    do
      excludes+=(" -o -path ${homedirs[i]}")
    done
    excludes+=(") -prune -o ")
  fi

  find  $(lsblk --list --noheadings --output MOUNTPOINT | grep /) \
        -xdev \
        ${excludes[@]} \
        -type f -mtime -7 ! -executable -print
}

readarray -t files < <(findlogfiles)
declare -A initialsize
for file in "${files[@]}"
do
  initialsize["$file"]=$(stat -c %s "$file")
done

#echo Waiting $sleeptime seconds for log files to grow... >&2
sleep $sleeptime

for file in "${files[@]}"
do
  # if the file went away, skip it
  [ -f "$file" ] || continue
  size2=$(stat -c %s "$file")
  if (( size2 >= (${initialsize["$file"]} + rate * sleeptime) ))
  then
        printf "%s\n" "$file"
  fi
done
    
por 03.02.2018 / 17:58
1

Então eu criei um plano, embora eu não esteja super feliz com isso.

Eu usei as ideias que eu já tinha, mas tornei isso menos genérico. Eu estou procurando arquivos de log em locais específicos e apenas aqueles maiores que um determinado tamanho (1M). Então, se alguém tem um log em um lugar estranho eu não posso encontrá-lo. Para excluir arquivos girados pelo logrotate, estou acionando manualmente uma rotação de log primeiro. Dessa forma, esses arquivos serão truncados antes de eu executar minhas pesquisas. Eu também estou assumindo arquivos de log chamados * .log, então se alguém tiver um log com nomes estranhos, então eu não o encontrarei e isso causará problemas eventualmente. Espero resolver isso ensinando a minha equipe a usar uma pilha ELK em um futuro próximo.

Aqui está meu script que eu executo em cada máquina:

#!/bin/sh

sudo logrotate -vf /etc/logrotate.conf
sudo find /var/log -type f -mtime -2 -name "*log" -size +1M -exec sudo ls -l {} \; 
sudo find /home -type f -mtime -2 -name "*log" -size +1M -exec sudo ls -l {} \; 
sudo find /root -type f -mtime -2 -name "*log" -size +1M -exec sudo ls -l {} \; 
    
por 02.02.2018 / 15:41

Tags