Linux / Sendmail um forro com problemas com grandes diretórios

1

Por alguma razão, os spammers encontraram uma maneira de retransmitir e-mails através de um sistema paralelo. A exploração já foi abordada.

O problema é que eu tinha uma quantidade enorme de e-mails no meu diretório / var / spool / mqueue (pelo menos 100.000+) que ainda preciso filtrar. Eu parei o sendmail e movi o conteúdo do diretório do mqueue para um novo local ...

Desde então, venho tentando usar o seguinte liner para ajudar:

for x in 'find . -type f -name “qf*” | xargs grep -l "foo" | cut -b3-'; do y=d'echo $x | cut -b2-'; mv $x /root/spammessages; mv $y /root/spammessages/; done

A ideia é:

1) verifique os arquivos QF quanto ao conteúdo exclusivo do cabeçalho relacionado a spam (foo).

2) Encontre o arquivo de contraparte DF

3) Mova os arquivos df e qf para uma área isolada.

O problema é que a consulta está em execução, mas não parece estar movendo nenhum arquivo. Se eu executar top, vejo xargs e grep ocasionalmente usando alguns recursos, mas nunca mais que 1% -2%. Além disso ... quando eu verifico a pasta spammessages, não vejo nenhum arquivo lá.

Se eu executar o mesmo comando em um subconjunto menor de mensagens, parece funcionar bem. Existem algumas limitações de arquivos linux aqui? Existem maneiras de otimizar o one-liner?

Obrigado.

-M

    
por Mike B 08.02.2010 / 19:03

1 resposta

2

Vamos dividir em várias linhas

for x in 'find . -type f -name "qf*" | xargs grep -l "foo" | cut -b3-'
do 
    y=d'echo $x | cut -b2-'
    mv $x /root/spammessages
    mv $y /root/spammessages/
done
  • Você sempre deve usar -print0 com find e -0 com xargs quando estiver canalizando nomes de arquivos de um para o outro
  • Use $() em vez de backticks para facilitar a leitura e a capacidade de aninhar e reduzir a necessidade de fugas
  • Sempre cite nomes de variáveis que armazenam nomes de arquivos
  • Chamar um externo ( cut ) muitas vezes em um loop é lento (eliminei como não era necessário de qualquer maneira)
  • Você tem uma barra terminal em um diretório, mas não o outro (consistência)
  • Você está cortando o "qf" quando cria a variável x , mas não a coloca de volta quando faz a mudança.
  • Você está cortando "qf", mas não colocando "f" ao fazer a variável y (que está cortando um caractere adicional de x )
  • Além disso, você tinha aspas tipográficas (inteligentes ou Unicode ou qualquer nome que você queira chamá-las) em torno de seu filespec em find , o que pode ter interferido

Tente isto:

for x in $(find . -type f -name "qf*" -print0 | xargs -0 grep -l "foo" | cut -b3-)
do 
    mv "qf$x" /root/spammessages/
    mv "df$x" /root/spammessages/
done

Coloque de volta em uma linha:

for x in $(find . -type f -name "qf*" -print0 | xargs -0 grep -l "foo" | cut -b3-); do mv "qf$x" /root/spammessages/; mv "df$x" /root/spammessages/; done

Editar:

Aqui está uma versão usando um loop while , que pode funcionar melhor para um grande número de arquivos:

find . -type f -name "qf*" -print0 | xargs -0 grep -l "foo" | cut -b3- |
while read -r x
do 
    mv "qf$x" /root/spammessages/
    mv "df$x" /root/spammessages/
done

Em um verso:

find . -type f -name "qf*" -print0 | xargs -0 grep -l "foo" | cut -b3- | while read -r x; do mv "qf$x" /root/spammessages/; mv "df$x" /root/spammessages/; done

Uma variação que usa a substituição de processos do Bash:

while read -r x
do 
    mv "qf$x" /root/spammessages/
    mv "df$x" /root/spammessages/
done < <(find . -type f -name "qf*" -print0 | xargs -0 grep -l "foo" | cut -b3-)

E:

while read -r x; do mv "qf$x" /root/spammessages/; mv "df$x" /root/spammessages/; done < <(find . -type f -name "qf*" -print0 | xargs -0 grep -l "foo" | cut -b3-)
    
por 08.02.2010 / 19:57