Estoy viendo un registro y quiero detectar cuándo un programa ha tenido 3 intentos fallidos:
tail -f file.log | grep --line-buffered program\ failed\ string
Si el recuento de líneas grep
llega a 3, quiero devolver un error.
¿Cómo puedo hacer esto?
Respuesta1
awkes una gran herramienta para escanear transmisiones.
Supuse que debería mostrar todas las líneas para ver el registro hasta que salga, al contrario de su ejemplo congrepque muestran solo líneas de error.
tail -f file.log | awk '
BEGIN {
count = 0
}
{
print($0)
if ($0 ~ /program failed/) {
count++
if (count == 3) {
exit(1)
}
}
}
'
Puedes mover el código awk acola.awky llama tail -f file.log | awk -f tail.awk
si lo prefieres.
De manera equivalente, en una forma más compacta:
tail -f file.log | awk '1; /program failed/ && ++count == 3 { exit 1 }'
Respuesta2
En caso de que alguien prefiera una alternativa a 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)