我有一个 udev 规则,当插入 USB 设备时会下载文件:
ACTION=="add", ATTRS{idVendor}=="cafe", MODE="0660", GROUP="root", SUBSYSTEM=="usbmisc", RUN+="/home/me/udev-net.sh"
该脚本执行一个简单的 wget:
#!/bin/sh
wget -o /tmp/wget.log -O /tmp/index.html http://www.google.com
这在 Ubuntu 16.04 上运行良好,但在 18.04 上 wget 无法解析 www.google.com - 触发脚本后 /tmp/wget.log 包含:
--2019-08-19 14:49:43-- http://www.google.com/
Resolving www.google.com (www.google.com)... failed: Name or service not known.
wget: unable to resolve host address 'www.google.com'
如果我向 /etc/hosts 添加条目“172.217.23.164 mygoogle”,则解析会成功,但 wget 会在套接字 connect() 中阻塞,并且一段时间后 wget 进程会被终止。
是否有某种方法可以在 Ubuntu 18.04 中实现这一点,以便其行为与 16.04 上的行为相同?
答案1
是的,这种行为与 udev 相同,触发时间很短,足以配置新设备,并且它在有限的环境中运行。
我建议使用在用户级别运行的更高级别的脚本,例如 Python/pyudev。
参考: man udev
请注意,由于 systemd-udevd.service 上强制执行的默认沙箱,udev 规则内不允许运行访问网络或挂载/卸载文件系统的程序。
更新:
另一种可能的方法是使用systemd
单位,如本例所示:
storage:
files:
- path: /etc/udev/rules.d/01-block.rules
filesystem: root
mode: 0644
contents:
inline: |
ACTION=="add", SUBSYSTEM=="block", TAG+="systemd", ENV{SYSTEMD_WANTS}="device-attach.service"
systemd:
units:
- name: device-attach.service
contents: |
[Unit]
Description=Notify about attached device
[Service]
Type=oneshot
ExecStart=/usr/bin/echo 'device has been attached'
来源:CoreOS - 使用 systemd 和 udev 规则
笔记:
- 我很惊讶,
systemd
以 root 身份运行的程序可以直接连接(wget
、curl
、...)并下载文件。最好观察并验证您从哪里下载了什么。如果需要,甚至可以对它们进行密钥签名。
答案2
man udev
请注意,由于 systemd-udevd.service 上强制执行的默认沙箱,udev 规则内不允许运行访问网络或挂载/卸载文件系统的程序。
尝试绕过atd
(仅 256kB):
sudo apt install --no-install-recommends at
sudo systemctl enable atd
sudo systemctl start atd
然后更换
RUN+="/home/me/udev-net.sh"
和
RUN+="/bin/sh -c 'echo /home/me/udev-net.sh | at now
“
man at
at 和 batch 使用 /bin/sh 从标准输入或指定文件读取稍后要执行的命令。
守护atd
进程将来(现在,使用at now
)在与 不同的上下文中运行您的脚本systemd-udv
并绕过网络限制。这在 2023 年的 Ubuntu 20 / Debian 11 中仍然有效。