Ich beobachte ein Protokoll und möchte erkennen, wenn ein Programm drei Fehlversuche hatte:
tail -f file.log | grep --line-buffered program\ failed\ string
Wenn die Zeilenanzahl grep
3 erreicht, möchte ich einen Fehler zurückgeben.
Wie kann ich das machen?
Antwort1
awkist ein großartiges Tool zum Scannen von Streams.
Ich bin davon ausgegangen, dass alle Zeilen angezeigt werden sollen, um das Protokoll anzuzeigen, bis es beendet wird, im Gegensatz zu Ihrem Beispiel mitgrepdie nur Fehlerzeilen anzeigen.
tail -f file.log | awk '
BEGIN {
count = 0
}
{
print($0)
if ($0 ~ /program failed/) {
count++
if (count == 3) {
exit(1)
}
}
}
'
Sie können den Awk-Code verschieben nachSchwanz.awkund rufen Sie an tail -f file.log | awk -f tail.awk
, wenn Sie möchten.
Entsprechend in einer kompakteren Form:
tail -f file.log | awk '1; /program failed/ && ++count == 3 { exit 1 }'
Antwort2
Nur für den Fall, dass jemand eine Python-Alternative bevorzugt:
#!/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)