资讯动态

WezTerm ExecDomain 配置详解:用 `wezterm.exec_domain` 包装本地命令派发

发布时间:2026/9/10 16:53:47 来源:尧图企业网站定制
WezTerm ExecDomain 配置详解用wezterm.exec_domain包装本地命令派发【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/weztermExecDomain是 WezTerm当前仓库GitHub_Trending/we/wezterm中用于定义本地执行型多路复用域local-execution multiplexer domain的核心配置对象。它的价值在于让 WezTerm 不直接执行用户请求的程序而是先把该命令交给一个 Luafixup函数改写wrap再由改写后的命令去启动真正的程序。读完本文你将掌握wezterm.exec_domain的完整参数语义、fixup与label回调的编写方式并能用两个完整范例systemd scope 隔离、Docker 容器域把这一机制落地到自己的wezterm.lua配置中。ExecDomain 是什么根据官方文档 docs/config/lua/ExecDomain.md一个ExecDomain定义的是一个本地执行的 multiplexer 域自版本20220807-113146-c2fee766起可用。通俗地说与其直接执行请求的程序ExecDomain允许你把该命令调用传递给其他进程来处理。举个典型场景如果你想更方便地在 Docker 容器里使用标签页tab与窗格pane可以定义一个ExecDomain让所有命令都经由docker exec来运行。诚然你也可以手动让 WezTerm 显式 spawn 一条执行docker exec的命令但那样你还得改动默认的分屏键位如SplitHorizontal、SplitVertical等 key assignment让它们知道这个偏好。而使用ExecDomain这个偏好会与 pane 绑定在一起分屏、新开标签页都能天然地继承该偏好交互上更直观。从源码结构看ExecDomain是配置层的一等公民。在 config/src/exec_domain.rs 中它被定义为一个 Rust 结构体#[derive(Debug, Clone, FromDynamic, ToDynamic)] pub struct ExecDomain { #[dynamic(validate validate_domain_name)] pub name: String, pub fixup_command: String, pub label: OptionValueOrFunc, }name域的唯一标识配置校验时会调用validate_domain_namefixup_commandLua 回调以字符串形式存储的 Lua 函数引用用于改写命令label可选可以是静态字符串Value或 Lua 回调函数Func对应ValueOrFunc枚举。在 config/src/config.rs 中配置结构体通过pub exec_domains: VecExecDomain承接用户在 Lua 中config.exec_domains {...}的赋值。定义 ExecDomain必须使用wezterm.exec_domain函数来定义域。它接受如下参数wezterm.exec_domain(NAME, FIXUP [, LABEL])name唯一标识该域。必须与其他任何 multiplexer 域unix/ssh/wsl/tls 等的名称都不冲突。配置加载时会统一做名称唯一性校验见 config/src/config.rs 中check_domain(d.name, exec domain)的检查逻辑fixup一个 Lua 函数被调用来fixup改写请求的命令并返回修订后的命令label可选可以是一个字符串作为 Launcher Menu启动器菜单 中显示的标签也可以是一个返回标签的 Lua 函数。fixup 函数最简单的 fixup 函数长这样wezterm.exec_domain(myname, function(cmd) return cmd end)cmd参数是一个 SpawnCommand 对象包含将要执行的命令信息。这个 SpawnCommand 要么是用户在 key assignment 中配置的产物要么是在响应新开标签页 / 分屏请求时生成的等价物。预期行为是fixup 函数调整传入命令的各个字段然后把它返回。WezTerm 将执行这个被调整后的命令以满足用户的 spawn 请求。从实现上看WezTerm 在 mux/src/domain.rs 的LocalDomain::fixup_command中完成了执行请求 → 构造 SpawnCommand → 调用 Lua fixup → 重组命令的完整链路先通过resolve_exec_domain()在config::configuration().exec_domains中按name查找匹配的域mux/src/domain.rs把CommandBuilder中的 argv、完整环境变量、cwd 提取出来构造一个SpawnCommand其中domain字段被设为SpawnTabDomain::DomainName(ed.name.clone())在主线程上以异步回调方式执行 Lua 的fixup_command并把返回结果反序列化回SpawnCommand最后用新的args、set_environment_variables、cwd重新填充CommandBuilder。也就是说fixup 函数拥有对 argv、环境变量、工作目录的完全控制权——这正是它能做命令包装的根本原因。label标签会显示在 Launcher Menu 中。你可以设置为静态字符串也可以设置为 Lua 回调。默认行为等价于下面这个回调-- domain_name 与调用 wezterm.exec_domain() 时的第一个参数相同 wezterm.exec_domains(domain_name, fixup_func, function(domain_name) return domain_name end)注意这是文档中表达默认语义的等价示意代码实际配置中第三参如果省略即取此默认行为。使用回调函数可以让你在 Launcher Menu 渲染前的最后一刻生成修订后的标签。这很适合把标签做成某种状态信息——例如为 Docker 容器或虚拟机定义 ExecDomain 时让标签反映它当前是否在运行。静态字符串与回调生成的字符串都可以包含影响文本样式的转义序列。建议使用 wezterm.format() 来管理这些样式。从实现上看domain_label()位于 mux/src/domain.rs若label是ValueOrFunc::Value(Value::String(s))直接返回该静态字符串若label是ValueOrFunc::Func(label_func)则在主线程异步调用该 Lua 函数把domain_name作为参数传入并将其返回值解释为字符串若回调出错会记录log::error!并回退到域名称本身若没有 label回退到self.name。示例一让每条命令运行在独立的 systemd scope 中完整示例来自 docs/config/lua/ExecDomain.mdlocal wezterm require wezterm local config {} -- Equivalent to POSIX basename(3) -- Given /foo/bar returns bar -- Given c:\\foo\\bar returns bar local function basename(s) return string.gsub(s, (.*[/\\])(.*), %2) end config.exec_domains { -- Defines a domain called scoped that will run the requested -- command inside its own individual systemd scope. -- This defines a strong boundary for resource control and can -- help to avoid OOMs in one pane causing other panes to be -- killed. wezterm.exec_domain(scoped, function(cmd) -- The cmd parameter is a SpawnCommand object. -- You can log it to see whats inside: wezterm.log_info(cmd) -- Synthesize a human understandable scope name that is -- (reasonably) unique. WEZTERM_PANE is the pane id that -- will be used for the newly spawned pane. -- WEZTERM_UNIX_SOCKET is associated with the wezterm -- process id. local env cmd.set_environment_variables local ident wezterm-pane- .. env.WEZTERM_PANE .. -on- .. basename(env.WEZTERM_UNIX_SOCKET) -- Generate a new argument array that will launch a -- program via systemd-run local wrapped { /usr/bin/systemd-run, --user, --scope, --descriptionShell started by wezterm, --same-dir, --collect, --unit .. ident, } -- Append the requested command -- Note that cmd.args may be nil; that indicates that the -- default program should be used. Here were using the -- shell defined by the SHELL environment variable. for _, arg in ipairs(cmd.args or { os.getenv SHELL }) do table.insert(wrapped, arg) end -- replace the requested argument array with our new one cmd.args wrapped -- and return the SpawnCommand that we want to execute return cmd end), } -- Making the domain the default means that every pane/tab/window -- spawned by wezterm will have its own scope config.default_domain scoped return config这个范例的几个关键点值得展开身份合成WEZTERM_PANE是新 pane 的 idWEZTERM_UNIX_SOCKET与 wezterm 进程 id 相关两者拼出的ident使 scope 名合理唯一。basename从 socket 路径中取出最后一段避免路径中的/破坏 systemd unit 名的合法性。默认程序兜底cmd.args可能为nil表示应使用默认程序。这里用cmd.args or { os.getenv SHELL }显式把$SHELL作为兜底。资源隔离语义systemd scope 为命令建立了强资源控制边界可避免某个 pane 触发 OOM 时殃及其他 pane。这也是把default_domain设为scoped的动机——让 WezTerm 派生的每个 pane/tab/window 都拥有独立的 scope。调试辅助fixup 里调用wezterm.log_info(cmd)可以把 SpawnCommand 的字段打印到日志中方便你确认对象结构。示例二把每个运行中的 Docker 容器变成一个域第二个完整示例同样来自 docs/config/lua/ExecDomain.md展示了如何动态地把每个运行中的 Docker 容器注册为域从而直接向容器内 spawn shell、或对容器进行分屏local wezterm require wezterm local config wezterm.config_builder() function docker_list() local docker_list {} local success, stdout, stderr wezterm.run_child_process { docker, container, ls, --format, {{.ID}}:{{.Names}}, } for _, line in ipairs(wezterm.split_by_newlines(stdout)) do local id, name line:match (.-):(.) if id and name then docker_list[id] name end end return docker_list end function make_docker_label_func(id) return function(name) local success, stdout, stderr wezterm.run_child_process { docker, inspect, --format, {{.State.Running}}, id, } local running stdout true\n local color running and Green or Red return wezterm.format { { Foreground { AnsiColor color } }, { Text docker container named .. name }, } end end function make_docker_fixup_func(id) return function(cmd) cmd.args cmd.args or { /bin/sh } local wrapped { docker, exec, -it, id, } for _, arg in ipairs(cmd.args) do table.insert(wrapped, arg) end cmd.args wrapped return cmd end end function compute_exec_domains() local exec_domains {} for id, name in pairs(docker_list()) do table.insert( exec_domains, wezterm.exec_domain( docker: .. name, make_docker_fixup_func(id), make_docker_label_func(id) ) ) end return exec_domains end config.exec_domains compute_exec_domains() return config使用以上配置后每次配置被重新加载reload可用域列表都会随之更新。打开 Launcher Menu 就能看到各个容器及其运行状态并可直接在这些容器内启动程序。该示例值得关注的工程细节动态域 即时标签make_docker_label_func(id)返回的闭包每次渲染菜单时都会执行一次docker inspect把{{.State.Running}}映射为Green/Red前景色并通过 wezterm.format() 生成带样式的文本——这正是用回调生成 label 以反映状态的最佳实践。颜色常量对应AnsiColor其语义与color模块一致。闭包捕获 idmake_docker_fixup_func(id)与make_docker_label_func(id)均以闭包捕获容器的真实 id而域 name 使用可读性更好的docker:容器名二者解耦。wezterm.config_builder()返回一个可写配置对象最终return config生效config.exec_domains支持表数组形式的多个域。ExecDomain 的底层实现原理从 mux/src/domain.rs 的源码可以确认以下实现事实ExecDomain 基于 LocalDomainLocalDomain::new_exec_domain(exec_domain)mux/src/domain.rs只是用域名称创建一个本地域执行仍然走本机 pty 通道resolve_exec_domain()按名称反查配置中的exec_domains未命中时返回None。命令改写发生在 spawn 之前fixup_commandmux/src/domain.rs依次处理 WSL 域wsl.exe包装、ExecDomainLua fixup 改写与 Flatpak 沙箱flatpak-spawn --host三者按优先级串联。对 ExecDomain 而言整个 Lua 回调通过config::lua::emit_async_callback在配置主线程上以异步方式执行返回值必须能被解释为SpawnCommand否则报错并带上下文信息calling ExecDomain {name} function。label 渲染同样经过 Lua 回调domain_label()mux/src/domain.rs把域名称作为参数传给 label 函数回调抛错时不会中断渲染而是记录错误并回退到域名。名称全局唯一性校验配置校验阶段会对unix_domains、ssh_domains、exec_domains、wsl_domains、tls_clients逐一执行check_domainconfig/src/config.rs因此 exec domain 的名称不能与任何其他类型的域重名。结合 SpawnCommand 理解 fixup 能改什么fixup 收到的cmd是 SpawnCommand 对象其字段在文档与实现中保持一致均可省略wezterm.action.SpawnCommandInNewWindow { -- 可选标签仅当该 SpawnCommand 出现在 launch_menu 中时才使用 label List all the files!, -- 命令及其参数的数组省略时使用目标域的默认程序 args { ls, -al }, -- 命令的工作目录省略时 wezterm 根据触发时刻的活动 pane 推断 -- 若活动 pane 的域与本次 SpawnCommand 指定的域一致则沿用其 cwd -- 无法推断时通常回退到当前用户主目录 cwd /some/path, -- 为本命令追加设置的环境变量 set_environment_variables { SOMETHING a value, }, -- 使用当前活动 pane 的 multiplexer 域默认行为 domain CurrentPaneDomain, -- 或使用默认域通常为 local除非用 wezterm connect/serial 启动 -- domain DefaultDomain, -- 或显式指定命名域 -- domain { DomainName my.server }, }对照 mux/src/domain.rs 的实现fixup 中真正会被采纳的字段是args重写 argv、set_environment_variables整体替换环境变量、cwd替换工作目录其余字段主要用于传递上下文。这也解释了为何两个示例都集中在重写cmd.args上——argv 是命令包装的核心载体。总结与适用范围ExecDomain最适合以下场景命令包装如通过docker exec、systemd-run、ssh、sudo、flatpak-spawn等包装器执行目标程序默认域注入把config.default_domain设为某个 ExecDomain 名称使所有 pane/tab/window 都套用同一种包装策略动态域名如示例二那样在配置加载时扫描外部资源容器、VM、连接并批量生成域配合label回调呈现实时状态键位联动由于偏好与 pane 关联默认的分屏/新标签键位会自动把命令交给正确的域无需逐个改 key assignment。需要留意的是ExecDomain是本地执行型域与远程多路复用域SSH/TLS/Unix domain定位不同它改写的是命令本身而不是建立跨主机的会话连接。相关对比可参考 docs/config/lua/SshDomain.md 与 docs/config/lua/WslDomain.mdWSL 域在 mux/src/domain.rs 中同样走fixup_command链路用wsl.exe --distribution ... --exec包装命令是理解本地包装思路的另一个实例。配置好config.exec_domains后重启或 reload WezTerm即可在 Launcher MenuCtrlShiftSpace等默认键位打开中看到每个域的标签并在其中启动程序。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价