我试图在安装 USB 后在 USB 中创建一个文件夹。我正在使用下面的 udev 规则,我**ID_FS_UUID_ENC** (64AC6F22AC6EEE4C)
作为参数发送,并start.sh
在此路径中创建一个子文件夹 -/media/pi/64AC6F22AC6EEE4C
KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"
# Import FS infos
IMPORT{program}="/sbin/blkid -o udev -p %N"
# Get a label if present, otherwise specify one
#ENV{ID_FS_UUID_ENC}!="", ENV{dir_name}="%E{ID_FS_UUID_ENC}"
#ENV{ID_FS_UUID_ENC}=="", ENV{dir_name}=""
# Global mount options
ACTION=="add", DRIVERS=="usb-storage", RUN+="/usr/bin/setsid /home/pi/raspberry-stilas/start.sh %E{ID_FS_UUID_ENC}"
ACTION=="add", DRIVERS=="usb-storage", RUN+="/bin/sh -c 'echo == >> /home/pi/raspberry-stilas/usb-storage-env.log; env >> /home/pi/raspberry-stilas/usb-storage-env.log'"
# Exit
LABEL="media_by_label_auto_mount_end"
现在的问题是,当我插入 USB 时,start.sh
会创建一个新文件夹并重命名传递的文件夹。因此64AC6F22AC6EEE4C
创建了一个新文件夹,并将 USB 标签重命名为64AC6F22AC6EEE4C1
.谁能告诉我我做错了什么?是不是USB没有安装,我正在尝试创建文件夹?
更新
我检查了系统日志和自定义日志,看起来设备正在脚本执行后安装。有什么办法可以让我只在安装后运行。
Custom Log - Stilas Python program run at 2019-05-18 11:33:01 PM
Syslog - May 18 23:33:02 raspberrypi udisksd[725]: Mounted /dev/sda1 at /media/pi/64AC6F22AC6EEE4C1 on behalf of uid 1000
添加后登录sleep 5
May 19 01:33:40 raspberrypi kernel: [ 944.893519] usb 1-1.2: USB disconnect, device number 8
May 19 01:33:42 raspberrypi kernel: [ 947.749507] usb 1-1.2: new high-speed USB device number 9 using dwc_otg
May 19 01:33:43 raspberrypi kernel: [ 947.880955] usb 1-1.2: New USB device found, idVendor=0781, idProduct=558a
May 19 01:33:43 raspberrypi kernel: [ 947.880971] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
May 19 01:33:43 raspberrypi kernel: [ 947.880980] usb 1-1.2: Product: Ultra
May 19 01:33:43 raspberrypi kernel: [ 947.880988] usb 1-1.2: Manufacturer: SanDisk
May 19 01:33:43 raspberrypi kernel: [ 947.880997] usb 1-1.2: SerialNumber: 4C530001270213117013
May 19 01:33:43 raspberrypi kernel: [ 947.881806] usb-storage 1-1.2:1.0: USB Mass Storage device detected
May 19 01:33:43 raspberrypi kernel: [ 947.882227] scsi host1: usb-storage 1-1.2:1.0
May 19 01:33:43 raspberrypi mtp-probe: checking bus 1, device 9: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2"
May 19 01:33:43 raspberrypi mtp-probe: bus: 1, device: 9 was not an MTP device
May 19 01:33:44 raspberrypi kernel: [ 948.890623] scsi 1:0:0:0: Direct-Access SanDisk Ultra 1.00 PQ: 0 ANSI: 6
May 19 01:33:44 raspberrypi kernel: [ 948.891609] sd 1:0:0:0: Attached scsi generic sg1 type 0
May 19 01:33:44 raspberrypi kernel: [ 948.891730] sd 1:0:0:0: [sdb] 120127488 512-byte logical blocks: (61.5 GB/57.3 GiB)
May 19 01:33:44 raspberrypi kernel: [ 948.892813] sd 1:0:0:0: [sdb] Write Protect is off
May 19 01:33:44 raspberrypi kernel: [ 948.892828] sd 1:0:0:0: [sdb] Mode Sense: 43 00 00 00
May 19 01:33:44 raspberrypi kernel: [ 948.893398] sd 1:0:0:0: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
May 19 01:33:44 raspberrypi kernel: [ 948.902832] sdb: sdb1
May 19 01:33:44 raspberrypi kernel: [ 948.905690] sd 1:0:0:0: [sdb] Attached SCSI removable disk
开始.sh
#!/bin/sh
sleep 5
echo "Device Mounted on - `date +"%Y-%m-%d %r."` Path - /media/pi/{$1}" env >> /home/pi/raspberry-stilas/mount.log
if [ "$1" != "" ]; then
echo "Stilas Python program run at `date +"%Y-%m-%d %r."` Path - /media/pi/{$1}" env >> /home/pi/raspberry-stilas/mount.log
python3 /home/pi/raspberry-stilas/stilas/stilas.py "/media/pi/$1"
fi
答案1
假设第 2 行/home/pi/start.sh
有一个 shebang(位于#!/bin/sh
第一行),sleep 5
并且设置了执行位 ( chmod +x /home/pi/start.sh
)。
使用setsid
,它会fork,这意味着脚本执行在后台执行。上述睡眠是为了让您的系统有时间挂载 USB 设备。 Udev 在安装设备之前不会等待脚本完成,setsid
将立即返回并且设备应该快速安装。
ACTION=="add", DRIVERS=="usb-storage", RUN+="/usr/bin/setsid /home/pi/start.sh %E{ID_FS_UUID_ENC}"
编辑:udev 等待所有子进程,因此该进程必须创建自己的组。
确保/home/pi/start.sh
具有以下标头:
#!/bin/sh
pgid_from_pid() {
local pid=$1
ps -o pgid= "$pid" 2>/dev/null | egrep -o "[0-9]+"
}
pid="$$"
if [ "$pid" != "$(pgid_from_pid $pid)" ]; then
exec setsid "$(readlink -f "$0")" "$@"
fi
sleep 5
创建 init.sh 脚本:
#!/bin/sh
/home/pi/start.sh "$@"
我们结合以下 udev 规则:
ACTION=="add", DRIVERS=="usb-storage", RUN+="/bin/sh /home/pi/init.sh %E{ID_FS_UUID_ENC}"
答案2
我建议 fork 的答案将不再适用于较新的 udev 系统:
RUN
...
Starting daemons or other long running processes is not appropriate for
udev; the forked processes, detached or not, will be unconditionally killed
after the event handling has finished.
您可以使用通用的 systemd 服务来mount
安装您的设备,您可以使用:sudo systemctl list-units -t mount
找到您的设备的 systemd 安装,写下其名称。
然后,您创建一个名为/etc/systemd/system/your.service
“
[Unit]
Description=My mount script trigger
Requires=<whatever the command above returned>.mount
After=<whatever the command above returned>.mount
[Service]
ExecStart=/home/pi/start.sh
[Install]
WantedBy=<whatever the command above returned>.mount
优点: 易于设置
缺点:仅适用于具有特定名称的 USB 设备。您必须自己在脚本中计算出 UUID。
答案3
需要实现一个对插入的 USB 闪存驱动器(插入自主 BBB 设备)做出反应的东西 - 获取设备名称,在那里挂载文件系统,rsync 东西到它,卸载。
为了避免任何并发问题(即并行地与设备发生冲突的多个问题)、正确的错误日志记录和其他启动问题,最明显的事情是将脚本包装在 systemd oneshot 服务中。
对我来说,唯一不立即明显的问题是如何将设备正确地传递给此类服务。
通过对谷歌结果进行一些挖掘(甚至在其中找到一篇文章),最终找到了“配对 udev 的 SYSTEMD_WANTS 和 systemd 的模板单元”解析线程,其中指定了似乎是当前最佳方法。
根据我的情况进行调整并与设备实例化服务的通用模式配对,得到以下配置。
udev规则:
ACTION=="add", PROGRAM="/usr/bin/systemd-escape -p [email protected] %E{ID_FS_UUID_ENC}", ENV{SYSTEMD_WANTS}+="%c"
[Unit]
BindTo=%i.device
After=%i.device
[Service]
Type=oneshot
TimeoutStartSec=300
ExecStart=/home/pi/raspberry-stilas/start.sh /%I
改编自这里。