我正在迁移一个现有的 udev 规则,该规则绑定到块设备的更改操作并运行给定的脚本。
SUBSYSTEM=="block", ENV{DEVNAME}=="/dev/sr0", ACTION=="change", RUN+="/usr/local/bin/script"
在此配置中,udev 传递了与硬件设备关联的环境变量,例如ID_CDROM_MEDIA-0
和ID_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
。