tuna-f1sh/cyme

GitHub: tuna-f1sh/cyme

cyme 是一个跨平台 USB 设备列表工具,旨在提供比 lsusb 更丰富的功能和更好的用户体验。

Stars: 1127 | Forks: 28

``` o o /---o /---/---o o---/ \---\---o o \---o o ``` # Cyme [![Crates.io](https://img.shields.io/crates/v/cyme?style=flat-square)](https://crates.io/crates/cyme) [![docs.rs](https://img.shields.io/docsrs/cyme?style=flat-square)](https://docs.rs/cyme/latest/cyme/) 列出系统 USB 总线和设备。这是一个现代化的跨平台 `lsusb` 替代工具,力求保持兼容性的同时增加新功能。它对系统 USB 总线及其上的设备进行剖析,包括完整的设备描述符。 作为一名嵌入式设备开发者,我经常使用 USB 列表工具,开发此工具是为了弥补我认为 `lsusb` 的不足之处:详细转储通常_过于_冗长,树状视图整体上缺乏有用数据,在非 Linux 平台上几乎无法工作,并且现代终端支持一些功能,使得浏览数据变得更加轻松。 该项目最初是为了快速替换那个几乎无法工作的 [lsusb 脚本](https://github.com/jlhonora/lsusb),同时也是为了让我保持 Rust 项目的熟悉度!就像大多数有趣的项目一样,在我将其开发成跨平台的 `lsusb` 替代品时,它很快就经历了功能蔓延。它最初是一个 macOS `system_profiler` 解析器,后来演变为包含基于 `libusb` 的剖析器以读取完整的设备描述符,现在默认使用纯 Rust 的剖析器 [nusb](https://github.com/kevinmehall/nusb)。 它并不完美,因为最初只是作为 Rust 的复习项目,但我在开发过程中获得了很多乐趣,并希望其他人能觉得它有用并做出贡献。阅读 [lsusb 源代码](https://github.com/gregkh/usbutils/blob/master/lsusb.c)、USB-IF 规范和通用 USB 信息也是一次很好的知识积累。 名字来源于苹果树上的一种花序类型的技术术语:[cyme](https://en.wikipedia.org/wiki/Inflorescence#Determinate_or_cymose) —— 它与苹果相关,并且看起来像一棵 USB 设备树 😃🌸。 ![cli tree output](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/1970752f6f194008.png) # 功能 * 使用 `--lsusb` 参数时与 `lsusb` 兼容。支持所有参数,包括 `--verbose` 输出 —— 完全解析的设备描述符!无参数列表(list)、树状视图(tree)(在非 Linux 上不包括驱动信息)的输出与 `lsusb` 相同,详细输出(verbose)也应匹配(可能存在格式差异)。 * 默认构建是使用 [nusb](https://docs.rs/nusb/latest/nusb) 的原生 Rust 剖析器。 * 类似 `lsusb` 的过滤器,但在打印 `--tree` 时也有效。增加了 `--filter-name`、`--filter-serial`、`--filter-class` 以及隐藏空 `--hide-buses`/`--hide-hubs` 的选项。也可使用 `--filter-exclude` 进行反向过滤。 * 改进的 `--tree` 模式;根据 `--verbose` 的级别,以树状形式显示设备、配置、接口和端点。 * 可控的显示 `--blocks`,包括设备 `--bus-blocks`、配置 `--config-blocks`、接口 `--interface-blocks` 和端点 `--endpoint-blocks`。使用 `--more` 可默认查看更多内容。 * 现代终端功能,支持彩色输出、utf-8 字符以及基于设备数据的图标查找。可关闭或自定义。参见 `--encoding`(字形[默认]、utf8 和 ascii,可确保图标/树状结构在特定编码范围内)、`--color`(auto [默认]、always 和 never)和 `--icon`(auto [默认]、always 和 never)。自动 `--icon` 仅在所有要显示的图标都受 `--encoding` 支持时才显示图标。 * 也可作为库使用,包含系统剖析器模块、USB 描述符模块以及用于打印的 `display` 模块等。 * `--json` 输出,遵守过滤器和 `--tree` 设置。 * `--headers` 仅在请求时显示元数据,否则不占用空间。 * `--mask-serials` 可将序列号字符串设置为 '\*' 或随机化,以便在共享包含敏感序列号的转储文件时使用。 * 自动适应终端宽度。长度可变的字符串(如描述符)将被截断并以 '...' 表示。可通过配置选项 'no-auto-width' 禁用,并用 'max-variable-string-len' 定义固定最大长度。 * `cyme watch` 子命令,用于监视 USB 设备热插拔事件,并可实时编辑显示设置。可与所有全局标志一起使用。 * 支持 Linux、macOS 和 Windows 平台。 ## 演示 * [watch 子命令的 YouTube 演示](https://youtu.be/ohRBrVBRolA) # 安装 ## 要求 预编译的二进制文件,请查看[发布页面](https://github.com/tuna-f1sh/cyme/releases)。预编译构建使用原生剖析后端,应无需额外依赖。 通过安装了 Rust 工具链的 crates.io 安装:`cargo install --locked cyme`。从本地克隆目录安装:`cargo install --locked --path .`。 ### 包管理器 * [Homebrew 'cyme'](https://formulae.brew.sh/formula/cyme),它还会安装 man 手册页、补全文件以及 'libusb' 依赖项: ``` brew install cyme ``` * [Arch Linux 官方包](https://archlinux.org/packages/extra/x86_64/cyme/) ``` pacman -S cyme ``` * [Debian 包(作为发布的一部分)](https://github.com/tuna-f1sh/cyme/releases) —— 需要一个 Debian 维护者来完成此工作。 更多包管理器/软件包分发将陆续支持,如果您想在这方面帮忙,请随时创建 PR。 ## 设置 `lsusb` 别名 如果希望创建 macOS 版本的 lsusb 或仅用此工具替代,可以在环境中创建一个带有 `--lsusb` 兼容性标志的别名: `alias lsusb='cyme --lsusb'` ## Linux udev 信息 要在 Linux 上像 `lsusb` 一样获取正在使用的设备和接口驱动程序信息,可以在构建时使用 `--features udev` 特性 —— 这是一个默认特性。该特性使用 Rust crate [udevrs](https://crates.io/crates/udevrs) 获取信息。要使用 C FFI libudev 库,请使用 `--no-default-features --features udevlib`,这将使用 'libudev' crate。请注意,这需要在主机上安装 'libudev-dev'。 若要像 `lsusb` 一样从 udev hwdb 查找 USB ID,请使用 `--features udev_hwdb`。如果不使用 hwdb,`cyme` 将使用 'usb-ids' crate,其数据源与 hwdb 二进制数据相同,但捆绑的 hwdb 可能因自定义或更新时间不同而存在差异('usb-ids' 将是最新的)。 ## 剖析器与特性标志 ### 原生 使用原生 Rust [nusb](https://docs.rs/nusb/latest/nusb) 和 [udevrs](https://crates.io/crates/udevrs) 进行设备剖析:sysfs (Linux)、IOKit (macOS) 和 WinUSB。 自 2.0.0 起成为默认剖析器。使用 `--feature=native`(Linux 上为 'nusb' 和 'udevrs')或 `--feature=nusb` 手动指定。 ### Libusb 使用 'libusb' 进行设备剖析。需要安装 [libusb 1.0.0](https://libusb.info):`brew install libusb`、`sudo apt install libusb-1.0-0-dev` 或您选择的包管理器。 在 2.0.0 之前是获取详细信息的默认特性。它是 `lsusb` 使用的剖析器,但由于 cyme 使用控制消息来收集相同信息,两者输出应无差异。如果希望使用 'libusb',请使用 `--no-default-features` 和 `--feature=libusb`,或同时使用 `--feature=ffi` 来支持 udevlib。 ### macOS `system_profiler` 使用 macOS 的 `system_profiler SPUSBDataType` 命令来剖析设备。 在 2.0.0 之前是 macOS 系统提供基础信息的默认特性;'libusb' 用于打开设备以获取详细信息。如果使用默认的原生剖析器,现在不再使用它,但可以通过 `--system-profiler` 强制使用 —— 原生剖析器使用相同的 IOKit 后端,但由于不反序列化 JSON,速度更快。并且它始终能捕获总线编号,而 `system_profiler` 则不能。 # 用法 使用 `cyme --help` 获取基本用法,或查看 `man ./doc/cyme.1`。'./doc' 目录中也有自动补全脚本。 ## 示例 ### 树状视图 ``` # 以树状格式列出所有 USB 设备和总线,默认显示块 cyme --tree # 如上所述,但同时包含配置 cyme --tree --verbose # 包括接口和端点 - 每个详细级别都进一步深入 USB 描述符树。此处使用短参数。 cyme --tree -vvv # 以树状格式列出所有 USB 设备和总线,包含更多显示块、所有详细级别和标题以显示正在显示的内容 cyme --tree --more --headings # 将树状结构导出为 JSON 文件 - --json 适用于所有选项 cyme --tree --verbose --json > tree.json # 然后导入 JSON 文件以查看导出时的系统 USB 树状结构。所有 cyme 参数均可与此外部导入数据一同使用,如同分析数据。 cyme --from-json tree.json ``` ### lsusb ``` # 类似 'lsusb' 列出所有 USB 设备和总线 cyme --lsusb # lsusb 详细设备转储,包含所有描述符信息 cyme --lsusb --verbose # lsusb 树状模式(可添加详细级别 [-v]) cyme --lsusb --tree ``` ### 区块 查看 `cyme --help` 了解可用的区块。也可以省略参数值来显示选项。指定多个区块需要多个参数或 CSV 格式。默认情况下,提供的区块会添加到默认区块中。使用 `--block-operation` 更改此行为。 ``` # 列出 USB 设备,显示更多块 cyme --more # 在默认显示中添加 base-class 和 last-event 块,在总线显示中添加 host-controller-vendor cyme --blocks base-class,last-event --bus-blocks host-controller-vendor # 在接口块中添加 dev-path 和 mount-paths cyme --interface-blocks dev-path,mount-paths # 列出 USB 设备,指定显示块:name, vid, pid, serial, speed(可使用短参数 -b) cyme --block-operation new --blocks name,vendor-id,product-id,serial -b speed # 自定义其他块 - 此时可能使用配置更为便捷 cyme --blocks name --bus-blocks name --config-blocks name --interface-blocks class --endpoint-blocks number # 使用 block-operation 通过参数块更改默认或配置块 cyme --block-operation remove --blocks serial ``` ### 过滤 ``` # 仅筛选 Apple 设备(vid:pid 为十六进制) cyme -d 0x05ac # 具体为 Apple 耳机,使用 '*' 掩盖序列号 cyme -d 05ac:8103 --mask-serials hide # 筛选具有特定名称和类别的设备(不同标志表示逻辑与) cyme --filter-name "Black Magic" --filter-class cdc-data # 通过重复标志对两个供应商进行逻辑或(每次出现为一个单独的或筛选器) cyme -d 0x05ac -d 0x1d50 # 对两个名称进行逻辑或 cyme --filter-name "Black Magic" --filter-name "FTDI" # 使用 --filter-exclude 排除特定设备(KEY=VALUE,键:vidpid, name, serial, class, bus, number) cyme --filter-exclude vidpid=05ac:8600 # 排除所有键盘同时仍按类别筛选 cyme --filter-class hid --filter-exclude name=Keyboard # 用逗号分隔对在一个排除项内进行逻辑与;重复标志以对排除项进行逻辑或 cyme --filter-exclude vidpid=05ac:8600,name=Hub ``` 过滤器也可以在配置文件中配置。示例可参考 './doc/cyme_example_filter_config.json' —— 这是一个演示所有字段的示例,并非建议直接使用! ### JSON - jq ``` # 为命名的 CDC ACM 设备查找 /dev/tty 设备(替换为 --filter-name 并配合 -d vid:pid 进行更具体筛选) cyme --filter-class cdc-communications --filter-name 'esp' --json | jq '.[] | (.extra.configurations[].interfaces[].devpaths[0]) | select(. != null)' # 查找大容量存储设备的挂载点 cyme --filter-class mass-storage --json | jq '.[] | {device_name: .name, devpaths: .extra.configurations[].interfaces[].devpaths, mounts: .extra.configurations[].interfaces[].mount_paths}' # 仅转储新连接的设备(使用 cyme watch) cyme --json watch | jq '.buses[] | .devices[]? | select( (.last_event | has("connected")))' ``` #### 函数 ``` ttyvid() { cyme --json --filter-class cdc-communications -d $1 | jq '.[] | (.extra.configurations[].interfaces[].devpaths[0]) | select(. != null)' | tr -d '"' } ttyname() { cyme --json --filter-class cdc-communications --filter-name $1 | jq '.[] | (.extra.configurations[].interfaces[].devpaths[0]) | select(. != null)' | tr -d '"' } ``` 然后配合串口 IO 工具,根据 VID 或名称打开设备:`tio $(ttyname 'edbg')` ## Crate 若要作为库使用来剖析系统 USB 设备,该 crate 100% 有文档记录,请查阅 [docs.rs](https://docs.rs/cyme/latest/cyme/)。主要导入的有用模块是 [profiler](https://docs.rs/cyme/latest/cyme/profiler/index.html) 和 [usb](https://docs.rs/cyme/latest/cyme/usb/index.html)。 'examples/' 目录中也有一些示例,可通过 `cargo run --example filter_devices` 运行。它并非从头设计为 crate,但所有的 USB 描述符可能对高级 USB 剖析很有用。 ## 配置 `cyme` 会在以下位置检查 'cyme.json' 配置文件: * Linux: "$XDG\_CONFIG\_HOME/cyme 或 $HOME/.config/cyme" * macOS: "$HOME/Library/Application Support/cyme" * Windows: "{FOLDERID\_RoamingAppData}/cyme" 也可以通过 `--config` 指定。复制或参考 './doc/cyme\_example\_config.json' 进行配置。该文件本质上是默认参数;提供的参数会覆盖这些默认值。使用 `--debug` 查看其查找路径或是否未加载。 `cyme watch` 也可用于实时编辑显示设置,然后通过 'Ctrl-s' 将配置保存到默认位置。这可能是自定义显示区块最简单的方法。 ### 自定义图标和颜色 请参阅 './doc/cyme\_example\_config.json' 了解如何定义图标的示例以及 [文档](https://docs.rs/cyme/latest/cyme/icon/enum.Icon.html)。如果不想定义任何新图标/颜色,配置中可以省略 "user"/"colours" 键。 图标按 User -> Default 顺序查找。对于设备:`Name` -> `VidPid` -> `VidPidMsb` -> `Vid` -> `UnknownVendor` -> `get_default_vidpid_icon`;对于类:`ClassifierSubProtocol` -> `Classifier` -> `UndefinedClassifier` -> `get_default_classifier_icon`。用户提供的颜色覆盖所有内部设置;如果缺少某个键,其值将为 `None`。 #### 图标不显示/显示为带问号的方框 内容复制自 [lsd](https://github.com/lsd-rs/lsd#icons-not-showing-up):为了让 `cyme` 能够显示图标,字体必须包含特殊的字形。您下载的大多数字体可能不包含这些字符。幸运的是,您可以使用 [NerdFont](https://www.nerdfonts.com/) 对大多数字体进行补丁以添加这些图标。或者,您可以直接从 [NerdFont 字体下载页面](https://www.nerdfonts.com/font-downloads) 下载已打补丁的您喜欢的字体版本。 以下是关于如何在 [macOS](https://github.com/Peltoche/lsd/issues/199#issuecomment-494218334) 和 [Android](https://github.com/Peltoche/lsd/issues/423) 上设置字体的指南。 要检查您使用的字体是否设置正确,请尝试在 shell 中运行以下代码片段,看看它是否[打印出一个文件夹图标](https://github.com/Peltoche/lsd/issues/510#issuecomment-860000306)。如果它打印出一个方框、问号或其他东西,那么您在设置字体或终端模拟器渲染字体的方式上可能存在问题。 ``` echo $'\uf115' ``` 如果不需要图标,请提供一个不包含任何 'icon\*' 块的自定义配置文件 —— 参见示例配置。或者,要仅使用所有字体支持的标准 UTF-8 字符(不使用私用区),请传递 `--encoding utf8` 和 `--icon auto`(默认值)。`--icon auto` 将在匹配的字符不被 `--encoding` 支持时丢弃图标块。 要完全不使用图标,请使用隐藏的 `--no-icons` 或 `--icon never` 参数。 # 已知问题 * 在 Linux 上,需要 `sudo` 权限才能打开和读取根集线器(root\_hub)字符串描述符,并且如果用户没有[权限](https://docs.rs/nusb/latest/nusb/#linux),可能需要对所有设备使用 sudo。然而,程序在没有这些权限的情况下也能正常工作,因为它会像 lsusb 一样使用 sysfs/hwdb/'usb-ids'。使用调试选项 `-z` 可查看哪些设备读取失败。环境变量 CYME_PRINT_NON_CRITICAL_PROFILER_STDERR 可用于将这些信息打印到标准错误输出。`--lsusb --verbose` 将始终向标准错误输出打印一条消息,以匹配 'lsusb' 的行为。 * 用户无法在 Apple 总线 (VHCI) 上打开特殊的非用户设备(例如 T2 芯片)。这些设备在使用 'native' 和 `system_profiler` 时仍会被列出,但使用 `--force-libusb` 则不会。它们不会打印详细信息,如果使用了 `--verbose`,会记录错误日志/如果使用了 `--lsusb` 则会打印错误。
标签:DNS解析, lsusb替代, Rust编程, USB总线, USB管理, WSL, 动态分析, 可视化界面, 嵌入式开发, 开源项目, 树状输出, 硬件监控, 硬件调试, 系统工具, 终端工具, 设备描述符, 通知系统