ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

mise watch 完整指南:基于 watchexec 的文件监听与任务热重跑

mise watch 完整指南:基于 watchexec 的文件监听与任务热重跑 mise watch 完整指南基于 watchexec 的文件监听与任务热重跑【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/misemise watch是 misedev tools、env vars、task runner内置的文件监听命令它复用任务系统声明的sources在文件变化时自动重跑指定任务实现编译、测试、服务热重载等持续开发工作流。本文以 docs/cli/watch.md 为骨架结合 src/cli/watch.rs 源码实现与 e2e 测试系统讲解mise watch的用法、全部参数语义、过滤机制与底层原理读完即可在项目中落地可靠的改完即跑开发体验。一、快速上手第一条监听命令mise watch的作用一句话概括运行任务并在文件变化时重新运行它。其内部委托给watchexec完成文件系统监听mise watch负责解析任务、收集sources、并把它们翻译成 watchexec 的监听路径与过滤规则。mise watch build这一条命令会找到名为build的任务 → 解析它的sources例如[Cargo.toml, src/**/*.rs]→ 让 watchexec 监听这些文件 → 每次变化后重新执行mise run build。关键前置条件watchexec 必须已安装。文档明确说明可用mise use -g watchexeclatest全局安装src/cli/watch.rs 中会先检测watchexec是否在 PATH 上若不存在且工具集里也没有则报错并给出上述安装提示。默认任务不带任务名时mise watch运行名为default的任务源码中args.is_empty()时补入default见 src/cli/watch.rs需要在任务配置中定义它。无 sources 时如果任务没声明任何sourceswatchexec 退化为监听当前目录见 src/cli/watch.rs 的opt out of source-based watching逻辑。# 别名 w等价于 mise watch mise w build安装 watchexecmise use -g watchexeclatest或仅安装在当前项目mise use watchexec见 docs/tasks/running-tasks.md 的 Watching files 一节。监听多个任务任务与参数之间用:::分隔支持同时指定多个任务及其各自的参数mise watch task1 arg1 arg2 ::: task2 arg1 arg2默认情况下依赖任务的 sources 也会被一并监听源码中通过Deps::new(config, tasks.clone())展开所有依赖再收集见 src/cli/watch.rs除非显式传入--skip-deps只监听你指定的任务。监听来自sources的进阶用法mise watch与任务声明的sources深度绑定sources既决定任务的新鲜度检查配合outputs跳过未变更任务也决定 watch 监听哪些文件。例如 docs/tasks/task-configuration.md 中的示例[tasks.build] description Build the CLI run cargo build sources [Cargo.toml, src/**/*.rs] outputs [target/debug/mycli]sources支持相对路径、glob 模式与花括号备选如src/**/*.{js,ts}支持!前缀排除!src/**/*.test.ts与 gitignore、watchexec、rsync 约定一致排除项同样影响mise watch的监听范围任务定义本身会被自动视为一个 source编辑任务定义也会触发重跑。二、mise watch的完整参数骨架mise watch [FLAGS] [TASK] [ARGS]…参数说明[TASK]要运行的任务可用:::指定多个默认default[ARGS]…任务及其参数文档与源码还支持一个隐藏的-t/--task旧式 flagtask_flag见 src/cli/watch.rse2e 测试 e2e/cli/test_watch_default_task 验证了mise watch -t named与位置参数等价且不会误加default任务。其余 flags 全部透传给 watchexec因此任何 watchexec 支持的高级选项都能在mise watch后直接使用。下面按文档的分组逐一详解。三、运行行为控制Busy Update 与进程管理-o, --on-busy-update MODE命令运行期间收到事件怎么办这是最核心的运行策略参数四种取值默认do-nothing模式行为do-nothing默认。命令运行期间到达的事件被忽略从而避免编译产物触发再次编译这类自激循环queue若运行期间有事件到达当前运行结束后再补跑一次restart终止正在运行的命令并启动新的一次signal只向进程发送信号适合能热加载配置的程序配合--signal-r, --restart重启简写等价于--on-busy-updaterestart。最典型的场景是开发服务器mise watch serve --watch src --exts rs --restart官方示例启动 API 服务器./src下任何 Rust 文件变化即重启。-s, --signal SIGNAL运行中发送信号向仍在运行的进程发送指定信号。隐含--on-busy-updatesignal否则 restart 模式下的停止信号由--stop-signal控制。Windows 暂不支持信号一律被覆盖为kill。--stop-signal SIGNAL停止命令的信号用于 restart / signal 模式。restart 的行为是发送信号 → 等待命令退出 → 超过--stop-timeout仍不退则强制终止。Unix 默认SIGTERM语法完整信号名SIGTERM、短名TERM或数字15大小写不敏感Windows 仅支持KILL事件Windows 无传统信号用终止与CTRLC/CTRLBREAK/CTRLCLOSE事件模拟Unix 的SIGKILL/SIGINT/SIGTERM/SIGHUP分别映射到这些事件。--stop-timeout TIMEOUT优雅退出等待时间默认10s设为0表示立即强杀接受无单位秒数已废弃会告警未来将报错或时间跨度值5min 20s对 Windows 无实际效果总是强制终止。--map-signal SIGNAL:SIGNAL信号翻译把 watchexec 收到的 OS 信号映射为发给命令的信号。例如TERM:INT把 SIGTERM 映射为 SIGINTTERM:省略第二个表示丢弃 SIGTERM、什么都不做。可多次指定以映射多个信号。⚠️ 若 SIGINT/SIGTERM 被映射它们就不再退出 watchexec 本身。例如INT:INT可把 Ctrl-C 传给命令而不连带终止 watchexec——但也会让你更难退出 watchexec。-d, --debounce TIMEOUT事件去抖事件到达后最多等待该时长再处理如运行命令。默认50ms强烈不建议设为 0。作用一次看起来是单个的改动往往产生大量事件去抖避免频繁执行文件写入通常非原子每次写入都可能发事件去抖防止在文件写一半时运行命令反向用法设高值如30min做省电/省流量的临时备份脚本——注意累积事件会占内存。接受无单位毫秒数已废弃告警或时间跨度5sec 20ms。--stdin-quitstdin 关闭即退出监听 stdin 文件描述符的 EOF关闭时优雅退出 watchexec。进程管理器可用它避免留下僵尸进程。-p, --postpone等第一次变化再运行默认启动即跑一次命令加此选项后等到检测到第一个事件才运行。--delay-run DURATION事件后延迟运行检测到事件后先睡指定时长再运行命令等价于sleep 5 command但更可移植高效。接受无单位秒数废弃告警或时间跨度2min 5s。--poll [INTERVAL]轮询模式默认使用 OS 原生文件系统监听此选项改为轮询效率较低但能绕开某些文件系统如网络共享盘或边界情况。可选间隔无单位毫秒废弃告警或2s 500ms未指定时默认30s。别名--force-poll。--project-origin DIRECTORY项目根watchexec 会按多种标记文件/目录模式自动发现项目 origin/root偶尔会猜错可用此选项覆盖。project origin 决定ignore 文件的查找路径、使用的 VCS、过滤模式中前导/的含义等。显式设置后 watchexec 不再搜索启动会明显变快。--workdir DIRECTORY命令工作目录默认命令的工作目录与 watchexec 一致可由此覆盖。注意与路径的配合可能不太直观。-h, --help打印帮助四、Filtering精确控制监听什么监听路径选项说明-w, --watch PATH监听指定文件或目录可多次指定。默认监听当前目录。监听单个文件时建议改监听其所在目录并用文件名过滤编辑器保存可能整体替换文件某些平台检测不到后续变化。特殊值/dev/null作为唯一监听路径表示不监听任何路径-W, --watch-non-recursive PATH监听目录但不递归可多次指定-F, --watch-file PATH从文件读取监听路径每行等价于一个-w。-表示从 STDIN 读与--stdin-quit不兼容。复杂场景可用 argfile把命令行选项写入文件后用path/to/argfile传给 watchexec忽略规则选项说明--no-vcs-ignore不加载 gitignore 等 VCS 排除文件含 Mercurial/Subversion/Bazaar/DARCS/Fossilwatchexec 会自动探测在用哪个。全局~/.gitignore与本地.gitignore都会加载。想监听被 Git 忽略的文件时很有用--no-project-ignore不加载项目本地 ignore 文件.gitignore、.ignore等--no-global-ignore不加载全局/用户级 ignore 文件~/.gitignore、~/.config/watchexec/ignore、%APPDATA%\Bazaar\2.0\ignore等--no-default-ignore不使用内置默认忽略编辑器交换文件、*.pyc、*.pyo、.DS_Store、.git、.hg、.svn、watchexec 日志等--no-discover-ignore完全不探测 ignore 文件 上面三者合体更高效但默认忽略仍加载--ignore-nothing什么都不忽略--no-discover-ignore--no-default-ignore。但通过--ignore/--ignore-file显式加载的仍生效支持的 ignore 文件清单文档原文Git 的.gitignore项目根及子目录、.git/info/exclude、core.excludesFile指向的文件Mercurial 的.hgignoreBazaar 的.bzrignoreDarcs 的_darcs/prefs/boringFossil 的.fossil-settings/ignore-globRipgrep/Watchexec 通用的.ignore。VCS 类 ignore 仅在对应 VCS 被探测为项目在用时才生效例如 Git 仓库里的.bzrignore会被丢弃。事件过滤选项说明-e, --exts EXTENSIONS只对指定扩展名的文件发事件。带不带前导点均可js或.js可重复选项或以逗号分隔-f, --filter PATTERNglob 风格模式只有匹配文件的事件才会触发。可重复。非文件事件信号、键盘不受影响--filter-file PATH从文件加载过滤器每行一条空行与#开头被忽略。也可用环境变量WATCHEXEC_FILTER_FILES-J, --filter-prog EXPRESSION[实验性]jaq类 jq语法自定义过滤程序事件格式同--emit-events-to必须返回布尔值。非法程序会使 watchexec 启动失败用-v看运行时错误-i, --ignore PATTERNglob 模式排除匹配文件的事件。可重复--ignore-file PATH从文件加载忽略规则每行一条。也可用环境变量WATCHEXEC_IGNORE_FILES--fs-events EVENTS只监听指定类型的文件系统事件access/create/remove/rename/modify/metadata可重复或以逗号分隔。默认create,remove,rename,modify,metadata除access外全部。可能在内核层过滤更高效但日志更费解--no-meta忽略 metadata 事件--fs-events create,remove,rename,modify与--fs-events同用无意义且被禁止--filter-prog的内置扩展与示例watchexec 在 jaq 标准库之外提供这些自定义过滤器文档原文path | file_meta返回文件元数据文件不存在返回 nullpath | file_size返回文件大小不存在返回 nullpath | file_read(bytes)返回文件前 n 字节没有读整个文件的过滤器鼓励限制读取量string | hash、path | file_hash返回字符串/文件的哈希算法无保证视为不透明值any | kv_store(key)、kv_fetch(key)、kv_clear内存键值存储不持久化一致性无保证any | printout、any | printerr、any | log(level)打印/记录任意值并透传。程序按顺序在所有其他过滤器之后运行短路求值任一过滤器拒绝即停止且输出第一个值后即停止迭代时要用any或all否则只处理第一项。文档示例# 正则忽略路径如排除 *.test.js all(.tags[] | select(.kind path); .absolute | test([.]test[.]js$)) | not # 通过任何创建文件事件 any(.tags[] | select(.kind fs); .simple create) # 通过触碰可执行文件的事件 any(.tags[] | select(.kind path and .filetype file); .absolute | file_meta | .executable) # 忽略以 shebang 开头的文件 any(.tags[] | select(.kind path and .filetype file); .absolute | file_read(2) #!) | not参数以开头时其余部分被当作包含 jaq 程序的文件路径。五、Output 与 Command输出控制与执行方式输出相关选项说明-c, --clear [MODE]运行命令前清屏clear默认或reset清不干净时试试--clearreset--only-emit-events只向 stdout 输出事件、不运行命令。要求设置--emit-events-to且模式限定为stdio与json-stdio改为写 stdout 而非命令的 stdin。适合把 watchexec 当纯文件监听器用-N, --notify命令开始/结束时发桌面通知支持平台--color MODE终端配色时机auto/always/never默认auto。设置环境变量NO_COLOR任意值等价于--colornever--timings打印命令耗时含 watchexec 自身开销非精确值要精确请用time或基准工具-q, --quiet不打印开始/停止消息只保留命令输出、警告与错误--bell命令完成时响终端铃命令执行选项说明--shell SHELL指定 shell。默认 Unix 用$SHELL或shWindows 用检测到的pwsh/powershell/cmd。值含空格时按命令行解析第一个词是 shell 程序其余为参数。命令以-c运行Windowscmd用/C。特殊值none禁用 shell直接把命令第一个词当可执行文件、其余当参数执行解析很简陋更快更严格但失去 glob、重定向、管道等能力-n--shellnone的简写--emit-events-to MODE事件信息的输出位置none默认、environment已废弃、stdio、file、json-stdio、json-file-E, --env KEYVALUE为命令附加环境变量不影响 watchexec 自身keyvalue语法可重复--wrap-process MODE进程包装方式group进程组/session进程会话/none直接运行。默认 macOS 用 session、其他 Unix 用进程组、Windows 用 Job ObjectWindows 上 group/session 都映射为 Job Object事件发射格式--emit-events-to文本模式stdio/filestdio把绝对路径逐行写入命令 stdin每行带create:/remove:/rename:/modify:/other:前缀后关闭句柄file写入临时文件路径通过$WATCHEXEC_EVENTS_FILE环境变量给出。JSON 模式json-stdio/json-file可表达完整事件集。文档给出的 Linux 下创建文件夹的示例{ tags: [ { kind: path, absolute: /home/user/your/new-folder, filetype: dir }, { kind: fs, simple: create, full: Create(Folder) }, { kind: source, source: filesystem } ], metadata: { notify-backend: inotify } }字段说明tags为结构化事件数据tags[].kind可取path含absolute、filetype、fssimple取access/create/modify/remove/otherfull形如General(Precise(Specific))、source来源filesystem/keyboard/mouse/os/time/internal、keyboardkeycode目前仅eof、processpid、signalhangup/interrupt/quit/terminate/user1/user2、completiondisposition取 success/error/signal/stop/exception/continued及codemetadata为附加信息。废弃的environment模式2.0 前的默认通过环境变量传递受影响路径$WATCHEXEC_COMMON_PATH是所有路径的最长公共前缀其余变量需拼上它才得到完整路径——$WATCHEXEC_CREATED_PATH、$WATCHEXEC_REMOVED_PATH、$WATCHEXEC_RENAMED_PATH、$WATCHEXEC_WRITTEN_PATH、$WATCHEXEC_META_CHANGED_PATH、$WATCHEXEC_OTHERWISE_CHANGED_PATH。多路径用系统分隔符Unix:/ Windows;分隔。文档明确警告不要假设重命名事件中旧/新路径的顺序半重命名、未知重命名、事件跨去抖边界拆分都可能出现且该模式对大量文件会截断甚至崩溃将来自会移除。六、Debugging诊断监听问题--print-events去抖后打印触发动作的事件人类可读排查过滤器非常有用需要更多诊断信息用-vvv。--manual显示 watchexec 手册页若输出不是终端或没有man则以 ROFF 格式打印到 stdout可写入watchexec.1文件。七、官方示例全景文档给出的四个示例覆盖了从最简到最复杂的用法# 运行 build 任务并在其 sources 变化时重跑 mise watch build # 不用任务的 sources改监听该 glob mise watch build --glob src/**/*.rs # 额外参数透传给 watchexec可查 watchexec --help mise watch build --clear # 启动 API 服务器./src 下 Rust 文件变化即重启 mise watch serve --watch src --exts rs --restart注意最后一个例子中--watch src --exts rs是显式覆盖监听范围的做法--restart则保证服务器进程始终运行最新代码。八、源码视角mise watch到底做了什么执行流程src/cli/watch.rs工具检测which::which(watchexec)找不到时检查工具集Toolset里是否已装 watchexec否则报错并提示mise use -g watchexeclatest任务解析把位置参数与-t标志合并空则补default通过get_task_lists解析出任务与参数依赖展开非--skip-deps时用Deps::new(config, tasks)展开全部依赖任务收集所有需要监听的 tasks参数翻译把文档中的 flags 逐项翻译为 watchexec 命令行参数。值得注意的细节仅在非默认值时才传--stop-timeout默认10s与--debounce默认50ms任务配置watch.no_vcs_ignore true会让整条命令附加--no-vcs-ignore见 src/cli/watch.rs 与tasks_disable_vcs_ignorese2e 用例 e2e/cli/test_watch_task_no_vcs_ignore 验证此行为用户显式传入的--ignore/--ignore-file/--print-events会被原样转发回归问题 #7776见 e2e/cli/test_watch_ignore--wrap-process按用户请求原样转发mise 不擅自设默认值——watchexec 的默认是平台相关的macOSsession、其余groupmise 替它决定反而会出错见 src/cli/watch.rs 的注释与单元测试sources 翻译核心src/cli/watch.rs每个任务的sources条目先parse_source解析出取反/字面叹号/普通三种类型与绝对路径计算所有任务 cwd 与 source 路径的公共祖先common_ancestor作为过滤锚点并尽可能收进 monorepo 根 / 项目根内把绝对路径相对锚点化relativize_source生成 watchexec 的-f过滤与--ignore排除!前缀被拆成排除而任务 A 的!pat不会压制任务 B 对同一pat的正向包含merge_watch_patterns有专门的回归测试每个任务的 cwd 和 source 的所在目录glob 之前的目录见source_watch_dir被加入--watch监听列表保证 glob 之外的目录也被覆盖锚点以--project-origin传给 watchexec因为 watchexec 把-f模式解释为相对 origin且会静默丢弃绝对路径组装并执行最终命令形如watchexec flags -- mise-bin run [--skip-deps] task1 ... ::: task2 ...并注入工具集环境变量与MISE_ENVe2e 用例 e2e/cli/test_watch_env_flag 验证mise --env dev watch会把MISE_ENVdev传给被监听的子任务。终端状态恢复src/cli/watch.rs一个容易踩坑的细节watchexec 的--clearreset会重置控制终端包括清除ECHO等 termios 标志且中断时不会恢复。mise 在启动 watchexec 前用TerminalState::capture()捕获控制终端优先/dev/tty无控制终端时回退到标准流的 termios 状态通过Drop恢复同时用signal_hook的线程监听SIGTERM/SIGHUP/SIGQUIT在进程被信号杀死例如嵌套在mise run里被exit::kill_all()以 SIGTERM 杀掉时也能先把终端放回去TerminalState::arm并以emulate_default_handler保留被信号杀死的退出状态语义。对应的单元测试见 src/cli/watch.rsmacOS 行为另有 e2e 用例 e2e/cli/test_watch_terminal_restore_on_signal_macos。与任务配置的联动sources字段既做新鲜度检查也驱动 watch见 docs/tasks/task-configuration.md 的sources一节!排除、\!转义字面叹号、..越出任务目录、花括号备选等规则全部生效watch字段watch { no_vcs_ignore true }等价于给 watchexec 传--no-vcs-ignore用于监听被 VCS 忽略的生成/中间文件docs/tasks/task-configuration.md。注意 watchexec 的忽略选项作用于整个监听进程多任务一起 watch 时只要有一个任务开了此选项VCS 忽略就对所有任务关闭务必把sources收窄否则对宽泛目录扫描可能显著拖慢文件系统遍历。九、典型实战组合# 编译任务只监听源码与清单文件Cargo 产物变化不触发重跑do-nothing 默认 mise watch build # 测试驱动等保存再跑且只关心 .ts 文件 mise watch test --postpone --exts ts # 热重启服务显式监听 src、忽略 dist 输出 mise watch serve --watch src --ignore dist/** --restart # 多任务先构建再测试测试依赖 build 时其 sources 也自动被监听 mise watch build ::: test # 只看事件、不跑命令配合脚本消费 JSON 事件流 mise watch --only-emit-events --emit-events-to json-stdio some-task # 诊断为什么监听不触发 mise watch build --print-events若你需要更进阶的进程管理能力——守护进程管理、自动重启、就绪检查readiness checks、cron 定时调度——可参考 mise 的姊妹项目 pitchfork文档原句 For more advanced process management..., see mises sister project。十、延伸阅读运行任务任务的运行、:::多任务、通配符与default任务约定任务配置sources、outputs、watch、depends等字段的完整语义命令参考mise 全部命令mise watch支持全局 flags 与参数语法源码实现上述翻译逻辑、终端恢复与单元测试的完整代码【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表