WezTerm Lua API 深入解析:`LocalProcessInfo` 进程信息对象与前台进程探测实战
2026/9/10 15:57:03 网站建设 项目流程

WezTerm Lua API 深入解析:LocalProcessInfo进程信息对象与前台进程探测实战

【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/wezterm

LocalProcessInfo是 WezTerm 向 Lua 配置脚本暴露的本地进程信息对象,它描述运行在本机上的进程及其子进程树,是mux-is-process-stateful事件回调与pane:get_foreground_process_info()方法的返回值类型。本文将以该对象为骨架,完整梳理其字段语义、平台限制,并深入结合 procinfo 模块源码 与 LocalPane 实现 讲解其底层数据来源,最后给出可复制的状态栏与关闭确认实战示例,帮助你在自己的 WezTerm 配置中安全、高效地使用进程信息。

什么是LocalProcessInfo

LocalProcessInfo(自 20220101-133340-7edc5b5a 版本起提供)表示运行在本地机器上的一个进程。WezTerm 通过它向 Lua 环境传递进程的 PID、父进程 PID、可执行文件路径、命令行参数、工作目录、运行状态以及完整的子进程树。

在 Rust 侧,该类型定义在 procinfo/src/lib.rs 中,并通过wezterm_dynamicFromDynamic/ToDynamic派生与luahelper::impl_lua_conversion_dynamic!宏转换为 Lua 可读的对象,这就是配置脚本中可以直接用点号访问proc.pidproc.argv等字段的原因。

字段一览

字段类型说明
pid整数进程 ID
ppid整数父进程 ID
name字符串进程的短名称。受平台限制可能不准确或被截断,应优先使用executableargv字段
status字符串进程状态,取值见下文
argv进程的参数数组
executable字符串可执行映像的完整路径(可能为空)
cwd字符串进程当前工作目录(可能为空)
children以子进程 PID 为键、值为LocalProcessInfo对象的子进程表

在源码中,name字段的注释明确指出它对应进程的 COMM 名称,与可执行映像名不一定相同,进程运行时可自行修改(例如 Linux 上的setproctitle()),且许多系统会将其截断到 15~16 个字符,因此文档建议把executableargv作为更可靠的判断依据。

status字段的类型在 Rust 侧为LocalProcessStatus枚举(见 procinfo/src/lib.rs),映射到 Lua 后的可取值为:

IdleRunSleepStopZombieTracingDeadWakekillWakingParkedLockBlockedUnknown

并非所有取值在所有平台上都可用——例如 Linux 内核的RSZTtX/x等状态码会在 procinfo/src/linux.rs 中被映射为上述枚举,其他平台则可能只支持其中一部分。

children是一棵递归的进程树:键为子进程 PID,值为描述子进程的LocalProcessInfo对象,因此你可以像遍历树一样层层递归访问整棵进程层级。

数据来源与平台差异

LocalProcessInfo的获取入口是LocalProcessInfo::with_root_pid(pid),它从指定 PID 出发构建整棵进程树。需要明确的是,该信息仅对本地 pane 可用:多路复用(multiplexer)远程 pane、通过ssh连接的远程主机均无法获取远程进程信息。

各平台实现位于 procinfo crate 的模块文件中:

  • Linux:procinfo/src/linux.rs
  • macOS:procinfo/src/macos.rs
  • Windows:procinfo/src/windows.rs

从源码结构看,Linux 实现完全基于/proc文件系统:枚举/proc下所有数值命名的目录得到 PID 列表,读取/proc/<pid>/stat解析进程名、状态、PPID 与启动时钟(starttime),通过read_link("/proc/<pid>/exe")获取可执行文件路径(procinfo/src/linux.rs),通过read_link("/proc/<pid>/cwd")获取工作目录(procinfo/src/linux.rs),通过拆分 NUL 字节分隔的/proc/<pid>/cmdline得到argv(procinfo/src/linux.rs),最后按ppid递归拼装出完整的进程树。

需要注意的是平台支持范围:

  • 可执行路径查询executable):仅 Linux、macOS、Windows 支持;FreeBSD 等其他 Unix 系统目前不支持;
  • 非 Linux/macOS/Windows 平台with_root_pidcurrent_working_direxecutable_path三个方法直接返回None(见 procinfo/src/lib.rs);
  • 路径查询可能因 WezTerm 无法控制的各种原因失败(如权限、进程退出、/proc 不可用),此时字段为空;
  • 查询进程信息存在一定运行时开销,过度使用可能拖慢 WezTerm(详见下文缓存机制)。

核心 API 一:pane:get_foreground_process_info()

pane:get_foreground_process_info()(自 20220624-141144-bd1b7c5d 起提供)返回当前 pane 中前台进程对应的LocalProcessInfo对象;若无法确定进程,则返回nil

前台进程的判定规则

该方法的语义在不同平台上有显著差异,这是实际使用时最容易踩坑的地方:

  • Unix 系统:查询的是进程组组长(process group leader),即终端前台进程组对应的进程;
  • Windows:不存在进程组的概念,因此改为检查最初启动程序的进程树,并把"最近产生的后代进程"视为前台进程。

后者的实现可以在 mux/src/localpane.rs 中看到:divine_process_list以根进程为起点,递归遍历children,利用start_time字段比较各进程的相对"年龄",选出start_time最大的(即最近启动的)后代作为foreground,并将其children清空后缓存。Windows 上还会通过console句柄字段过滤(child.console == 0时跳过),以规避不相关控制台进程的干扰。

使用限制

  • 仅本地 pane 可用;多路复用 pane、ssh远程连接场景下无法获取;
  • 查询可执行路径仅限 Linux、macOS、Windows;
  • 查询失败时返回nil,脚本必须做好空值处理。

实战:状态栏显示前台进程

官方文档给出的示例将前台进程的 PID 与可执行文件 basename 显示在右侧状态栏:

local wezterm = require 'wezterm' -- 等价于 POSIX basename(3) -- 给定 "/foo/bar" 返回 "bar" -- 给定 "c:\\foo\\bar" 返回 "bar" function basename(s) return string.gsub(s, '(.*[/\\])(.*)', '%2') end wezterm.on('update-right-status', function(window, pane) local info = pane:get_foreground_process_info() if info then window:set_right_status( tostring(info.pid) .. ' ' .. basename(info.executable) ) else window:set_right_status '' end end) return {}

basename函数同时兼容 POSIX 的/与 Windows 的\路径分隔符,这段配置在 Linux、macOS、Windows 上都能正确工作。由于get_foreground_process_info()可能返回nil,必须先判空再使用字段。

值得一提的是,WezTerm 内部对前台进程信息做了缓存与后台刷新处理:在 mux/src/localpane.rs 中,CachedLeaderInfo保存了前台进程 PID、可执行路径与工作目录,并带有 TTL 过期机制;源码注释还提到tcgetpgrp单次可能耗时约 700µs,若 10 个标签页都被鼠标扫过,仅取 PID 就可能累计 7ms 造成卡顿——这正是缓存存在的意义。因此"查询进程信息有运行时开销,应避免过度使用"的官方提示对应着真实的性能考量。

核心 API 二:mux-is-process-stateful事件

mux-is-process-stateful事件在多路复用层想要判断"某个 pane 是否可以无需用户确认直接关闭"时触发。

事件语义与返回值

  • 该事件是同步的,回调必须尽快返回,以免阻塞多路复用器;
  • 事件回调会收到一个代表该 pane 对应进程树的LocalProcessInfo对象;
  • 返回值约定:
返回值含义
true该进程树被视为有状态(stateful),关闭 pane 前应提示用户
false该进程树可以被直接终止,无需提示
nil使用默认行为:依据skip_close_confirmation_for_processes_named配置判定
其他任意值或出错等价于返回nil

Rust 侧的调用点在 mux/src/localpane.rs:can_close_without_prompting通过config::lua::emit_sync_callback同步调用 Lua 钩子,仅把BooleanNil识别为有效返回值,其余一律回退到默认逻辑,与文档描述完全一致。

默认判定逻辑(skip_close_confirmation_for_processes_named

当事件返回nil或未定义时,WezTerm 使用skip_close_confirmation_for_processes_named配置项做判定。该配置(自 20210404-112810-b63a949d 起提供)列出被认为"无状态"、可安全关闭的进程名:

config.skip_close_confirmation_for_processes_named = { 'bash', 'sh', 'zsh', 'fish', 'tmux', 'nu', 'cmd.exe', 'pwsh.exe', 'powershell.exe', }

关闭 pane 时,WezTerm 会检查该 pane 启动的程序所派生的所有进程名:如果全部进程名都命中列表,则不弹确认框;只要存在一个不在列表中的进程,就视为有状态并提示确认。默认判定逻辑在 mux/src/localpane.rs 中实现,值得注意两个细节:

  1. 它使用的是flatten_to_exe_names()(见 procinfo/src/lib.rs),即把整棵进程树展开为"可执行文件 basename"的集合,再与配置列表比对;
  2. 出于对 Fig 工具链的兼容,比较前会剥离进程名中(figterm)后缀——Fig 的figterm伪终端夹在 shell 与终端之间,进程名形如<shell> (figterm),不剥离会导致判定永远失败。

若事件回调抛错,WezTerm 会记录错误日志并回退到默认行为(mux/src/localpane.rs),保证配置异常不会影响关闭功能。

实战:递归打印进程树

官方示例演示了如何用递归函数遍历children字段并缩进输出,通过wezterm.log_info记录进程树全貌。该示例不改变任何行为(返回nil走默认逻辑),但完整展示了对LocalProcessInfo各字段的读取方式:

local wezterm = require 'wezterm' function log_proc(proc, indent) indent = indent or '' wezterm.log_info( indent .. 'pid=' .. proc.pid .. ', name=' .. proc.name .. ', status=' .. proc.status ) wezterm.log_info(indent .. 'argv=' .. table.concat(proc.argv, ' ')) wezterm.log_info( indent .. 'executable=' .. proc.executable .. ', cwd=' .. proc.cwd ) for pid, child in pairs(proc.children) do log_proc(child, indent .. ' ') end end wezterm.on('mux-is-process-stateful', function(proc) log_proc(proc) -- 使用默认行为 return nil end) return {}

对一个zsh启动bashbash再启动vim foo的场景,输出日志形如:

INFO config::lua > lua: pid=1913470, name=zsh, status=Sleep INFO config::lua > lua: argv=-zsh INFO config::lua > lua: executable=/usr/bin/zsh, cwd=/home/wez INFO config::lua > lua: pid=1913567, name=bash, status=Sleep INFO config::lua > lua: argv=bash INFO config::lua > lua: executable=/usr/bin/bash, cwd=/home/wez INFO config::lua > lua: pid=1913624, name=vim, status=Sleep INFO config::lua > lua: argv=vim foo INFO config::lua > lua: executable=/usr/bin/vim, cwd=/home/wez

递归遍历时注意proc.children以 PID 为键,pairs的遍历顺序在 Lua 中不保证稳定,若需要固定顺序应先对键排序。

进阶:基于进程信息定制关闭行为

把前面两块内容组合起来,可以构建一个比skip_close_confirmation_for_processes_named更精细的关闭策略。例如:默认对vimgit(可能正处在交互式操作中)等进程保持提示,而对其他无状态进程直接关闭:

local wezterm = require 'wezterm' -- 若进程树中存在需要保护的有状态程序,则要求提示 local STATEFUL = { vim = true, nvim = true, emacs = true, git = true, } local function tree_has_stateful(proc) if STATEFUL[proc.name] or STATEFUL[(proc.executable:match('([^/\\]+)$') or '')] then return true end for _, child in pairs(proc.children) do if tree_has_stateful(child) then return true end end return false end wezterm.on('mux-is-process-stateful', function(proc) if tree_has_stateful(proc) then return true end return false end) return {}

这个示例展示了mux-is-process-stateful的核心价值:它收到的proc是整棵进程树(根节点),你拥有比内置默认逻辑更自由的判定空间。同时它也是同步回调,递归遍历深进程树时注意控制复杂度,避免拖慢多路复用器。

总结与常见陷阱

LocalProcessInfo是 WezTerm 连接"终端 UI 层"与"操作系统进程层"的桥梁,掌握它就能在状态栏展示前台程序、按进程内容定制关闭确认策略。使用时的要点可归纳为:

  1. 字段优先级name可能被截断或被setproctitle()篡改,关键判定用executableargv
  2. 平台边界:仅本地 pane 有数据;executable路径查询仅限 Linux/macOS/Windows;Windows 的"前台进程"由进程树中最年轻的后代推断而来,与 Unix 的进程组组长语义不同;
  3. 空值处理get_foreground_process_info()返回nilexecutable/cwd可能为空,脚本需判空;
  4. 性能意识:进程查询有运行时开销,WezTerm 内部通过 TTL 缓存缓解(相关实现见 mux/src/localpane.rs),自定义脚本也应避免在热点回调(如update-right-status的每次触发)中高频重建进程树;
  5. 事件返回值mux-is-process-stateful只认true/false/nil,其余值一律回退默认逻辑;回调出错会回退默认逻辑,因此配置错误不会造成关闭功能失效,但请留意错误日志。

相关文档可继续阅读 mux-is-process-stateful 事件、pane:get_foreground_process_info() 与 skip_close_confirmation_for_processes_named 配置,完整的 Lua API 索引位于 docs/config/lua。

【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/wezterm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询