我希望我的 RPi 2(使用MiniBian
(基于 Debian 的操作系统的最小版本Raspbian
)作为其操作系统)在检测到 USB 闪存插入时执行脚本。这就是我所做的:
我/etc/udev/rules.d/10-usbstick.rules
用这些内容创建了:
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd*" SYMLINK+="usbflash", RUN+="/path/to/myscript.sh"
然后/path/to/myscript.sh
用这些内容创建:
#!/bin/bash
mount /dev/usbflash /mnt/
service omxd stop
rm -r /path/to/myfolder/*
cp -f /mnt/*.mp4 /path/to/myfolder/
cp -f /mnt/*.avi /path/to/myfolder/
sleep 1
umount /dev/usbflash
halt
现在,当我插入 USB 闪存时,它会识别它、安装它、停止omxd
守护程序并删除所有旧文件。
但问题是它halt
在复制所有文件之前就关闭了( )。后来查看发现只复制了1个文件,并且没有正确复制,就像halt
复制过程中执行了命令一样。
所以,我决定用wait
command来保证halt
命令只在最后执行。我将/path/to/myscript.sh
文件编辑如下:
#!/bin/bash
mount /dev/usbflash /mnt/
PID1 = $!
wait PID1
service omxd stop
rm -r /path/to/myfolder/*
PID2 = $!
wait PID2
cp -f /mnt/*.mp4 /path/to/myfolder/
PID3 = $!
wait PID3
cp -f /mnt/*.avi /path/to/myfolder/
PID4 = $!
wait PID4
sleep 1
umount /dev/usbflash
PID5 = $!
wait PID5
halt
但同样的情况再次发生:系统在复制过程中停止。
那么我的系统出了什么问题呢?
我该怎么做才能告诉系统halt
仅在那之后所有新文件都已成功复制!?
更新1
sync
之前添加过umount
,halt
没有效果。同样的场景再次发生。
更新2
我将该/path/to/myscript.sh
文件编辑如下:
mkdir -p /mnt/usb
if mount /dev/usbflash /mnt/usb
then
service omxd stop
rm -r /path/to/myfolder/*
cp -f /mnt/usb/*.mp4 /path/to/myfolder/
cp -f /mnt/usb/*.avi /path/to/myfolder/
sync
umount /mnt/usb
sync
shutdown -h now
fi
但这也没有帮助!同样的场景再次发生!这次更糟糕:它根本没有复制任何文件!
更新3
我将其更改/etc/udev/rules.d/10-usbstick.rules
为以下内容:
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]1" SYMLINK+="usbflash", RUN+="/path/to/myscript.sh"
现在效果很好。它复制所有文件。但有一个新问题:它无法关闭!
更新4
我发现了一些新东西:
当我myscript.sh
直接从终端运行时,它工作得很好:删除旧文件,复制新文件,然后关闭系统。完美的。
myscript.sh
那么,为什么当我从 udev 规则调用它时它不能完美执行呢?
还有其他方法可以在复制文件后关闭系统吗!?
答案1
wait
除非它在后台运行(而您的不是),否则 for 命令是没有意义的。您可能缺少的是sync
强制所有写入介质,尽管这应该作为umount
命令的一部分发生。
我有兴趣看看这个简化的脚本是否按您的要求工作:
#!/bin/bash
#
export PATH=/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin
mkdir -p /mnt/usb
if mount /dev/usbflash /mnt/usb
then
service omxd stop
rm -r /path/to/myfolder/*
cp -f /mnt/usb/*.mp4 /path/to/myfolder/
cp -f /mnt/usb/*.avi /path/to/myfolder/
sync
umount /mnt/usb
sync
shutdown -h now
fi
我必须承认我有点困惑,因为您的描述似乎表明您想要更新 USB 记忆棒上的文件。但是你的代码更新了文件/path/to/my/folder
从USB 记忆棒而不是写入/mnt/usb/...
答案2
我不知道为什么更改内核名称会产生影响(也许在允许更多时间完成工作sd*1
后运行?),但 udev 不喜欢事件中长时间运行的操作:sd*
启动守护进程或其他长时间运行的进程不适合 udev;分叉的进程,无论是否分离,都将在事件处理完成后被无条件终止。
原创nohup
建议
我最初建议nohup
在完全阅读我自己的链接之前:)——这表明这实际上可能行不通
udev规则:
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]1" SYMLINK+="usbflash", RUN+="/path/to/mywrapper.sh"
mywrapper.sh
(注意:如果您不重定向输出,nohup 可能会在您的目录中散布文件nohup.out
):
#!/bin/sh
nohup /path/to/myscript.sh >/log/myscript.log 2>&1 &
然后myscript.sh
就可以了。
较新的systemd
建议
下面的第三个链接建议在设备插入时关闭 systemd 服务。由于确保设备信息传递到服务,该博客条目所做的工作比我认为您需要的要多,我思考您可以简单地使用 systemd 作为守护进程的方法:
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd[a-z]1" SYMLINK+="usbflash", RUN+="/usr/bin/systemctl start my-usb-backup.service"
通过简单的一次性服务my-usb-backup.service
:
[Unit]
Description=run myscript
[Service]
Type=oneshot
ExecStart=/path/to/myscript.sh
也可以看看: