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

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

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

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

在此配置中,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"

systemd 服务文件:

[Unit]
Description=changes to dvd drive

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

[Install]
WantedBy=multi-user.target

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

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

答案1

虽然我没有找到将环境从 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

我使用这个实例变量来评估 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
 ...

答案2

为了延续伟大的回答作者:@Ben Campbell..

以下是设备触发 udev 规则后如何从 udev 环境数据库访问属性。例如,刚刚连接了一个 USB 驱动器,您想获取其标签。

在 systemd 服务运行的脚本中,在该eval $(udevadm info --query=env --export $1)行后面添加类似以下内容:
echo $ID_FS_LABEL >> "/tmp/file.txt"

ID_PART_ENTRY_UUID类似地,您可以获取等的值ID_VENDOR

相关内容