Udev

為什麼這個 udev 規則沒有觸發?

  • October 27, 2020

我有一個位於 /etc/udev/rules.d/usbmount.rules 的 udev 規則文件,其內容如下:

ACTION=="add", KERNEL=="sd*[!0-9]", RUN+="/tmp/debug.sh"

創建規則後,我做了:

chmod +x /tmp/debug.sh
udevadm control --reload-rules

此規則的目的是在插入 USB 塊設備(拇指驅動器、硬碟等)時執行腳本。我正在撕扯我的頭髮,為什麼它沒有觸發。udevadmmonitor當 USB 硬碟驅動器塢站通過 USB 3.0 埠連接到系統時,A為我提供以下資訊。

KERNEL[367.932459] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2 (usb)
KERNEL[367.934622] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0 (usb)
KERNEL[367.935236] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0 (scsi)
KERNEL[367.935301] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/scsi_host/host0 (scsi_host)
KERNEL[367.935414] bind     /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0 (usb)
KERNEL[367.935527] bind     /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2 (usb)
UDEV  [367.937750] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2 (usb)
UDEV  [367.939195] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0 (usb)
UDEV  [367.939940] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0 (scsi)
UDEV  [367.945817] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/scsi_host/host0 (scsi_host)
UDEV  [367.947464] bind     /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0 (usb)
UDEV  [367.950394] bind     /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2 (usb)
KERNEL[368.957786] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0 (scsi)
KERNEL[368.957902] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0 (scsi)
KERNEL[368.957993] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0 (scsi_device)
KERNEL[368.958128] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/scsi_generic/sg0 (scsi_generic)
KERNEL[368.958250] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0 (bsg)
KERNEL[368.960906] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0 (scsi_disk)
UDEV  [368.961035] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0 (scsi)
UDEV  [368.965594] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0 (scsi)
UDEV  [368.971313] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/scsi_device/0:0:0:0 (scsi_device)
UDEV  [368.973129] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/bsg/0:0:0:0 (bsg)
UDEV  [368.975431] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/scsi_generic/sg0 (scsi_generic)
UDEV  [368.976153] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0 (scsi_disk)
KERNEL[369.010196] add      /devices/virtual/bdi/8:0 (bdi)
UDEV  [369.011230] add      /devices/virtual/bdi/8:0 (bdi)
KERNEL[369.270352] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/block/sda (block)
KERNEL[369.270455] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1 (block)
KERNEL[369.276694] bind     /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0 (scsi)
UDEV  [369.874116] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/block/sda (block)
UDEV  [370.252695] add      /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1 (block)
UDEV  [370.275646] bind     /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-2/2-2:1.0/host0/target0:0:0/0:0:0:0 (scsi)

機器資訊:

OS: Raspbian GNU/Linux 10 (buster)
Kernel: 5.4.72-v7l+

debug.sh 的唯一內容是echo "TESTING" >> /tmp/debuglog.txt. 未創建 Debuglog.txt。

看起來這個規則沒有被觸發。為什麼?我能做些什麼來解決這個問題?

debug.sh的唯一內容是echo "TESTING" >> /tmp/debuglog.txt. 未創建 Debuglog.txt。

這就是問題所在。核心不會執行這樣的 shell 腳本,因為它沒有以強制#!/bin/bash告訴核心將執行委託給bash解釋器開始。

這種情況很少發生,因為如果命令沒有立即執行,大多數工具將使用 shell 來執行命令。這是一個範例,當strace-ing perl 執行此命令時(在沒有成功搜尋會使腳本執行立即失敗的工具時):

$ strace -e execve perl -e 'exec ("/tmp/debug.sh");'
execve("/usr/bin/perl", ["perl", "-e", "exec (\"/tmp/debug.sh\");"], [/* 15 vars */]) = 0
execve("/tmp/debug.sh", ["/tmp/debug.sh"], [/* 15 vars */]) = -1 ENOEXEC (Exec format error)
execve("/bin/sh", ["/bin/sh", "/tmp/debug.sh"], [/* 15 vars */]) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=14452, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

它首先嘗試在第一行沒有解釋器的情況下執行腳本並得到:

ENOEXEC (Exec format error)

然後通過插入一個shell再次嘗試,這樣它就可以工作了。這裡/bin/sh, 甚至不在bash這個環境中,所以如果腳本包含bash構造,它會在以後巧妙地行為不端。

本來/tmp/debug.sh就是這樣(和u+rx燙髮):

#!/bin/bash
echo "TESTING" >> /tmp/debuglog.txt

然後:

$ strace -e execve perl -e 'exec ("/tmp/debug.sh");'
execve("/usr/bin/perl", ["perl", "-e", "exec (\"/tmp/debug.sh\");"], [/* 15 vars */]) = 0
execve("/tmp/debug.sh", ["/tmp/debug.sh"], [/* 15 vars */]) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=14474, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

然後/tmp/debug.sh將由核心直接執行(實際上會將執行推遲到/bin/bash)。

udev不會嘗試這樣做,因此它需要一個有效的核心二進製文件作為命令中的第一個文件。要麼直接提供它,要麼通過從核心的角度提供一個從該#!/path/to/interpreter行開始的足夠可執行的腳本來提供它。

引用自:https://unix.stackexchange.com/questions/616584