# tasker_win **Repository Path**: polewt/tasker_win ## Basic Information - **Project Name**: tasker_win - **Description**: 轻量级 Windows 后台进程启动与进程树管理器 类似于 nohup 命令,零外部依赖静默运行后台命令,单二进制程序。收集 stdout/stderr 至日志文件,利用 Windows Job Object(作业对象)管理进程树,无孤儿/脏进程残留。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: release - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-02 - **Last Updated**: 2026-09-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: Rust, taskmgr, nohup ## README # tasker - Windows 后台进程启动与进程树管理器 > 在 Windows 上零外部依赖静默运行后台命令。收集 stdout/stderr 至日志文件,利用 Windows Job Object(作业对象)管理进程树,杜绝孤儿/脏进程残留。 [English](README.md) | [简体中文](README_ZH.md) [![Rust](https://img.shields.io/badge/rust-1.74%2B-blue.svg)](https://www.rust-lang.org) [![Platform](https://img.shields.io/badge/platform-Windows-0078d4.svg)](https://www.microsoft.com/windows) [![Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)]() [![Binary Size](https://img.shields.io/badge/release%20size-~243KB-success.svg)]() [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT) --- ## 核心特性 - **零外部依赖** - 仅使用 Rust 标准库与 Windows 系统原生 API - **内核级作业对象(Job Object)** - 进程树生命周期深度纳管,彻底解决子孙孤儿进程(脏进程)残留问题 - **深度调用链一键终止** - `tasker kill ` 原子性灭杀父进程、中间 Shell 以及下属全部子服务 - **静默后台运行** - `CREATE_NO_WINDOW` 结合 `STARTUPINFO` `SW_HIDE` 全方位隐藏控制台与 GUI 初始窗口 - **单二进制产物** - 独立单个 `tasker.exe`,约 243KB - **统一输出收集** - stdout 与 stderr 自动合并重定向至日志文件 - **纯环境变量配置** - 无需任何额外配置文件 --- ## 快速上手 ### 下载安装 从 [Releases](https://github.com/polewt/tasker_win/releases) 下载 `tasker.exe` 并将其加入系统的 `PATH` 环境变量。 ### 从源码编译 ```bash git clone https://github.com/polewt/tasker_win.git cd tasker_win cargo build --release # 生成二进制文件: target/release/tasker.exe ``` ### 环境要求 - Windows 10 或更高版本 - Rust 1.74+(仅源码编译需要) --- ## 使用指南 ```bash # 在后台启动程序(自动绑定至 Job Object) tasker notepad.exe # 输出: 12345 (PID) # 附带命令行参数 tasker myapp.exe --port 8080 --verbose # 启动框架包装器/多层服务(如 ThinkPHP、Node、Python 等) tasker php think run # 彻底终止整棵进程树(包括根进程、中间层 cmd.exe 及深层服务进程) tasker kill 12345 # 或者使用别名: tasker stop 12345 # 输出: Killed process tree for PID 12345 ``` ### 日志文件 默认情况下,标准输出(stdout)和标准错误(stderr)合并输出至当前目录下的 `./tasker.out`: ```bash tasker myapp.exe type tasker.out ``` ### 环境变量配置 | 环境变量 | 默认值 | 说明 | |----------|--------|------| | `TASKER_LOG_FILE` | `tasker.out` | 日志文件路径(支持相对或绝对路径) | | `TASKER_LOG_MODE` | `append` | 日志写入模式:`append`(追加)或 `truncate`(覆盖清空) | | `TASKER_QUIET` | (未设置) | 设置为任意非空值时启用静默模式,启动时不输出 PID | ```batch REM 自定义日志路径 set TASKER_LOG_FILE=D:\logs\myapp.log tasker myapp.exe REM 每次启动截断清空旧日志 set TASKER_LOG_MODE=truncate tasker myapp.exe REM 静默运行模式(不输出 PID) set TASKER_QUIET=1 tasker myapp.exe ``` --- ## 运行机制与原理 ```text +------------------+ | tasker.exe | <-- 启动器进程 +--------+---------+ | | 1. 读取环境变量构建 Config 配置 | 2. 解析 CLI 参数 -> (exe_path, args) | 3. 检查可执行文件存在性 (PATH / PATHEXT) | 4. 打开日志文件获取独立句柄 | 5. 以挂起状态创建子进程 (CREATE_SUSPENDED) | - 标志: CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP | - STARTUPINFO: SW_HIDE (强制隐藏窗口) | - 重定向: stdout/stderr -> 日志文件, stdin -> NUL | 6. 创建命名作业对象: Local\tasker_job_ | - 配置策略: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | - 将子进程挂载入 Job Object | - 复制 Job 句柄给子进程持有 (bInherit = false) | 7. 唤醒子进程线程并释放父进程句柄,tasker 退出 v +------------------+ | 根子进程 | <-- Job Object 成员 | (PID: 12345) | +--------+---------+ | | 派生子孙进程(如 cmd.exe -> php -S) v +------------------+ | 子孙进程 | <-- Windows 内核自动纳入同一 Job Object | (零孤儿脏进程) | +------------------+ ``` ### 退出与清理覆盖: - **通过 `tasker kill `**:打开命名作业对象并调用 `TerminateJobObject`,由内核瞬时、原子级彻底销毁整个进程树。 - **通过通用 `kill `(或任务管理器杀掉根节点)**:根进程退出时其自身句柄表关闭,Job Object 的最后一个句柄被释放,内核触发 `KILL_ON_JOB_CLOSE` 自动强行终止所有衍生子进程。 --- ## 项目结构 ```text tasker_win/ |-- Cargo.toml # 项目构建与依赖配置 |-- README.md # 英文说明文档 |-- README_ZH.md # 中文说明文档 |-- LICENSE-MIT # MIT 许可证 |-- LICENSE-APACHE # Apache 2.0 许可证 |-- doc/ | |-- constraints.md # 项目设计与开发规范约束 | `-- job_object_architecture.md # Job Object 架构与进程生命周期规范 |-- src/ | |-- lib.rs # 库入口(暴露模块供集成测试使用) | |-- main.rs # CLI 入口(命令编排、run/kill/stop 子命令) | |-- config.rs # 环境变量配置解析 | |-- job.rs # Windows 作业对象(Job Object)核心管理 | |-- process.rs # 进程创建、窗口隐藏与句柄隔离 | |-- error.rs # 自定义 TaskerError 错误类型 | `-- utils.rs # 可执行文件发现与辅助工具函数 `-- tests/ |-- schemes_verification.rs # 启动标志与基础 E2E 测试套件 `-- job_object_test.rs # 作业对象与进程树级联销毁集成测试 ``` --- ## 模块说明 | 模块 | 文件 | 核心职责 | |------|------|----------| | 入口编排 | `src/main.rs` | CLI 参数解析(`run`, `kill`, `stop`)、输出处理与错误退出 | | 核心库 | `src/lib.rs` | 暴露核心模块供二进制目标和集成测试复用 | | 配置管理 | `src/config.rs` | 读取环境变量,构建 Config 结构体 | | 作业对象 | `src/job.rs` | 命名 Job Object 创建、策略配置、句柄克隆与进程树终止 | | 进程管理 | `src/process.rs` | 进程挂起创建、`SW_HIDE` 窗口隐藏、标准句柄继承隔离 | | 错误类型 | `src/error.rs` | 定义 TaskerError 枚举(保持纯 ASCII 错误信息) | | 辅助工具 | `src/utils.rs` | `PATH` 及 `PATHEXT` 探测检查、命令行转义 | --- ## 开发与构建 ```bash # 调试构建 cargo build # 发布构建(推荐,全优化) cargo build --release # 运行全部测试套件 cargo test # 代码格式化 cargo fmt # 静态代码检查 cargo clippy -- -D warnings ``` --- ## 项目核心规范 详细的开发约束和技术指标请参阅: - [doc/constraints.md](doc/constraints.md) - [doc/job_object_architecture.md](doc/job_object_architecture.md) 关键准则: 1. **零外部依赖**:仅使用 Rust 标准库和系统原生 Win32 FFI。 2. **纯 ASCII 输出约束**:所有命令行输出(`stdout` 与 `stderr`)必须仅包含 ASCII 字符(0x00-0x7F)。 3. **单二进制**:输出独立可执行文件 `tasker.exe`(约 243KB)。 4. **安全与健壮性**:核心逻辑不随意 `unwrap`/`expect`,Win32 unsafe 调用具备明确注释与前置校验。 --- ## 同类工具对比 | 工具 | 外部依赖 | 体积 | 接口交互 | 进程树清理能力 | 配置方式 | |------|----------|------|----------|----------------|----------| | **tasker** | 0 | ~243KB | 极简 | 内核级 Job Object(零残留) | 环境变量 | | NSSM | 0 | ~500KB | 中等 | Windows 服务宿主 | GUI / CLI | | WinSW | .NET 运行时 | ~500KB | 中等 | 进程树遍历 | XML 配置文件 | | PowerShell | 系统内置 | 无独立二进制 | 复杂 | 需编写脚本循环终止 | 命令行参数 | --- ## 路线图 (Roadmap) | 阶段 | 特性 | 状态 | |------|------|------| | Phase 1 | 后台脱钩运行 + 日志合并重定向 + PID 返回 | 已完成 | | Phase 1.5 | Windows Job Object 进程树生命周期纳管(`kill`/`stop`) | 已完成 | | Phase 2 | 进程状态监控与列表展示(`list`/`status`) | 规划中 | | Phase 2 | 进程持久化与元数据管理 | 规划中 | | Phase 2 | 自动重启策略(崩溃自愈) | 规划中 | | Phase 3 | Windows SCM 系统服务注册 | 规划中 | | Phase 3 | 命名管道(Named Pipe)IPC 通信 | 规划中 | --- ## 许可证 双许可证发布:[MIT](LICENSE-MIT) 或 [Apache 2.0](LICENSE-APACHE)。