From f8b2bf2afce5528a510183652c339712e4555bb5 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 1 Apr 2026 10:47:40 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=83=A8=E7=BD=B2=E8=84=9A?= =?UTF-8?q?=E6=9C=ACnetstat=E7=AB=AF=E5=8F=A3=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/prod/deploy_from_package.sh | 13 ++++++-- bin/prod/deploy_from_package_test.sh | 23 +++++++++++++ ...ction-one-click-deploy-netstat-fallback.md | 32 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 doc/implementation-report-2026-04-01-production-one-click-deploy-netstat-fallback.md diff --git a/bin/prod/deploy_from_package.sh b/bin/prod/deploy_from_package.sh index 10848c3..f527416 100755 --- a/bin/prod/deploy_from_package.sh +++ b/bin/prod/deploy_from_package.sh @@ -65,7 +65,11 @@ require_port_command() { return 0 fi - log_error "缺少端口检测命令: ss 或 lsof" + if command -v netstat >/dev/null 2>&1; then + return 0 + fi + + log_error "缺少端口检测命令: ss、lsof 或 netstat" exit 1 } @@ -177,7 +181,12 @@ is_port_listening() { return $? fi - lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1 + if command -v lsof >/dev/null 2>&1; then + lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1 + return $? + fi + + netstat -an 2>/dev/null | grep -E "[\\.:]$port[[:space:]].*LISTEN" >/dev/null 2>&1 } is_managed_backend_pid() { diff --git a/bin/prod/deploy_from_package_test.sh b/bin/prod/deploy_from_package_test.sh index 6959798..4cc94b1 100755 --- a/bin/prod/deploy_from_package_test.sh +++ b/bin/prod/deploy_from_package_test.sh @@ -182,10 +182,33 @@ test_multiple_release_zip_should_fail() { cleanup_release_dir "$release_dir" } +test_netstat_fallback_should_work() { + release_dir=$(mktemp -d) + backend_port=$(find_free_port) + trap 'cleanup_release_dir "$release_dir"' EXIT INT TERM + + prepare_release_dir "$release_dir" "$backend_port" + mkdir -p "$release_dir/fake-port-bin" + ln -sf /usr/sbin/netstat "$release_dir/fake-port-bin/netstat" + + ( + cd "$release_dir" + PATH="$release_dir/fake-port-bin:/usr/bin:/bin" ./deploy_from_package.sh + ) + + assert_file_exists "$release_dir/frontend/dist/index.html" + backend_pid=$(cat "$release_dir/backend/backend.pid") + kill -0 "$backend_pid" 2>/dev/null || fail "expected backend pid to be running with netstat fallback" + + trap - EXIT INT TERM + cleanup_release_dir "$release_dir" +} + main() { [ -f "$SCRIPT_UNDER_TEST" ] || fail "script under test not found: $SCRIPT_UNDER_TEST" test_deploy_success test_multiple_release_zip_should_fail + test_netstat_fallback_should_work printf 'PASS: deploy_from_package tests\n' } diff --git a/doc/implementation-report-2026-04-01-production-one-click-deploy-netstat-fallback.md b/doc/implementation-report-2026-04-01-production-one-click-deploy-netstat-fallback.md new file mode 100644 index 0000000..3473736 --- /dev/null +++ b/doc/implementation-report-2026-04-01-production-one-click-deploy-netstat-fallback.md @@ -0,0 +1,32 @@ +# 生产一键部署脚本 netstat 端口检测兼容实施记录 + +## 问题现象 +- 运行 `bin/prod/deploy_from_package.sh` 时出现报错: + - `[2026-04-01 02:45:09] 缺少端口检测命令: ss 或 lsof` + +## 根因分析 +- 脚本启动后端前会先检查端口检测命令 +- 之前的实现只支持 `ss` 和 `lsof` +- 用户实际环境中两者都不可用,因此脚本在前置校验阶段直接退出 +- 当前仓库开发环境中还存在 `netstat`,说明“只支持 `ss`/`lsof`”不是部署链路本身的要求,而是脚本实现约束过窄 + +## 修改内容 +- 更新 `bin/prod/deploy_from_package.sh` +- 将端口检测命令支持范围从: + - `ss` + - `lsof` + 扩展为: + - `ss` + - `lsof` + - `netstat` +- 更新端口检测失败提示文案为“缺少端口检测命令: ss、lsof 或 netstat” +- 更新 `bin/prod/deploy_from_package_test.sh` +- 新增 `netstat` 回退场景自测,验证在 `PATH` 中无 `ss`、无 `lsof`、仅有 `netstat` 时脚本仍可正常完成部署 + +## 验证结果 +- 已执行 `sh -n bin/prod/deploy_from_package.sh` +- 已执行 `sh bin/prod/deploy_from_package_test.sh` +- 自测结果覆盖: + - 正常部署成功 + - 多个发布 zip 失败 + - 仅 `netstat` 可用时,端口监听检测仍然通过