# bakserver
**Repository Path**: zinface/bakserver
## Basic Information
- **Project Name**: bakserver
- **Description**: 轻量 HTTP 服务,每次请求时将指定目录实时打包为 tar 流返回。
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-20
- **Last Updated**: 2026-07-21
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# bakserver
轻量 HTTP 服务,每次请求时将指定目录实时打包为 tar 流返回。
## 构建
```bash
go build -o bakserver
```
## 使用
```bash
./bakserver -port 8080 -dir /path/to/dir
```
拉取归档:
```bash
curl -o backup.tar http://localhost:8080/
```
## 程序设计
### 整体架构
```
HTTP 请求
│
▼
启动 tar cf -
进程
│
▼
tar stdout ──pipe──→ HTTP ResponseWriter
│
▼
等待 拷贝完成 或 客户端断开
```
### 逻辑考虑
#### 1. 流式传输 vs 全量缓存
tar 输出通过 `StdoutPipe` 直连 `ResponseWriter`,用 `io.Copy` 在内核缓冲区层面流式转发,避免将整个归档写入内存再一次性 flush。对大目录场景内存开销恒定。
#### 2. 客户端断开时的进程清理
HTTP 请求的 `context` 在客户端断开连接时自动取消。通过 `select` 同时监听两个信号:
- `r.Context().Done()` — 客户端断开,立即 `cmd.Process.Kill()` 杀掉 tar 进程
- `copyDone` — `io.Copy` 正常结束
避免了客户端断开后 tar 进程继续在后台空跑。
#### 3. 进程生命周期管理
```
cmd.Start() → 拷贝 goroutine 启动 → 等待 select → cmd.Wait()
```
`cmd.Wait()` 确保子进程的僵尸回收(reap),防止进程泄漏。
#### 4. 错误处理
- 管道创建或进程启动失败 → 直接返回 500,不启动无用拷贝
- `io.Copy` 写入失败(如客户端断连)→ 仅日志记录,不阻塞请求结束
- tar 非零退出 → 日志记录,不影响 HTTP 响应(可能已输出部分数据)
#### 5. 竞态安全
`cmd.Process.Kill()` 与 `io.Copy` 之间的竞态由 `select` 保证只会进入一个分支;若拷贝在 Kill 前瞬间完成,`Kill` 调用会返回错误(进程已退出),此错误被忽略,行为正确。