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