18.04:udev 规则 RUN 脚本如何访问网络

18.04:udev 规则 RUN 脚本如何访问网络

我有一个 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 身份运行的程序可以直接连接(wgetcurl、...)并下载文件。最好观察并验证您从哪里下载了什么。如果需要,甚至可以对它们进行密钥签名。

答案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 中仍然有效。

相关内容