当我从笔记本电脑上拔下AC适配器时,我希望所有USB驱动器都能自动卸载。如果应用程序打开阻止设备,则应该将其杀死。一旦所有东西都被杀死并卸下,信号音就会格格不齐,表明它现在可以安全拔掉它。
用例是快速抓取并移动您的笔记本电脑而不必使用ui来解决所有驱动器断开连接但避免不干净的卸载。
任何有关如何开始的提示都会非常棒,谢谢!
ANSWER
有关完整的副本和粘贴脚本,请参阅下面的答案。
如果您的USB设备安装到/ mount / media,请执行以下操作:
kill -9 $(lsof -t $(mount | grep "/mount/media" | cut -d " " -f 1)) # Exit processes blocking umount cleanly
kill $(lsof -t $(mount | grep "/mount/media" | cut -d " " -f 1)) # Force kill remaining open processes
umount $(mount | grep "/mount/media" | cut -d " " -f 1) # Unmount USB drives
请注意这一点,因为如果您没有阻止应用程序打开lsof
将返回所有pids
,您将kill
正在运行的操作系统。请参阅下面的复制和粘贴脚本,了解处理此案例的工作实现。
然后通过将此行添加到/etc/udev/rules.d
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="0" , RUN+="/path/to/script/shown/above"
Nuetrino下面的答案显示了如何检测AC拔出事件,这个答案: How do I find out which process is preventing a umount?显示如何列出并杀死阻止设备卸载的所有进程(我使用lsof比fuser -c更成功有时候没有列出任何进程,即使umount仍然被阻止了)
详情
使用udevadm monitor
记录事件,例如
KERNEL[20154.545075] change /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP0 (power_supply)
然后将udevadm info -a -p
与事件一起使用以获取属性
udevadm info -a -p /devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP0
looking at device '/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0003:00/power_supply/ADP0':
KERNEL=="ADP0"
SUBSYSTEM=="power_supply"
DRIVER==""
ATTR{online}=="0"
ATTR{type}=="Mains"
现在,您可以使用您喜欢的属性设置udev规则,如下所示。
答案 0 :(得分:1)
您可以定义udev规则来执行此操作。
只需将您的规则放入/etc/udev/rules.d
以下是我用来控制亮度的示例,当我取下AC适配器时。
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="0" , RUN+="/usr/local/bin/bright_unplug"
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="1" , RUN+="/usr/local/bin/bright_replug
当我收到内核uvent时,我运行自定义脚本'bright_replug'和'bright_unplug'。
您可以使用udevadm monitor
monitor将打印收到的事件:UDEV - 事件当中 udev在规则处理后发出KERNEL - 内核uevent
您可以使用udevadm info
来匹配更多属性
答案 1 :(得分:-1)
分步解决方案
1。
创建此脚本,例如在/home/user/uall.sh
中,将mount_root
替换为您的发行版安装usb驱动器的文件夹,例如/media/user
#!/bin/bash
mount_root=/run/media/user
echo "Try unmounting.."
umount $(ls -d -1 $mount_root/*) # Unmount USB drives
mounted=$(ls -d -1 $mount_root/*) # Probe if there are still applications blocking
if ! [ -z "$mounted" ]
then
echo "Found blocked devices: $mounted, killing.."
kill -9 $(lsof -t $mounted) # Exit processes blocking umount cleanly
kill $(lsof -t $mounted) # Force kill remaining open processes
echo "Unmounting.."
umount $(ls -d -1 $mount_root/*) # Unmount USB drives
mounted=$(ls -d -1 $mount_root/*) # Probe if there are still applications blocking
fi
if [ -z "$mounted" ]
then
echo "Success!"
echo "All USB devices umount."
paplay /usr/share/sounds/speech-dispatcher/test.wav
else
echo "Error!"
echo "Tried it all but couldn't umount all USB devices."
echo "These devices are still mounted:"
echo "$mounted"
fi
2。
创建一个执行/home/user/uall-udev-wrapper
作为用户名的udev包装器脚本(称之为uall.sh
):
#!/bin/bash
runuser -l <user> -c '/home/user/uall.sh > /home/user/uall.log'
3。 使用内容
创建文件/etc/udev/rules.d/99-usb-unmount.rules
SUBSYSTEM=="power_supply", ACTION=="change", ATTR{online}=="0" , RUN+="/home/user/uall-udev-wrapper"
4。
重新启动或运行sudo udevadm control --reload-rules && udevadm trigger
以加载新的udev规则
可选。将alias uall=/home/user/uall.sh
添加到~/.bashrc
以便从终端轻松访问脚本,并使用桌面环境配置热键以快速卸载所有USB驱动器
<强>注意事项强>
1。
当udev运行时,脚本mount
将不会显示gvfsd-fuse
个挂载点,即使使用cat /proc/mounts
包装器,也不会cat /etc/mtab
或runuser -l <user>
。相反,我现在使用ls -d -1 $mount_root/*
仅返回由$mount_root
中指定的当前用户挂载的设备,在由不同用户挂载的多用户系统设备上将不会被此脚本卸载。
2。
当udev运行脚本时,我无法从paplay
或spd-say
获取音频。
对这些警告的任何意见都将不胜感激。