安装任何 USB 设备后启动应用程序(GUI)

安装任何 USB 设备后启动应用程序(GUI)

我正在运行 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 导出到用户会话...

我认为应该有另一种方法来实现以下情况:

  1. 检测何时/是否安装了新的(USB)设备
  2. 在用户桌面上以 USER 权限启动应用程序/脚本(在终端中)(即用户的 Xsession?)
  3. (可选:将设备名称作为变量传递)

(创建特定于挂载的 .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

使用

  1. 将脚本复制到一个空文件中,另存为run_usbactions.py
  2. 通过以下命令测试运行脚本:

    python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
    

    在我的测试中,我使用了例如:

    python3 /path/to/run_usbactions.py gedit file
    

    file一旦连接了 USB 驱动器,就使用 gedit打开。

  3. 如果一切正常,请将其添加到启动应用程序: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

进一步的说明完全相同。

相关内容