Getting udev to describe your system as assertions
Emery Hemingway came up with an excellent
hack for getting udev
to
automatically populate a dataspace with assertions describing the devices attached to a Linux
system. As devices are plugged in, reconfigured, and unplugged, the system automatically
creates, updates and removes files in /run/etc/syndicate/hardware
describing each device.
The trick is to install a udev
RUN
rule to execute a script which uses udevadm info
--json=short
to write out a Preserves file. Preserves is, syntactically, a superset of JSON,
so it’s possible to directly use JSON output from programs like this as Preserves.
A syndicate-server can then be configured to load
all files in /run/etc/syndicate/hardware
into a dataspace by placing something like
1
2
let ?devices = dataspace
<require-service <config-watcher "/run/etc/syndicate/hardware" { config: $devices }>>
in the server’s configuration.
udev configuration and script
The run rule, placed in a file named something like
/usr/local/lib/udev/rules.d/50-syndicate.rules
, should be something like this:
1
ACTION=="add|change|move|remove", RUN+="/usr/local/bin/udev-syndicate-rule.sh"
And the script that does the work of maintaining the Preserves files in response to trigger
events from udev
, placed in /usr/local/bin/udev-syndicate-rule.sh
, should look something
like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/sh
# Script based on https://git.syndicate-lang.org/ehmry/syndev#assertions-from-udev
if [ -z "$DEVNAME" -o -z "$MAJOR" -o -z "$MINOR" ]
then
exit
fi
HARDWARE_DIR=/run/etc/syndicate/hardware
PR_FILE=$HARDWARE_DIR/$MAJOR-$MINOR.pr
mkdir -p $HARDWARE_DIR
case "$ACTION" in
remove)
rm -f $PR_FILE
;;
*)
echo '<device ' > $PR_FILE
udevadm info --json=short $DEVNAME >> $PR_FILE
echo '>' >> $PR_FILE
;;
esac
After adding the rule and the script to your system, you will need to either reboot or run
1
udevadm control --reload-rules && udevadm trigger
to get things started.
Example output
After installing the script on my system, I see about 250 files appear in
/run/etc/syndicate/hardware
.
For example, if I pipe /run/etc/syndicate/hardware/13-78.pr
through
preserves-tool for pretty-printing, I see:
<device {
"CURRENT_TAGS": ":power-switch:"
"DEVNAME": "/dev/input/event14"
"DEVPATH": "/devices/pci0000:00/0000:00:01.1/0000:01:00.0/0000:02:00.0/0000:03:00.1/sound/card1/input14/event14"
"ID_INPUT": "1"
"ID_INPUT_SWITCH": "1"
"ID_PATH": "pci-0000:03:00.1"
"ID_PATH_TAG": "pci-0000_03_00_1"
"ID_PROCESSING": "1"
"LIBINPUT_DEVICE_GROUP": "0/0/0:ALSA"
"MAJOR": "13"
"MINOR": "78"
"SUBSYSTEM": "input"
"SYSNAME": "event14"
"SYSNUM": "14"
"TAGS": ":power-switch:"
"USEC_INITIALIZED": "8598957"
}>