#!/usr/bin/env bash # Docker Desktop 引擎假死自愈(macOS) # 场景:com.docker.backend 在跑,但 Linux 引擎无响应 → 无鲸鱼 / 打不开界面 / docker 报 500 # 策略:仅当「后端进程存在 && docker info 在时限内失败」时执行 docker desktop restart,避免用户完全退出 Docker 时被误拉起。 # # 用法: # bash sdk/scripts/docker_engine_guard.sh # 检查一次,必要时修复 # bash sdk/scripts/docker_engine_guard.sh --dry-run # 只打印将执行的操作,不重启 # bash sdk/scripts/docker_engine_guard.sh --open-ui # 修复后尝试打开仪表盘(适合手动排障) set -uo pipefail # launchd 默认 PATH 极窄,需显式加入 Docker CLI 常见路径 export PATH="/opt/homebrew/bin:/usr/local/bin:${HOME}/.docker/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH:-}" DRY_RUN=false OPEN_UI=false for arg in "$@"; do case "$arg" in --dry-run) DRY_RUN=true ;; --open-ui) OPEN_UI=true ;; esac done if [[ "$(uname -s)" != "Darwin" ]]; then exit 0 fi if [[ ! -d "/Applications/Docker.app" ]]; then exit 0 fi if ! command -v docker >/dev/null 2>&1; then exit 0 fi log_line() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" } # 后端未运行:视为用户未开 Docker,不处理 if ! pgrep -f "com.docker.backend" >/dev/null 2>&1; then log_line "skip: com.docker.backend 未运行" exit 0 fi # 限时探测 docker info(避免 launchd 任务挂死,最多约 15s) info_ok=false docker info >/dev/null 2>&1 & dp=$! for _ in $(seq 1 15); do if ! kill -0 "$dp" 2>/dev/null; then if wait "$dp"; then info_ok=true; fi break fi sleep 1 done if kill -0 "$dp" 2>/dev/null; then kill -9 "$dp" 2>/dev/null || true wait "$dp" 2>/dev/null || true fi if [[ "$info_ok" == true ]]; then log_line "ok: docker info 正常" exit 0 fi log_line "bad: docker info 失败但后端在跑 → 判定引擎假死" if [[ "$DRY_RUN" == true ]]; then log_line "dry-run: 将执行 docker desktop restart" exit 2 fi if docker desktop restart 2>&1; then log_line "done: docker desktop restart 已执行,等待引擎…" else log_line "warn: docker desktop restart 返回非 0" fi for _ in $(seq 1 60); do if docker info >/dev/null 2>&1; then log_line "ok: 引擎已恢复" if [[ "$OPEN_UI" == true ]]; then open "/Applications/Docker.app/Contents/MacOS/Docker Desktop.app" 2>/dev/null || open -a Docker sleep 1 open "docker-desktop://dashboard" 2>/dev/null || true log_line "open-ui: 已尝试打开仪表盘" fi exit 0 fi sleep 2 done log_line "fail: 重启后 docker info 仍失败,请人工:升级 Docker Desktop 或 Troubleshoot → Reset" exit 1