7

I am migrating an existing udev rule that bound to the change action of a block device and runs a given script.

SUBSYSTEM=="block", ENV{DEVNAME}=="/dev/sr0", ACTION=="change", RUN+="/usr/local/bin/script"

In this configuration udev passed the environment variables associated to the hardware device such as ID_CDROM_MEDIA-0 and ID_FS_LABEL. I've since updated the udev rule to use systemd to start a service on the hardware change.

SUBSYSTEM=="block", ENV{DEVNAME}=="/dev/sr0", ACTION=="change", TAG+="systemd", ENV{SYSTEMD_WANTS}=="drive-change.service"

The systemd service file:

[Unit]
Description=changes to dvd drive

[Service]
Type=oneshot
ExecStart=/usr/local/bin/script

[Install]
WantedBy=multi-user.target

At this point the service is run on change events but the environment variables passed by the RUN command in udev are not passed to the execution of the service.

Is it possible to pass the environment from udev to the execution environment of systemd or do I need to explicitly pass parameters?

2 Answers 2

7

While I did not find a way to pass the environment from udev to to systemd it is possible to query the udev database for the environment properties. The udevadm info command has both the --query and --export parameters that allow you to query for only a environment properties and print them in a format that can be evaluated.

I used a combination of systemd instance variables and the udevadm commands to initialize the environment variables.

SUBSYSTEM=="block", ENV{DEVNAME}=="/dev/sr0", ACTION=="change", TAG+="systemd", ENV{SYSTEMD_WANTS}=="drive-change@%E{DEVNAME}.service"

This udev rule will execute the following service file and pass the DEVNAME variable as an instance variable with the service.

[Unit]
Description=changes to dvd drive

[Service]
Type=oneshot
ExecStart=/usr/local/bin/script %I

[Install]
WantedBy=multi-user.target

I used this instance variable to evaluate the environment properties of the udev element and resolved my issue.

#!/bin/sh

# Systemd passes the DEVNAME as the first parameter to the script
eval $(udevadm info --query=env --export $1)

 # The rest of the script that depends on the udev environment
 ...
1
  • After that eval $(......) line, here is how to access just one property from the udev environment database and print it to a file from the script run by the systemd service: echo $ID_FS_LABEL >> "/tmp/file.txt" May 10, 2022 at 19:00
0

To extend the great answer by @Ben Campbell..

Here's how to access a property from the udev environment database after a device triggered the udev rule. Say for instance a USB drive was just attached and you want to get its label.

In the script run by the systemd service, after the eval $(udevadm info --query=env --export $1) line, add something like:
echo $ID_FS_LABEL >> "/tmp/file.txt"

Similarly you could get the values for ID_PART_ENTRY_UUID, ID_VENDOR etc..

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .