【问题标题】:Bash - How to run code whenever USB device is connectedBash - 如何在连接 USB 设备时运行代码
【发布时间】:2017-09-02 01:47:31
【问题描述】:

我正在编写一个 bash 脚本来自动检测我的 USB 键盘何时插入我的笔记本电脑(运行 Ubuntu 14),因此我可以自动更改键盘布局。

到目前为止,这是我的代码(我从 Stack Overflow 上的另一篇文章中得到它,所以我不能 100% 确定它是如何工作的)

#!/bin/bash
setxkbmap es
for dev in /sys/bus/usb/devices/ *-*:*
do
    if [ -f $dev/bInterfaceClass ]
    then
        if [[ "$(cat $dev/bInterfaceClass)" == "03" && "$(cat $dev/bInterfaceProtocol)" == "01" ]]
        then
            setxkbmap gb
        fi
    fi
done

到目前为止,我已经让它在启动时运行...但我希望它在每次连接或断开 USB 设备时运行。

重要的是我将它全部运行在一个 Bash 脚本中,而不是作为 ...udev/... 中的 .rules 文件或任何东西。但是,单个 Python 脚本也可以。

【问题讨论】:

  • @M. Becerra 这不是我要找的.. “重要的是我让它在一个 Bash 脚本中运行,而不是作为 ...udev/... 中的 .rules 文件或任何东西。”

标签: python linux bash keyboard usb


【解决方案1】:

感谢ralf htp 我能够提出以下解决方案。 它有以下改进:

  • 它不依赖于特定的键盘,它将以相同的方式处理所有 USB 键盘。
  • 如果用户手动切换到不同的键盘布局(既不是默认键盘也不是 USB 键盘),它不会自动切换回默认或 USB 布局。

请随时通过GitHub Gist改进此代码

#!/bin/bash
kbd1=es #default keyboard layout
kbd2=gb #USB keyboard layout

flag=0
while true
do
    layout="$(setxkbmap -query | grep -a layout | cut -c13-14)"
    if [[ $layout == $kbd1 ]] || [[ $layout == $kbd2 ]]
    then
        for dev in /sys/bus/usb/devices*-*
        do
            if [ -f $dev/bInterfaceClass ]
            then
                if [[ "$(cat $dev/bInterfaceClass)" == "03" && "$(cat 
$dev/bInterfaceProtocol)" == "01" ]]
                then
                    if [[ "$flag" == "0" ]]
                    then
                            setxkbmap $kbd2
                    fi
                    flag=1
                    break
                fi 
                if [[ "$flag" == "1" ]]
                then
                    setxkbmap $kbd1
                fi
                flag=0
            fi
        done
    fi
    sleep 5s
done

【讨论】:

    【解决方案2】:

    这是可行的,因为在 linux 系统上文件系统结构总是相同的

    cat $dev/bInterfaceClass 查询每个 USB 设备的接口类

    cat $dev/bInterfaceProtocol 查询每个 USB 设备的接口协议

    尝试ls /sys/bus/usb/devices/,您会看到所有 USB 设备节点

    然后选择一个,即ls /sys/bus/usb/devices/usb1并使用ls /sys/bus/usb/devices/usb1/idVendor

    我将使用 idVendoridProduct 而不是 bInterfaceProtocol,您可以通过连接键盘并使用 lsusb 并从列表中选择来确定键盘的产品 ID 和供应商 ID

    更新

    以下脚本将执行此操作。插入设备的供应商和产品 ID。也许在没有setxkbmap 命令的情况下进行测试。 flag 变量用于不每 5 秒设置一次键盘映射 ...

    #!/bin/bash
    
    flag=0
    
    
    while true
    
    do
    
    for dev in /sys/bus/usb/devices/*-*
    do
        if [ -f $dev/idVendor ]
        then
            if [[ "$(cat $dev/idVendor)" == "your_vendor_id" && "$(cat $dev/idProduct)" == "your_product_id" ]]
            then
                if [[ "$flag" == "0" ]]
                  then
                    echo 'USB device attached'
                     setxkbmap gb
                fi
                flag=1
                break
            fi 
                if [[ "$flag" == "1" ]]
                   then
                     echo 'USB device detached'
                     setxkbmap es
                fi
                flag=0
        fi
    
     done
    
      sleep 5s
    
    done
    

    请注意,要使 setxkbmap 正常工作,您必须安装 x11-xkb-utils

    (https://superuser.com/questions/404457/how-to-change-keyboard-layout-while-in-console)

    【讨论】:

    • 感谢您的改进,但这并不能真正回答我的问题。我在问我如何让它检测 USB 何时插入或拔出,​​所以只要我插入键盘,它就可以改变,而不是只有一次(在启动时)
    • 我想这可以解决问题,但是每 5 秒检查一次似乎不是很正统......难道没有一种方法可以在每次连接或分离 USB 设备时运行吗?
    • 我决定使用这个,但我保留了接口类和协议,而不是供应商和产品 ID。我在这里把它写成一个要点:gist.github.com/abrahammurciano/…
    • 更新了上面的答案并删除了下面的其他版本,因为 SIGPIPE 机制无法可靠地工作。每 5 秒轮询一次非常节省 CPU...
    • 为什么几乎相同的代码重复了两次?为什么它比以前更好?这似乎运行一次代码,然后在循环中每 5 秒再次运行一次。第一次运行不在循环中有什么意义?
    猜你喜欢
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 2023-02-06
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    相关资源
    最近更新 更多