# 图片迁移脚本 (Image Migration Script)

从本地目录或SSH服务器迁移图片到远程SSH服务器，保持相对路径结构一致。

## 功能特性

- ✅ **灵活的源支持**：支持本地目录(`local`)和SSH服务器(`ssh`)作为源
- ✅ **远程目标**：通过SSH迁移到远程服务器
- ✅ **路径保持**：在目标服务器上保持相同的相对路径和文件名
- ✅ **配置灵活**：支持配置文件和命令行参数
- ✅ **目录自动创建**：递归创建目标目录结构
- ✅ **重复文件处理**：默认跳过已存在文件，支持覆盖选项
- ✅ **进度统计**：显示详细的传输进度和统计信息
- ✅ **错误处理**：完善的连接管理和错误处理

## 环境要求

- Python 3.6+
- paramiko 库（用于SSH连接）

## 快速开始

### 1. 安装依赖

```bash
cd /var/www/html/orico-official-website/scripts
pip install -r requirements.txt
```

### 2. 创建配置文件

```bash
# 创建示例配置文件
python image_migrate.py --create-config config.json

# 编辑配置文件，填写真实的服务器信息
vim config.json
```

### 3. 准备图片路径列表

创建一个文本文件（如 `images.txt`），每行一个相对路径：

```
uploads/products/2024/01/product1.jpg
uploads/products/2024/01/product2.jpg
assets/images/logo.png
```

### 4. 执行迁移

#### 从本地目录迁移到远程服务器（最常用）

```bash
# 使用配置文件迁移（源为本地目录）
python image_migrate.py --config config.json --input images.txt

# 或直接指定参数迁移（源为本地目录）
python image_migrate.py \
  --source-type local --source-dir /path/to/local/images \
  --target-host dst.example.com --target-user user2 --target-dir /home/user/images \
  --input images.txt --verbose
```

#### 从SSH服务器迁移到另一个SSH服务器

```bash
# 使用配置文件迁移（源为SSH服务器）
python image_migrate.py --config config.json --input images.txt

# 或直接指定参数迁移（源为SSH服务器）
python image_migrate.py \
  --source-type ssh --source-host src.example.com --source-user user1 --source-dir /var/www/images \
  --target-host dst.example.com --target-user user2 --target-dir /home/user/images \
  --input images.txt --verbose
```

## 配置文件格式

配置文件为JSON格式，支持两种源类型配置：

### 本地目录作为源（推荐）

```json
{
    "source": {
        "type": "local",
        "base_dir": "/path/to/local/images"
    },
    "target": {
        "type": "ssh",
        "base_dir": "/var/www/html/images",
        "ssh": {
            "host": "target-server.example.com",
            "port": 22,
            "username": "username",
            "password": "your_password_here",
            "key_file": "/path/to/private/key"
        }
    }
}
```

### SSH服务器作为源

```json
{
    "source": {
        "type": "ssh",
        "base_dir": "/var/www/html/images",
        "ssh": {
            "host": "source-server.example.com",
            "port": 22,
            "username": "username",
            "password": "your_password_here",
            "key_file": "/path/to/private/key"
        }
    },
    "target": {
        "type": "ssh",
        "base_dir": "/var/www/html/images",
        "ssh": {
            "host": "target-server.example.com",
            "port": 22,
            "username": "username",
            "password": "your_password_here",
            "key_file": "/path/to/private/key"
        }
    }
}
```

**注意：**

- `type`：可以是 `"local"`（本地目录）或 `"ssh"`（SSH服务器）
- `base_dir`：图片的基础目录，图片的相对路径将相对于这个目录
- 对于SSH类型，需要提供`ssh`配置部分
- `password` 和 `key_file` 二选一即可
- 目标服务器**必须**是SSH类型

## 命令行参数

### 主要选项

| 参数                   | 说明                   |
| ---------------------- | ---------------------- |
| `--config FILE`        | 使用配置文件           |
| `--create-config FILE` | 创建示例配置文件       |
| `--input FILE`         | 包含图片路径列表的文件 |
| `--verbose`, `-v`      | 显示详细输出           |
| `--overwrite`          | 覆盖已存在的文件       |

### 源服务器参数（可覆盖配置文件）

| 参数                     | 说明                                                         |
| ------------------------ | ------------------------------------------------------------ |
| `--source-type TYPE`     | 源类型: `local`(本地目录) 或 `ssh`(SSH服务器)，默认: `local` |
| `--source-dir DIR`       | **必需** 源服务器图片基础目录                                |
| `--source-host HOST`     | 源服务器地址（仅SSH类型需要）                                |
| `--source-port PORT`     | 源服务器端口（仅SSH类型，默认: 22）                          |
| `--source-user USER`     | 源服务器用户名（仅SSH类型需要）                              |
| `--source-password PASS` | 源服务器密码（仅SSH类型需要）                                |
| `--source-key FILE`      | 源服务器私钥文件路径（仅SSH类型需要）                        |

### 目标服务器参数（可覆盖配置文件）

| 参数                     | 说明                                 |
| ------------------------ | ------------------------------------ |
| `--target-host HOST`     | **必需** 目标服务器地址（必须是SSH） |
| `--target-port PORT`     | 目标服务器端口（默认: 22）           |
| `--target-user USER`     | **必需** 目标服务器用户名            |
| `--target-password PASS` | 目标服务器密码                       |
| `--target-key FILE`      | 目标服务器私钥文件路径               |
| `--target-dir DIR`       | **必需** 目标服务器图片基础目录      |

## 使用示例

### 示例1：从本地目录迁移到远程服务器（推荐）

```bash
# 1. 创建配置文件
python image_migrate.py --create-config myconfig.json

# 2. 编辑配置文件
# 将 source.type 设置为 "local"
# 设置 source.base_dir 为本地目录路径
# 填写目标服务器的SSH信息

# 3. 创建图片路径文件
echo "uploads/test.jpg" > images.txt
echo "assets/logo.png" >> images.txt

# 4. 执行迁移
python image_migrate.py --config myconfig.json --input images.txt
```

### 示例2：直接从命令行迁移本地图片

```bash
python image_migrate.py \
  --source-type local \
  --source-dir /home/user/my_website/images \
  --target-host 192.168.1.200 \
  --target-user deploy \
  --target-key ~/.ssh/id_rsa \
  --target-dir /var/www/html/images \
  --input images.txt \
  --verbose
```

### 示例3：从SSH服务器迁移到另一个SSH服务器

```bash
python image_migrate.py \
  --source-type ssh \
  --source-host old-server.example.com \
  --source-user admin \
  --source-key ~/.ssh/id_rsa \
  --source-dir /var/www/images \
  --target-host new-server.example.com \
  --target-user deploy \
  --target-dir /home/deploy/images \
  --input images.txt \
  --overwrite
```

### 示例4：直接从命令行指定图片路径

```bash
python image_migrate.py --config config.json \
  "uploads/product1.jpg" \
  "uploads/product2.jpg" \
  "assets/logo.png"
```

### 示例5：批量迁移数据库导出的图片路径

```bash
# 从数据库导出图片路径（假设每行一个路径）
mysql -e "SELECT image_path FROM products" --skip-column-names > products.txt

# 清理路径（如果需要）
sed -i 's/^\.\///' products.txt

# 迁移图片
python image_migrate.py --config config.json --input products.txt --verbose
```

## 图片路径格式

图片路径应为**相对路径**，相对于配置文件中指定的 `base_dir`：

```
# 正确示例（相对路径）
uploads/products/2024/01/product1.jpg
assets/images/logo.png

# 错误示例（绝对路径）
/var/www/html/images/uploads/product1.jpg  # 错误！应该使用相对路径

# 在目标服务器上，文件将保存为：
# 目标 base_dir + 相对路径
```

## 工作流程

1. **连接建立**：连接到目标SSH服务器（源为本地时不需要连接）
2. **路径处理**：为每个图片构建完整源路径和目标路径
3. **目录创建**：在目标服务器上创建必要的目录结构
4. **文件检查**：检查源文件是否存在，目标文件是否已存在（跳过）
5. **文件传输**：通过本地临时文件传输（源→本地临时文件→目标）
6. **统计报告**：显示传输结果和统计信息

## 故障排除

### 常见问题

#### 1. 连接失败

```
错误: 连接失败: [Errno 111] Connection refused
```

- 检查目标服务器地址和端口
- 确认SSH服务正在运行
- 检查防火墙设置

#### 2. 认证失败

```
错误: Authentication failed.
```

- 确认用户名和密码正确
- 检查SSH密钥权限（chmod 600 ~/.ssh/id_rsa）
- 确认密钥已添加到目标服务器的 authorized_keys

#### 3. 源文件不存在

```
错误: 源文件不存在: /path/to/local/images/uploads/test.jpg
```

- 确认相对路径正确
- 确认源基础目录正确
- 使用 `--verbose` 查看完整路径

#### 4. 权限不足

```
错误: Permission denied
```

- 确认用户有读取源文件的权限（本地文件）
- 确认用户有写入目标目录的权限

#### 5. 目录创建失败

```
错误: 无法创建目标目录: /var/www/html/images/uploads
```

- 检查目标目录的写入权限
- 确认目标服务器磁盘空间充足

### 调试技巧

1. **使用详细模式**：添加 `--verbose` 参数查看详细信息
2. **测试连接**：手动SSH连接测试目标服务器是否可达
3. **检查路径**：在源目录上确认文件存在
4. **查看日志**：脚本会显示详细的错误信息

## 性能优化

### 大文件传输

- 脚本使用流式传输，适用于大文件
- 临时文件存储在系统临时目录，传输完成后自动清理

### 批量传输

- 对于大量文件，建议分批处理
- 可以使用多个图片路径文件，分别执行迁移

### 网络优化

- 确保到目标服务器的网络连接稳定
- 考虑使用内网传输以提高速度

## 安全注意事项

1. **认证方式**：建议使用SSH密钥认证而非密码
2. **权限控制**：配置文件建议设置权限 `chmod 600 config.json`
3. **最小权限**：使用具有最小必要权限的账户执行迁移
4. **本地文件安全**：确保本地目录不包含敏感信息
5. **临时文件清理**：脚本会自动清理临时传输文件

## 扩展和定制

### 修改脚本

- 可以在 `ImageMigrator` 类中添加额外的功能
- 支持断点续传、并行传输等高级功能

### 集成到工作流

- 可以与其他脚本结合使用
- 可以作为CI/CD流程的一部分

### 添加进度条

```python
# 可选：安装 tqdm 库
pip install tqdm

# 在脚本中添加进度条显示
```

## 文件结构

```
scripts/
├── image_migrate.py          # 主脚本
├── image_migrate_backup.py   # 原始版本备份
├── requirements.txt          # Python依赖
├── README.md                # 本文档
└── examples/                # 示例文件
    ├── config.example.json  # 配置文件示例
    └── images.example.txt   # 图片路径示例
```

## 版本更新

### v2.0 更新

- ✅ 新增本地目录(`local`)作为源的支持
- ✅ 默认源类型改为`local`
- ✅ 简化配置文件结构
- ✅ 改进错误处理和临时文件管理

## 许可证

本脚本根据项目需要自由使用和修改。

## 支持

如有问题，请：

1. 检查本文档的故障排除部分
2. 使用 `--verbose` 参数获取详细信息
3. 确认服务器配置正确

---

**提示**：首次使用前，建议在测试服务器上进行小规模测试。
