# CLI 自动化

{% hint style="success" %}
**先决条件：** 安装 SDK（`pip install clore-ai`）并配置您的 API 密钥。请参阅 [Python 快速入门](https://docs.clore.ai/guides/guides_v2-zh/kuai-su-ru-men/python-quickstart) 如果您还没有。
{% endhint %}

## 基本工作流

核心循环： **搜索 → 部署 → 连接 → 取消**.

```bash
# 1. 寻找 GPU
clore search --gpu "RTX 4090" --max-price 2.0 --sort price --limit 5

# 2. 部署（使用第 1 步中的服务器 ID）
clore deploy 142 \
  --image cloreai/ubuntu22.04-cuda12 \
  --type on-demand \
  --currency bitcoin \
  --ssh-password MySecurePass \
  --port 22:tcp \
  --port 8888:http

# 3. 检查您的订单
clore orders

# 4. SSH 登录到服务器
clore ssh 38

# 5. 完成后取消
clore cancel 38

# 6. 检查钱包余额
clore wallets
```

***

## CLI 命令参考

| 命令                                    | 说明             |
| ------------------------------------- | -------------- |
| `clore search`                        | 搜索 GPU 市场      |
| `clore deploy <server_id>`            | 创建新订单          |
| `clore orders`                        | 列出活动订单         |
| `clore orders --completed`            | 列出包括已完成在内的所有订单 |
| `clore ssh <order_id>`                | SSH 登录到活动订单    |
| `clore cancel <order_id>`             | 取消订单           |
| `clore wallets`                       | 显示钱包余额         |
| `clore servers`                       | 列出您托管的服务器      |
| `clore server-config <name>`          | 显示服务器配置        |
| `clore spot <server_id>`              | 查看服务器的现货市场     |
| `clore spot-price <order_id> <price>` | 为订单设置现货价格      |
| `clore config set <key> <value>`      | 设置配置值          |
| `clore config get <key>`              | 获取配置值          |
| `clore config show`                   | 显示所有配置         |

***

## 使用 CLI 脚本

### 部署并等待 SSH

```bash
#!/bin/bash
# deploy-and-connect.sh — 部署服务器并在准备好时 SSH 登录

set -euo pipefail

SERVER_ID=${1:?Usage: $0 <server_id>}
IMAGE=${2:-cloreai/ubuntu22.04-cuda12}
PASSWORD="AutoDeploy$(date +%s)"

echo "🚀 正在部署服务器 $SERVER_ID..."
clore deploy "$SERVER_ID" \
  --image "$IMAGE" \
  --type on-demand \
  --currency bitcoin \
  --ssh-password "$PASSWORD" \
  --port 22:tcp

echo "⏳ 等待订单就绪..."
sleep 15

echo "📦 活动订单："
clore orders

echo ""
echo "🔑 SSH 密码： $PASSWORD"
echo "💡 连接方式： clore ssh <order_id>"
```

### 查找最便宜的 GPU 并部署

```bash
#!/bin/bash
# cheapest-gpu.sh — 查找并部署匹配条件的最便宜 GPU

GPU_MODEL=${1:-"RTX 4090"}
MAX_PRICE=${2:-5.0}

echo "🔍 正在搜索每小时低于 \$$MAX_PRICE 的最便宜 $GPU_MODEL..."
clore search --gpu "$GPU_MODEL" --max-price "$MAX_PRICE" --sort price --limit 5

echo ""
read -p "输入要部署的服务器 ID（或输入 'q' 退出）： " SERVER_ID

if [ "$SERVER_ID" = "q" ]; then
    echo "已取消。"
    exit 0
fi

read -sp "SSH 密码： " SSH_PASS
echo ""

clore deploy "$SERVER_ID" \
  --image cloreai/ubuntu22.04-cuda12 \
  --type on-demand \
  --currency bitcoin \
  --ssh-password "$SSH_PASS" \
  --port 22:tcp \
  --port 8888:http

echo "✅ 已部署！查看 'clore orders' 以获取状态。"
```

### 取消所有订单

```bash
#!/bin/bash
# cancel-all.sh — 取消所有活动订单

echo "📦 当前订单："
clore orders

echo ""
read -p "取消所有活动订单？（yes/no）： " CONFIRM

if [ "$CONFIRM" = "yes" ]; then
    # 使用 Python 单行脚本因为 CLI 每次只能取消一个
    python3 -c "
from clore_ai import CloreAI
client = CloreAI()
orders = client.my_orders()
for o in orders:
    client.cancel_order(o.id, issue='Batch cleanup')
    print(f'Cancelled order {o.id}')
print(f'Done. Cancelled {len(orders)} orders.')
"
else
    echo "已取消。"
fi
```

***

## CI/CD 集成

### GitHub Actions：为训练部署 GPU

```yaml
# .github/workflows/train.yml
名称：GPU Training

触发：
  workflow_dispatch：
    输入：
      gpu_model：
        说明：'GPU 型号'
        默认：'RTX 4090'
      max_price：
        说明：'最高每小时价格（美元）'
        默认：'2.0'

环境变量：
  CLORE_API_KEY: ${{ secrets.CLORE_API_KEY }}

作业：
  train：
    运行于：ubuntu-latest
    步骤：
      - uses: actions/checkout@v4

      - 名称：安装 clore-ai
        运行：pip install clore-ai

      - 名称：查找并部署 GPU
        运行： |
          python3 << 'EOF'
          import time, os
          from clore_ai import CloreAI

          client = CloreAI()

          # 查找最便宜的匹配 GPU
          servers = client.marketplace(
              gpu="${{ github.event.inputs.gpu_model }}",
              max_price_usd=float("${{ github.event.inputs.max_price }}")
          )
          servers.sort(key=lambda s: s.price_usd or float("inf"))

          if not servers:
              print("没有可用的服务器！")
              exit(1)

          best = servers[0]
          print(f"正在在服务器 {best.id} 上部署：{best.gpu_model} @ ${best.price_usd:.4f}/h")

          order = client.create_order(
              server_id=best.id,
              image="cloreai/ubuntu22.04-cuda12",
              type="on-demand",
              currency="bitcoin",
              ssh_password=os.environ.get("SSH_PASSWORD", "CITraining123"),
              ports={"22": "tcp"},
              command="bash /workspace/train.sh"
          )

          print(f"订单 {order.id} 已创建")

          # 等待就绪
          for _ in range(30):
              orders = client.my_orders()
              o = next((x for x in orders if x.id == order.id), None)
              if o and o.pub_cluster:
                  print(f"已就绪： {o.pub_cluster}")
                  break
              time.sleep(10)

          # 保存订单 ID 以便清理
          with open(os.environ["GITHUB_ENV"], "a") as f:
              f.write(f"ORDER_ID={order.id}\n")
          EOF

      - 名称：等待训练完成
        运行： |
          echo "训练进行中..."
          # 在此添加您的监控逻辑
          sleep 60

      - 名称：清理 GPU
        if: always()
        运行： |
          python3 -c "
          from clore_ai import CloreAI
          import os
          client = CloreAI()
          order_id = int(os.environ.get('ORDER_ID', 0))
          if order_id:
              client.cancel_order(order_id, issue='CI job complete')
              print(f'Cancelled order {order_id}')
          "
```

### GitLab CI：批处理

```yaml
# .gitlab-ci.yml
gpu-batch-job：
  阶段：process
  镜像：python:3.11
  变量：
    CLORE_API_KEY: $CLORE_API_KEY
  before_script：
    - pip install clore-ai
  脚本：
    - |
      python3 << 'EOF'
      from clore_ai import CloreAI
      import time

      client = CloreAI()

      servers = client.marketplace(gpu="RTX 4090", max_price_usd=3.0)
      if not servers:
          print("没有可用的 GPU")
          exit(1)

      servers.sort(key=lambda s: s.price_usd or float("inf"))
      order = client.create_order(
          server_id=servers[0].id,
          image="cloreai/ubuntu22.04-cuda12",
          type="spot",
          currency="bitcoin",
          spot_price=0.00005,
          ports={"22": "tcp"}
      )
      print(f"已部署：订单 {order.id}")

      # ... 执行工作 ...

      client.cancel_order(order.id)
      print("完成并已清理")
      EOF
  after_script：
    - |
      python3 -c "
      from clore_ai import CloreAI
      client = CloreAI()
      for o in client.my_orders():
          client.cancel_order(o.id, issue='CI cleanup')
      "
```

***

## 监控

### 定期检查订单

```bash
#!/bin/bash
# monitor.sh — 每 60 秒检查一次订单

while true; do
    echo "=== $(date) ==="
    clore orders
    clore wallets
    echo ""
    sleep 60
done
```

### Python 监控脚本

```python
#!/usr/bin/env python3
"""monitor-orders.py — 监控活动订单并在出现问题时发出警报。"""

import time
from clore_ai import CloreAI

POLL_INTERVAL = 60  # 秒
LOW_BALANCE_THRESHOLD = 0.001  # BTC

def monitor():
    client = CloreAI()

    while True:
        try:
            # 检查订单
            orders = client.my_orders()
            print(f"[{time.strftime('%H:%M:%S')}] 活动订单： {len(orders)}")
            for o in orders:
                print(f"  订单 {o.id}：类型={o.type}, IP={o.pub_cluster or 'pending'}")

            # 检查余额
            wallets = client.wallets()
            for w in wallets:
                if w.name.lower() == "bitcoin" and w.balance < LOW_BALANCE_THRESHOLD:
                    print(f"  ⚠️  BTC 余额低： {w.balance:.8f}")

        except Exception as e:
            print(f"  ❌ 错误： {e}")

        time.sleep(POLL_INTERVAL)

if __name__ == "__main__":
    monitor()
```

***

## 批量操作

### 在多台服务器上部署

```bash
#!/bin/bash
# batch-deploy.sh — 在多台服务器上部署

SERVER_IDS=(142 305 891 450)
IMAGE="cloreai/ubuntu22.04-cuda12"
PASSWORD="BatchRun$(date +%s)"

for SID in "${SERVER_IDS[@]}"; do
    echo "🚀 正在在服务器 $SID 上部署..."
    clore deploy "$SID" \
      --image "$IMAGE" \
      --type on-demand \
      --currency bitcoin \
      --ssh-password "$PASSWORD" \
      --port 22:tcp \
      || echo "⚠️  部署 $SID 失败"
    sleep 6  # 遵守速率限制
done

echo ""
echo "📦 所有订单："
clore orders
echo "🔑 密码： $PASSWORD"
```

### 使用 Python（异步）批量部署

```python
#!/usr/bin/env python3
"""batch-deploy.py — 在多台服务器上并发部署。"""

import asyncio
from clore_ai import AsyncCloreAI
from clore_ai.exceptions import CloreAPIError

async def batch_deploy(server_ids, image="cloreai/ubuntu22.04-cuda12"):
    async with AsyncCloreAI() as client:
        tasks = [
            client.create_order(
                server_id=sid,
                image=image,
                type="on-demand",
                currency="bitcoin",
                ssh_password="BatchPass123",
                ports={"22": "tcp"}
            )
            for sid in server_ids
        ]

        results = await asyncio.gather(*tasks, return_exceptions=True)

        for sid, result in zip(server_ids, results):
            if isinstance(result, CloreAPIError):
                print(f"❌ 服务器 {sid}：{result}")
            elif isinstance(result, Exception):
                print(f"❌ 服务器 {sid}：{result}")
            else:
                print(f"✅ 服务器 {sid}：订单 {result.id}")

if __name__ == "__main__":
    import sys
    server_ids = [int(x) for x in sys.argv[1:]]
    if not server_ids:
        print("用法：python batch-deploy.py 142 305 891")
        exit(1)
    asyncio.run(batch_deploy(server_ids))
```

用法：

```bash
python batch-deploy.py 142 305 891
```

### 现货市场扫描器

```bash
#!/bin/bash
# spot-scanner.sh — 为一列服务器扫描现货价格

SERVERS=(6 12 42 100)

echo "📊 现货市场扫描 — $(date)"
echo "---"

for SID in "${SERVERS[@]}"; do
    echo "服务器 $SID："
    clore spot "$SID"
    echo ""
done
```

***

## 定时任务

### 每日 GPU 价格检查

```bash
# 添加到 crontab： crontab -e
# 每天上午 9 点运行
0 9 * * * CLORE_API_KEY=your_key /usr/local/bin/clore search --gpu "RTX 4090" --sort price --limit 5 >> /var/log/clore-prices.log 2>&1
```

### 每小时余额检查

```bash
# 每小时检查余额
0 * * * * CLORE_API_KEY=your_key /usr/local/bin/clore wallets >> /var/log/clore-balance.log 2>&1
```

***

## 提示

1. **始终设置 `CLORE_API_KEY`** 作为脚本和 CI 中的环境变量
2. **添加 `sleep 6`** 在 bash 循环中的部署命令之间以遵守速率限制
3. **使用 `--type spot`** 用于批处理/CI 作业 — 更便宜且可中断
4. **在 `after_script`** / `if: always()` 中取消订单以避免遗忘计费
5. **将 SSH 密码存储在密钥中** （GitHub Secrets、GitLab CI 变量等）
6. **使用 `clore orders --completed`** 以审计过去的使用情况

***

## 下一步

* [Python SDK 指南](https://docs.clore.ai/guides/guides_v2-zh/gao-ji/python-sdk) — 带有异步模式的完整 SDK 参考
* [批处理处理](https://docs.clore.ai/guides/guides_v2-zh/gao-ji/batch-processing) — 处理大型 AI 工作负载
* [API 集成](https://docs.clore.ai/guides/guides_v2-zh/gao-ji/api-integration) — 将 AI 服务连接到您的应用
