mtr-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mtr_cli-0.1.0/.gitignore +19 -0
- mtr_cli-0.1.0/.pre-commit-config.yaml +14 -0
- mtr_cli-0.1.0/.python-version +1 -0
- mtr_cli-0.1.0/AGENTS.md +85 -0
- mtr_cli-0.1.0/LICENSE +21 -0
- mtr_cli-0.1.0/PKG-INFO +291 -0
- mtr_cli-0.1.0/README.md +264 -0
- mtr_cli-0.1.0/examples/config.yaml +68 -0
- mtr_cli-0.1.0/mtr/__init__.py +0 -0
- mtr_cli-0.1.0/mtr/cli.py +358 -0
- mtr_cli-0.1.0/mtr/config.py +87 -0
- mtr_cli-0.1.0/mtr/logger.py +133 -0
- mtr_cli-0.1.0/mtr/ssh.py +199 -0
- mtr_cli-0.1.0/mtr/sync.py +338 -0
- mtr_cli-0.1.0/pyproject.toml +60 -0
- mtr_cli-0.1.0/tests/__init__.py +0 -0
- mtr_cli-0.1.0/tests/conftest.py +0 -0
- mtr_cli-0.1.0/tests/integration/__init__.py +0 -0
- mtr_cli-0.1.0/tests/integration/test_cli_flow.py +82 -0
- mtr_cli-0.1.0/tests/integration/test_cli_phase1.py +75 -0
- mtr_cli-0.1.0/tests/unit/__init__.py +0 -0
- mtr_cli-0.1.0/tests/unit/test_config.py +79 -0
- mtr_cli-0.1.0/tests/unit/test_logger.py +168 -0
- mtr_cli-0.1.0/tests/unit/test_ssh.py +60 -0
- mtr_cli-0.1.0/tests/unit/test_ssh_interactive.py +299 -0
- mtr_cli-0.1.0/tests/unit/test_ssh_pre_cmd.py +43 -0
- mtr_cli-0.1.0/tests/unit/test_sync_rsync.py +142 -0
- mtr_cli-0.1.0/tests/unit/test_sync_sftp.py +178 -0
- mtr_cli-0.1.0/uv.lock +709 -0
mtr_cli-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.9.3
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/pre-commit/mirrors-prettier
|
|
10
|
+
rev: v4.0.0-alpha.8
|
|
11
|
+
hooks:
|
|
12
|
+
- id: prettier
|
|
13
|
+
types: [yaml]
|
|
14
|
+
name: Format YAML
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
mtr_cli-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
MTRemote (mtr) 需求规格与设计文档
|
|
2
|
+
1. 项目概述
|
|
3
|
+
MTRemote 是一个用于 AI Infra 开发的 CLI 工具,旨在简化“本地开发、远端执行”的工作流。它允许开发者在本地修改代码,通过简单的命令前缀 mtr,自动将代码同步到远端服务器并在其上执行命令,同时保持本地的交互体验。
|
|
4
|
+
2. 核心功能需求
|
|
5
|
+
2.1 多服务器配置与管理
|
|
6
|
+
* 多环境支持:支持在配置文件中定义多个服务器节点(如 dev-gpu, prod-train)。
|
|
7
|
+
* 默认服务器策略:
|
|
8
|
+
1. 若 CLI 指定 -s/--server,使用指定服务器。
|
|
9
|
+
2. 若未指定,检查配置中是否存在 default 字段。
|
|
10
|
+
3. 若无 default 字段,自动选择 servers 列表中的第一个定义的服务器。
|
|
11
|
+
* 认证管理:支持在配置文件中显式指定 SSH 私钥路径 (key_filename) 或 密码 (password),不依赖系统 SSH Agent。
|
|
12
|
+
2.2 智能代码同步 (Sync Engine)
|
|
13
|
+
* 双引擎支持:
|
|
14
|
+
* *Rsync (推荐)*:调用系统 rsync 命令,通过 SSH 隧道传输,支持增量同步,速度快。
|
|
15
|
+
* *SFTP (兼容)*:基于 paramiko 实现的纯 Python 同步,用于无 rsync 的环境。
|
|
16
|
+
* 可配置性:支持在全局或单台服务器级别指定同步引擎。
|
|
17
|
+
* 文件过滤:支持忽略特定文件(如 .git, __pycache__),支持 .mtrignore 或配置字段。
|
|
18
|
+
2.3 远程执行 (Remote Execution)
|
|
19
|
+
* 命令透传:mtr python train.py --lr 0.01 -> 远端执行 python train.py --lr 0.01。
|
|
20
|
+
* 环境上下文:支持指定远程工作目录 (remote_dir)。
|
|
21
|
+
* 实时流式输出:远端的 stdout 和 stderr 必须实时回显到本地,支持颜色代码。
|
|
22
|
+
* 交互性:支持 PTY 分配,允许运行交互式命令(如 ipython, pdb)。
|
|
23
|
+
---
|
|
24
|
+
3. 系统设计与模块划分
|
|
25
|
+
我们将系统划分为四个核心模块,这也将是 TDD 的测试边界:
|
|
26
|
+
3.1 配置模块 (mtr.config)
|
|
27
|
+
负责加载、合并和校验配置。
|
|
28
|
+
* 输入:CLI 参数、./.mtr/config.yaml、~/.config/mtr/config.yaml。
|
|
29
|
+
* 逻辑:
|
|
30
|
+
* 配置层级合并(Project Config 覆盖 User Config)。
|
|
31
|
+
* 解析服务器列表,确定 Target Host。
|
|
32
|
+
* *数据结构 (Config Schema)*:
|
|
33
|
+
defaults:
|
|
34
|
+
sync: "rsync" # or "sftp"
|
|
35
|
+
exclude: [".git", "__pycache__"]
|
|
36
|
+
servers:
|
|
37
|
+
gpu-01: # 第一个即为隐式默认
|
|
38
|
+
host: "192.168.1.10"
|
|
39
|
+
user: "dev"
|
|
40
|
+
key_filename: "~/.ssh/id_rsa"
|
|
41
|
+
remote_dir: "/data/codes/project_x"
|
|
42
|
+
|
|
43
|
+
fallback-node:
|
|
44
|
+
host: "10.0.0.5"
|
|
45
|
+
user: "dev"
|
|
46
|
+
password: "secret_password"
|
|
47
|
+
sync: "sftp" # 覆盖默认配置
|
|
48
|
+
|
|
49
|
+
3.2 连接模块 (mtr.ssh)
|
|
50
|
+
负责底层的 SSH 连接管理。
|
|
51
|
+
* 基于 paramiko 封装。
|
|
52
|
+
* 提供 connect(), exec_command_stream() 接口。
|
|
53
|
+
* 处理连接异常和认证失败。
|
|
54
|
+
3.3 同步模块 (mtr.sync)
|
|
55
|
+
定义 BaseSyncer 抽象基类,统一接口 sync(local_dir, remote_dir, exclude_list)。
|
|
56
|
+
* RsyncSyncer: 构造 subprocess 调用系统命令。
|
|
57
|
+
* SftpSyncer: 遍历文件树,对比 mtime/size,使用 paramiko sftp 上传。
|
|
58
|
+
3.4 CLI 入口 (mtr.cli)
|
|
59
|
+
* 基于 click 库。
|
|
60
|
+
* 负责参数解析、调用 Config -> Connect -> Sync -> Exec 流程。
|
|
61
|
+
---
|
|
62
|
+
4. TDD 测试策略与目录规划
|
|
63
|
+
在编写任何业务代码前,我们将按照以下结构建立测试目录。
|
|
64
|
+
4.1 测试目录结构
|
|
65
|
+
tests/
|
|
66
|
+
├── __init__.py
|
|
67
|
+
├── conftest.py # 通用 Fixtures (模拟配置文件、模拟文件系统)
|
|
68
|
+
├── unit/ # 单元测试 (Mock 外部依赖)
|
|
69
|
+
│ ├── test_config.py # 重点:测试配置加载优先级、默认服务器选择逻辑
|
|
70
|
+
│ ├── test_sync_rsync.py # 测试 Rsync 命令生成逻辑 (不实际传输)
|
|
71
|
+
│ ├── test_sync_sftp.py # 测试文件过滤逻辑、差异对比逻辑 (Mock SFTP)
|
|
72
|
+
│ └── test_ssh.py # 测试 SSH 客户端封装 (Mock paramiko)
|
|
73
|
+
└── integration/ # 集成/功能测试
|
|
74
|
+
└── test_cli_flow.py # 测试 CLI 参数解析与流程串联
|
|
75
|
+
4.2 关键测试用例 (Test Cases)
|
|
76
|
+
1. 配置加载测试 (test_config.py)
|
|
77
|
+
* test_load_default_server_explicit: 当配置中有 default 字段时,应选中该 Server。
|
|
78
|
+
* test_load_default_server_implicit_first: 当无 default 字段时,应选中 servers 列表的第一个。
|
|
79
|
+
* test_server_override: CLI -s 参数应覆盖配置文件的默认值。
|
|
80
|
+
* test_auth_config: 验证 Key 和 Password 都能被正确读取。
|
|
81
|
+
2. 同步逻辑测试 (test_sync_*.py)
|
|
82
|
+
* test_rsync_command_generation: 验证生成的 rsync 命令是否包含正确的 exclude 参数和路径。
|
|
83
|
+
* test_sftp_should_sync: 给定本地和远端文件状态(大小/时间),验证 should_sync 逻辑是否正确判断需要更新的文件。
|
|
84
|
+
3. SSH 执行测试 (test_ssh.py)
|
|
85
|
+
* test_exec_stream: Mock paramiko 的 stdout,验证回调函数能否正确接收流式数据。
|
mtr_cli-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Yang Xiang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mtr_cli-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mtr-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A CLI tool for seamless local development and remote execution on GPU servers.
|
|
5
|
+
Project-URL: Homepage, https://github.com/lecoan/mtremote
|
|
6
|
+
Project-URL: Repository, https://github.com/lecoan/mtremote
|
|
7
|
+
Author: lecoan
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
20
|
+
Classifier: Topic :: System :: Systems Administration
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: click>=8.0.0
|
|
23
|
+
Requires-Dist: paramiko>=2.11.0
|
|
24
|
+
Requires-Dist: pyyaml>=6.0
|
|
25
|
+
Requires-Dist: rich>=12.0.0
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# MTRemote (mtr)
|
|
29
|
+
|
|
30
|
+
MTRemote 是一个专为 AI Infra 和 Python/C++ 混合开发设计的命令行工具。它允许你在本地修改代码,通过简单的 `mtr` 前缀,自动将代码同步到远端 GPU 服务器并执行命令,同时保留本地的交互体验(实时日志、颜色高亮、Ctrl+C 支持)。
|
|
31
|
+
|
|
32
|
+
## 🚀 核心特性
|
|
33
|
+
|
|
34
|
+
* **多服务器管理**:通过配置文件管理多个 GPU 节点,支持默认服务器 (Implicit/Explicit)。
|
|
35
|
+
* **智能同步引擎**:
|
|
36
|
+
* **Rsync (推荐)**:调用系统 `rsync`,支持增量同步,速度极快。支持 `sshpass` 自动处理密码认证。
|
|
37
|
+
* **SFTP (兼容)**:纯 Python 实现,适用于无 `rsync` 的环境,配置简单。
|
|
38
|
+
* **双向同步**:支持从远端下载文件/文件夹到本地(`--get` 参数)。
|
|
39
|
+
* **双模式交互 (Dual-Mode Interaction)**:
|
|
40
|
+
* **交互模式 (Interactive)**:自动检测 TTY,支持 PTY 分配、Raw Mode、Rich UI 动画。完美支持 `vim`, `ipython`, `pdb`, `htop`。
|
|
41
|
+
* **批处理模式 (Batch)**:当被脚本调用或重定向时自动切换。禁用 PTY 和动画,输出纯净文本,适合 AI Agent 集成或 CI/CD。
|
|
42
|
+
* **环境预设 (Pre-cmd)**:支持在执行命令前自动加载环境(如 `conda activate`, `source .env`)。
|
|
43
|
+
* **调试日志**:可选的文件日志系统,按会话独立存储,便于排查问题。
|
|
44
|
+
* **零侵入**:只需在现有命令前加上 `mtr`。
|
|
45
|
+
|
|
46
|
+
## 📦 安装
|
|
47
|
+
|
|
48
|
+
推荐使用 `uv` 或 `pipx` 安装:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv tool install mtremote
|
|
52
|
+
# 或者
|
|
53
|
+
pip install mtremote
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 系统依赖
|
|
57
|
+
|
|
58
|
+
MTRemote 需要以下系统命令:
|
|
59
|
+
|
|
60
|
+
| 命令 | 用途 | 安装方式 |
|
|
61
|
+
|------|------|----------|
|
|
62
|
+
| `ssh` | 交互式 Shell (TTY) | macOS/Linux 自带,或 `brew install openssh` |
|
|
63
|
+
| `rsync` | 快速文件同步 (推荐) | macOS/Linux 自带 |
|
|
64
|
+
| `sshpass` | 密码认证 (可选) | `brew install hudochenkov/sshpass/sshpass` (macOS) / `apt install sshpass` (Ubuntu) |
|
|
65
|
+
|
|
66
|
+
**注意**:交互式 Shell 功能(如 `mtr bash`, `mtr ipython`)**必须**安装 `ssh`。密码认证**必须**安装 `sshpass`。
|
|
67
|
+
|
|
68
|
+
## 🛠️ 快速开始
|
|
69
|
+
|
|
70
|
+
### 1. 初始化配置
|
|
71
|
+
|
|
72
|
+
在你的项目根目录下运行:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
mtr --init
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
这将在 `.mtr/config.yaml` 生成配置文件。
|
|
79
|
+
|
|
80
|
+
### 2. 编辑配置
|
|
81
|
+
|
|
82
|
+
编辑 `.mtr/config.yaml`,填入你的服务器信息:
|
|
83
|
+
|
|
84
|
+
```yaml
|
|
85
|
+
defaults:
|
|
86
|
+
sync: "rsync" # 或 "sftp"
|
|
87
|
+
exclude: [".git/", "__pycache__/"]
|
|
88
|
+
download_dir: "./downloads" # 默认下载位置(可选)
|
|
89
|
+
|
|
90
|
+
servers:
|
|
91
|
+
gpu-node:
|
|
92
|
+
host: "192.168.1.100"
|
|
93
|
+
user: "your_username"
|
|
94
|
+
key_filename: "~/.ssh/id_rsa"
|
|
95
|
+
remote_dir: "/home/your_username/projects/my-project"
|
|
96
|
+
download_dir: "./backups/gpu" # 该服务器的下载位置(可选,覆盖默认值)
|
|
97
|
+
pre_cmd: "source ~/.bashrc && conda activate pytorch_env"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 3. 运行命令
|
|
101
|
+
|
|
102
|
+
现在,你可以在本地直接运行远程命令:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# 同步代码并在 gpu-node 上运行 python train.py
|
|
106
|
+
mtr python train.py --epochs 10
|
|
107
|
+
|
|
108
|
+
# 进入远程交互式 Shell (支持 Tab 补全和颜色)
|
|
109
|
+
mtr bash
|
|
110
|
+
|
|
111
|
+
# 使用 ipython 调试
|
|
112
|
+
mtr ipython
|
|
113
|
+
|
|
114
|
+
# 指定特定服务器
|
|
115
|
+
mtr -s prod-node python train.py
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 📖 命令行选项
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
mtr [OPTIONS] COMMAND [ARGS...]
|
|
122
|
+
|
|
123
|
+
Options:
|
|
124
|
+
-s, --server TEXT Target server alias
|
|
125
|
+
--sync / --no-sync Enable/Disable code sync [default: True]
|
|
126
|
+
--dry-run Print commands without executing
|
|
127
|
+
--tty / --no-tty Force enable/disable TTY [default: True]
|
|
128
|
+
--get TEXT Remote path to download from
|
|
129
|
+
--to TEXT Local destination path for download (optional)
|
|
130
|
+
--enable-log Enable logging to file
|
|
131
|
+
--log-level TEXT Log level: DEBUG/INFO/WARNING/ERROR [default: INFO]
|
|
132
|
+
--log-file PATH Custom log file path (default: ~/.mtr/logs/mtr_YYYYMMDD_HHMMSS.log)
|
|
133
|
+
--init Initialize configuration file
|
|
134
|
+
--help Show this message and exit
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 常用选项示例
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# 禁用同步,直接执行命令
|
|
141
|
+
mtr --no-sync python script.py
|
|
142
|
+
|
|
143
|
+
# 强制批处理模式(无颜色、无动画)
|
|
144
|
+
mtr --no-tty python train.py > output.log
|
|
145
|
+
|
|
146
|
+
# 启用调试日志
|
|
147
|
+
mtr --enable-log --log-level DEBUG python train.py
|
|
148
|
+
|
|
149
|
+
# 指定自定义日志路径
|
|
150
|
+
mtr --enable-log --log-file ./debug.log python train.py
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 📖 高级用法
|
|
154
|
+
|
|
155
|
+
### 1. 强制批处理模式 (--no-tty)
|
|
156
|
+
如果你在终端中运行但希望获得纯文本输出(不想要进度条或颜色控制字符),可以使用 `--no-tty`:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
mtr --no-tty python train.py > log.txt
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 2. 使用 SFTP 模式
|
|
163
|
+
如果本地或远程无法使用 rsync,可以在配置中指定 `sync: sftp`:
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
servers:
|
|
167
|
+
win-server:
|
|
168
|
+
host: "10.0.0.9"
|
|
169
|
+
sync: "sftp"
|
|
170
|
+
password: "secret_password"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 3. 密码认证
|
|
174
|
+
支持 SSH 密码认证,但推荐使用 SSH Key。
|
|
175
|
+
* **交互式 Shell**: 使用 `sshpass` 包装 `ssh -t` 命令。
|
|
176
|
+
* **SFTP**: 原生支持密码。
|
|
177
|
+
* **Rsync**: 需要本地安装 `sshpass` 工具才能使用密码认证。
|
|
178
|
+
|
|
179
|
+
**密码认证依赖**: 使用密码认证时,必须安装 `sshpass`:
|
|
180
|
+
```bash
|
|
181
|
+
# macOS
|
|
182
|
+
brew install hudochenkov/sshpass/sshpass
|
|
183
|
+
|
|
184
|
+
# Ubuntu/Debian
|
|
185
|
+
sudo apt-get install sshpass
|
|
186
|
+
|
|
187
|
+
# CentOS/RHEL
|
|
188
|
+
sudo yum install sshpass
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 4. 从远端下载文件 (--get)
|
|
192
|
+
使用 `--get` 参数可以从远端服务器下载文件或文件夹到本地:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# 下载文件到当前目录
|
|
196
|
+
mtr --get /remote/path/to/file.txt
|
|
197
|
+
|
|
198
|
+
# 下载文件到指定位置
|
|
199
|
+
mtr --get /remote/path/to/file.txt --to ./local/path/
|
|
200
|
+
|
|
201
|
+
# 下载整个文件夹
|
|
202
|
+
mtr --get /remote/path/to/checkpoints/ --to ./backups/
|
|
203
|
+
|
|
204
|
+
# 跳过上传同步,仅下载
|
|
205
|
+
mtr --no-sync --get /remote/path/to/file.txt
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**配置下载目录**:
|
|
209
|
+
可以在配置文件中设置默认下载位置:
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
defaults:
|
|
213
|
+
download_dir: "./downloads" # 默认下载位置
|
|
214
|
+
|
|
215
|
+
servers:
|
|
216
|
+
gpu-node:
|
|
217
|
+
host: "192.168.1.100"
|
|
218
|
+
download_dir: "./backups/gpu" # 该服务器的下载位置(覆盖默认值)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**路径解析优先级**:
|
|
222
|
+
1. `--to` 参数指定的路径
|
|
223
|
+
2. 服务器配置中的 `download_dir`
|
|
224
|
+
3. 默认配置中的 `download_dir`
|
|
225
|
+
4. 当前工作目录
|
|
226
|
+
|
|
227
|
+
### 5. 调试日志 (--enable-log)
|
|
228
|
+
当遇到问题需要排查时,可以启用文件日志:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# 启用 INFO 级别日志(默认)
|
|
232
|
+
mtr --enable-log python train.py
|
|
233
|
+
|
|
234
|
+
# 启用 DEBUG 级别日志(更详细)
|
|
235
|
+
mtr --enable-log --log-level DEBUG python train.py
|
|
236
|
+
|
|
237
|
+
# 查看日志
|
|
238
|
+
cat ~/.mtr/logs/mtr_20260128_171216.log
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
日志文件按会话独立生成,格式为 `mtr_YYYYMMDD_HHMMSS.log`,包含:
|
|
242
|
+
- 命令启动参数
|
|
243
|
+
- 配置加载过程
|
|
244
|
+
- SSH 连接状态
|
|
245
|
+
- 文件同步详情
|
|
246
|
+
- 命令执行结果
|
|
247
|
+
|
|
248
|
+
## 🤖 AI Agent 集成指南
|
|
249
|
+
|
|
250
|
+
MTRemote 非常适合作为 AI Agent (如 OpenCode, LangChain Agents) 的底层执行工具。
|
|
251
|
+
|
|
252
|
+
### 为什么适合 Agent?
|
|
253
|
+
1. **自动同步**:Agent 只需要修改本地文件,`mtr` 负责将修改“热更新”到运行环境。
|
|
254
|
+
2. **纯净输出**:使用 `--no-tty` 参数,`mtr` 会禁用 ANSI 颜色代码、进度条动画和交互式 Shell 提示符,只返回最纯粹的 stdout/stderr。这大大降低了 Agent 解析日志的难度。
|
|
255
|
+
3. **状态透传**:`mtr` 的退出代码 (Exit Code) 与远程命令完全一致。Agent 可以通过 `$?` 判断远程任务是否成功。
|
|
256
|
+
|
|
257
|
+
### 推荐调用方式
|
|
258
|
+
|
|
259
|
+
Agent 在调用 `mtr` 时,**强烈建议**始终加上 `--no-tty` 参数。
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
import subprocess
|
|
263
|
+
|
|
264
|
+
def run_remote_command(cmd):
|
|
265
|
+
# 使用 --no-tty 确保输出无干扰
|
|
266
|
+
full_cmd = ["mtr", "--no-tty"] + cmd.split()
|
|
267
|
+
|
|
268
|
+
result = subprocess.run(
|
|
269
|
+
full_cmd,
|
|
270
|
+
capture_output=True,
|
|
271
|
+
text=True
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
if result.returncode != 0:
|
|
275
|
+
return f"Error: {result.stderr}"
|
|
276
|
+
return result.stdout
|
|
277
|
+
|
|
278
|
+
# 示例:Agent 修改完代码后运行测试
|
|
279
|
+
output = run_remote_command("python tests/test_model.py")
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## 📖 配置详解
|
|
283
|
+
|
|
284
|
+
请参考 [examples/config.yaml](examples/config.yaml) 获取完整的配置示例。
|
|
285
|
+
|
|
286
|
+
## 🤝 贡献
|
|
287
|
+
|
|
288
|
+
欢迎提交 Issue 和 PR!
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
License: MIT
|
mtr_cli-0.1.0/README.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# MTRemote (mtr)
|
|
2
|
+
|
|
3
|
+
MTRemote 是一个专为 AI Infra 和 Python/C++ 混合开发设计的命令行工具。它允许你在本地修改代码,通过简单的 `mtr` 前缀,自动将代码同步到远端 GPU 服务器并执行命令,同时保留本地的交互体验(实时日志、颜色高亮、Ctrl+C 支持)。
|
|
4
|
+
|
|
5
|
+
## 🚀 核心特性
|
|
6
|
+
|
|
7
|
+
* **多服务器管理**:通过配置文件管理多个 GPU 节点,支持默认服务器 (Implicit/Explicit)。
|
|
8
|
+
* **智能同步引擎**:
|
|
9
|
+
* **Rsync (推荐)**:调用系统 `rsync`,支持增量同步,速度极快。支持 `sshpass` 自动处理密码认证。
|
|
10
|
+
* **SFTP (兼容)**:纯 Python 实现,适用于无 `rsync` 的环境,配置简单。
|
|
11
|
+
* **双向同步**:支持从远端下载文件/文件夹到本地(`--get` 参数)。
|
|
12
|
+
* **双模式交互 (Dual-Mode Interaction)**:
|
|
13
|
+
* **交互模式 (Interactive)**:自动检测 TTY,支持 PTY 分配、Raw Mode、Rich UI 动画。完美支持 `vim`, `ipython`, `pdb`, `htop`。
|
|
14
|
+
* **批处理模式 (Batch)**:当被脚本调用或重定向时自动切换。禁用 PTY 和动画,输出纯净文本,适合 AI Agent 集成或 CI/CD。
|
|
15
|
+
* **环境预设 (Pre-cmd)**:支持在执行命令前自动加载环境(如 `conda activate`, `source .env`)。
|
|
16
|
+
* **调试日志**:可选的文件日志系统,按会话独立存储,便于排查问题。
|
|
17
|
+
* **零侵入**:只需在现有命令前加上 `mtr`。
|
|
18
|
+
|
|
19
|
+
## 📦 安装
|
|
20
|
+
|
|
21
|
+
推荐使用 `uv` 或 `pipx` 安装:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
uv tool install mtremote
|
|
25
|
+
# 或者
|
|
26
|
+
pip install mtremote
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 系统依赖
|
|
30
|
+
|
|
31
|
+
MTRemote 需要以下系统命令:
|
|
32
|
+
|
|
33
|
+
| 命令 | 用途 | 安装方式 |
|
|
34
|
+
|------|------|----------|
|
|
35
|
+
| `ssh` | 交互式 Shell (TTY) | macOS/Linux 自带,或 `brew install openssh` |
|
|
36
|
+
| `rsync` | 快速文件同步 (推荐) | macOS/Linux 自带 |
|
|
37
|
+
| `sshpass` | 密码认证 (可选) | `brew install hudochenkov/sshpass/sshpass` (macOS) / `apt install sshpass` (Ubuntu) |
|
|
38
|
+
|
|
39
|
+
**注意**:交互式 Shell 功能(如 `mtr bash`, `mtr ipython`)**必须**安装 `ssh`。密码认证**必须**安装 `sshpass`。
|
|
40
|
+
|
|
41
|
+
## 🛠️ 快速开始
|
|
42
|
+
|
|
43
|
+
### 1. 初始化配置
|
|
44
|
+
|
|
45
|
+
在你的项目根目录下运行:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
mtr --init
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
这将在 `.mtr/config.yaml` 生成配置文件。
|
|
52
|
+
|
|
53
|
+
### 2. 编辑配置
|
|
54
|
+
|
|
55
|
+
编辑 `.mtr/config.yaml`,填入你的服务器信息:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
defaults:
|
|
59
|
+
sync: "rsync" # 或 "sftp"
|
|
60
|
+
exclude: [".git/", "__pycache__/"]
|
|
61
|
+
download_dir: "./downloads" # 默认下载位置(可选)
|
|
62
|
+
|
|
63
|
+
servers:
|
|
64
|
+
gpu-node:
|
|
65
|
+
host: "192.168.1.100"
|
|
66
|
+
user: "your_username"
|
|
67
|
+
key_filename: "~/.ssh/id_rsa"
|
|
68
|
+
remote_dir: "/home/your_username/projects/my-project"
|
|
69
|
+
download_dir: "./backups/gpu" # 该服务器的下载位置(可选,覆盖默认值)
|
|
70
|
+
pre_cmd: "source ~/.bashrc && conda activate pytorch_env"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 3. 运行命令
|
|
74
|
+
|
|
75
|
+
现在,你可以在本地直接运行远程命令:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 同步代码并在 gpu-node 上运行 python train.py
|
|
79
|
+
mtr python train.py --epochs 10
|
|
80
|
+
|
|
81
|
+
# 进入远程交互式 Shell (支持 Tab 补全和颜色)
|
|
82
|
+
mtr bash
|
|
83
|
+
|
|
84
|
+
# 使用 ipython 调试
|
|
85
|
+
mtr ipython
|
|
86
|
+
|
|
87
|
+
# 指定特定服务器
|
|
88
|
+
mtr -s prod-node python train.py
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 📖 命令行选项
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
mtr [OPTIONS] COMMAND [ARGS...]
|
|
95
|
+
|
|
96
|
+
Options:
|
|
97
|
+
-s, --server TEXT Target server alias
|
|
98
|
+
--sync / --no-sync Enable/Disable code sync [default: True]
|
|
99
|
+
--dry-run Print commands without executing
|
|
100
|
+
--tty / --no-tty Force enable/disable TTY [default: True]
|
|
101
|
+
--get TEXT Remote path to download from
|
|
102
|
+
--to TEXT Local destination path for download (optional)
|
|
103
|
+
--enable-log Enable logging to file
|
|
104
|
+
--log-level TEXT Log level: DEBUG/INFO/WARNING/ERROR [default: INFO]
|
|
105
|
+
--log-file PATH Custom log file path (default: ~/.mtr/logs/mtr_YYYYMMDD_HHMMSS.log)
|
|
106
|
+
--init Initialize configuration file
|
|
107
|
+
--help Show this message and exit
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 常用选项示例
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# 禁用同步,直接执行命令
|
|
114
|
+
mtr --no-sync python script.py
|
|
115
|
+
|
|
116
|
+
# 强制批处理模式(无颜色、无动画)
|
|
117
|
+
mtr --no-tty python train.py > output.log
|
|
118
|
+
|
|
119
|
+
# 启用调试日志
|
|
120
|
+
mtr --enable-log --log-level DEBUG python train.py
|
|
121
|
+
|
|
122
|
+
# 指定自定义日志路径
|
|
123
|
+
mtr --enable-log --log-file ./debug.log python train.py
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 📖 高级用法
|
|
127
|
+
|
|
128
|
+
### 1. 强制批处理模式 (--no-tty)
|
|
129
|
+
如果你在终端中运行但希望获得纯文本输出(不想要进度条或颜色控制字符),可以使用 `--no-tty`:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
mtr --no-tty python train.py > log.txt
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 2. 使用 SFTP 模式
|
|
136
|
+
如果本地或远程无法使用 rsync,可以在配置中指定 `sync: sftp`:
|
|
137
|
+
|
|
138
|
+
```yaml
|
|
139
|
+
servers:
|
|
140
|
+
win-server:
|
|
141
|
+
host: "10.0.0.9"
|
|
142
|
+
sync: "sftp"
|
|
143
|
+
password: "secret_password"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 3. 密码认证
|
|
147
|
+
支持 SSH 密码认证,但推荐使用 SSH Key。
|
|
148
|
+
* **交互式 Shell**: 使用 `sshpass` 包装 `ssh -t` 命令。
|
|
149
|
+
* **SFTP**: 原生支持密码。
|
|
150
|
+
* **Rsync**: 需要本地安装 `sshpass` 工具才能使用密码认证。
|
|
151
|
+
|
|
152
|
+
**密码认证依赖**: 使用密码认证时,必须安装 `sshpass`:
|
|
153
|
+
```bash
|
|
154
|
+
# macOS
|
|
155
|
+
brew install hudochenkov/sshpass/sshpass
|
|
156
|
+
|
|
157
|
+
# Ubuntu/Debian
|
|
158
|
+
sudo apt-get install sshpass
|
|
159
|
+
|
|
160
|
+
# CentOS/RHEL
|
|
161
|
+
sudo yum install sshpass
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 4. 从远端下载文件 (--get)
|
|
165
|
+
使用 `--get` 参数可以从远端服务器下载文件或文件夹到本地:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# 下载文件到当前目录
|
|
169
|
+
mtr --get /remote/path/to/file.txt
|
|
170
|
+
|
|
171
|
+
# 下载文件到指定位置
|
|
172
|
+
mtr --get /remote/path/to/file.txt --to ./local/path/
|
|
173
|
+
|
|
174
|
+
# 下载整个文件夹
|
|
175
|
+
mtr --get /remote/path/to/checkpoints/ --to ./backups/
|
|
176
|
+
|
|
177
|
+
# 跳过上传同步,仅下载
|
|
178
|
+
mtr --no-sync --get /remote/path/to/file.txt
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**配置下载目录**:
|
|
182
|
+
可以在配置文件中设置默认下载位置:
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
defaults:
|
|
186
|
+
download_dir: "./downloads" # 默认下载位置
|
|
187
|
+
|
|
188
|
+
servers:
|
|
189
|
+
gpu-node:
|
|
190
|
+
host: "192.168.1.100"
|
|
191
|
+
download_dir: "./backups/gpu" # 该服务器的下载位置(覆盖默认值)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**路径解析优先级**:
|
|
195
|
+
1. `--to` 参数指定的路径
|
|
196
|
+
2. 服务器配置中的 `download_dir`
|
|
197
|
+
3. 默认配置中的 `download_dir`
|
|
198
|
+
4. 当前工作目录
|
|
199
|
+
|
|
200
|
+
### 5. 调试日志 (--enable-log)
|
|
201
|
+
当遇到问题需要排查时,可以启用文件日志:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# 启用 INFO 级别日志(默认)
|
|
205
|
+
mtr --enable-log python train.py
|
|
206
|
+
|
|
207
|
+
# 启用 DEBUG 级别日志(更详细)
|
|
208
|
+
mtr --enable-log --log-level DEBUG python train.py
|
|
209
|
+
|
|
210
|
+
# 查看日志
|
|
211
|
+
cat ~/.mtr/logs/mtr_20260128_171216.log
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
日志文件按会话独立生成,格式为 `mtr_YYYYMMDD_HHMMSS.log`,包含:
|
|
215
|
+
- 命令启动参数
|
|
216
|
+
- 配置加载过程
|
|
217
|
+
- SSH 连接状态
|
|
218
|
+
- 文件同步详情
|
|
219
|
+
- 命令执行结果
|
|
220
|
+
|
|
221
|
+
## 🤖 AI Agent 集成指南
|
|
222
|
+
|
|
223
|
+
MTRemote 非常适合作为 AI Agent (如 OpenCode, LangChain Agents) 的底层执行工具。
|
|
224
|
+
|
|
225
|
+
### 为什么适合 Agent?
|
|
226
|
+
1. **自动同步**:Agent 只需要修改本地文件,`mtr` 负责将修改“热更新”到运行环境。
|
|
227
|
+
2. **纯净输出**:使用 `--no-tty` 参数,`mtr` 会禁用 ANSI 颜色代码、进度条动画和交互式 Shell 提示符,只返回最纯粹的 stdout/stderr。这大大降低了 Agent 解析日志的难度。
|
|
228
|
+
3. **状态透传**:`mtr` 的退出代码 (Exit Code) 与远程命令完全一致。Agent 可以通过 `$?` 判断远程任务是否成功。
|
|
229
|
+
|
|
230
|
+
### 推荐调用方式
|
|
231
|
+
|
|
232
|
+
Agent 在调用 `mtr` 时,**强烈建议**始终加上 `--no-tty` 参数。
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
import subprocess
|
|
236
|
+
|
|
237
|
+
def run_remote_command(cmd):
|
|
238
|
+
# 使用 --no-tty 确保输出无干扰
|
|
239
|
+
full_cmd = ["mtr", "--no-tty"] + cmd.split()
|
|
240
|
+
|
|
241
|
+
result = subprocess.run(
|
|
242
|
+
full_cmd,
|
|
243
|
+
capture_output=True,
|
|
244
|
+
text=True
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
if result.returncode != 0:
|
|
248
|
+
return f"Error: {result.stderr}"
|
|
249
|
+
return result.stdout
|
|
250
|
+
|
|
251
|
+
# 示例:Agent 修改完代码后运行测试
|
|
252
|
+
output = run_remote_command("python tests/test_model.py")
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## 📖 配置详解
|
|
256
|
+
|
|
257
|
+
请参考 [examples/config.yaml](examples/config.yaml) 获取完整的配置示例。
|
|
258
|
+
|
|
259
|
+
## 🤝 贡献
|
|
260
|
+
|
|
261
|
+
欢迎提交 Issue 和 PR!
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
License: MIT
|