From 5424efd48a9b51e34fd56c84a03cf062791244e7 Mon Sep 17 00:00:00 2001 From: Table Date: Sat, 29 Nov 2025 08:10:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Docker=20=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E4=B8=8B=20SERVER=5FPORT=20=E6=9C=AA=E7=94=9F?= =?UTF-8?q?=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 Makefile 中的 PORT 变量重命名为 SERVER_PORT,更清晰地表示应用端口 - 修复 docker-up-dev/stage/prod 命令中的 sed 命令: * 将 $(PORT) 改为 $(SERVER_PORT) * 修改 sed 命令从 s/[0-9]\+/... 改为 s|port:.*|port: $(SERVER_PORT)| * 这样可以处理 config 文件中 port: 为空的情况 - 修复 dev/stage/prod 命令中的 sed 命令,统一使用新的格式 - 在 main.go 中增加端口为空检查: * 在启动服务器前检查 cfg.Server.Port 是否为空 * 如果为空,输出明确的错误信息并退出,便于排查问题 问题原因: - docker-up-dev 中使用的是 $(PORT) 而不是 $(SERVER_PORT) - 当 port: 为空时,sed 的 s/[0-9]\+/... 无法匹配(需要数字才能匹配) - 改为 s|port:.*|port: ...| 可以处理空值情况 --- Makefile | 70 ++++++++++++++++++++++++++--------------------------- src/main.go | 3 +++ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index ffe66f0..22a5f04 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ DOCKER := docker DOCKER_COMPOSE := $(DOCKER) compose # 应用端口 -PORT := 1234 +SERVER_PORT := 1234 # 默认目标 .PHONY: help @@ -30,8 +30,8 @@ help: ## 显示帮助信息 dev: ## 启动开发环境(本地模式,使用 localhost) @echo "启动开发环境(本地模式)..." @bash -c '\ - PORT=$(PORT); \ - echo "检查端口 $(PORT) 是否被占用..."; \ + PORT=$(SERVER_PORT); \ + echo "检查端口 $(SERVER_PORT) 是否被占用..."; \ PID=""; \ if command -v lsof >/dev/null 2>&1; then \ PID=$$(lsof -ti:$$PORT 2>/dev/null | head -1); \ @@ -98,15 +98,7 @@ dev: ## 启动开发环境(本地模式,使用 localhost) echo "配置本地模式(使用 localhost)..."; \ cp config/dev.yaml config/dev.yaml.bak 2>/dev/null || true; \ sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/dev.yaml; \ - trap "mv config/dev.yaml.bak config/dev.yaml 2>/dev/null; rm -f config/dev.yaml.tmp 2>/dev/null" INT TERM EXIT; \ - $(GO) run src/main.go -env=dev; \ - EXIT_CODE=$$?; \ - mv config/dev.yaml.bak config/dev.yaml 2>/dev/null || true; \ - rm -f config/dev.yaml.tmp 2>/dev/null || true; \ - exit $$EXIT_CODE' - @bash -c '\ - cp config/dev.yaml config/dev.yaml.bak 2>/dev/null || true; \ - sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/dev.yaml; \ + sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/dev.yaml; \ trap "mv config/dev.yaml.bak config/dev.yaml 2>/dev/null; rm -f config/dev.yaml.tmp 2>/dev/null" INT TERM EXIT; \ $(GO) run src/main.go -env=dev; \ EXIT_CODE=$$?; \ @@ -117,26 +109,27 @@ dev: ## 启动开发环境(本地模式,使用 localhost) .PHONY: stage stage: ## 启动预发布环境(本地模式,使用 localhost) @echo "启动预发布环境(本地模式)..." - @echo "检查端口 $(PORT) 是否被占用..." + @echo "检查端口 $(SERVER_PORT) 是否被占用..." @PID=""; \ if command -v lsof >/dev/null 2>&1; then \ - PID=$$(lsof -ti:$(PORT) 2>/dev/null | head -1); \ + PID=$$(lsof -ti:$(SERVER_PORT) 2>/dev/null | head -1); \ fi; \ if [ -z "$$PID" ] && command -v netstat >/dev/null 2>&1; then \ - PID=$$(netstat -tlnp 2>/dev/null | grep ":$(PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \ + PID=$$(netstat -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \ fi; \ if [ -z "$$PID" ] && command -v ss >/dev/null 2>&1; then \ - PID=$$(ss -tlnp 2>/dev/null | grep ":$(PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \ + PID=$$(ss -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \ fi; \ if [ -n "$$PID" ] && [ "$$PID" != "-" ] && [ "$$PID" != "0" ]; then \ - echo "⚠️ 警告: 端口 $(PORT) 已被进程 $$PID 占用"; \ - echo " 提示: 使用 'make kill-$(PORT)' 或 'make kill-port-force PORT=$(PORT)' 终止该进程"; \ + echo "⚠️ 警告: 端口 $(SERVER_PORT) 已被进程 $$PID 占用"; \ + echo " 提示: 使用 'make kill-$(SERVER_PORT)' 或 'make kill-port-force PORT=$(SERVER_PORT)' 终止该进程"; \ echo ""; \ fi; \ echo "配置本地模式(使用 localhost)..." @bash -c '\ cp config/stage.yaml config/stage.yaml.bak 2>/dev/null || true; \ sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/stage.yaml; \ + sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/stage.yaml; \ trap "mv config/stage.yaml.bak config/stage.yaml 2>/dev/null; rm -f config/stage.yaml.tmp 2>/dev/null" INT TERM EXIT; \ $(GO) run src/main.go -env=stage; \ EXIT_CODE=$$?; \ @@ -147,26 +140,27 @@ stage: ## 启动预发布环境(本地模式,使用 localhost) .PHONY: prod prod: ## 启动生产环境(本地模式,使用 localhost) @echo "启动生产环境(本地模式)..." - @echo "检查端口 $(PORT) 是否被占用..." + @echo "检查端口 $(SERVER_PORT) 是否被占用..." @PID=""; \ if command -v lsof >/dev/null 2>&1; then \ - PID=$$(lsof -ti:$(PORT) 2>/dev/null | head -1); \ + PID=$$(lsof -ti:$(SERVER_PORT) 2>/dev/null | head -1); \ fi; \ if [ -z "$$PID" ] && command -v netstat >/dev/null 2>&1; then \ - PID=$$(netstat -tlnp 2>/dev/null | grep ":$(PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \ + PID=$$(netstat -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \ fi; \ if [ -z "$$PID" ] && command -v ss >/dev/null 2>&1; then \ - PID=$$(ss -tlnp 2>/dev/null | grep ":$(PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \ + PID=$$(ss -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \ fi; \ if [ -n "$$PID" ] && [ "$$PID" != "-" ] && [ "$$PID" != "0" ]; then \ - echo "⚠️ 警告: 端口 $(PORT) 已被进程 $$PID 占用"; \ - echo " 提示: 使用 'make kill-$(PORT)' 或 'make kill-port-force PORT=$(PORT)' 终止该进程"; \ + echo "⚠️ 警告: 端口 $(SERVER_PORT) 已被进程 $$PID 占用"; \ + echo " 提示: 使用 'make kill-$(SERVER_PORT)' 或 'make kill-port-force PORT=$(SERVER_PORT)' 终止该进程"; \ echo ""; \ fi; \ echo "配置本地模式(使用 localhost)..." @bash -c '\ cp config/prod.yaml config/prod.yaml.bak 2>/dev/null || true; \ sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/prod.yaml; \ + sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/prod.yaml; \ trap "mv config/prod.yaml.bak config/prod.yaml 2>/dev/null; rm -f config/prod.yaml.tmp 2>/dev/null" INT TERM EXIT; \ $(GO) run src/main.go -env=prod; \ EXIT_CODE=$$?; \ @@ -276,7 +270,7 @@ docker-compose-dev: ## 生成开发环境Docker Compose文件 echo " context: .." >> $(DOCKER_DIR)/docker-compose.dev.yml; \ echo " dockerfile: Dockerfile" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ echo " ports:" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ - echo " - \"$(PORT):$(PORT)\"" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ + echo " - \"$(SERVER_PORT):$(SERVER_PORT)\"" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ echo " environment:" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ echo " - APP_ENV=dev" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ echo " volumes:" >> $(DOCKER_DIR)/docker-compose.dev.yml; \ @@ -293,6 +287,7 @@ docker-up-dev: docker-compose-dev ## 启动开发环境Docker容器 @echo "配置 Docker 模式(使用 host.docker.internal)..." @cp config/dev.yaml config/dev.yaml.bak 2>/dev/null || true; \ sed -i.tmp 's|host: localhost|host: host.docker.internal|g' config/dev.yaml; \ + sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/dev.yaml; \ HOST_IP=$$(hostname -I | awk '{print $$1}' 2>/dev/null || ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $$2}' | cut -d/ -f1); \ if [ -z "$$HOST_IP" ]; then \ mv config/dev.yaml.bak config/dev.yaml 2>/dev/null || true; \ @@ -314,6 +309,7 @@ docker-up-stage: ## 启动预发布环境Docker容器 @echo "配置 Docker 模式(使用 host.docker.internal)..." @cp config/stage.yaml config/stage.yaml.bak 2>/dev/null || true; \ sed -i.tmp 's|host: localhost|host: host.docker.internal|g' config/stage.yaml; \ + sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/stage.yaml; \ HOST_IP=$$(hostname -I | awk '{print $$1}' 2>/dev/null || ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $$2}' | cut -d/ -f1); \ if [ -z "$$HOST_IP" ]; then \ mv config/stage.yaml.bak config/stage.yaml 2>/dev/null || true; \ @@ -324,6 +320,7 @@ docker-up-stage: ## 启动预发布环境Docker容器 echo "使用宿主机 IP: $$HOST_IP"; \ cd $(DOCKER_DIR) && \ sed -i.tmp2 "s|host.docker.internal:[0-9.]*|host.docker.internal:$$HOST_IP|g" docker-compose.stage.yml && \ + sed -i.tmp2 "s|\"1234:1234\"|\"$(SERVER_PORT):$(SERVER_PORT)\"|g" docker-compose.stage.yml && \ $(DOCKER_COMPOSE) -f docker-compose.stage.yml up -d && \ rm -f docker-compose.stage.yml.tmp2; \ mv config/stage.yaml.bak config/stage.yaml 2>/dev/null || true; \ @@ -336,6 +333,7 @@ docker-up-prod: ## 启动生产环境Docker容器 @echo "配置 Docker 模式(使用 host.docker.internal)..." @cp config/prod.yaml config/prod.yaml.bak 2>/dev/null || true; \ sed -i.tmp 's|host: localhost|host: host.docker.internal|g' config/prod.yaml; \ + sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/prod.yaml; \ HOST_IP=$$(hostname -I | awk '{print $$1}' 2>/dev/null || ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $$2}' | cut -d/ -f1); \ if [ -z "$$HOST_IP" ]; then \ mv config/prod.yaml.bak config/prod.yaml 2>/dev/null || true; \ @@ -346,6 +344,8 @@ docker-up-prod: ## 启动生产环境Docker容器 echo "使用宿主机 IP: $$HOST_IP"; \ cd $(DOCKER_DIR) && \ sed -i.tmp2 "s|host.docker.internal:[0-9.]*|host.docker.internal:$$HOST_IP|g" docker-compose.prod.yml && \ + sed -i.tmp2 "s|\"1234:1234\"|\"$(SERVER_PORT):$(SERVER_PORT)\"|g" docker-compose.prod.yml && \ + sed -i.tmp2 "s|http://localhost:[0-9]*/health|http://localhost:$(SERVER_PORT)/health|g" docker-compose.prod.yml && \ $(DOCKER_COMPOSE) -f docker-compose.prod.yml up -d && \ rm -f docker-compose.prod.yml.tmp2; \ mv config/prod.yaml.bak config/prod.yaml 2>/dev/null || true; \ @@ -440,10 +440,10 @@ docker-ps: ## 查看所有Docker容器状态 # 端口管理 .PHONY: kill-port -kill-port: ## 终止指定端口的进程 (用法: make kill-port PORT=$(PORT)) +kill-port: ## 终止指定端口的进程 (用法: make kill-port PORT=$(SERVER_PORT)) @if [ -z "$(PORT)" ]; then \ echo "❌ 错误: 请指定端口号"; \ - echo "用法: make kill-port PORT=$(PORT)"; \ + echo "用法: make kill-port PORT=$(SERVER_PORT)"; \ exit 1; \ fi; \ echo "查找端口 $(PORT) 的进程..."; \ @@ -472,7 +472,7 @@ kill-port: ## 终止指定端口的进程 (用法: make kill-port PORT=$(PORT)) fi .PHONY: kill-port-force -kill-port-force: ## 强制终止指定端口的进程,无需确认 (用法: make kill-port-force PORT=$(PORT)) +kill-port-force: ## 强制终止指定端口的进程,无需确认 (用法: make kill-port-force PORT=$(SERVER_PORT)) @if [ -z "$(PORT)" ]; then \ echo "❌ 错误: 请指定端口号"; \ echo "用法: make kill-port-force PORT=$(PORT)"; \ @@ -498,21 +498,21 @@ kill-port-force: ## 强制终止指定端口的进程,无需确认 (用法: ma echo "进程信息: $$PROCESS_INFO"; \ kill -9 $$PID 2>/dev/null && echo "✅ 已强制终止进程 $$PID" || echo "❌ 终止进程失败" -.PHONY: kill-$(PORT) -kill-$(PORT): ## 终止端口 $(PORT) 的进程(应用默认端口) - @echo "终止端口 $(PORT) 的进程..." +.PHONY: kill-$(SERVER_PORT) +kill-$(SERVER_PORT): ## 终止端口 $(SERVER_PORT) 的进程(应用默认端口) + @echo "终止端口 $(SERVER_PORT) 的进程..." @PID=""; \ if command -v lsof >/dev/null 2>&1; then \ - PID=$$(lsof -ti:$(PORT) 2>/dev/null | head -1); \ + PID=$$(lsof -ti:$(SERVER_PORT) 2>/dev/null | head -1); \ fi; \ if [ -z "$$PID" ] && command -v netstat >/dev/null 2>&1; then \ - PID=$$(netstat -tlnp 2>/dev/null | grep ":$(PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \ + PID=$$(netstat -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \ fi; \ if [ -z "$$PID" ] && command -v ss >/dev/null 2>&1; then \ - PID=$$(ss -tlnp 2>/dev/null | grep ":$(PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \ + PID=$$(ss -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \ fi; \ if [ -z "$$PID" ] || [ "$$PID" = "-" ] || [ "$$PID" = "0" ]; then \ - echo "✅ 端口 $(PORT) 未被占用"; \ + echo "✅ 端口 $(SERVER_PORT) 未被占用"; \ exit 0; \ fi; \ echo "找到进程 PID: $$PID"; \ diff --git a/src/main.go b/src/main.go index 0a75b82..5ec37aa 100644 --- a/src/main.go +++ b/src/main.go @@ -79,6 +79,9 @@ func main() { } // 启动服务器 + if cfg.Server.Port == "" { + log.Fatalf("❌ 错误: 服务器端口配置为空!请检查配置文件中的 server.port 设置") + } log.Printf("服务器启动在端口 %s,环境: %s", cfg.Server.Port, env) // 优雅关闭