為什麼這個 udev 規則沒有觸發?
我有一個位於 /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
行開始的足夠可執行的腳本來提供它。