收起左侧

利用udev规则进行一些自动化操作

0
回复
38
查看
[ 复制链接 ]

12

主题

98

回帖

195

牛值

共建版主

社区上线纪念勋章社区共建团荣誉勋章

利用udev规则进行一些自动化操作

什么是udev规则

udev 是 Linux 中的一个用户空间设备管理器 (userspace device manager),用于动态管理设备节点和设备事件。

下文,我们将以打印机使用场景进行简单的讲解演示,亦可用于其他功能。

场景环境与触发逻辑

环境:飞牛nas中新建了win10虚拟机,并设置打印机硬件直通。

逻辑:当打印机被开启/关闭时,利用规则联动脚本操作虚拟机的开启或关闭

注:我的打印机比较老旧,没有联网功能也没有linux驱动,因此cups无法正常使用

开始实操

1、查看虚拟机名称

使用 sudo virsh list --all命令,会得到如下输出

cming@EWEDL:~$ sudo virsh list --all
 Id   Name       State
---------------------------
 3    tangjq53   running
 -    u5wohjw8   shut off

其中name列即为虚拟机名称,可以根据虚拟机状态进行确定,我这里需要控制的是“u5wohjw8”

2、查看需要监测的设备信息

此处建议直接使用命令 lsusb 进行查看。

3、编写自动化脚本

主要用于udev调用,当需要开机时调用start部份,需要关机时调用stop部份。

#!/bin/bash
echo "脚本已被udev调用,参数:$1" >> /tmp/udev_printer_debug.log
# 自动获取脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="$SCRIPT_DIR/printer_vm_control.log"

# 配置虚拟机名称
VM_NAME="u5wohjw8"

# 获取当前时间
TIME_NOW=$(date "+%Y-%m-%d %H:%M:%S")

# 日志函数
lo**essage() {
    echo "$TIME_NOW [$ACTION] $1" >> "$LOG_FILE"
}

# 获取操作类型
ACTION="$1"

# 启动虚拟机
start_vm() {
    virsh start "$VM_NAME" >> "$LOG_FILE" 2>&1
    if [ $? -eq 0 ]; then
        lo**essage "✅ 已启动虚拟机: $VM_NAME"
    else
        lo**essage "❌ 启动虚拟机失败: $VM_NAME"
    fi
}

# 关闭虚拟机
stop_vm() {
    virsh shutdown "$VM_NAME" >> "$LOG_FILE" 2>&1
    local try=0
    local max_try=5
    local sleep_time=3

    while [ $try -lt $max_try ]; do
        sleep $sleep_time
        VM_STATE=$(virsh domstate "$VM_NAME" 2>/dev/null)
        if [[ "$VM_STATE" == "shut off" ]]; then
            lo**essage "🛑 已关闭虚拟机: $VM_NAME"
            return 0
        fi
        try=$((try+1))
        lo**essage "⚠️ 第$try次检测,虚拟机仍未关闭: $VM_NAME,状态: $VM_STATE"
    done

    # 如果多次尝试后仍未关闭,可以选择强制关闭
    virsh destroy "$VM_NAME" >> "$LOG_FILE" 2>&1
    VM_STATE=$(virsh domstate "$VM_NAME" 2>/dev/null)
    if [[ "$VM_STATE" == "shut off" ]]; then
        lo**essage "❗多次尝试后已强制关闭虚拟机: $VM_NAME"
    else
        lo**essage "❌ 强制关闭虚拟机失败: $VM_NAME,当前状态: $VM_STATE"
    fi
}

# 主逻辑
case "$ACTION" in
    start)
        VM_STATE=$(virsh domstate "$VM_NAME" 2>/dev/null)
        if [[ "$VM_STATE" == "shut off" ]]; then
            start_vm
        elif [[ "$VM_STATE" == "running" ]]; then
            lo**essage "🔵 虚拟机已运行,无需操作"
        else
            lo**essage "❓ 虚拟机状态未知: $VM_STATE"
        fi
        ;;
    stop)
        VM_STATE=$(virsh domstate "$VM_NAME" 2>/dev/null)
        if [[ "$VM_STATE" == "running" ]]; then
            stop_vm
        else
            lo**essage "🟢 虚拟机未运行,无需关闭"
        fi
        ;;
    *)
        lo**essage "🚫 未知操作: $ACTION"
        ;;
esac

保存到想要存放的位置,记得chmod一下使其可执行!随后我们便可以将设备直通给虚拟机了。

4、创建udev规则,需要注意的是,移除设备后ID便不存在了,此时只能使用PRODUCT去做判定,不能直接采用插入事件的写法去监测,我们需要将文件进行规范命名,此处我命名为99-konica-printer.rules,我们需要将此文件保存到/etc/udev/rules.d/下

# 插入事件
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{ID_VENDOR_ID}=="132b", ENV{ID_MODEL_ID}=="20a3", ENV{PATH}="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", RUN+="/bin/sh -c '/vol1/1000/config/printer.sh start >> /tmp/udev_printer_debug.log 2>&1'"
# 拔出事件
ACTION=="remove", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ENV{PRODUCT}=="132b/20a3/100", ENV{PATH}="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", RUN+="/bin/sh -c '/vol1/1000/config/printer.sh stop >> /tmp/udev_printer_debug.log 2>&1'"

5、效果展示

image.png

总结

本文主要介绍如何利用udev规则配合脚本,来实现设备状态的监控并执行所需要的后续操作。文中的脚本为AI编写,存在一些不必要的内容,请不要照抄。本文更多的是提供一种联动思路,具体使用场景可以发挥各自脑洞去尝试。

另外,udev规则可以视为默认使用root权限运行,因此不用担心因脚本权限不足而造成无法正常运行的问题。

收藏
送赞
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则