Red*_*dro 40 linux bash ubuntu udev
我想在我的 Linux 机器上插入设备时执行脚本。例如,xinput
在鼠标或某个驱动器上的备份脚本上运行。
我看过很多关于这方面的文章,最近一次是这里和这里。但我就是无法让它工作。
下面是一些试图获得至少某种响应的简单示例。
/etc/udev/rules.d/test.rules
#KERNEL=="sd*", ATTRS{vendor}=="*", ATTRS{model}=="*", ATTRS{serial}=="*", RUN+="/usr/local/bin/test.sh"
#KERNEL=="sd*", ACTION=="add", "SUBSYSTEM=="usb", ATTRS{model}=="My Book 1140 ", ATTRS{serial}=="0841752394756103457194857249", RUN+="/usr/local/bin/test.sh"
#ACTION=="add", "SUBSYSTEM=="usb", RUN+="/usr/local/bin/test.sh"
#KERNEL=="sd*", ACTION=={add}, RUN+="/usr/local/bin/test.sh"
KERNEL=="sd*", RUN+="/usr/local/bin/test.sh"
KERNEL=="*", RUN+="/usr/local/bin/test.sh"
Run Code Online (Sandbox Code Playgroud)
/usr/local/bin/test.sh
#!/usr/bin/env bash
echo touched >> /var/log/test.log
if [ "${ACTION}" = "add" ] && [ -f "${DEVICE}" ]
then
echo ${DEVICE} >> /var/log/test.log
fi
Run Code Online (Sandbox Code Playgroud)
规则文件夹由监视inotify
并应立即激活。我不断地重新插入我的键盘、鼠标、平板电脑、记忆棒和 USB 驱动器,但没有。没有触及日志文件。
现在,至少知道某些事情正在起作用的最简单方法是什么?使用有效的方法比使用无效的方法更容易。
Ola*_*che 35
如果要在特定设备上运行脚本,可以使用供应商和产品 ID
在 /etc/udev/rules.d/test.rules
:
ATTRS{idVendor}=="152d", ATTRS{idProduct}=="2329", RUN+="/tmp/test.sh"
Run Code Online (Sandbox Code Playgroud)在test.sh
:
#! /bin/sh
env >>/tmp/test.log
file "/sys${DEVPATH}" >>/tmp/test.log
if [ "${ACTION}" = add -a -d "/sys${DEVPATH}" ]; then
echo "add ${DEVPATH}" >>/tmp/test.log
fi
Run Code Online (Sandbox Code Playgroud)使用env
,您可以查看从 udev 设置的环境,使用file
,您将发现文件类型。
可以通过以下方式发现您设备的具体属性 lsusb
lsusb
Run Code Online (Sandbox Code Playgroud)
给
...
Bus 001 Device 016: ID 152d:2329 JMicron Technology Corp. / JMicron USA Technology Corp. JM20329 SATA Bridge
...
小智 10
这不是直接关于你的问题,而是关于你在做什么。如果您从 udev 启动备份脚本,您将面临两个主要问题:
我的建议是在您的用户主目录中创建一个脚本,该脚本侦听命名管道并将异步启动,例如:
#!/bin/bash
PIPE="/tmp/IomegaUsbPipe"
REMOTE_PATH="/path/to/mount/point"
LOCAL_PATH="/local/path/"
doSynchronization()
{
#your backup here
}
trap "rm -f $PIPE" EXIT
#If the pipe doesn't exist, create it
if [[ ! -p $PIPE ]]; then
mkfifo $PIPE
fi
#If the disk is already plugged on startup, do a syn
if [[ -e "$REMOTE_PATH" ]]
then
doSynchronization
fi
#Make the permanent loop to watch the usb connection
while true
do
if read line <$PIPE; then
#Test the message read from the fifo
if [[ "$line" == "connected" ]]
then
#The usb has been plugged, wait for disk to be mounted by KDE
while [[ ! -e "$REMOTE_PATH" ]]
do
sleep 1
done
doSynchronization
else
echo "Unhandled message from fifo : [$line]"
fi
fi
done
echo "Reader exiting"
Run Code Online (Sandbox Code Playgroud)
注意:我使用 kde 的自动挂载,所以我检查文件夹是否出现。您可以在 udev 规则的 fifo 中传递 /dev/sd* 参数,并在脚本中自行挂载。要写入 fifo,请不要忘记 udev 不是 shell 并且重定向不起作用。你的 RUN 应该是这样的:
RUN+="/bin/sh -c '/bin/echo 已连接 >> /tmp/IomegaUsbPipe'"
我已经在https://askubuntu.com/a/516336上发布了一个解决方案,并且我还在此处复制粘贴了该解决方案。
我使用pyudev编写了一个 Python 脚本,并在后台运行。该脚本监听 udev 事件(因此,它非常高效)并运行我想要的任何代码。就我而言,它运行xinput
命令来设置我的设备(链接到最新版本)。
这是同一脚本的简短版本:
#!/usr/bin/env python3
import pyudev
import subprocess
def main():
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='usb')
monitor.start()
for device in iter(monitor.poll, None):
# I can add more logic here, to run different scripts for different devices.
subprocess.call(['/home/foo/foobar.sh', '--foo', '--bar'])
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)