You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible如何优雅获取打印机USB路径?替代shell模块的方案

问题

我正在为Raspberry Pi 4编写Ansible playbook,其中的podman容器需要访问位于/dev/bus/usb/XXX/YYY路径的打印机设备。目前我已通过shell模块实现该功能,但shell模块并不推荐使用,现有任务代码如下:

- name: "ScannerJS - Detect printer's USB bus"
  block:
    - name: "ScannerJS - Detect printer's USB bus"
      ansible.builtin.shell: |
        set -e -o pipefail
        lsusb | grep Epson | awk '{print "/dev/bus/usb/"$2"/"substr($4, 1, length($4)-1)}'
      args:
        executable: /bin/bash
      register: scUSBBus
      failed_when: scUSBBus.stdout | regex_search("^\/dev\/bus\/usb\/(\\d{3})\/(\\d{3})$") is none

    - name: "ScannerJS - assert the device path exists"
      ansible.builtin.stat:
        path: "{{ scUSBBus.stdout }}"
      register: scUSBBusStat
      failed_when: scUSBBusStat.stat.exists is not true

请问是否有更规范的方式获取该打印机的USB总线路径?我已尝试查看Ansible facts,但未找到USB设备相关信息,也未发现对应模块。

解决方案

可以通过读取系统sysfs文件系统的USB设备信息,或者使用第三方Ansible模块来替代shell命令,避免依赖外部工具,更符合模块化规范。

方案1:基于sysfs的原生模块实现

利用Ansible的find、lookup等模块直接读取系统USB设备的标识文件,无需调用外部命令:

- name: "ScannerJS - 获取Epson打印机的USB设备路径"
  block:
    - name: "ScannerJS - 枚举所有USB根设备目录"
      ansible.builtin.find:
        paths: "/sys/bus/usb/devices"
        patterns: "usb*"
        recurse: false
        file_type: directory
      register: usb_devices

    - name: "ScannerJS - 筛选Epson设备并提取总线/设备号"
      ansible.builtin.set_fact:
        epson_usb_path: "{{ item }}"
      loop: "{{ usb_devices.files | map(attribute='path') | list }}"
      vars:
        # 替换为你的Epson设备厂商ID,可通过lsusb查询,Epson通用ID为04b8
        target_vendor_id: "04b8"
        device_vendor_id: "{{ lookup('file', item ~ '/idVendor') | trim }}"
      when: device_vendor_id == target_vendor_id
      no_log: true

    - name: "ScannerJS - 生成/dev/bus/usb完整路径"
      ansible.builtin.set_fact:
        scUSBBus: >-
          /dev/bus/usb/
          {{ epson_usb_path | regex_search('usb(\\d+)', '\\1') | first }}/
          {{ epson_usb_path | basename | regex_search('(\\d+)-', '\\1') | first }}
      when: epson_usb_path is defined

    - name: "ScannerJS - 验证设备路径存在"
      ansible.builtin.stat:
        path: "{{ scUSBBus }}"
      register: scUSBBusStat
      failed_when: not scUSBBusStat.stat.exists

说明

  • 通过find模块遍历系统USB设备的根目录
  • 读取每个设备的idVendor文件,匹配Epson的厂商ID来筛选目标设备
  • 用正则从设备路径中提取总线号和设备号,拼接成/dev/bus/usb下的完整路径
  • 最后验证路径的有效性

方案2:使用第三方USB设备模块

如果可以安装第三方集合,community.general.usb_device模块能直接返回USB设备的结构化信息,代码更简洁:

  1. 先安装对应的Ansible集合:
ansible-galaxy collection install community.general
  1. 在playbook中使用该模块:
- name: "ScannerJS - 获取Epson打印机USB信息"
  community.general.usb_device:
    state: list
  register: usb_devices

- name: "ScannerJS - 筛选Epson设备并生成路径"
  ansible.builtin.set_fact:
    scUSBBus: "/dev/bus/usb/{{ item.bus_number }}/{{ item.device_number }}"
  loop: "{{ usb_devices.devices }}"
  when: item.vendor == 'Epson'

- name: "ScannerJS - 验证设备路径存在"
  ansible.builtin.stat:
    path: "{{ scUSBBus }}"
  register: scUSBBusStat
  failed_when: not scUSBBusStat.stat.exists

说明

  • 模块会直接返回所有USB设备的bus_number和device_number字段,直接拼接即可得到目标路径
  • 无需手动处理系统文件,代码可读性更高

内容的提问来源于stack exchange,提问作者tholeb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 01:25:12