This commit is contained in:
2026-07-05 14:43:34 +08:00
commit 17a8027b20
277 changed files with 63794 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
echo "--- Check nginx processes ---"
ps -efL | grep -E "nginx|openresty" | grep -v grep
echo "--- Sleep 3s, then check again ---"
sleep 3
ps -efL | grep -E "nginx" | grep -v grep | head -5
echo "--- Find master ---"
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Master PID: $NGINX_MASTER"
if [ -n "$NGINX_MASTER" ]; then
kill -HUP "$NGINX_MASTER"
sleep 2
echo "--- TEST uploads ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "--- TEST api ---"
curl -o /dev/null -s -w "HTTP %{http_code}\n" http://localhost/api/v1/banners
fi
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
# 清理 home_config 表被前一次错误 absolutize 污染的数据
# - 把所有 "http://124.221.67.199:3000/" 前缀的"假URL"还原成原文本
# - 只在 home_config 表中清理,不动上传文件路径(那些是真的需要 base 的)
set -e
PASSWORD="Szgt888."
HOST="124.221.67.199"
USER="root"
sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${USER}@${HOST} "mysql -uyygh_app -p'Yygh@2026#App' yuyueguahao -e \"
SET @b = 'http://124.221.67.199:3000/';
-- 看一眼当前数据
SELECT 'BEFORE' AS phase, data FROM home_config WHERE id=1 \G
-- 清理被错误 absolutize 的非 URL 字段:把所有 BASE 前缀剔除(仅针对 home_config.data 字段)
UPDATE home_config
SET data = REPLACE(data, @b, '')
WHERE id = 1
AND data LIKE CONCAT('%', @b, '%');
-- 看一眼清理后
SELECT 'AFTER' AS phase, data FROM home_config WHERE id=1 \G
\" 2>&1"
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
echo "--- 1. Express on 3000 - direct test ---"
curl -o /dev/null -s -w "API direct 3000: HTTP %{http_code}\n" http://127.0.0.1:3000/api/v1/banners
curl -o /dev/null -s -w "Uploads direct 3000: HTTP %{http_code} size=%{size_download}\n" http://127.0.0.1:3000/uploads/1781403331659-1cac3cac.png
echo "--- 2. Nginx proxy test ---"
curl -o /dev/null -s -w "API nginx 80: HTTP %{http_code}\n" http://127.0.0.1:80/api/v1/banners
curl -o /dev/null -s -w "Uploads nginx 80: HTTP %{http_code} size=%{size_download}\n" http://127.0.0.1:80/uploads/1781403331659-1cac3cac.png
echo "--- 3. Check if Express is actually listening ---"
ss -tlnp 2>/dev/null | grep 3000
echo "--- 4. List of PM2 processes ---"
ps -ef | grep -E "pm2|node" | grep -v grep | head -5
echo "--- 5. Check what openresty config is reading ---"
cat /etc/nginx/sites-enabled/yuyueguahao | grep -A1 "location /uploads"
cat /etc/nginx/sites-enabled/yuyueguahao | grep -A1 "location /api"
echo "--- 6. Error log fresh ---"
tail -5 /var/log/nginx/error.log
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
echo "--- Test: what does nginx see? ---"
echo "--- Express handler for unknown route ---"
curl -v http://127.0.0.1:3000/api/v1/banners 2>&1 | grep -E "HTTP|Server|Content-Type" | head -3
echo "--- Test with Host header ---"
curl -v -H "Host: 124.221.67.199" http://127.0.0.1:3000/api/v1/banners 2>&1 | grep -E "HTTP|< " | head -5
echo "--- Test with X-Forwarded-Proto header (like nginx sends) ---"
curl -v -H "Host: 124.221.67.199" -H "X-Forwarded-Proto: http" -H "X-Real-IP: 1.2.3.4" http://127.0.0.1:3000/api/v1/banners 2>&1 | grep -E "HTTP|< " | head -5
echo "--- Test Express trust proxy setting ---"
grep -E "trust.proxy|app.set" /opt/yuyueguahao/server/src/index.js | head -5
echo "--- Curl the configured express IP directly ---"
curl -v -H "Host: localhost" http://127.0.0.1:3000/api/v1/banners 2>&1 | grep -E "HTTP|< |^>" | head -8
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
echo "--- Network namespace of openresty vs node ---"
NGINX_PID=$(ps -efL | grep "nginx" | grep -v grep | awk '{print $2}' | head -1)
NODE_PID=$(ps -efL | grep "node /opt/yuyueguahao" | grep -v grep | awk '{print $2}' | head -1)
echo "nginx: $NGINX_PID, node: $NODE_PID"
# readlink /proc/PID/ns/net
echo "nginx netns: $(readlink /proc/$NGINX_PID/ns/net)"
echo "node netns: $(readlink /proc/$NODE_PID/ns/net)"
echo "--- /etc/hosts in both contexts ---"
ls -la /proc/$NGINX_PID/root/etc/hosts 2>&1
cat /proc/$NGINX_PID/root/etc/hosts 2>&1 | head
echo "--- Test connectivity from nginx's network ns to 3000 ---"
# Run a process in nginx's netns and test
NS=$(readlink /proc/$NGINX_PID/ns/net)
echo "Testing from netns: $NS"
echo "--- Use nsenter to test ---"
nsenter -t $NGINX_PID -n -- curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 5 http://127.0.0.1:3000/api/v1/banners
nsenter -t $NGINX_PID -n -- curl -s -o /dev/null -w "HTTP %{http_code} size=%{size_download}\n" --max-time 5 http://127.0.0.1:3000/uploads/1781403331659-1cac3cac.png
echo "--- Check if /uploads is being intercepted somewhere ---"
ls -la /proc/$NGINX_PID/root/opt/yuyueguahao/uploads 2>&1
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/expect -f
# deploy-phase-hospitalimg.exp
# 部署 hospitalImage 模块 + admin 更新到 124.221.67.199
set timeout 30
set password "Szgt888."
set host "124.221.67.199"
set user "root"
set remote_dir "/root/yuyueguahao"
# 1. 上传后端新文件
spawn scp -r $argv \
${user}@${host}:${remote_dir}/
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
# 完整部署脚本:上传后端 + 管理后台代码到服务器并重启
# 版本:v2.1
set -e
SERVER="124.221.67.199"
USER="root"
PASS="Szgt888."
REMOTE_DIR="/opt/yuyueguahao/server"
LOCAL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=10"
SCP_OPTS="-o StrictHostKeyChecking=no"
echo "=== 苏州肛泰中医院 · 完整部署 v2.0 ==="
echo "本地目录: $LOCAL_DIR"
echo "服务器: $USER@$SERVER:$REMOTE_DIR"
echo ""
echo "=== 1. 上传后端全部代码 ==="
sshpass -p "$PASS" ssh $SSH_OPTS "$USER@$SERVER" "mkdir -p $REMOTE_DIR/src/modules/wechat"
sshpass -p "$PASS" scp $SCP_OPTS -r "$LOCAL_DIR/server/src/" "$USER@$SERVER:$REMOTE_DIR/src/"
echo " 后端代码已上传"
echo "=== 2. 上传管理后台 ==="
sshpass -p "$PASS" scp $SCP_OPTS "$LOCAL_DIR/admin/app.js" "$USER@$SERVER:$REMOTE_DIR/admin/"
sshpass -p "$PASS" scp $SCP_OPTS "$LOCAL_DIR/admin/index.html" "$USER@$SERVER:$REMOTE_DIR/admin/"
echo " 管理后台已上传"
echo "=== 3. 安装后端依赖 ==="
sshpass -p "$PASS" ssh $SSH_OPTS "$USER@$SERVER" "cd $REMOTE_DIR && npm install --production 2>&1 | tail -5"
echo "=== 4. 重启后端服务 ==="
sshpass -p "$PASS" ssh $SSH_OPTS "$USER@$SERVER" "cd $REMOTE_DIR && pm2 restart yuyueguahao-api 2>&1 || pm2 start src/index.js --name yuyueguahao-api 2>&1"
echo "=== 5. 等待服务启动 ==="
sleep 3
echo "=== 6. 验证 API ==="
sshpass -p "$PASS" ssh $SSH_OPTS "$USER@$SERVER" "curl -s http://127.0.0.1:3000/api/v1/wechat/phone-required && echo '' && curl -s http://127.0.0.1:3000/api/v1/banners | head -c 100 && echo ''"
echo ""
echo "=== 部署完成!==="
echo "管理后台: https://y.szgtlive.com/admin/"
echo "请检查电话设置中是否显示:AppID / AppSecret / 手机号获取开关"
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/expect -f
# 部署 hospitalImage 模块 + admin 更新到 124.221.67.199
# 用法: expect deploy-hospitalimg.exp
set timeout 60
set password "Szgt888."
set host "124.221.67.199"
set user "root"
set remote_dir "/opt/yuyueguahao"
# 1. 上传后端新文件 (hospitalImage + upload + seed + index.js + modules/index.js + schema.sql)
puts "\n>>> STEP 1: 上传后端新文件..."
foreach f {
server/src/modules/hospitalImage
server/src/modules/upload
server/src/seeds/hospitalImages.js
server/src/modules/index.js
server/src/index.js
server/src/schema.sql
} {
spawn scp -r $f ${user}@${host}:${remote_dir}/$f
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
}
# 2. 上传 admin 更新
puts "\n>>> STEP 2: 上传 admin 更新..."
spawn scp admin/app.js admin/index.html ${user}@${host}:${remote_dir}/admin/
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
# 3. 重启 PM2
puts "\n>>> STEP 3: 重启 PM2..."
spawn ssh ${user}@${host} "cd ${remote_dir}/server && pm2 restart yuyueguahao-api 2>&1; sleep 3; pm2 list 2>&1 | head -10"
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
# 4. 验证接口
puts "\n>>> STEP 4: 验证接口..."
spawn ssh ${user}@${host} "curl -s 'http://localhost:3000/api/v1/hospital-images?enabled=true' && echo '' && echo '---uploads---' && curl -s -X POST http://localhost:3000/api/v1/uploads/image -H 'Content-Type: application/json' -H 'Authorization: Bearer xxx' -d '{\"url\":\"https://picsum.photos/200\"}'"
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
puts "\n>>> DEPLOY DONE"
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/expect -f
# 部署 home/hospital 简化版 + admin 轮播图上传
# 用法: expect deploy-v3-simplify.exp
set timeout 60
set password "Szgt888."
set host "124.221.67.199"
set user "root"
set remote_dir "/opt/yuyueguahao"
# 1. 上传 admin
puts "\n>>> STEP 1: 上传 admin/app.js..."
spawn scp admin/app.js ${user}@${host}:${remote_dir}/admin/app.js
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
# 2. 验证接口 (无需重启,前端代码 + admin 都是静态资源,只要后端有接口)
puts "\n>>> STEP 2: 验证接口..."
spawn ssh ${user}@${host} "curl -s 'http://localhost:3000/api/v1/banners?enabled=true' | head -c 800; echo ''; echo '---hosp-images---'; curl -s 'http://localhost:3000/api/v1/hospital-images?enabled=true' | head -c 800"
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
puts "\n>>> DEPLOY DONE"
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/expect -f
# 部署 Phase 7 - upload 重做 + centers + home-intro + admin 重构
# 用法: expect deploy-v4-cleanup.exp
set timeout 60
set password "Szgt888."
set host "124.221.67.199"
set user "root"
set remote_dir "/opt/yuyueguahao"
puts "\n>>> STEP 1: 上传后端 (新模块 + 改动)"
foreach f {
server/src/modules/upload
server/src/modules/center
server/src/modules/homeIntro
server/src/seeds/centers.js
server/src/modules/index.js
server/src/index.js
server/src/schema.sql
} {
spawn scp -r $f ${user}@${host}:${remote_dir}/$f
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
}
puts "\n>>> STEP 2: 上传 admin"
foreach f {
admin/app.js
admin/index.html
admin/styles.css
} {
spawn scp $f ${user}@${host}:${remote_dir}/$f
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
}
puts "\n>>> STEP 3: 重启 PM2 + 验证新表自动创建"
spawn ssh ${user}@${host} "cd ${remote_dir}/server && pm2 restart yuyueguahao-api 2>&1; sleep 3; pm2 logs yuyueguahao-api --lines 20 --nostream 2>&1 | head -40"
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
puts "\n>>> STEP 4: 验证 endpoints"
spawn ssh ${user}@${host} "echo '---/api/v1/centers---' && curl -s 'http://localhost:3000/api/v1/centers' && echo '' && echo '---/api/v1/home-intro---' && curl -s 'http://localhost:3000/api/v1/home-intro' && echo '' && echo '---/api/v1/banners---' && curl -s 'http://localhost:3000/api/v1/banners' | head -c 300"
expect {
"password:" { send "$password\r" }
"yes/no" { send "yes\r"; exp_continue }
}
expect eof
puts "\n>>> DEPLOY DONE"
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/expect -f
# 部署 Phase 8: upload 修复 + tabBar 图标 + 电话直拨 + 后台电话设置
set timeout 60
set password "Szgt888."
set host "124.221.67.199"
set user "root"
set remote_dir "/opt/yuyueguahao"
puts "\n>>> STEP 1: 上传后端"
foreach f {
server/src/modules/upload/route.js
server/src/modules/config/route.js
server/src/modules/config/service.js
server/src/index.js
} {
spawn scp $f ${user}@${host}:${remote_dir}/$f
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
}
puts "\n>>> STEP 2: 上传 admin"
foreach f {
admin/app.js
admin/index.html
} {
spawn scp $f ${user}@${host}:${remote_dir}/$f
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
}
puts "\n>>> STEP 3: 确保 server/uploads 存在"
spawn ssh ${user}@${host} "mkdir -p ${remote_dir}/server/uploads && chmod 755 ${remote_dir}/server/uploads && ls -la ${remote_dir}/server/uploads/ && echo '---RESTART---' && pm2 restart yuyueguahao-api 2>&1 && sleep 2"
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
puts "\n>>> STEP 4: 验证"
spawn ssh ${user}@${host} "echo '---site---' && curl -s 'http://localhost:3000/api/v1/config/site' && echo '' && echo '---upload test (with valid auth)---'"
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
puts "\n>>> DONE"
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/expect -f
# 部署:图片 URL 绝对化修复
# - 后端:新增 utils/url.js + 4 个 DTO 应用 toAbsoluteUrl + config/service.js 递归应用
# - 前端:services/request.ts 设置 BASE_URL 为公网地址
# - 重启 PM2 让后端生效;前端需要在小程序开发工具里点"编译"重新构建
set timeout 60
set password "Szgt888."
set host "124.221.67.199"
set user "root"
set remote_dir "/opt/yuyueguahao"
puts "\n>>> STEP 1: 上传后端 (新增 url.js + 修改 5 个文件)"
foreach f {
server/src/utils/url.js
server/src/modules/upload/route.js
server/src/modules/banner/dto.js
server/src/modules/center/dto.js
server/src/modules/homeIntro/dto.js
server/src/modules/hospitalImage/dto.js
server/src/modules/config/service.js
} {
spawn scp $f ${user}@${host}:${remote_dir}/$f
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
}
puts "\n>>> STEP 2: 重启 PM2"
spawn ssh ${user}@${host} "pm2 restart yuyueguahao-api 2>&1 && sleep 2"
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
puts "\n>>> STEP 3: 验证 API 返回的 URL 是绝对地址"
spawn ssh ${user}@${host} "echo '--- banners ---' && curl -s 'http://localhost:3000/api/v1/banners?enabled=true' | head -c 600 && echo '' && echo '--- centers ---' && curl -s 'http://localhost:3000/api/v1/centers?enabled=true' | head -c 600 && echo '' && echo '--- home-intro ---' && curl -s 'http://localhost:3000/api/v1/home-intro' | head -c 600 && echo '' && echo '--- config/home ---' && curl -s 'http://localhost:3000/api/v1/config/home' | head -c 600"
expect { "password:" { send "$password\r" } "yes/no" { send "yes\r"; exp_continue } }
expect eof
puts "\n>>> DONE - 后端已部署。请在小程序开发者工具中点'编译'重新构建前端"
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
# 一键部署:图片 URL 绝对化修复
set -e
PASSWORD="Szgt888."
HOST="124.221.67.199"
USER="root"
REMOTE="/opt/yuyueguahao"
SSH="sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${USER}@${HOST}"
SCP="sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
echo ">>> STEP 1: 上传后端文件"
$SCP server/src/utils/url.js ${USER}@${HOST}:${REMOTE}/server/src/utils/url.js
$SCP server/src/modules/upload/route.js ${USER}@${HOST}:${REMOTE}/server/src/modules/upload/route.js
$SCP server/src/modules/banner/dto.js ${USER}@${HOST}:${REMOTE}/server/src/modules/banner/dto.js
$SCP server/src/modules/center/dto.js ${USER}@${HOST}:${REMOTE}/server/src/modules/center/dto.js
$SCP server/src/modules/homeIntro/dto.js ${USER}@${HOST}:${REMOTE}/server/src/modules/homeIntro/dto.js
$SCP server/src/modules/hospitalImage/dto.js ${USER}@${HOST}:${REMOTE}/server/src/modules/hospitalImage/dto.js
$SCP server/src/modules/config/service.js ${USER}@${HOST}:${REMOTE}/server/src/modules/config/service.js
echo " OK"
echo ">>> STEP 2: 重启 PM2"
$SSH "pm2 restart yuyueguahao-api 2>&1 && sleep 2"
echo " OK"
echo ">>> STEP 3: 验证 API 返回的 URL 是否绝对化"
echo "--- banners ---"
$SSH "curl -s 'http://localhost:3000/api/v1/banners?enabled=true' | head -c 500"
echo ""
echo ""
echo "--- centers ---"
$SSH "curl -s 'http://localhost:3000/api/v1/centers?enabled=true' | head -c 500"
echo ""
echo ""
echo "--- home-intro ---"
$SSH "curl -s 'http://localhost:3000/api/v1/home-intro' | head -c 500"
echo ""
echo ""
echo "--- home config (取前 800 字符) ---"
$SSH "curl -s 'http://localhost:3000/api/v1/config/home' | head -c 800"
echo ""
echo ""
echo "--- 找一个 banner image URL 测试可访问性 ---"
$SSH "curl -s 'http://localhost:3000/api/v1/banners?enabled=true' | python3 -c 'import json,sys;d=json.load(sys.stdin)[\"data\"];print(\"first image url:\", d[0][\"image\"] if d else \"(empty)\")' 2>/dev/null || echo '(no banner)'"
echo ""
echo ">>> DONE"
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
set -e
PASSWORD="Szgt888."
HOST="124.221.67.199"
USER="root"
REMOTE="/opt/yuyueguahao"
SSH="sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${USER}@${HOST}"
SCP="sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
echo ">>> STEP 1: 上传 server/src/utils/url.js"
$SCP server/src/utils/url.js ${USER}@${HOST}:${REMOTE}/server/src/utils/url.js
echo " OK"
echo ""
echo ">>> STEP 2: 重启 PM2 (PUBLIC_BASE_URL=https://y.szgtlive.com)"
$SSH "pm2 restart yuyueguahao-api --update-env 2>&1 && sleep 2"
echo " OK"
echo ""
echo ">>> STEP 3: 验证 API 返回的 URL 是 https://y.szgtlive.com"
echo "--- banners ---"
$SSH "curl -s 'http://localhost:3000/api/v1/banners?enabled=true' | head -c 400"
echo ""
echo ""
echo "--- home-intro ---"
$SSH "curl -s 'http://localhost:3000/api/v1/home-intro' | head -c 400"
echo ""
echo ""
echo "--- home config ---"
$SSH "curl -s 'http://localhost:3000/api/v1/config/home' | head -c 500"
echo ""
echo ""
echo ">>> STEP 4: 通过 HTTPS 域名访问最终 URL"
echo "--- HTTPS API (经 Nginx 443) ---"
curl -s --max-time 10 "https://y.szgtlive.com/api/v1/banners?enabled=true" | head -c 400
echo ""
echo ""
echo "--- HTTPS 图片 (经 Nginx 443) ---"
curl -s -o /dev/null -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" --max-time 10 "https://y.szgtlive.com/uploads/1781403331659-1cac3cac.png"
echo ""
echo ">>> DONE"
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
# 部署 admin/ 后台优化(删除医生/专家/科室 + 简化电话设置)
set -e
PASSWORD="Szgt888."
HOST="124.221.67.199"
USER="root"
REMOTE="/opt/yuyueguahao"
SSH="sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ${USER}@${HOST}"
SCP="sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
echo ">>> STEP 1: 上传 admin 文件"
$SCP admin/index.html ${USER}@${HOST}:${REMOTE}/admin/index.html
$SCP admin/app.js ${USER}@${HOST}:${REMOTE}/admin/app.js
echo " OK"
echo ">>> STEP 2: 验证服务器上的文件已更新"
$SSH "stat -c '%y %s %n' /opt/yuyueguahao/admin/index.html /opt/yuyueguahao/admin/app.js"
echo ""
echo ">>> STEP 3: 验证 admin/app.js 不再含医生/专家/科室"
echo "--- DEPT_OPTIONS ---"
$SSH "grep -c 'DEPT_OPTIONS' /opt/yuyueguahao/admin/app.js"
echo "--- renderDoctors ---"
$SSH "grep -c 'renderDoctors' /opt/yuyueguahao/admin/app.js"
echo "--- renderExperts ---"
$SSH "grep -c 'renderExperts' /opt/yuyueguahao/admin/app.js"
echo "--- renderDepartments ---"
$SSH "grep -c 'renderDepartments' /opt/yuyueguahao/admin/app.js"
echo "--- sitePhone2/siteWorkHours/siteAddress/siteWechat (应为 0) ---"
$SSH "grep -cE 'sitePhone2|siteWorkHours|siteAddress|siteWechat' /opt/yuyueguahao/admin/app.js"
echo "--- sitePhone (应为 >0) ---"
$SSH "grep -c 'sitePhone' /opt/yuyueguahao/admin/app.js"
echo ""
echo ">>> STEP 4: 验证侧栏(HTML 中应只剩 7 个 side-link)"
$SSH "grep -c 'side-link' /opt/yuyueguahao/admin/index.html"
echo "--- 关键导航文字(医生/专家/科室应为 0)---"
$SSH "grep -cE '医生|专家|科室' /opt/yuyueguahao/admin/index.html"
echo ""
echo ">>> STEP 5: 验证 admin 可访问(HTTP 200 + 关键内容)"
$SSH "curl -s -o /dev/null -w 'HTTP %{http_code} size=%{size_download}\n' https://y.szgtlive.com/admin/index.html"
echo "--- 通过 nginx 访问 admin/app.js(同样应 200)---"
$SSH "curl -s -o /dev/null -w 'HTTP %{http_code} size=%{size_download}\n' https://y.szgtlive.com/admin/app.js"
echo ""
echo ">>> DONE"
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
# 部署脚本:上传后端+管理后台代码到服务器并重启
set -e
SERVER="124.221.67.199"
USER="root"
PASS="Szgt888."
REMOTE_DIR="/opt/yuyueguahao/server"
LOCAL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
echo "=== 1. 上传后端 wechat 模块 ==="
sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no "$USER@$SERVER" "mkdir -p $REMOTE_DIR/src/modules/wechat"
sshpass -p "$PASS" scp -o StrictHostKeyChecking=no \
"$LOCAL_DIR/server/src/modules/wechat/service.js" \
"$LOCAL_DIR/server/src/modules/wechat/route.js" \
"$USER@$SERVER:$REMOTE_DIR/src/modules/wechat/"
echo "=== 2. 上传后端 modules/index.js ==="
sshpass -p "$PASS" scp -o StrictHostKeyChecking=no \
"$LOCAL_DIR/server/src/modules/index.js" \
"$USER@$SERVER:$REMOTE_DIR/src/modules/"
echo "=== 3. 上传后端 index.js ==="
sshpass -p "$PASS" scp -o StrictHostKeyChecking=no \
"$LOCAL_DIR/server/src/index.js" \
"$USER@$SERVER:$REMOTE_DIR/src/"
echo "=== 4. 上传管理后台 ==="
sshpass -p "$PASS" scp -o StrictHostKeyChecking=no \
"$LOCAL_DIR/admin/app.js" \
"$USER@$SERVER:$REMOTE_DIR/admin/"
echo "=== 5. 重启后端服务 ==="
sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no "$USER@$SERVER" \
"cd $REMOTE_DIR && npm install --production 2>&1 | tail -5 && pm2 restart yuyueguahao-api 2>&1 || pm2 start src/index.js --name yuyueguahao-api 2>&1"
echo "=== 6. 验证 ==="
sleep 3
sshpass -p "$PASS" ssh -o StrictHostKeyChecking=no "$USER@$SERVER" \
"curl -s http://127.0.0.1:3000/api/v1/wechat/phone-required | head -c 200"
echo ""
echo "=== 部署完成 ==="
+27
View File
@@ -0,0 +1,27 @@
#!/bin/bash
NGINX_PID=$(ps -efL | grep "nginx" | grep -v grep | awk '{print $2}' | head -1)
echo "nginx PID: $NGINX_PID"
echo ""
echo "--- 1. Find host's IP from container's perspective ---"
# In docker, host gateway is usually 172.17.0.1 or 10.0.0.1
nsenter -t $NGINX_PID -n -- ip route 2>&1 | head -5
echo ""
echo "--- 2. Try various host IPs to find which one has port 3000 ---"
for IP in 10.0.4.1 172.17.0.1 172.19.0.1 host.docker.internal 10.0.0.1 172.18.0.1; do
result=$(nsenter -t $NGINX_PID -n -- curl -s -o /dev/null -w "%{http_code}" --max-time 3 http://$IP:3000/api/v1/banners 2>/dev/null)
echo "$IP:3000 -> HTTP $result"
done
echo ""
echo "--- 3. Find IP that gives 200 ---"
for IP in 10.0.4.1 172.17.0.1 172.19.0.1 172.20.0.1 10.0.4.2 10.0.0.1 192.168.0.1; do
result=$(nsenter -t $NGINX_PID -n -- curl -s -o /dev/null -w "%{http_code}" --max-time 2 http://$IP:3000/api/v1/banners 2>/dev/null)
if [ "$result" = "200" ]; then
echo "FOUND: $IP:3000 returns 200"
fi
done
echo ""
echo "--- 4. Find the host machine's main IP from openresty container ---"
nsenter -t $NGINX_PID -n -- cat /etc/hosts 2>&1
echo ""
nsenter -t $NGINX_PID -n -- ip addr 2>&1 | grep inet | head -10
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
sed -i 's|proxy_pass http://10.0.4.1:3000;|proxy_pass http://127.0.0.1:3000;|' /etc/nginx/sites-enabled/yuyueguahao
echo "--- Updated config ---"
grep -B1 -A3 uploads /etc/nginx/sites-enabled/yuyueguahao
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Reload master PID: $NGINX_MASTER"
kill -HUP "$NGINX_MASTER"
sleep 2
echo "--- TEST 80 ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "--- TEST API (sanity) ---"
curl -o /dev/null -s -w "HTTP %{http_code}\n" http://localhost/api/v1/banners
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/expect -f
set timeout 30
spawn ssh [email protected]
expect "password:"
send "Szgt888.\r"
expect "\\$"
set payload [exec base64 -i scripts/fix-nginx-final.sh]
send "echo '$payload' | base64 -d > /tmp/fix-final.sh && bash /tmp/fix-final.sh\r"
expect "\\$"
send "exit\r"
expect eof
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# 修 Nginx /uploads/ proxy_pass - 因为 nginx 在 docker 容器里, 127.0.0.1 不是宿主
# 改成 host.docker.internal (Docker Desktop) 或宿主 IP (Linux)
NGINX_SITE=/etc/nginx/sites-enabled/yuyueguahao
# 1) 确认宿主 IP(bridge 网关通常 172.17.0.1)
HOST_IP=$(ip route | grep default | awk '{print $3}' | head -1)
echo "Host IP (default gateway): $HOST_IP"
# 2) 测试哪个 IP 能连到 3000
echo "--- Test 127.0.0.1:3000 ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 3 http://127.0.0.1:3000/api/v1/banners || echo "FAIL"
echo "--- Test $HOST_IP:3000 ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 3 http://$HOST_IP:3000/api/v1/banners || echo "FAIL"
echo "--- Test host.docker.internal:3000 ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 3 http://host.docker.internal:3000/api/v1/banners || echo "FAIL"
# 3) 改 nginx 配置
echo "--- Updating nginx config ---"
sed -i 's|proxy_pass http://127.0.0.1:3000;|proxy_pass http://'"$HOST_IP"':3000;|' "$NGINX_SITE"
grep -A3 uploads "$NGINX_SITE"
# 4) reload
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Reload nginx master PID: $NGINX_MASTER"
kill -HUP "$NGINX_MASTER"
sleep 2
# 5) 验证
echo "--- TEST 80 ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
# 改用 172.19.0.1 (openresty 容器的 default gateway, = 宿主 IP)
NGINX_SITE=/etc/nginx/sites-enabled/yuyueguahao
# 替换所有 127.0.0.1:3000 为 172.19.0.1:3000
sed -i 's|127.0.0.1:3000|172.19.0.1:3000|g' "$NGINX_SITE"
echo "--- Updated /uploads/ ---"
grep -A2 'location /uploads' "$NGINX_SITE"
echo ""
echo "--- Updated /api/ ---"
grep -A2 'location /api' "$NGINX_SITE"
# Test config + reload
nginx -t 2>&1 | tail -2
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Master: $NGINX_MASTER"
kill -HUP "$NGINX_MASTER"
sleep 2
# Test
echo "--- TEST uploads (port 80) ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "--- TEST api (port 80) ---"
curl -o /dev/null -s -w "HTTP %{http_code}\n" http://localhost/api/v1/banners
echo "--- TEST home (port 80) ---"
curl -o /dev/null -s -w "HTTP %{http_code}\n" http://localhost/
# Save the IP for future use
echo "172.19.0.1" > /tmp/host-ip.txt
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
# 把 /uploads/ 的 proxy_pass 改成和 /api/ 完全一致, 加 proxy_http_version 等
cat > /tmp/new-uploads-loc.txt << 'NGINX'
# 静态资源上传目录(Express 落盘位置, 反代到本机 3000)
location /uploads/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
}
NGINX
# 替换 /uploads/ 那块
python3 -c "
import re
with open('/etc/nginx/sites-enabled/yuyueguahao', 'r') as f:
content = f.read()
with open('/tmp/new-uploads-loc.txt', 'r') as f:
new_loc = f.read().rstrip()
# 用 re 替换原 /uploads/ 整个 location 块
pattern = r' # 静态资源上传目录.*?\n \}\n'
new = re.sub(pattern, new_loc + '\n', content, flags=re.DOTALL)
with open('/etc/nginx/sites-enabled/yuyueguahao', 'w') as f:
f.write(new)
print('OK')
"
echo "--- Updated /uploads/ location ---"
grep -A12 'location /uploads/' /etc/nginx/sites-enabled/yuyueguahao
echo "--- nginx -t ---"
nginx -t 2>&1 | tail -3
echo "--- reload ---"
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Master PID: $NGINX_MASTER"
kill -HUP "$NGINX_MASTER"
sleep 2
echo "--- TEST 80 ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "--- TEST API sanity ---"
curl -o /dev/null -s -w "HTTP %{http_code}\n" http://localhost/api/v1/banners
echo "--- error log tail ---"
tail -3 /var/log/nginx/error.log
+37
View File
@@ -0,0 +1,37 @@
#!/bin/bash
set -e
# 修复 Nginx /uploads/ 502 - 改用 proxy_pass 给 Express 端口 3000
# Express 已经能正常服务 /uploads/* (验证过 200)
NGINX_SITE=$(ls /etc/nginx/sites-enabled/yuyueguahao 2>/dev/null || ls /etc/nginx/conf.d/yuyueguahao.conf 2>/dev/null)
echo "Nginx site file: $NGINX_SITE"
if [ -z "$NGINX_SITE" ]; then
echo "未找到 nginx site config, 搜索 uploads 相关配置"
find /etc/nginx -name "*.conf" -exec grep -l "uploads" {} \;
exit 1
fi
echo "---BEFORE---"
grep -B1 -A4 uploads "$NGINX_SITE" 2>&1
# 替换 /uploads/ 的 location 为 proxy_pass
# 使用 sed 把 alias 那一行替换成 proxy_pass
sed -i '/location \/uploads\//,/^ }/{
s|alias .*|proxy_pass http://127.0.0.1:3000;|
s|autoindex off;||
}' "$NGINX_SITE"
echo "---AFTER---"
grep -B1 -A4 uploads "$NGINX_SITE" 2>&1
echo "---TEST CONFIG---"
nginx -t 2>&1 | tail -3
echo "---RELOAD NGINX---"
nginx -s reload 2>&1 || systemctl reload nginx 2>&1 || service nginx reload 2>&1
sleep 2
echo "---TEST IMAGE---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "DONE"
+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
set -e
echo "---STEP 1: Move files---"
cd /opt/yuyueguahao
ls uploads/ 2>/dev/null || mkdir -p uploads
if [ -d "server/uploads" ] && [ "$(ls -A server/uploads 2>/dev/null)" ]; then
mv server/uploads/* uploads/
rmdir server/uploads
fi
ls -la uploads/ | head -6
echo
echo "---STEP 2: Restart PM2---"
pm2 restart yuyueguahao-api 2>&1 | tail -3
sleep 3
echo
echo "---STEP 3: Test 80 (Nginx)---"
curl -I http://localhost/uploads/1781403331659-1cac3cac.png 2>&1 | head -3
echo
echo "---STEP 4: Test 3000 (Express)---"
curl -I http://localhost:3000/uploads/1781403331659-1cac3cac.png 2>&1 | head -3
echo
echo "---STEP 5: Fix DB URLs (strip absolute host)---"
mysql -uyygh_app -p'Yygh@2026#App' yuyueguahao -e "
UPDATE banners SET image = REPLACE(image, 'http://124.221.67.199:3000', '') WHERE image LIKE 'http%';
UPDATE centers SET image = REPLACE(image, 'http://124.221.67.199:3000', '') WHERE image LIKE 'http%';
UPDATE home_intro SET image = REPLACE(image, 'http://124.221.67.199:3000', '') WHERE image LIKE 'http%';
UPDATE hospital_images SET image = REPLACE(image, 'http://124.221.67.199:3000', '') WHERE image LIKE 'http%';
" 2>&1
echo
echo "---STEP 6: Verify DB---"
mysql -uyygh_app -p'Yygh@2026#App' yuyueguahao -e 'SELECT id, image FROM banners LIMIT 3; SELECT id, image FROM home_intro;' 2>&1
echo
echo "---DONE---"
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""
生成微信小程序 tabBar 图标 (81x81 PNG, normal + selected 共 2 套)
- 5 个 tab: home, hospital, appointment, self-test, phone
- normal 色 #94a3b8 (gray), selected 色 #1f7ae0 (blue)
"""
from PIL import Image, ImageDraw
import os
OUT_DIR = "src/assets/tabbar"
os.makedirs(OUT_DIR, exist_ok=True)
SIZE = 81
GRAY = (148, 163, 184, 255)
BLUE = (31, 122, 224, 255)
WHITE = (255, 255, 255, 255)
def draw_icon(name, color):
img = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
if name == "home":
# 屋顶 + 房身
d.polygon([(40, 12), (12, 36), (68, 36)], fill=color)
d.rectangle([18, 36, 62, 68], fill=color)
d.rectangle([34, 46, 46, 68], fill=WHITE)
elif name == "hospital":
# 圆角矩形 + 十字
d.rounded_rectangle([10, 14, 70, 74], radius=10, fill=color)
d.rectangle([34, 24, 46, 64], fill=WHITE)
d.rectangle([24, 36, 56, 48], fill=WHITE)
elif name == "appointment":
# 日历 + 勾
d.rounded_rectangle([10, 16, 70, 72], radius=6, fill=color)
d.rectangle([18, 16, 24, 26], fill=color)
d.rectangle([56, 16, 62, 26], fill=color)
d.line([(24, 44), (36, 54), (56, 36)], fill=WHITE, width=5)
elif name == "self-test":
# 圆 + 问号
d.ellipse([10, 10, 70, 70], fill=color)
# 问号白色: 用两个矩形 (竖 + 横) + 圆点
d.rectangle([36, 22, 44, 42], fill=WHITE)
d.rectangle([36, 38, 50, 46], fill=WHITE)
d.rectangle([36, 50, 44, 58], fill=WHITE)
elif name == "phone":
# 话筒
d.rounded_rectangle([30, 10, 50, 50], radius=10, fill=color)
d.arc([18, 28, 62, 72], start=0, end=180, fill=color, width=6)
d.line([40, 50, 40, 68], fill=color, width=6)
return img
for name in ["home", "hospital", "appointment", "self-test", "phone"]:
img_gray = draw_icon(name, GRAY)
img_blue = draw_icon(name, BLUE)
img_gray.save(os.path.join(OUT_DIR, name + ".png"))
img_blue.save(os.path.join(OUT_DIR, name + "_selected.png"))
print(" + " + name + ".png, " + name + "_selected.png")
print("DONE")
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/expect -f
set timeout 30
spawn ssh [email protected]
expect "password:"
send "Szgt888.\r"
expect "\\$"
# Use base64 to safely transfer the script content
set payload [exec base64 -i scripts/reload-nginx.sh]
send "echo '$payload' | base64 -d > /tmp/reload.sh && bash /tmp/reload.sh\r"
expect "\\$"
send "exit\r"
expect eof
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# 直接对运行中的 nginx master 进程发 SIGHUP 重载
echo "--- Finding nginx master ---"
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Master PID: $NGINX_MASTER"
if [ -z "$NGINX_MASTER" ]; then
echo "No nginx master found, trying to start one..."
nginx
sleep 2
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "New Master PID: $NGINX_MASTER"
fi
if [ -n "$NGINX_MASTER" ]; then
echo "--- Sending SIGHUP to $NGINX_MASTER ---"
kill -HUP "$NGINX_MASTER"
sleep 2
echo "--- nginx reloaded ---"
fi
echo ""
echo "--- TEST 80 (Nginx) ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "--- TEST 3000 (Express) ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download}\n" http://localhost:3000/uploads/1781403331659-1cac3cac.png
echo ""
echo "--- File check ---"
ls -la /opt/yuyueguahao/uploads/ | head -5
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
echo "--- before ---"
ps -efL | grep "nginx" | grep -v grep | head -5
# Find s6-supervise for nginx
S6_PID=$(ps -efL | grep "s6-supervise nginx" | grep -v grep | awk '{print $2}' | head -1)
echo "S6 supervisor PID: $S6_PID"
# Send SIGTERM/QUIT to nginx master - s6 will restart it
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Killing nginx master $NGINX_MASTER with SIGQUIT (graceful)"
# Try SIGQUIT first (graceful shutdown)
kill -QUIT "$NGINX_MASTER" 2>&1
sleep 3
# If still running, force kill
if kill -0 "$NGINX_MASTER" 2>/dev/null; then
echo "Still running, sending SIGTERM"
kill -TERM "$NGINX_MASTER"
sleep 2
fi
if kill -0 "$NGINX_MASTER" 2>/dev/null; then
echo "Still running, sending SIGKILL"
kill -KILL "$NGINX_MASTER"
sleep 2
fi
# Wait for s6 to restart
sleep 5
echo "--- after ---"
ps -efL | grep "nginx" | grep -v grep | head -5
# Test
echo "--- TEST 80 ---"
curl -o /dev/null -s -w "HTTP %{http_code} size=%{size_download} type=%{content_type}\n" http://localhost/uploads/1781403331659-1cac3cac.png
echo "--- TEST 80 API ---"
curl -o /dev/null -s -w "HTTP %{http_code}\n" http://localhost/api/v1/banners
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
echo "--- All nginx/openresty processes ---"
ps -efL | grep -E "nginx|openresty" | grep -v grep
echo "--- Find s6 control files for nginx ---"
ls -la /etc/s6-overlay/s6-rc.d/ 2>/dev/null | head -20
ls -la /run/service/ 2>/dev/null | head -10
ls -la /etc/services.d/ 2>/dev/null | head -10
find / -name "nginx" -type d 2>/dev/null | head -5
echo "--- Find s6 finish / down files ---"
find /etc/s6-overlay /etc/services.d /run/service -name "finish" -o -name "down" 2>/dev/null | head -10
echo "--- Try s6-svc or svc to restart ---"
which s6-svc 2>&1
which s6-rc 2>&1
echo "--- kill master brutally, s6 should restart ---"
NGINX_MASTER=$(ps -efL | grep "nginx: master" | grep -v grep | awk '{print $2}' | head -1)
echo "Old master: $NGINX_MASTER"
kill -9 "$NGINX_MASTER" 2>&1
sleep 5
ps -efL | grep -E "nginx" | grep -v grep
echo "--- Test 80 after restart ---"
curl -o /dev/null -s -w "API: HTTP %{http_code}\n" http://localhost/api/v1/banners
curl -o /dev/null -s -w "Uploads: HTTP %{http_code} size=%{size_download}\n" http://localhost/uploads/1781403331659-1cac3cac.png