---
myst:
html_meta:
description: |
The event handler watches the system log and runs a user-supplied
script when a preconfigured event occurs. Configure a pattern,
optionally a syslog identifier, and a script path per event.
keywords: event-handler, syslog, log monitoring, script, automation
---
(event-handler)=
# Event handler
The event handler watches the system log and runs a user-supplied
script when a preconfigured event occurs. For each event, you configure
a pattern to look for in the log, optionally restrict matching to a
specific syslog identifier, and a script to run when a match occurs.
Upon a match, the event handler launches the script. The script can
read the matched log entry from an environment variable named
`message` (for example, to extract an IP address or include the log
line in a notification). You can also pass your own environment
variables or a fixed argument string to the script.
## Configuration
Each event must be configured with a name, a pattern, and a script
path. All other settings are optional.
### Mandatory settings
```{cfgcmd} set service event-handler event \ filter pattern \
**Configure a regular expression to match against log entries for the
specified event.**
The regular expression must match the entire log entry, not just a
part of it. For example, to match any log entry that contains `eth0`,
wrap it as `.*eth0.*`. Matching is case-sensitive.
```
Example:
```none
set service event-handler event LINK-DOWN filter pattern '.*eth0.*,RUNNING,.*->.*'
```
```{cfgcmd} set service event-handler event \ script path \
**Configure the path to the script run for the specified event.**
```
```{note}
Event-handler scripts must be executable (see
{ref}`command-scripting`). Storing them under `/config/scripts/`
ensures they are preserved across image upgrades.
```
```{warning}
Event-handler scripts run with root privileges. Review them carefully
before use.
```
Example:
```none
set service event-handler event LINK-DOWN script path /config/scripts/link-down.py
```
### Optional settings
```{cfgcmd} set service event-handler event \ filter syslog-identifier \
**For the specified event, match the regular expression only against
log entries produced by the specified process.**
```
Example:
```none
set service event-handler event LINK-DOWN filter syslog-identifier kernel
```
```{cfgcmd} set service event-handler event \ script environment \ value \
**Add an environment variable, with the specified name and value, to
the script's execution environment.**
Repeat the command for each variable.
```
```{note}
The variable name `message` is reserved for the matched log entry and
cannot be reused.
```
Example:
```none
set service event-handler event LINK-DOWN script environment interface_name value eth0
```
```{cfgcmd} set service event-handler event \ script arguments \
**Append an argument string to the script invocation.**
The string is appended verbatim after the script path. To pass
multiple arguments, separate them with spaces within a single string.
```
```{note}
Prefer environment variables for passing data to the script.
```
Example:
```none
set service event-handler event LINK-DOWN script arguments '--notify admin@example.com'
```
## Example
The following example configures an event handler that reacts to
link-state messages emitted by `netplugd` for `eth0` and runs a Python
script. When triggered, the script writes a line containing the
original log entry and the configured `interface_name` value to
`/tmp/link-state.log`.
### Configuration
```none
set service event-handler event LINK-DOWN filter pattern '.*eth0.*,RUNNING,.*->.*'
set service event-handler event LINK-DOWN filter syslog-identifier 'netplugd'
set service event-handler event LINK-DOWN script environment interface_name value 'eth0'
set service event-handler event LINK-DOWN script path '/config/scripts/link-down.py'
```
### Event handler script
Save the following as `/config/scripts/link-down.py`:
```none
#!/usr/bin/env python3
#
# VyOS event-handler script example
from datetime import datetime
from os import environ
from pathlib import Path
from sys import exit
LOG_FILE = Path('/tmp/link-state.log')
def process_event() -> None:
# 'message' is set by the event handler and holds the log entry
# that matched the configured pattern.
log_line = environ.get('message', '')
# User-defined environment variables are read the same way.
interface = environ.get('interface_name', '')
timestamp = datetime.now().isoformat()
with LOG_FILE.open('a') as f:
f.write(
f'{timestamp} link-state change on {interface}: {log_line}\n'
)
if __name__ == '__main__':
try:
process_event()
exit(0)
except Exception as err:
# Script stdout is discarded by the event handler, but stderr
# is captured and surfaces in the system journal.
from sys import stderr
print(f'Error running script: {err}', file=stderr)
exit(1)
```
After creating the script, make it executable:
```none
sudo chmod +x /config/scripts/link-down.py
```