Question

J'essaie d'écrire un script d'analyse de journal pour extraire les événements ayant échoué. Je peux les tirer avec grep:

$ grep -A5 "FAILED" log.txt

2008-08-19 17:50:07 [7052] [14] DEBUG:      data: 3a 46 41 49 4c 45 44 20 20 65 72 72 3a 30 32 33   :FAILED  err:023
2008-08-19 17:50:07 [7052] [14] DEBUG:      data: 20 74 65 78 74 3a 20 00                            text: .
2008-08-19 17:50:07 [7052] [14] DEBUG:    Octet string dump ends.
2008-08-19 17:50:07 [7052] [14] DEBUG: SMPP PDU dump ends.
2008-08-19 17:50:07 [7052] [14] DEBUG: SMPP[test] handle_pdu, got DLR
2008-08-19 17:50:07 [7052] [14] DEBUG: DLR[internal]: Looking for DLR smsc=test, ts=1158667543, dst=447872123456, type=2
--
2008-08-19 17:50:07 [7052] [8] DEBUG:      data: 3a 46 41 49 4c 45 44 20 20 65 72 72 3a 30 32 34   :FAILED  err:024
2008-08-19 17:50:07 [7052] [8] DEBUG:      data: 20 74 65 78 74 3a 20 00                            text: .
2008-08-19 17:50:07 [7052] [8] DEBUG:    Octet string dump ends.
2008-08-19 17:50:07 [7052] [8] DEBUG: SMPP PDU dump ends.
2008-08-19 17:50:07 [7052] [8] DEBUG: SMPP[test] handle_pdu, got DLR
2008-08-19 17:50:07 [7052] [8] DEBUG: DLR[internal]: Looking for DLR smsc=test, ts=1040097716, dst=447872987654, type=2
Ce qui m'intéresse, c'est, pour chaque bloc, le code d'erreur (c'est-à-dire la partie "023" de ": FAILED err: 023" sur la première ligne) et le numéro dst (c'est-à-dire "447872123456" à partir de "dst = 447872123456" sur la dernière ligne.)

Quelqu'un peut-il aider avec un shell one-liner à extraire ces deux valeurs, ou donner des indices sur la façon dont je devrais aborder cette question?

Était-ce utile?

La solution

grep -A 5 FAILED log.txt | \              # Get FAILED and dst and other lines
    egrep '(FAILED|dst=)' | \             # Just the FAILED/dst lines
    egrep -o "err:[0-9]*|dst=[0-9]*" | \  # Just the err: and dst= phrases
    cut -d':' -f 2 | \                    # Strip "err:" from err: lines
    cut -d '=' -f 2 | \                   # Strip "dst=" from dst= lines
    xargs -n 2                            # Combine pairs of numbers

023 447872123456
024 447872987654

Comme pour tous les "un" liners, il existe certainement une manière plus élégante de le faire. Cependant, je trouve l’approche itérative très réussie pour obtenir ce que je veux: commencer par trop d’informations (votre grep), puis affiner les lignes que je veux (avec grep), puis extraire les parties de chaque ligne que je veux (avec couper).

Bien que l'utilisation de la boîte à outils linux prenne plus de lignes, il vous suffit de connaître les bases de quelques commandes pour faire à peu près tout ce que vous voulez. Une alternative consiste à utiliser awk, python ou d’autres langages de script, qui nécessitent des connaissances en programmation plus pointues, mais prennent moins d’espace à l’écran.

Autres conseils

Solution simple en Ruby, voici filter.rb :

#! /usr/bin/env ruby
File.read(ARGV.first).scan(/:FAILED\s+err:(\d+).*?, dst=(\d+),/m).each do |err, dst|
  puts "#{err} #{dst}"
end

Exécutez-le avec:

ruby filter.rb my_log_file.txt

Et vous obtenez:

023 447872123456
024 447872987654

S'il y a toujours le même nombre de champs, vous pouvez simplement

grep -A5 "FAILED" log.txt | awk '$24~/err/ {print $24} $12~/dst/{print $12}' error.txt

err:023
dst=447872123456,
err:024
dst=447872987654,

Et selon l’apparence du reste du fichier, vous pourrez peut-être ignorer le grep tout ensemble.

Le " $ 24 ~ / err / {print $ 24} " partie indique à awk d’imprimer le champ numéro 24 s’il contient err, ~ / XXX / où XXX est une expression régulière.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top