Events
Four types of event are supported, at least for now. On Linux, DBus is the mechanism that handles the majority of the communication between the system and the applications, via a well described subscription mechanism. On Windows, on the other side, WMI is a WBEM based interface that allows for subscription to system events in a streamlined way, thus it has been implemented specifically for the Windows platform. WMI, of course, is not available on Linux, while DBus is optionally available on Windows. Other environments may expose interfaces that are not directly supported by whenever.
One very specific case, which is also particularly useful, is the notification of changes in the filesystem for watched entities (files or directories), which is also implemented in whenever as one of the possible events that can fire conditions.
The last kind of events supported by whenever relies on its stdin based
command interface. These events are directly raised by
issuing a trigger
command followed by the event name: a wrapper, even possibly a platform
specific one, can therefore notify whenever that a specific event took place, or that the
user explicitly required to trigger it from the available user interface. This type of event is
the simplest one to define, as it has no criteria to be specified.
Note that if an event arises more that once within the tick interval, it is automatically debounced and a single occurrence is counted.
All event definition sections must start with the TOML [[event]]
header.
An optional entry, namely tags
, is accepted in item configuration: this entry is ignored by
whenever itself, however it is checked for correctness at startup and the configuration is
refused if not set to an array (of strings) or a table.
The associated conditions must exist, otherwise an error is raised and whenever aborts.
Filesystem changes
This type of event arises when there is a modification in the filesystems, regarding one of more monitored files and/or directories. whenever allows to monitor a list of items for each defined event of this type, and to associate an event based condition to the event itself. A sample configuration follows:
[[event]]
name = "FilesystemChangeEventName"
type = "fschange"
condition = "AssignedConditionName"
# optional parameters (if omitted, defaults are used)
watch = [
"/path/to/resource",
"/another/path/to/file.txt",
]
recursive = false
poll_seconds = 2
The configuration entries are:
Entry |
Default |
Description |
---|---|---|
|
N/A |
the unique name of the event (mandatory) |
|
N/A |
must be set to |
|
N/A |
the name of the associated event based condition (mandatory) |
|
(empty) |
a list of items to be monitored: possibly expressed with their full path |
|
false |
if true, listed directories will be monitored recursively |
|
2 |
generally not used, can be needed on systems where the notification service is unavailable |
DBus signals (optional)
DBus provides signals that can be subscribed by applications, to receive information about various aspects of the system status in an asynchronous way. whenever offers the possibility to subscribe to these signals, so that when the return parameters match the provided constraints, then the event occurs and the associated condition is fired.
Note
This type of item is only available when the dbus
feature is enabled.
Subscription is performed by providing a watch expression in the same form that is used by the dbus-monitor <https://dbus.freedesktop.org/doc/dbus-monitor.1.html> utility. The criteria that the signal parameters must meet in order for the event to arise, are specified using the same format that is used for return message parameter checks in DBus method based conditions.
A sample configuration section follows:
[[event]]
name = "DbusMessageEventName"
type = "dbus" # mandatory value
bus = ":session" # either ":session" or ":system"
condition = "AssignedConditionName"
rule = """\
type='signal',\
sender='org.freedesktop.DBus',\
interface='org.freedesktop.DBus',\
member='NameOwnerChanged',\
arg0='org.freedesktop.zbus.MatchRuleStreamTest42'\
"""
# optional parameters (if omitted, defaults are used)
parameter_check_all = false
parameter_check = [
{ index = 0, operator = "eq", value = false },
{ index = [1, 5], operator = "neq", operator = "forbidden" },
{ index = [2, "mapidx", 5], operator = "match", value = "^[A-Z][a-zA-Z0-9_]*$" },
]
and the details of the configuration entries are described in the table below:
Entry |
Default |
Description |
---|---|---|
|
N/A |
the unique name of the event (mandatory) |
|
N/A |
must be set to |
|
N/A |
the name of the associated event based condition (mandatory) |
|
N/A |
the bus on which to listen for events: must be either |
|
false |
if true, all the provided criteria will have to be satisfied for the event to be fired, otherwise one is enough |
|
(empty) |
a list of maps consisting of three fields each, each of which is a check to be performed on return parameters |
The considerations about indexes in return parameters are the same that have been seen for DBus message based conditions. It is worth to remind that any errors that may arise during checks will cause the check itself to yield false.
If no parameter checks are provided, the event arises simply when the signal is caught.
WMI (optional, Windows only)
On Windows, whenever can subscribe to WMI events using event specific WML queries. This kind of query allows for an extremely precise determination of every aspect of the event that has to be caught, including the possibility to specify any criteria regarding the payload of an event in order to consider it verified. Thus whenever leaves to the query part of a WMI event definition the task of filtering the specific event for which it enables a listener.
Note
This type of item is only available when the wmi
feature is enabled.
As a result, the configuration of a WMI based event is much simpler than the one of DBus signal
based ones, by only having to specify a mandatory query
entry, whose syntax and semantic is
similar to the one of the queries used in WMI Query based conditions,
but has to be expressly built for events.
An example of WMI based event configuration follows:
[[event]]
name = "WMIEventName"
type = "wmi" # mandatory value
condition = "AssignedConditionName"
query = """
SELECT * FROM __InstanceModificationEvent
WHERE TargetInstance ISA "Win32_LogicalDisk"
AND TargetInstance.FreeSpace < 5000000000
"""
which will occur every time the remaining space of a logical disk goes roughly under 5GB. The details of the configuration entries are described in the table below:
Entry |
Default |
Description |
---|---|---|
|
N/A |
the unique name of the event (mandatory) |
|
N/A |
must be set to |
|
N/A |
the name of the associated event based condition (mandatory) |
|
N/A |
the WQL query used specify what criteria must be satisfied for the event to occur |
As with DBus match rules, whenever does not do any parsing or check on the provided query: an incorrect query will only cause the event registration to fail and log an error message, at least in the debug log level.
Every event returned by the system matches the criteria specified in the query, and will cause the assigned condition to fire.
Warning
Some antimalware tools might detect event subscriptions as suspicious.
Command line
As said above, this type of event has no other parameters than the name, the type identifier, and
the associated condition. All parameters are mandatory. The event is raised when a wrapper (or
the user) passes a trigger
command to whenever through
the stdin stream of an active session.
A sample configuration section follows:
name = "ManuallyTriggeredEvent"
type = "cli" # mandatory value
condition = "AssignedConditionName"
and the details of the configuration entries are described in the table below:
Entry |
Default |
Description |
---|---|---|
|
N/A |
the unique name of the event (mandatory) |
|
N/A |
must be set to |
|
N/A |
the name of the associated event based condition (mandatory) |
No listening service is installed, so the impact on resource consumption and performance is almost unnoticeable.