Estou observando um log e quero detectar quando um programa teve três tentativas malsucedidas:
tail -f file.log | grep --line-buffered program\ failed\ string
Se a linha contar dos grep
hits 3, quero retornar um erro.
Como posso fazer isso?
Responder1
estranhoé uma ótima ferramenta para escanear streams.
Presumi que deveria exibir todas as linhas para ver o log até sair, ao contrário do seu exemplo comgrepque exibem apenas linhas de erro.
tail -f file.log | awk '
BEGIN {
count = 0
}
{
print($0)
if ($0 ~ /program failed/) {
count++
if (count == 3) {
exit(1)
}
}
}
'
Você pode mover o código awk paracauda.awke ligue tail -f file.log | awk -f tail.awk
se preferir.
Equivalentemente, de forma mais compacta:
tail -f file.log | awk '1; /program failed/ && ++count == 3 { exit 1 }'
Responder2
Caso alguém prefira uma alternativa Python:
#!/usr/bin/env python2
# -*- encoding: ascii -*-
"""tail.py"""
import sys
import argparse
import time
import re
# Create a command-line parser
parser = argparse.ArgumentParser()
parser.add_argument(
"-f", "--input-file",
help="File to search through.",
dest="input_file", type=str,
)
parser.add_argument(
"-p", "--pattern",
help="Regular expression to match.",
default=r'.*',
dest="pattern", type=str,
)
parser.add_argument(
"-m", "--match-limit",
help="Number of matches before exiting.",
default=float(1),
dest="match_limit", type=int,
)
parser.add_argument(
"-q", "--quiet",
help="Don't print matched lines.",
default=False,
dest="quiet", type=bool,
)
# Define the file-watching function
def watch_for_matches(file_handle, pattern, match_limit, quiet):
# Count the number of matched lines
matches_found = 0
# Get the next line
line = file_handle.readline()
# Check to see if the limit has been reached
while(matches_found < match_limit):
# Match the line against the given regular expression
if(line and re.search(pattern, line)):
# Optionally print the matched line
if not quiet:
sys.stdout.write(line)
# Increment the match counter
matches_found += 1
# Optionally wait for a moment
time.sleep(0.25)
# Get the next line of input
line = file_handle.readline()
# If the match limit is reached, exit with an error
sys.exit(1)
# Parse the command-line arguments
args = parser.parse_args()
# Execute the function
if args.input_file:
with open(args.input_file, 'r') as file_handle:
watch_for_matches(file_handle, args.pattern, args.match_limit, args.quiet)
# If no file is given, use standard input instead
else:
watch_for_matches(sys.stdin, args.pattern, args.match_limit, args.quiet)