将 udev 环境变量传递给 systemd 服务执行

Ben*_*ell 5 linux udev systemd

我正在迁移绑定到块设备的更改操作并运行给定脚本的现有 udev 规则。

SUBSYSTEM=="block", ENV{DEVNAME}=="/dev/sr0", ACTION=="change", RUN+="/usr/local/bin/script"
Run Code Online (Sandbox Code Playgroud)

在此配置中,udev 传递了与硬件设备相关的环境变量,例如ID_CDROM_MEDIA-0ID_FS_LABEL。我已经更新了 udev 规则以使用 systemd 在硬件更改时启动服务。

SUBSYSTEM=="block", ENV{DEVNAME}=="/dev/sr0", ACTION=="change", TAG+="systemd", ENV{SYSTEMD_WANTS}=="drive-change.service"
Run Code Online (Sandbox Code Playgroud)

systemd 服务文件:

[Unit]
Description=changes to dvd drive

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

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

此时服务在更改事件上运行,但 udev 中 RUN 命令传递的环境变量不会传递给服务的执行。

是否可以将环境从 udev 传递到 systemd 的执行环境,还是需要显式传递参数?

Ben*_*ell 6

虽然我没有找到将环境从 udev 传递到 systemd 的方法,但可以在 udev 数据库中查询环境属性。该udevadm info 命令同时具有--query--export参数,允许您仅查询环境属性并以可以评估的格式打印它们。

我使用了 systemd 实例变量和udevadm命令的组合来初始化环境变量。

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

此 udev 规则将执行以下服务文件,并将该DEVNAME变量作为服务的实例变量传递。

[Unit]
Description=changes to dvd drive

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

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

我使用这个实例变量来评估 udev 元素的环境属性并解决了我的问题。

#!/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
 ...
Run Code Online (Sandbox Code Playgroud)