journal-triggerd - Runs trigger on journal messages
journal-triggerd
journal-triggerd is a small daemon that runs in the background, listening to systemd(1)'s journal, and will run "triggers" (i.e. exec a command line) when certain messages are added.
You can define which messages to listen for, and what to run when such messages are added to the journal, by defining rules.
Rules are defined in (UTF8 encoded) text files, whose names must end with .rule and placed in /etc/journal-triggerd.rules
Any file whose name not end in .rule will be ignored. Files are not processed in any defined order, neither will rules be processed in any given order; Not that it should matter, since all rules are always processed against every new message added to the journal.
A rule is composed of two things : a filter, used to match messages added to the journal, and a trigger, to be run when match occurs.
Rule files have a syntax similar to that of conf/INI files, or systemd's unit files. A section [Rule] must exist, where filter/trigger be defined.
The trigger is simply a command line, define under option trigger
You can use as variable any field from the journal, using $FIELD. For example: trigger=echo $MESSAGE
To use a dollar sign, simply double it.
Note that the value of the field as put as-is. You can also use a single quote between the dollar sign and the field name ($'FIELD), to produce a shell-compatible escaped string of the field value.
For example, if the field MESSAGE contains "this is 'foobar'" (without the double quotes) then using: trigger=mail -s $'MESSAGE
would result in the following command line to be executed: mail -s 'this is '\''foobar'
Also note that this trigger does not directly support shell command lines. If you need to use shell command lines, you need to explicitly call the shell implementation of your choice, e.g: trigger=sh -c 'echo Unit $_SYSTEMD_UNIT just failed >> /path/to/file'
A filter can be either a list of conditions to match, or use boolean logic to create more complex filtering. For the former, no option under [Rule] is needed, simply create a section [Filter] and define the conditions there; See CONDITIONS below for more.
To create more complex filters, an option filer can be set under [Rule] and must be an expression that can make use of parenthesis, AND, OR and NOT as well as named filters/groups.
Those names are case-sensitive names of sections that must exist in the file, where a list of conditions will be defined.
For example, one could use: filter=foobar AND (foo OR bar) AND NOT barfoo
And there must be sections [foobar], [foo], [bar], and [barfoo] defined in the rule file, all of which defining one or more conditions to be matched.
It is of course possible to only use one group name, i.e. when no option filter is set, it defaults to filter=Filter
As a facility it is possible to define multiple rules from a single file, thus allowing to use the same groups in different filters. To do so, simply create an option filterXXX with a matching triggerXXX
For example: [Rule] filter_foo=foo AND NOT foobar trigger_foo=foobar --foo filter_bar=bar AND NOT foobar trigger_bar=foobar --bar filter=foobar AND (foo OR bar) trigger=foobar --foobar
The heart of a filter is a group of conditions, defined simply as a section in the rule file. All conditions are simply the name of a field from the journal, an optional comparison operator before the required equal sign ('='), and the value to compare with.
For a list of special fields and their meaning, refer to systemd.journal-fields(7)
The supported operators are :
- Exact match: =
-
The field must be of the specified value.
- Pattern match: ?
-
You can use '*' and '?' wildcards with similar semantics as the standard glob(3) functions: '*' matches an arbitrary, possibly empty, string, '?' matches an arbitrary character.
Note that in contrast to glob(), the '/' character can be matched by the wildcards, there are no '[...]' character ranges and '*' and '?' can not be escaped to include them literally in a pattern.
- Lesser match: <
-
The value must be an integer, the value of the field will also be parsed as an integer value, and must be less than or equal to the specified value to match.
- Greater match: >
-
The value must be an integer, the value of the field will also be parsed as an integer value, and must be greater than or equal to the specified value to match.
You can specify as many conditions as you want in each group; All will need to be a match for the entire group to be a match. You can specify conditions on the same field multiple times.
It is also possible to prefix the comparison operator with a '!' in order to inverse the match, i.e. the field shall not match the condition for it to be a match.
Example: [Filter] PRIORITY<=3 MESSAGE!=Some message to ignore MESSAGE!=Another message to ignore
They're probably crawling somewhere in there... if you happen to catch one, (or more) report it and I'll do my best to squash it.
You can find the latest source code of journal-triggerd as well as report bugs and/or suggest features on its GitHub repository, available at https://github.com/jjk-jacky/journal-triggerd
- Olivier Brunel <jjk AT jjacky DOT com>