# DEPLOY.md - 手动部署 paper + live copybot 到新服务器

> 一步一步来，可以一边看一边敲。不要一次性复制粘贴大段命令--每一步做完、看到预期输出，再进下一步。
>
> 适用：把 paper bot + live bot 部署到一台新的 Linux 服务器（Ubuntu/Debian），从你自己的 Gitea 拉代码。如果服务器在 Polymarket 禁单地区（美国/英国/法国等），用 mihomo 代理绕开 geo-block。
>
> 完成时间参考：60-90 分钟（含每步等待 + live 配置）。
>
> 完成部署后提供：
> - **paper bot**：24/7 模拟跟单（直连，不走代理）
> - **live bot**：24/7 真钱跟单（走代理绕 geo-block）
> - **bot 实时账本（中文 web dashboard）**：`http://服务器IP:18080/`
> - **原始 JSON**：`https://<GITEA>/<USERNAME>/winning-wallet-finder/raw/branch/main/live/copybot_live.json`

---

## 目录

- [Part A: Paper Bot 部署](#part-a-paper-bot-部署) （§0-§13）
- [Part B: 代理配置（geo-block 绕行）](#part-b-代理配置geo-block-绕行) （§14-§16）
- [Part C: Live Bot 部署](#part-c-live-bot-部署) （§17-§23）
- [常见坑](#常见坑)
- [日常命令](#日常用的命令)

---

# Part A: Paper Bot 部署

## 0. 前置条件

- [ ] 一台 Linux VPS（Ubuntu 20.04+ / Debian 11+）
- [ ] 你有 root SSH 权限
- [ ] 你的 Gitea 上有这个仓库的镜像
- [ ] Gitea PAT（权限 `repository: Write`）

测 Polymarket 直连：

```bash
python3 -c "
import urllib.request, time
for url in [
    'https://data-api.polymarket.com/v1/leaderboard?limit=1',
    'https://gamma-api.polymarket.com/markets?limit=1',
    'https://clob.polymarket.com/markets?next_cursor=',
]:
    t = time.time()
    try:
        urllib.request.urlopen(urllib.request.Request(url, headers={'User-Agent':'Mozilla/5.0'}), timeout=10)
        print(f'OK   {(time.time()-t)*1000:6.0f}ms  {url}')
    except Exception as e:
        print(f'FAIL {type(e).__name__}: {url}')
"
```

三行 `OK` = 能读 API（paper 够用）。

## 1. 装基础依赖

```bash
ssh root@你的服务器IP
apt-get update
apt-get install -y git python3 python3-pip ca-certificates
```

## 2. 从 Gitea 拉代码

```bash
cd /opt
git clone https://<USERNAME>:<TOKEN>@<GITEA>/<USERNAME>/winning-wallet-finder.git
cd winning-wallet-finder/live
```

## 3. 装 duckdb + 首次回测

```bash
pip3 install duckdb --break-system-packages
python3 portfolio.py --days 30
```

预期：`portfolio[30d rolling]: equity $... | ... | -> portfolio.json`

## 4. 前台测试 bot

```bash
python3 ../copybot.py --config copybot.paper.json --state copybot_state.json --poll 60
```

看到 `watching N wallets` + 2-3 条心跳后 `Ctrl+C`。

## 5. 配 Gitea 凭证

### 5.1 生成 PAT

Gitea -> 用户设置 -> Applications -> Generate Token（权限 `repository: Write`）

### 5.2 写 .netrc

```bash
nano ~/.netrc
```

```
machine <GITEA域名>
login <USERNAME>
password <TOKEN>
```

```bash
chmod 600 ~/.netrc
cd /opt/winning-wallet-finder
git push origin main --dry-run
```

### 5.3 root git 白名单

```bash
git config --global --add safe.directory /opt/winning-wallet-finder
```

## 6. 建专用用户 wwf

```bash
useradd --system --shell /usr/sbin/nologin --home /opt/winning-wallet-finder wwf
chown -R wwf:wwf /opt/winning-wallet-finder
chmod -R u+rwX,g+rX,o-rwx /opt/winning-wallet-finder
sudo cp /root/.netrc /opt/winning-wallet-finder/.netrc
sudo chown wwf:wwf /opt/winning-wallet-finder/.netrc
sudo chmod 600 /opt/winning-wallet-finder/.netrc
sudo -u wwf git config --global user.name "copybot[bot]"
sudo -u wwf git config --global user.email "copybot@wwf.local"
```

> **坑**：wwf 没配 git identity 会导致 commit 报 `Author identity unknown`。上面最后两行不能漏。

## 7. 写 paper systemd unit

```bash
cat > /etc/systemd/system/copybot-paper.service <<'EOF'
[Unit]
Description=Polymarket Paper Copybot
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=wwf
Group=wwf
WorkingDirectory=/opt/winning-wallet-finder/live
ExecStart=/usr/bin/python3 /opt/winning-wallet-finder/copybot.py \
    --config /opt/winning-wallet-finder/live/copybot.paper.json \
    --state /opt/winning-wallet-finder/copybot_state.json \
    --poll 60

Restart=always
RestartSec=10
TimeoutStopSec=30
Nice=5

StandardOutput=journal
StandardError=journal
SyslogIdentifier=copybot-paper

EnvironmentFile=-/etc/copybot/paper.env

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
RestrictSUIDSGID=true
RestrictNamespaces=true
LockPersonality=true
RestrictRealtime=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
SystemCallArchitectures=native
ReadWritePaths=/opt/winning-wallet-finder

[Install]
WantedBy=multi-user.target
EOF
```

## 8. 启动 paper bot

```bash
systemctl daemon-reload
systemctl enable --now copybot-paper
sleep 5
systemctl status copybot-paper
```

## 9. 验证 Gitea 推送

```bash
cd /opt/winning-wallet-finder
sudo -u wwf git add -A
sudo -u wwf git commit -m "manual sync"
sudo -u wwf git push
```

## 10. 加 Alchemy RPC

```bash
sudo install -d -m 750 -o wwf -g wwf /etc/copybot
sudo tee /etc/copybot/paper.env > /dev/null <<EOF
ALCHEMY_RPC_URL=https://polygon-mainnet.g.alchemy.com/v2/你的KEY
EOF
sudo chown wwf:wwf /etc/copybot/paper.env
sudo chmod 600 /etc/copybot/paper.env
sudo systemctl restart copybot-paper
```

## 11. 加每日 cron

```bash
timedatectl | grep "Time zone"
# UTC 服务器 -> 北京 10:00 = cron 0 2
(crontab -l 2>/dev/null; echo "0 2 * * * cd /opt/winning-wallet-finder/live && bash daily.sh >> daily.log 2>&1") | crontab -
```

## 12. 部署 web dashboard

```bash
cat > /etc/systemd/system/copybot-dashboard.service <<'EOF'
[Unit]
Description=Polymarket Copybot Live Dashboard
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=wwf
Group=wwf
WorkingDirectory=/opt/winning-wallet-finder/live
ExecStart=/usr/bin/python3 /opt/winning-wallet-finder/live/serve_dashboard.py
Restart=always
RestartSec=5
Nice=10

StandardOutput=journal
StandardError=journal
SyslogIdentifier=copybot-dashboard

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
RestrictNamespaces=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now copybot-dashboard
sleep 3
curl -s http://localhost:18080/api/feed | python3 -m json.tool | head -10
```

浏览器访问 `http://服务器IP:18080/`。如果打不开，放行防火墙 TCP 18080。

## 13. Paper 完成检查

- [x] paper bot systemd 24/7 跑
- [x] web dashboard @ :18080
- [x] Alchemy RPC ON
- [x] 状态推 Gitea
- [x] 每日 cron

---

# Part B: 代理配置（geo-block 绕行）

> **为什么要代理**：Polymarket 禁止美国/英国/法国/德国/意大利/荷兰/波兰/新加坡/澳大利亚/加拿大安大略/巴西 等地区的 IP 下单。如果你的服务器在这些地区，live bot 需要走代理。
>
> paper bot 不受影响（只读 API 全球开放）。

## 14. 检查 geo-gate

```bash
cd /opt/winning-wallet-finder
python3 host/geocheck.py
```

- `VERDICT: TRADABLE` -> 跳过 Part B，直接去 Part C
- `VERDICT: BLOCKED` -> 继续往下配代理

## 15. 装 mihomo（Clash Meta 内核）

### 15.1 下载 mihomo

```bash
mkdir -p /etc/mihomo
cd /tmp
wget -q https://github.com/MetaCubeX/mihomo/releases/download/v1.19.0/mihomo-linux-amd64-v1.19.0.gz
gzip -d mihomo-linux-amd64-v1.19.0.gz
mv mihomo-linux-amd64-v1.19.0 /usr/local/bin/mihomo
chmod +x /usr/local/bin/mihomo
mihomo -v
```

### 15.2 拉订阅配置

> **坑**：机场会检测 User-Agent，wget 默认 UA 会被返回假节点。必须伪装 UA。

```bash
wget -O /etc/mihomo/config.yaml \
  --user-agent="clash-verge/v1.7.7" \
  "你的订阅链接&flag=meta"
```

验证拿到的是真实节点（不是"当前Clash客户端不支持本机场协议"）：

```bash
grep "name:" /etc/mihomo/config.yaml | grep -i "日本\|香港\|新加坡" | head -10
```

### 15.3 改全局模式 + 启动

```bash
sed -i 's/^mode: rule/mode: global/' /etc/mihomo/config.yaml

nohup mihomo -d /etc/mihomo > /var/log/mihomo.log 2>&1 &
sleep 5

# 选一个非美国节点（以日本为例）
curl -s -X PUT http://127.0.0.1:9090/proxies/GLOBAL \
  -H "Content-Type: application/json" \
  -d '{"name":"节点名"}'

# 验证
HTTPS_PROXY=http://127.0.0.1:7890 python3 host/geocheck.py
```

期望 `VERDICT: TRADABLE`。

### 15.4 做 systemd 服务

```bash
kill $(pgrep mihomo)

cat > /etc/systemd/system/mihomo.service <<'EOF'
[Unit]
Description=Mihomo (Clash Meta) Proxy
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mihomo -d /etc/mihomo
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mihomo
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now mihomo
sleep 5

# 重选节点（mihomo 重启会记住，但第一次要手动选）
curl -s -X PUT http://127.0.0.1:9090/proxies/GLOBAL \
  -H "Content-Type: application/json" \
  -d '{"name":"节点名"}'

# 验证代理 + geo-gate
HTTPS_PROXY=http://127.0.0.1:7890 python3 host/geocheck.py | tail -1
```

> **mihomo 会记住节点选择**：`cache.db` 持久化，重启不丢。

### 15.5 自动健康检查（节点挂了自动换）

```bash
cat > /opt/mihomo-healthcheck.sh <<'SCRIPT'
#!/bin/bash
API="http://127.0.0.1:9090"
PROXY="http://127.0.0.1:7890"
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -x $PROXY \
  "https://clob.polymarket.com/markets?next_cursor=" 2>/dev/null)
if [ "$code" = "200" ]; then exit 0; fi
nodes=$(curl -s "$API/proxies" | python3 -c "
import sys, json
d = json.load(sys.stdin)
skip = {'DIRECT','REJECT','自动选择','故障转移','良心云','GLOBAL'}
for name, info in d.get('proxies', {}).items():
    if name in skip: continue
    if info.get('type') in ('Selector','URLTest','Fallback','LoadBalance'): continue
    if any(k in name for k in ['美国','US','United States']): continue
    print(name)
")
for node in $nodes; do
  curl -s -X PUT "$API/proxies/GLOBAL" -H "Content-Type: application/json" -d "{\"name\":\"$node\"}" > /dev/null
  sleep 2
  code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 -x $PROXY \
    "https://clob.polymarket.com/markets?next_cursor=" 2>/dev/null)
  if [ "$code" = "200" ]; then
    logger "mihomo-healthcheck: switched to $node"
    exit 0
  fi
done
logger "mihomo-healthcheck: ALL nodes failed"
exit 1
SCRIPT

chmod +x /opt/mihomo-healthcheck.sh
(crontab -l 2>/dev/null | grep -v mihomo-healthcheck; echo "*/5 * * * * /opt/mihomo-healthcheck.sh") | crontab -
```

> **代理只影响 live bot**：mihomo 监听 `127.0.0.1:7890`，不是透明代理。只有设了 `HTTPS_PROXY` 的程序才走代理。paper bot / dashboard / Gitea 全部直连，不受影响。
>
> **不要**把 `HTTPS_PROXY` 写进 `/etc/environment` 或 `~/.bashrc`（会全局生效），只放在 `/etc/copybot/live.env` 里。

---

# Part C: Live Bot 部署

> **真钱！** 每一步验证完再进下一步。建议先 $3-5 测试。

## 17. 装 live 依赖

```bash
pip3 install py-clob-client==0.34.6 web3==7.16.0 polymarket-client==0.1.0b16 websocket-client --break-system-packages
```

> **坑**：`preflight_live.py` 需要 `polymarket-client`（不是 `py-clob-client`），漏装会报 `ModuleNotFoundError: No module named 'polymarket'`。

## 18. 准备钱包

### 18.1 钱包架构说明

Polymarket 2026 新架构有两套钱包系统：

```
你的私钥（MetaMask 导出）
    |
    +-- EOA 地址（MetaMask 本身）
    +-- 代理钱包（邮箱登录自动创建，POLY_PROXY type=1）
    +-- 存款钱包（API 自动创建，POLY_1271 type=3）<- bot 用这个
```

**bot 只能用存款钱包**。pUSD 在 EOA 或代理钱包里 bot 看不到。

### 18.2 用 MetaMask 登录（推荐，比邮箱简单）

1. 浏览器装 MetaMask，创建新钱包
2. 用 MetaMask 登录 polymarket.com
3. MetaMask -> 账户详情 -> 导出私钥

### 18.3 创建存款钱包

```bash
cd /opt/winning-wallet-finder
export HTTPS_PROXY=http://127.0.0.1:7890
export LIVE_PRIVATE_KEY=0x你的MetaMask私钥

python3 -c "
from polymarket import SecureClient
client = SecureClient.create(private_key='$LIVE_PRIVATE_KEY')
print('存款钱包:', client.wallet)
b = client.get_balance_allowance(asset_type='COLLATERAL')
print('pUSD 余额: \$' + str(b.balance / 1e6))
client.close()
"
```

> **坑（邮箱登录用户）**：如果用邮箱登录的私钥（Magic.link 导出），`SecureClient.create()` 会报 `Gasless transactions require a Builder API Key`。需要用 Builder API 凭证创建存款钱包：
> ```python
> bk = BuilderApiKey(key=..., secret=..., passphrase=...)
> client = SecureClient.create(private_key=pk, api_key=bk)
> ```
> Builder 凭证在 polymarket.com -> Settings -> API Keys 获取。创建完存款钱包后不再需要 Builder 凭证。
>
> **MetaMask 登录用户不受此影响**，存款钱包自动创建。

### 18.4 充值 USDC -> pUSD

**关键**：必须充到**存款钱包地址**，不是 MetaMask 地址。

1. 从交易所提 USDC 到 Polygon 链
2. 接收地址 = 步骤 18.3 打印的存款钱包地址
3. 到账后 USDC 自动转成 pUSD

> **坑**：充到 Polymarket 网站显示的充值地址（代理钱包）是错的，bot 在存款钱包里看不到。必须充到存款钱包地址。

### 18.5 验证余额

```bash
export HTTPS_PROXY=http://127.0.0.1:7890
export LIVE_PRIVATE_KEY=0x你的私钥
python3 -c "
from polymarket import SecureClient
client = SecureClient.create(private_key='$LIVE_PRIVATE_KEY')
b = client.get_balance_allowance(asset_type='COLLATERAL')
print('pUSD: \$' + str(b.balance / 1e6))
client.close()
"
```

## 19. 创建 config.live.json

```bash
cd /opt/winning-wallet-finder
cp config.live.example.json config.live.json
# 改 bankroll_usd 为实际 pUSD 余额
sed -i 's/"bankroll_usd": 22.28/"bankroll_usd": 你的余额/' config.live.json
chown wwf:wwf config.live.json
chmod 640 config.live.json
```

> **坑**：config.live.json 是 root 创建的，wwf 用户读不了会报 `PermissionError`。必须 `chown wwf:wwf`。

## 20. 创建 live.env

```bash
cat > /etc/copybot/live.env <<'EOF'
LIVE_PRIVATE_KEY=0x你的MetaMask私钥
LIVE_FUNDER_ADDRESS=0x你的MetaMask地址
LIVE_SIGNATURE_TYPE=1
LIVE_CONFIRM=TRADE LIVE
HTTPS_PROXY=http://127.0.0.1:7890
EOF

chown wwf:wwf /etc/copybot/live.env
chmod 600 /etc/copybot/live.env
```

> **坑 1**：`LIVE_CONFIRM` 的值必须是 `TRADE LIVE`（copytrade.py:48 的 `CONFIRM_PHRASE`），不是 `I understand real money is at risk`。填错会报 `Aborted - LIVE_CONFIRM is set but does not match the phrase`。
>
> **坑 2**：systemd EnvironmentFile 里值**不要加引号**。`LIVE_CONFIRM=TRADE LIVE` 是对的，`LIVE_CONFIRM="TRADE LIVE"` 会让值带引号导致不匹配。
>
> **坑 3**：`HTTPS_PROXY` 只在 live.env 里设，不要放 paper.env（paper bot 不需要代理）。

## 21. 跑 preflight

```bash
cd /opt/winning-wallet-finder
export LIVE_PRIVATE_KEY=$(grep LIVE_PRIVATE_KEY /etc/copybot/live.env | cut -d= -f2-)
export LIVE_FUNDER_ADDRESS=$(grep LIVE_FUNDER_ADDRESS /etc/copybot/live.env | cut -d= -f2-)
export HTTPS_PROXY=http://127.0.0.1:7890
python3 preflight_live.py
```

全绿才能继续。常见失败：
- `ModuleNotFoundError: No module named 'websocket'` -> `pip3 install websocket-client`
- `Gasless transactions require a Builder API Key` -> 见 §18.3 邮箱登录的坑
- `Invalid private_key: 'ascii' codec can't encode` -> 私钥里有非 ASCII 字符（中文占位符没替换）

## 22. 写 live systemd unit

```bash
cat > /etc/systemd/system/copybot-live.service <<'EOF'
[Unit]
Description=Polymarket LIVE Copybot (real money)
After=network-online.target mihomo.service
Wants=network-online.target
Requires=mihomo.service

[Service]
Type=simple
User=wwf
Group=wwf
WorkingDirectory=/opt/winning-wallet-finder/live
ExecStart=/usr/bin/python3 /opt/winning-wallet-finder/copybot.py \
    --config /opt/winning-wallet-finder/config.live.json \
    --state /opt/winning-wallet-finder/copybot_state.live.json \
    --poll 60 --live

Restart=always
RestartSec=10
TimeoutStopSec=30
Nice=5

StandardOutput=journal
StandardError=journal
SyslogIdentifier=copybot-live

EnvironmentFile=/etc/copybot/live.env

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
RestrictSUIDSGID=true
RestrictNamespaces=true
LockPersonality=true
RestrictRealtime=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
SystemCallArchitectures=native
ReadWritePaths=/opt/winning-wallet-finder

[Install]
WantedBy=multi-user.target
EOF
```

> `Requires=mihomo.service` + `After=mihomo.service`：代理先启动，live bot 才启动。

## 23. 启动 live bot

```bash
systemctl daemon-reload
systemctl enable --now copybot-live
sleep 10
journalctl -u copybot-live --since "15 seconds ago" --no-pager
```

预期看到：

```
geo-gate: TRADABLE - order endpoint reachable
LIVE MODE - this will place REAL orders with REAL money.
confirmed via LIVE_CONFIRM env - armed.
mode: LIVE - REAL MONEY
watching 5 wallets
```

### 清空 live state（如果出现 LEDGER DRIFT）

```bash
systemctl stop copybot-live
rm -f /opt/winning-wallet-finder/copybot_state.live.json
rm -f /opt/winning-wallet-finder/copybot_fills.live.jsonl
rm -f /opt/winning-wallet-finder/live/copybot_live_real.json
systemctl start copybot-live
```

### 监控第一笔成交

```bash
journalctl -u copybot-live -f
```

看到 `FOLLOW` + `[LIVE] order placed` = 第一笔真钱成交。然后去 polymarket.com 用 MetaMask 登录确认仓位。

---

# 完整部署架构

```
服务器
|
+-- mihomo.service              代理（日本节点，127.0.0.1:7890）
|   +-- healthcheck cron        每 5 分钟自动换节点
|
+-- copybot-paper.service       paper bot（直连，不走代理）
|   +-- EnvironmentFile: paper.env（ALCHEMY_RPC_URL）
|   +-- state: copybot_state.json
|   +-- feed: live/copybot_live.json
|
+-- copybot-live.service        live bot（走代理绕 geo-block）
|   +-- EnvironmentFile: live.env（LIVE_PRIVATE_KEY + HTTPS_PROXY + TRADE LIVE）
|   +-- state: copybot_state.live.json
|   +-- feed: live/copybot_live_real.json
|
+-- copybot-dashboard.service   web dashboard（:18080）
|
+-- cron                        每日 02:00 UTC daily.sh
```

---

# 常见坑

| 坑 | 症状 | 解法 |
| --- | --- | --- |
| 没装 duckdb | `ModuleNotFoundError: No module named 'duckdb'` | `pip3 install duckdb --break-system-packages` |
| 没装 polymarket-client | `ModuleNotFoundError: No module named 'polymarket'` | `pip3 install polymarket-client==0.1.0b16` |
| 没装 websocket-client | preflight 报 `No module named 'websocket'` / 日志 `rtds off` | `pip3 install websocket-client` |
| wwf 没配 git identity | commit 报 `Author identity unknown` | §6 最后两行 |
| root 看不到 wwf 仓库 | `dubious ownership` | `git config --global --add safe.directory ...` |
| config.live.json 权限 | `PermissionError: [Errno 13]` | `chown wwf:wwf config.live.json` |
| LIVE_CONFIRM 值错 | `Aborted - LIVE_CONFIRM is set but does not match` | 值必须是 `TRADE LIVE`，不加引号 |
| 私钥有非 ASCII 字符 | `UnicodeEncodeError: 'ascii' codec can't encode` | env 文件里私钥必须是纯 hex（0x + 64 位），不能有中文占位符 |
| 邮箱登录建存款钱包失败 | `Gasless transactions require a Builder API Key` | 用 Builder API 凭证创建（§18.3），或改用 MetaMask 登录 |
| 充错钱包 | bot 余额 $0 | 必须充到存款钱包地址，不是 MetaMask 地址或网站充值地址 |
| geo-gate BLOCKED | `VERDICT: BLOCKED` | 服务器在禁单区，需配代理（Part B） |
| 机场返回假节点 | 节点名是"当前Clash客户端不支持" | wget 加 `--user-agent="clash-verge/v1.7.7"` + `&flag=meta` |
| mihomo 重启丢节点 | 出口 IP 变回美国 | mihomo cache.db 自动记忆；第一次需手动选节点 |
| LEDGER DRIFT | `check_book could not attribute it` | 清空 live state 重来（§23） |
| bot 不自动 commit | dashboard 数据陈旧 | commit-on-change 节流，无新交易不写；手动 commit 见 §9 |
| 浏览器 dashboard 不更新 | 数据没变 | `Ctrl+Shift+R` 强制刷新 |
| cron 时区错 | daily.sh 时间不对 | 服务器 UTC，北京 10:00 = cron `0 2` |
| 防火墙挡 18080 | 浏览器打不开 dashboard | 放行 TCP 18080 |

---

# 日常用的命令

```bash
# === 看日志 ===
journalctl -u copybot-paper -f          # paper bot
journalctl -u copybot-live -f           # live bot
journalctl -u copybot-dashboard -f      # dashboard
journalctl -u mihomo -f                 # 代理

# === 看 dashboard ===
# 浏览器：http://服务器IP:18080/

# === 改配置 ===
nano /opt/winning-wallet-finder/live/copybot.paper.json   # paper 跟单钱包/金额
sudo systemctl restart copybot-paper

nano /opt/winning-wallet-finder/config.live.json          # live 跟单钱包/金额
sudo systemctl restart copybot-live

# === 代理管理 ===
# 看当前节点
curl -s http://127.0.0.1:9090/proxies/GLOBAL | python3 -c "import sys,json;print(json.load(sys.stdin).get('now'))"
# 换节点
curl -s -X PUT http://127.0.0.1:9090/proxies/GLOBAL -H "Content-Type: application/json" -d '{"name":"节点名"}'
# 手动健康检查
/opt/mihomo-healthcheck.sh

# === 停/启动 ===
sudo systemctl stop copybot-live           # 停 live（真钱！）
sudo systemctl start copybot-live
sudo systemctl stop copybot-paper          # 停 paper
sudo systemctl stop mihomo                 # 停代理（live 也会停）

# === 完全卸载 ===
sudo systemctl disable --now copybot-paper copybot-live copybot-dashboard mihomo
sudo rm /etc/systemd/system/copybot-*.service /etc/systemd/system/mihomo.service
sudo userdel wwf
rm -rf /opt/winning-wallet-finder
```
