![安装任何 USB 设备后启动应用程序(GUI)](https://linux22.com/image/891107/%E5%AE%89%E8%A3%85%E4%BB%BB%E4%BD%95%20USB%20%E8%AE%BE%E5%A4%87%E5%90%8E%E5%90%AF%E5%8A%A8%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%EF%BC%88GUI%EF%BC%89.png)
我正在运行 Ubuntu-gnome 16.04 LTS 4.4.0-62-generic。
我想要执行以下操作:运行...
- (a) 申请(图形用户界面)[/路径/到/my_app.desktop]
- 或 (b)交互的终端中的脚本[例如:$ gnome-terminal -x /path/to/script.sh]
...每当任何(USB) 设备已被识别。
在用户的 X 服务器上执行似乎是强制性的,因为响应正在运行的应用程序/脚本需要改变用户输入;它不能简单地在后台运行。
在过去的两天里,我做了大量的研究,并进行了实验,udev 规则和systemd.服务。我反复遇到的问题是,无论后者的方法是什么需要 X 身份验证。虽然确实有(复杂的)方法来实现身份验证,但我不喜欢这个想法破坏固有系统安全通过将 $XAUTHORITY 变量从 root 导出到用户会话...
我认为应该有另一种方法来实现以下情况:
- 检测何时/是否安装了新的(USB)设备
- 在用户桌面上以 USER 权限启动应用程序/脚本(在终端中)(即用户的 Xsession?)
- (可选:将设备名称作为变量传递)
(创建特定于挂载的 .config 文件?;org.gnome.desktop.media-handling?;自动启动脚本观察 /home/$USERNAME/media .mounts?;编辑 /etc/fstab;......?)
如能得到任何提示我将非常感激。
答案1
(旧答案,新答案如下)
运行脚本或命令,在 USB 驱动器连接时运行
如果出于某种原因,您不想使用udev
规则或任何更复杂的东西,请使用下面的脚本。
只需运行脚本,并使用要运行的命令作为参数,即可完成该工作。
剧本:
#!/usr/bin/env python3
import subprocess
import time
import sys
cmd = " ".join(sys.argv[1:])
def get_mountedlist():
return [(item.split()[0].replace("├─", "").replace("└─", ""),
item[item.find("/"):]) for item in subprocess.check_output(
["/bin/bash", "-c", "lsblk"]).decode("utf-8").split("\n") if "/" in item]
def identify(disk):
command = "find /dev/disk -ls | grep /"+disk
return "usb" in subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")
mounted1 = get_mountedlist()
while True:
time.sleep(4)
mounted2 = get_mountedlist()
if [d for d in mounted2 if all([not d in mounted1, d != "/", identify(d[0]) == True])]:
subprocess.Popen(["/bin/bash", "-c", cmd])
mounted1 = mounted2
使用
- 将脚本复制到一个空文件中,另存为
run_usbactions.py
通过以下命令测试运行脚本:
python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
在我的测试中,我使用了例如:
python3 /path/to/run_usbactions.py gedit file
file
一旦连接了 USB 驱动器,就使用 gedit打开。如果一切正常,请将其添加到启动应用程序:Dash > 启动应用程序 > 添加。添加命令:
python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
解释
每四秒一次,在函数中
get_mountedlist()
,脚本读取的输出lsblk
。以防万一额外的分区或设备已挂载,例如命令的输出:
find /dev/disk -ls | grep sdc1
将包含字符串
usb
,并将安装的驱动器标识为 USB 驱动器。
现在来看,我完全可以用一种更“pythonic”的方式来替换它,而不是系统调用,但由于我是从旧脚本中复制的,所以我没有(暂时没有)。- 随后,如果新的驱动器是 USB,
" ".join(sys.argv[1:])
运行所设置的命令(+可能的参数)。
编辑
(2017 年 12 月 29 日)
使用 pyudev
自从我“认识”了 pyudev,我认为我应该分享它带来的重大简化和更清晰的操作。插入 USB 设备后执行任何操作的简单脚本变为:
#!/usr/bin/env python3
import pyudev
import subprocess
import sys
cmd = " ".join(sys.argv[1:])
monitor = pyudev.Monitor.from_netlink(pyudev.Context())
monitor.filter_by('block')
for device in iter(monitor.poll, None):
if all([
device['ACTION'] == "add", 'ID_FS_TYPE' in device,
device['ID_USB_DRIVER'] == "usb-storage",
]):
print("added", device.get('ID_FS_LABEL'))
subprocess.Popen(["/bin/bash", "-c", cmd])
用法
确保pyudev
已安装:
sudo apt install python3-pyudev
进一步的说明完全相同。