126 lines
4.0 KiB
Bash
126 lines
4.0 KiB
Bash
# shellcheck shell=bash
|
||
# 由 pull-and-restart.sh / restart.sh 在定义好 ROOT、compose_cmd、run_sudo 之后 source。
|
||
# 统一策略:仅使用宿主机 Nginx;容器 yh_nginx 不再作为入口。
|
||
|
||
YH_COMPOSE_FILES="-f docker-compose.yml -f docker-compose.host-nginx.yml"
|
||
|
||
require_cmd() {
|
||
local c="$1"
|
||
command -v "$c" >/dev/null 2>&1 || {
|
||
echo "错误: 缺少命令 $c,请先安装后重试。" >&2
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
ensure_host_deploy_env() {
|
||
require_cmd systemctl
|
||
require_cmd ss
|
||
require_cmd sed
|
||
require_cmd awk
|
||
}
|
||
|
||
host_nginx_online() {
|
||
command -v systemctl >/dev/null 2>&1 || return 1
|
||
systemctl is-active nginx >/dev/null 2>&1 && return 0
|
||
systemctl is-active nginx.service >/dev/null 2>&1 && return 0
|
||
return 1
|
||
}
|
||
|
||
force_release_port() {
|
||
local p="$1"
|
||
local victims
|
||
victims="$(run_sudo ss -tlnp "sport = :$p" 2>/dev/null | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' | awk '!seen[$0]++')"
|
||
[ -z "$victims" ] && return 0
|
||
|
||
for pid in $victims; do
|
||
[ -z "$pid" ] && continue
|
||
local comm
|
||
comm="$(run_sudo sh -c "cat /proc/$pid/comm 2>/dev/null" || true)"
|
||
if [ "$comm" = "nginx" ]; then
|
||
continue
|
||
fi
|
||
echo "端口 $p 被非宿主机 nginx 进程占用(pid=$pid, comm=${comm:-unknown}),强制停止..."
|
||
run_sudo kill -9 "$pid" 2>/dev/null || true
|
||
done
|
||
}
|
||
|
||
force_release_host_ports() {
|
||
# 先优先停掉所有发布了宿主机 80/443 的容器(最常见冲突源)
|
||
if command -v docker >/dev/null 2>&1; then
|
||
for cid in $(run_sudo docker ps --filter "publish=80" --format "{{.ID}}" 2>/dev/null); do
|
||
[ -n "$cid" ] && run_sudo docker rm -f "$cid" 2>/dev/null || true
|
||
done
|
||
for cid in $(run_sudo docker ps --filter "publish=443" --format "{{.ID}}" 2>/dev/null); do
|
||
[ -n "$cid" ] && run_sudo docker rm -f "$cid" 2>/dev/null || true
|
||
done
|
||
fi
|
||
# 再兜底杀掉非 nginx 的占用进程
|
||
force_release_port 80
|
||
force_release_port 443
|
||
}
|
||
|
||
ensure_host_nginx_started() {
|
||
ensure_host_deploy_env
|
||
force_release_host_ports
|
||
|
||
if host_nginx_online; then
|
||
echo "宿主机 Nginx 在线,跳过启动。"
|
||
return 0
|
||
fi
|
||
echo "宿主机 Nginx 未在线,尝试启动..."
|
||
run_sudo systemctl start nginx 2>/dev/null || run_sudo systemctl start nginx.service
|
||
run_sudo systemctl enable nginx 2>/dev/null || true
|
||
if host_nginx_online; then
|
||
echo "宿主机 Nginx 启动成功。"
|
||
return 0
|
||
fi
|
||
echo "错误: 无法启动宿主机 Nginx,请检查 systemctl status nginx" >&2
|
||
exit 1
|
||
}
|
||
|
||
# 停止本项目 Compose 栈(包含可能残留的 yh_nginx),不停止宿主机 Nginx。
|
||
yh_compose_down() {
|
||
if [ ! -f "$ROOT/docker-compose.host-nginx.yml" ]; then
|
||
compose_cmd down --remove-orphans 2>/dev/null || true
|
||
return 0
|
||
fi
|
||
compose_cmd $YH_COMPOSE_FILES down --remove-orphans 2>/dev/null || true
|
||
}
|
||
|
||
# 仅启动业务容器,不再启动容器 yh_nginx。
|
||
yh_compose_up() {
|
||
if [ ! -f "$ROOT/docker-compose.host-nginx.yml" ]; then
|
||
echo "未找到 docker-compose.host-nginx.yml,使用默认 compose 启动业务容器。"
|
||
compose_cmd up -d --force-recreate mongo api web admin
|
||
return 0
|
||
fi
|
||
compose_cmd $YH_COMPOSE_FILES up -d --force-recreate mongo api web admin
|
||
}
|
||
|
||
# 从模板生成宿主机站点配置,并在配置检查通过后 reload(若离线则 start)。
|
||
yh_install_host_nginx_site_conf() {
|
||
local domain="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
|
||
local tpl="$ROOT/nginx/yuheng.host.conf"
|
||
local out="/etc/nginx/conf.d/${domain}.conf"
|
||
|
||
if [ ! -f "$tpl" ]; then
|
||
echo "未找到 $tpl,跳过宿主机站点配置生成。"
|
||
return 0
|
||
fi
|
||
|
||
ensure_host_deploy_env
|
||
mkdir -p "$ROOT/verify-root"
|
||
sed "s|__VERIFY_ROOT__|$ROOT/verify-root|g" "$tpl" | run_sudo tee "$out" >/dev/null
|
||
|
||
if ! run_sudo nginx -t 2>/dev/null; then
|
||
echo "错误: 宿主机 nginx -t 失败,请检查 $out" >&2
|
||
exit 1
|
||
fi
|
||
|
||
if host_nginx_online; then
|
||
run_sudo systemctl reload nginx 2>/dev/null && echo "宿主机 Nginx 已重载($out)。" || true
|
||
else
|
||
ensure_host_nginx_started
|
||
fi
|
||
}
|