Skip to content

Check logfile

Overview

Scans a logfile for matching patterns or regular expressions and alerts based on the number of matches found. Supports both simple string matching (--warning-pattern, --critical-pattern) and Python regular expressions (--warning-regex, --critical-regex). Lines can be excluded via --ignore-pattern or --ignore-regex.

Important Notes:

  • Requires root or sudo to access most system logfiles
  • On Linux, --filename is confined to /var/log. The check runs as root via sudo, so it refuses a path that resolves outside the system log directory, which stops it from being turned into an arbitrary root file read. To monitor a log stored elsewhere, bind-mount that location under /var/log (a symlink is rejected); see the Troubleshooting section. On Windows, where the check runs as the account of the monitoring agent's service and there is no sudo, it reads any path.
  • At least one --warning-pattern, --warning-regex, --critical-pattern, or --critical-regex must be specified
  • When using --icinga-callback, the parameters --icinga-url, --icinga-password, --icinga-username, and --icinga-service-name are all required. Create an Icinga API user like so:
object ApiUser "linuxfabrik-check-logfile" {
  password = "linuxfabrik"
  permissions = [
  {
    permission = "objects/query/service"
  }]
}
  • For more complex log analysis use cases, consider using a dedicated logging server like Graylog

Data Collection:

  • Expands time macros in --filename on every run, so logfiles whose name contains the current date ({today}.log, app-{today}.log, {%Y}{%m}{%d}.log, etc.) can be monitored directly. For {today} and {yesterday}, the compact form (YYYYMMDD) is tried first and ISO 8601 (YYYY-MM-DD) is used as fallback. The read offset and pending matches carry over when the filename changes on the next day, so no wrapper script is needed
  • Scans only the lines that were added since the previous run, and rescans the whole logfile once it was rotated, truncated, or rewritten from the beginning by the application. A rewrite that reproduces the first 256 bytes of the logfile unchanged is not recognized as one
  • Keeps its state in a SQLite database. Each combination of logfile and pattern set gets its own database, so two services watching the same logfile for different things do not interfere. Changing a pattern starts a new database, and the next run therefore reports every match the logfile still holds
  • --warning-pattern and --critical-pattern search for plain substrings and are faster than their regex counterparts
  • Matches keep alerting across runs, even once the logfile stops growing: for --alarm-duration minutes (default 60), or, with --icinga-callback, until the service is acknowledged in Icinga. They appear in the output as "Unacknowledged warning/critical matches from previous runs" and count towards the thresholds like new matches do
  • --before-context, --after-context and --context print up to 10 lines around each match, like grep. The lines are shown in the order the logfile holds them, with the matching line marked by >>>. Because only new lines are read, the lines in front of a match often come from the previous run, and the lines after it often only arrive on the following runs; the check keeps the former back and adds the latter to the match as they are written. As in grep, no line is printed twice, so a line between two matches belongs to the first one. Context lines are taken from the logfile as it is, regardless of --match and --ignore, and a rotation discards what was kept back. The context applies to matches found from then on: a match that was already reported keeps the text it was found with, and the lines around it cannot be added later

Fact Sheet

Fact Value
Check Plugin Download https://github.com/Linuxfabrik/monitoring-plugins/tree/main/check-plugins/logfile
Nagios/Icinga Check Name check_logfile
Check Interval Recommendation Every minute
Can be called without parameters No (--filename and at least one pattern/regex are required)
Runs on Cross-platform
Compiled for Windows Yes
Uses State File $TEMP/linuxfabrik-monitoring-plugins-logfile-<basename>-<hash>.db (one DB per combination of logfile and pattern set)

Help

usage: logfile [-h] [-V] [--after-context AFTER_CONTEXT]
               [--alarm-duration ALARM_DURATION] [--always-ok]
               [--before-context BEFORE_CONTEXT] [--context CONTEXT] [-c CRIT]
               [--critical-pattern CRIT_PATTERN] [--critical-regex CRIT_REGEX]
               --filename FILENAME [--icinga-callback]
               [--icinga-password ICINGA_PASSWORD]
               [--icinga-service-name ICINGA_SERVICE_NAME]
               [--icinga-url ICINGA_URL] [--icinga-username ICINGA_USERNAME]
               [--ignore IGNORE] [--insecure] [--match MATCH] [--no-insecure]
               [--no-match-severity {ok,warn,crit,unknown}] [--no-perfdata]
               [--no-proxy] [--proxy PROXY] [--suppress-lines]
               [--timeout TIMEOUT] [-w WARN] [--warning-pattern WARN_PATTERN]
               [--warning-regex WARN_REGEX]

Scans a logfile for matching patterns or regular expressions and alerts based
on the number of matches found. Only the lines added since the previous run
are scanned, and the whole file is rescanned whenever it was rotated,
truncated or rewritten in place. Optionally asks the monitoring server whether
the service running this check is acknowledged, and suppresses repeated alerts
for known issues where it is. Configurable alarm duration limits how long
matches trigger alerts. `--filename` accepts time macros, so logfiles whose
name contains the current date (`20260422.log`, `app-2026-04-22.log`, etc.)
can be monitored directly. `{today}` / `{yesterday}` resolve tolerantly:
compact (`YYYYMMDD`) first, ISO 8601 (`YYYY-MM-DD`) as fallback if the compact
file does not exist. Read offset and pending matches carry over when the
filename changes on the next day, no wrapper script needed. Prints the lines
around each match on request, like `grep --context`, including lines the
logfile only receives after the run that found the match. Requires root or
sudo.

options:
  -h, --help            show this help message and exit
  -V, --version         show program's version number and exit
  --after-context AFTER_CONTEXT
                        Print this many lines that follow a matching line
                        along with it, like `grep --after-context`. Lines the
                        logfile does not hold yet are added on the following
                        runs. Applies to matches found from then on. Takes
                        precedence over `--context`. Takes 0 to 10. Default:
                        the value of `--context`
  --alarm-duration ALARM_DURATION
                        Duration in minutes for how long new matches trigger
                        an alert. Overwritten by `--icinga-callback`. Default:
                        60
  --always-ok           Always returns OK.
  --before-context BEFORE_CONTEXT
                        Print this many lines that precede a matching line
                        along with it, like `grep --before-context`. Lines
                        read by the previous run count as well. Applies to
                        matches found from then on. Takes precedence over
                        `--context`. Takes 0 to 10. Default: the value of
                        `--context`
  --context CONTEXT     Print this many lines before and after a matching line
                        along with it, like `grep --context`. Sets `--before-
                        context` and `--after-context` where they are not
                        given. Applies to matches found from then on. Takes 0
                        to 10. Default: 0
  -c, --critical CRIT   CRIT threshold for the number of found critical
                        matches. Default: 1
  --critical-pattern CRIT_PATTERN
                        Any line containing this pattern will count as a
                        critical. Can be specified multiple times.
  --critical-regex CRIT_REGEX
                        Any line matching this Python regex will count as a
                        critical. Can be specified multiple times.
  --filename FILENAME   Path to the logfile. Supports time macros that are
                        expanded on every run: `{today}` / `{yesterday}` first
                        try the compact form `YYYYMMDD`, then fall back to
                        `YYYY-MM-DD` if that file does not exist. `{%Y}`,
                        `{%y}`, `{%m}`, `{%d}`, `{%H}`, `{%M}`, `{%S}` render
                        the matching strftime component of the current time.
                        Example: `/var/log/app/{today}.log`. Example:
                        `/var/log/app/app-{today}.log`. Example:
                        `/var/log/app/{%Y}{%m}{%d}.log`.
  --icinga-callback     Ask the monitoring server whether the service running
                        this check is acknowledged. Where it is, what this run
                        reports is remembered as already handled, so it no
                        longer raises an alert on the following runs. Requires
                        `--icinga-url`, `--icinga-username`, `--icinga-
                        password` and `--icinga-service-name`.
  --icinga-password ICINGA_PASSWORD
                        Monitoring server API password.
  --icinga-service-name ICINGA_SERVICE_NAME
                        Unique name of the service running this check, as the
                        monitoring server knows it. Take it from the `__name`
                        service attribute. Example: `monitoring-server!my-
                        service-name`.
  --icinga-url ICINGA_URL
                        Monitoring server API URL. Example:
                        `https://monitoring.example.com:5665`.
  --icinga-username ICINGA_USERNAME
                        Monitoring server API username.
  --ignore IGNORE       Ignore a line matching this Python regular expression,
                        whichever warning or critical pattern it also matches.
                        Case-sensitive by default; use `(?i)` for case-
                        insensitive matching. Can be specified multiple times.
                        Example: `--ignore='(?i)linuxfabrik'`.
  --insecure            Applies to the connection to the monitoring server
                        that `--icinga-callback` makes, which is the only
                        network connection this check opens. This option
                        explicitly allows insecure SSL connections.
  --match MATCH         Only consider a line matching this Python regular
                        expression. Applied before the warning and critical
                        patterns decide the severity, so it narrows what is
                        looked at rather than what counts as a problem. Case-
                        sensitive by default; use `(?i)` for case-insensitive
                        matching. Can be specified multiple times. If both
                        `--match` and `--ignore` are given, an item must match
                        `--match` AND not match `--ignore` to be reported
                        (include first, exclude second). Example:
                        `--match='^\[prod\]'`.
  --no-insecure         Applies to the connection to the monitoring server
                        that `--icinga-callback` makes, which is the only
                        network connection this check opens. Verify the TLS
                        certificate against the system trust store, overriding
                        the insecure default of this check. Use it once the
                        endpoint presents a publicly trusted certificate, or
                        once its CA has been added to the system trust store.
  --no-match-severity {ok,warn,crit,unknown}
                        State to report when no item matches the filters and
                        nothing is checked. Default: ok
  --no-perfdata         Suppress the performance data section from the output.
                        The status message and the exit code are unaffected,
                        so alerting keeps working while trending data is
                        dropped.
  --no-proxy            Applies to the connection to the monitoring server
                        that `--icinga-callback` makes, which is the only
                        network connection this check opens. Do not use a
                        proxy, not even one the environment names. Overrides
                        `--proxy`.
  --proxy PROXY         Applies to the connection to the monitoring server
                        that `--icinga-callback` makes, which is the only
                        network connection this check opens. Proxy to reach
                        the target through. The scheme defaults to `http` when
                        omitted. Overrides the proxy the environment names
                        (`http_proxy`, `https_proxy`, `all_proxy`) together
                        with the exceptions it lists in `no_proxy`, and is
                        itself overridden by `--no-proxy`. Without either
                        parameter the environment applies. Credentials belong
                        into the environment variable rather than here,
                        because a command-line argument is visible to every
                        user on the host. Example:
                        `--proxy=http://proxy.example.com:3128`.
  --suppress-lines      Suppress the found lines in the output and only report
                        the number of findings.
  --timeout TIMEOUT     Network timeout in seconds. Default: 5 (seconds)
  -w, --warning WARN    WARN threshold for the number of found warning
                        matches. Default: 1
  --warning-pattern WARN_PATTERN
                        Any line containing this pattern will count as a
                        warning. Can be specified multiple times.
  --warning-regex WARN_REGEX
                        Any line matching this Python regex will count as a
                        warning. Can be specified multiple times.

Documentation:
https://linuxfabrik.github.io/monitoring-plugins/check-plugins/logfile/

Usage Examples

cat > /tmp/test-logfile << 'EOF'
test0
test1
warning
test2
test
error1
error2
test4
EOF

./logfile --filename=/tmp/test-logfile --critical-pattern='error' --warning-pattern='warn'

Output:

Scanned /tmp/test-logfile (8 lines) using patterns 'warn' (matched 1 line) [WARNING] and 'error' (matched 2 lines) [CRITICAL].

Warning matches:
* warning

Critical matches:
* error1
* error2

The (N lines) figure counts the lines that are new since the previous run, not the length of the logfile. Both are the same on the first run and after a rotation.

With the lines around each match:

./logfile --filename=/var/log/myapp/app.log --critical-regex=' ERROR ' --context=2

Output:

Scanned /var/log/myapp/app.log (9 lines) using patterns ' ERROR ' (matched 1 line) [CRITICAL].

Critical matches:
* 2026-09-21 10:00:00 INFO GET /
  2026-09-21 10:00:01 INFO POST /api/order
  >>> 2026-09-21 10:00:02 ERROR Request failed
  Traceback (most recent call last):
    File "app.py", line 12, in handle

States

  • OK if no matches are found or the number of matches is below both thresholds.
  • WARN if the number of warning matches (new + old) is >= --warning (default: 1).
  • CRIT if the number of critical matches (new + old) is >= --critical (default: 1).
  • UNKNOWN if the logfile does not exist, is not readable, or no pattern/regex is specified.
  • --always-ok suppresses all alerts and always returns OK.

Perfdata / Metrics

Name Type Description
crit_matches Number Number of new critical matches found in this run.
scanned_lines Number Total number of new lines scanned in this run.
warn_matches Number Number of new warning matches found in this run.

Credits, License