根因確認: - _diag/pages 衝突發生在 "Set up job" 階段 - 這是在任何自定義步驟執行之前 - Runner 內部 bug,workflow 層清理無法解決 永久解決方案: - cancel-in-progress: true (確保同一時間只有一個 workflow) - 不再嘗試清理 RUNNER_TEMP (會破壞其他 Job) - 保留 _diag/pages 清理作為輔助措施 更新 ops/runner/README.md: - 完整根因分析 - v3 最終解決方案說明 - 警告: 不要清理 RUNNER_TEMP Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GitHub Actions Runner 穩定性修復
問題: _diag/pages 檔案衝突
Error: The file '/home/wooo/actions-runner-awoooi/_diag/pages/xxx.log' already exists.
根因分析 (2026-03-29 完整診斷)
- 發生時機: "Set up job" 階段 (在任何自定義步驟之前)
- 原因: GitHub Actions Runner 內部 bug
- Runner 在 Job 初始化時寫入
_diag/pages/*.log - 並行執行的多個 Job 可能寫入相同的 UUID 檔案
- 這發生在我們的清理步驟執行之前
- Runner 在 Job 初始化時寫入
- 次要問題:
RUNNER_TEMP共享_work/_temp/_runner_file_commands在所有 Jobs 之間共享- 清理此目錄會導致 "Missing file at path" 錯誤
解決方案 (v3 - 最終版)
1. Workflow Concurrency (核心修復)
concurrency:
group: cd-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 必須為 true!
關鍵: cancel-in-progress: true 確保同一時間只有一個 workflow 在執行
2. Job 層清理 (輔助)
每個 Job 開始時只清理 _diag/pages,不碰 RUNNER_TEMP:
- name: "Clean Runner Diagnostics"
run: |
RUNNER_ROOT=$(dirname "$(dirname "$RUNNER_TEMP")")
rm -rf "$RUNNER_ROOT/_diag/pages" .claude/worktrees 2>/dev/null || true
mkdir -p "$RUNNER_ROOT/_diag/pages" 2>/dev/null || true
警告: 絕對不要清理 $RUNNER_TEMP/*,會破壞其他 Job 的內部通訊
2. Systemd Timer (背景清理)
每 5 分鐘自動清理過期的診斷檔案:
# 部署
ssh wooo@192.168.0.110
cd /path/to/awoooi/ops/runner
bash deploy-runner-cleanup.sh
檔案說明
| 檔案 | 用途 |
|---|---|
cleanup-runner-diag.sh |
清理腳本 (安裝到 Runner 目錄) |
runner-diag-cleanup.service |
Systemd service 定義 |
runner-diag-cleanup.timer |
Systemd timer (每 5 分鐘) |
deploy-runner-cleanup.sh |
一鍵部署腳本 |
監控
# 查看 timer 狀態
sudo systemctl status runner-diag-cleanup.timer
# 查看清理日誌
journalctl -u runner-diag-cleanup.service -f
# 手動觸發清理
sudo systemctl start runner-diag-cleanup.service
相關文件
- Memory:
feedback_runner_zombie_process.md - ADR: 待建立 (如果問題持續)
版本: v1.0 | 建立: 2026-03-29 | 作者: Claude Code