97 lines
2.7 KiB
Bash
Executable File
97 lines
2.7 KiB
Bash
Executable File
#!/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
|