Initial commit
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
# 股票投资分析系统 - 远程服务器部署情况
|
||||
|
||||
> 最后更新:2026-03-17
|
||||
|
||||
## 一、服务器概览
|
||||
|
||||
| 服务器 | IP | 域名 | 用途 | 状态 |
|
||||
|--------|-----|------|------|------|
|
||||
| **主服务器(原有)** | 43.135.128.39 | - | 腾讯云,IP直连 | 运行中 |
|
||||
| **新服务器** | 152.136.182.184 | stock.allbyai.cn | 腾讯云,HTTPS域名 | 已配置 |
|
||||
|
||||
---
|
||||
|
||||
## 二、新服务器 (stock.allbyai.cn) 部署架构
|
||||
|
||||
### 2.1 访问方式
|
||||
- **HTTPS(推荐)**:https://stock.allbyai.cn
|
||||
- **IP直连**:http://152.136.182.184:3333
|
||||
|
||||
### 2.2 技术栈
|
||||
- **Web 应用**:Flask (Python) 端口 3333
|
||||
- **反向代理**:Nginx + HTTPS (acme.sh 证书)
|
||||
- **数据库**:PostgreSQL (stock_app)
|
||||
- **数据采集**:stock-data-service (systemd 后台服务)
|
||||
|
||||
### 2.3 部署路径
|
||||
- 应用目录:`/opt/stock-app`
|
||||
- Nginx 配置:`/etc/nginx/sites-available/stock.allbyai.cn`
|
||||
- SSL 证书:`/etc/nginx/ssl/stock.allbyai.cn.crt` / `.key`
|
||||
|
||||
---
|
||||
|
||||
## 三、部署脚本清单
|
||||
|
||||
| 脚本 | 用途 | 执行位置 |
|
||||
|------|------|----------|
|
||||
| `deploy/deploy-to-new-server.sh` | 一键完整部署(同步+初始化+Nginx+重启) | 本地 |
|
||||
| `deploy/sync-to-new-server.sh` | 快速同步代码并重启(日常更新) | 本地 |
|
||||
| `deploy/setup-server.sh` | 服务器环境初始化(首次部署) | 服务器 |
|
||||
| `deploy/setup-ssl.sh` | SSL 证书申请/安装(acme.sh) | 服务器 |
|
||||
| `setup_cron_scan.sh` | 配置全景扫描定时任务 | 本地→服务器 |
|
||||
|
||||
---
|
||||
|
||||
## 四、部署流程
|
||||
|
||||
### 4.1 首次部署新服务器
|
||||
|
||||
```bash
|
||||
cd /Users/freedak/Documents/go-new/stock/stock-html
|
||||
|
||||
# 1. 执行一键部署(会同步代码、配置 Nginx、重启服务)
|
||||
./deploy/deploy-to-new-server.sh
|
||||
|
||||
# 2. 首次部署需取消 deploy-to-new-server.sh 第43行注释,执行服务器初始化
|
||||
# ssh ubuntu@152.136.182.184 "${APP_DIR}/deploy/setup-server.sh"
|
||||
|
||||
# 3. 若需 SSL,在服务器上执行
|
||||
# ssh ubuntu@152.136.182.184
|
||||
# 先配置 acme.sh + DNS TXT 记录,再运行:
|
||||
# /opt/stock-app/deploy/setup-ssl.sh
|
||||
|
||||
# 4. 配置定时任务(全景扫描、K线采集、资金流向)
|
||||
./setup_cron_scan.sh
|
||||
# 或手动指定:STOCK_SERVER=ubuntu@152.136.182.184 STOCK_APP_DIR=/opt/stock-app ./setup_cron_scan.sh
|
||||
```
|
||||
|
||||
### 4.2 日常代码更新
|
||||
|
||||
```bash
|
||||
cd /Users/freedak/Documents/go-new/stock/stock-html
|
||||
./deploy/sync-to-new-server.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、服务管理命令
|
||||
|
||||
### 5.1 新服务器 (152.136.182.184)
|
||||
|
||||
```bash
|
||||
# Web 应用
|
||||
ssh ubuntu@152.136.182.184 "systemctl start stock-app"
|
||||
ssh ubuntu@152.136.182.184 "systemctl stop stock-app"
|
||||
ssh ubuntu@152.136.182.184 "systemctl restart stock-app"
|
||||
ssh ubuntu@152.136.182.184 "systemctl status stock-app"
|
||||
|
||||
# 数据采集服务
|
||||
ssh ubuntu@152.136.182.184 "systemctl start stock-data-service"
|
||||
ssh ubuntu@152.136.182.184 "systemctl restart stock-data-service"
|
||||
ssh ubuntu@152.136.182.184 "systemctl status stock-data-service"
|
||||
|
||||
# 查看日志
|
||||
ssh ubuntu@152.136.182.184 "journalctl -u stock-app -f"
|
||||
ssh ubuntu@152.136.182.184 "journalctl -u stock-data-service -f"
|
||||
```
|
||||
|
||||
### 5.2 SSL 证书续期
|
||||
|
||||
- **自动**:acme.sh 已配置 cron 自动续期
|
||||
- **手动**:`/home/ubuntu/.acme.sh/acme.sh --renew -d stock.allbyai.cn --ecc --force`
|
||||
|
||||
---
|
||||
|
||||
## 六、注意事项与待办
|
||||
|
||||
### 6.1 已知差异
|
||||
- `sync-to-new-server.sh` 仅重启 `stock-app`,不重启 `stock-data-service`
|
||||
- 完整部署时 `deploy-to-new-server.sh` 会重启两个服务
|
||||
|
||||
### 6.2 同步排除项
|
||||
部署时排除:`.git`、`venv`、`__pycache__`、`stock_data_cache`、`*.pyc`、`.DS_Store`、`stock_names.json`、`alerts_cache.json`、`trades.json`、`watchlist.json`、`*.log`、`.playwright-mcp`、根目录 `/app.js`、`/index.html`、`/main.css`、`/css`、`/js`、`.windsurfrules`
|
||||
|
||||
### 6.3 定时任务(新服务器需单独配置)
|
||||
- 11:50 午休扫描
|
||||
- 16:30 收盘扫描
|
||||
- 17:30 5分钟K线采集
|
||||
- 18:00 资金流向采集
|
||||
|
||||
使用 `setup_cron_scan.sh` 或按 `run.md` 手动配置 crontab。
|
||||
|
||||
---
|
||||
|
||||
## 七、快速参考
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 同步并重启新服务器 | `./deploy/sync-to-new-server.sh` |
|
||||
| 完整部署新服务器 | `./deploy/deploy-to-new-server.sh` |
|
||||
| 查看服务状态 | `ssh ubuntu@152.136.182.184 "systemctl status stock-app stock-data-service"` |
|
||||
| 访问地址 | https://stock.allbyai.cn |
|
||||
Executable
+73
@@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
# 一键部署脚本 - 从本地部署到新服务器 152.136.182.184 (stock.allbyai.cn)
|
||||
# 在本地执行此脚本
|
||||
|
||||
set -e
|
||||
|
||||
# 配置
|
||||
NEW_SERVER="ubuntu@152.136.182.184"
|
||||
APP_DIR="/opt/stock-app"
|
||||
LOCAL_DIR="/Users/freedak/Documents/go-new/stock/stock-html"
|
||||
|
||||
echo "=========================================="
|
||||
echo "部署到新服务器: 152.136.182.184"
|
||||
echo "域名: stock.allbyai.cn"
|
||||
echo "=========================================="
|
||||
|
||||
# 1. 同步代码(使用 sudo 写入 /opt/stock-app)
|
||||
echo "[1/5] 同步代码到服务器..."
|
||||
rsync -avz --progress --rsync-path="sudo rsync" ${LOCAL_DIR}/ ${NEW_SERVER}:${APP_DIR}/ \
|
||||
--exclude='.git' \
|
||||
--exclude='venv' \
|
||||
--exclude='__pycache__' \
|
||||
--exclude='stock_data_cache' \
|
||||
--exclude='*.pyc' \
|
||||
--exclude='.DS_Store' \
|
||||
--exclude='stock_names.json' \
|
||||
--exclude='alerts_cache.json' \
|
||||
--exclude='trades.json' \
|
||||
--exclude='watchlist.json' \
|
||||
--exclude='*.log' \
|
||||
--exclude='.playwright-mcp' \
|
||||
--exclude='/app.js' \
|
||||
--exclude='/index.html' \
|
||||
--exclude='/main.css' \
|
||||
--exclude='/css' \
|
||||
--exclude='/js' \
|
||||
--exclude='/.windsurfrules'
|
||||
|
||||
# 2. 在服务器上执行初始化(首次部署时需要)
|
||||
echo "[2/5] 执行服务器初始化..."
|
||||
ssh ${NEW_SERVER} "sudo chmod +x ${APP_DIR}/deploy/setup-server.sh"
|
||||
# 如果是首次部署,取消下行注释
|
||||
# ssh ${NEW_SERVER} "sudo ${APP_DIR}/deploy/setup-server.sh"
|
||||
|
||||
# 3. 配置Nginx
|
||||
echo "[3/5] 配置Nginx..."
|
||||
ssh ${NEW_SERVER} "sudo cp ${APP_DIR}/deploy/nginx-stock.conf /etc/nginx/sites-available/stock.allbyai.cn"
|
||||
ssh ${NEW_SERVER} "sudo ln -sf /etc/nginx/sites-available/stock.allbyai.cn /etc/nginx/sites-enabled/"
|
||||
ssh ${NEW_SERVER} "sudo nginx -t && sudo systemctl reload nginx"
|
||||
|
||||
# 4. 重启服务
|
||||
echo "[4/5] 重启应用服务..."
|
||||
ssh ${NEW_SERVER} "sudo systemctl restart stock-app"
|
||||
ssh ${NEW_SERVER} "sudo systemctl restart stock-data-service"
|
||||
|
||||
# 5. 检查状态
|
||||
echo "[5/5] 检查服务状态..."
|
||||
ssh ${NEW_SERVER} "sudo systemctl status stock-app --no-pager"
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "部署完成!"
|
||||
echo ""
|
||||
echo "访问地址:"
|
||||
echo " - IP直连: http://152.136.182.184:3333"
|
||||
echo " - HTTPS访问: https://stock.allbyai.cn"
|
||||
echo ""
|
||||
echo "SSL证书信息:"
|
||||
echo " - 证书路径: /etc/nginx/ssl/stock.allbyai.cn.crt"
|
||||
echo " - 密钥路径: /etc/nginx/ssl/stock.allbyai.cn.key"
|
||||
echo " - 自动续期: 已配置 (acme.sh cron)"
|
||||
echo " - 手动续期: /home/ubuntu/.acme.sh/acme.sh --renew -d stock.allbyai.cn --ecc --force"
|
||||
echo "=========================================="
|
||||
Executable
+168
@@ -0,0 +1,168 @@
|
||||
#!/bin/bash
|
||||
# 修复 stock.allbyai.cn 数据库连接问题
|
||||
# 在服务器上执行: sudo bash /opt/stock-app/deploy/fix-db-connection.sh
|
||||
|
||||
DB_PASS="stock_password_2025"
|
||||
APP_DIR="/opt/stock-app"
|
||||
|
||||
echo "=========================================="
|
||||
echo "诊断并修复 PostgreSQL 数据库连接"
|
||||
echo "=========================================="
|
||||
|
||||
# 0. 诊断:收集当前状态
|
||||
echo ""
|
||||
echo "[诊断] 检查 PostgreSQL 服务状态..."
|
||||
systemctl status postgresql --no-pager 2>&1 | head -10
|
||||
echo ""
|
||||
|
||||
echo "[诊断] 检查 PostgreSQL 版本和集群..."
|
||||
pg_lsclusters 2>/dev/null || echo "pg_lsclusters 不可用"
|
||||
echo ""
|
||||
|
||||
echo "[诊断] 检查 PostgreSQL 监听端口..."
|
||||
ss -tlnp | grep 5432 || netstat -tlnp 2>/dev/null | grep 5432 || echo "未检测到5432端口监听"
|
||||
echo ""
|
||||
|
||||
echo "[诊断] 检查 pg_hba.conf 配置..."
|
||||
PG_HBA=$(find /etc/postgresql -name pg_hba.conf 2>/dev/null | head -1)
|
||||
if [ -n "$PG_HBA" ]; then
|
||||
echo "文件位置: $PG_HBA"
|
||||
echo "--- 当前认证配置 ---"
|
||||
grep -v '^#' "$PG_HBA" | grep -v '^$'
|
||||
echo "---"
|
||||
else
|
||||
echo "未找到 pg_hba.conf"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "[诊断] 检查 stock-app 服务环境变量..."
|
||||
systemctl show stock-app --property=Environment 2>/dev/null || echo "无法读取服务配置"
|
||||
echo ""
|
||||
|
||||
echo "[诊断] 尝试 peer 认证连接..."
|
||||
sudo -u postgres psql -c "SELECT 1 as peer_auth_ok;" 2>&1 || echo "peer 认证失败"
|
||||
echo ""
|
||||
|
||||
echo "[诊断] 检查 stock_app 数据库是否存在..."
|
||||
sudo -u postgres psql -c "SELECT datname FROM pg_database WHERE datname='stock_app';" 2>&1
|
||||
echo ""
|
||||
|
||||
# 1. 确保 PostgreSQL 服务运行
|
||||
echo "=========================================="
|
||||
echo "[1/6] 确保 PostgreSQL 服务运行..."
|
||||
systemctl start postgresql 2>/dev/null || true
|
||||
systemctl enable postgresql 2>/dev/null || true
|
||||
|
||||
# 2. 重置 postgres 用户密码
|
||||
echo "[2/6] 重置 postgres 用户密码..."
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD '${DB_PASS}';" 2>/dev/null || {
|
||||
echo "尝试使用 peer 认证重置密码..."
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD '${DB_PASS}';" || {
|
||||
echo "❌ 密码重置失败,尝试重启 PostgreSQL 后重试..."
|
||||
systemctl restart postgresql
|
||||
sleep 2
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD '${DB_PASS}';"
|
||||
}
|
||||
}
|
||||
echo "✅ 密码已重置"
|
||||
|
||||
# 3. 确保数据库存在
|
||||
echo "[3/6] 确保 stock_app 数据库存在..."
|
||||
sudo -u postgres createdb stock_app 2>/dev/null || echo "数据库已存在"
|
||||
|
||||
# 4. 修复 pg_hba.conf 认证配置
|
||||
echo "[4/6] 检查并修复 pg_hba.conf..."
|
||||
if [ -n "$PG_HBA" ]; then
|
||||
if ! grep -q "host.*all.*all.*127.0.0.1/32.*md5\|host.*all.*all.*127.0.0.1/32.*scram-sha-256" "$PG_HBA"; then
|
||||
echo "添加 localhost md5 认证规则..."
|
||||
cp "$PG_HBA" "${PG_HBA}.bak.$(date +%Y%m%d%H%M%S)"
|
||||
|
||||
# 在文件末尾前插入规则(确保在其他 host 规则之前或文件末尾)
|
||||
if ! grep -q "^host.*all.*all.*127.0.0.1/32" "$PG_HBA"; then
|
||||
echo "host all all 127.0.0.1/32 md5" >> "$PG_HBA"
|
||||
fi
|
||||
if ! grep -q "^host.*all.*all.*::1/128" "$PG_HBA"; then
|
||||
echo "host all all ::1/128 md5" >> "$PG_HBA"
|
||||
fi
|
||||
|
||||
echo "✅ pg_hba.conf 已更新,重启 PostgreSQL..."
|
||||
systemctl restart postgresql
|
||||
sleep 2
|
||||
else
|
||||
echo "✅ pg_hba.conf 认证配置正常"
|
||||
fi
|
||||
else
|
||||
echo "⚠️ 未找到 pg_hba.conf,跳过"
|
||||
fi
|
||||
|
||||
# 5. 测试数据库连接
|
||||
echo "[5/6] 测试数据库连接..."
|
||||
PGPASSWORD="${DB_PASS}" psql -h localhost -U postgres -d stock_app -c "SELECT 1 as ok;" 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 数据库连接测试通过"
|
||||
else
|
||||
echo "❌ 连接测试失败!"
|
||||
echo ""
|
||||
echo "尝试替代修复方案..."
|
||||
|
||||
# 尝试将所有 host 认证改为 md5
|
||||
if [ -n "$PG_HBA" ]; then
|
||||
echo "将 scram-sha-256 改为 md5..."
|
||||
sed -i 's/scram-sha-256/md5/g' "$PG_HBA"
|
||||
systemctl restart postgresql
|
||||
sleep 2
|
||||
|
||||
# 重新设置密码(用 md5 格式)
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD '${DB_PASS}';"
|
||||
|
||||
PGPASSWORD="${DB_PASS}" psql -h localhost -U postgres -d stock_app -c "SELECT 1 as ok;" 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 替代方案成功"
|
||||
else
|
||||
echo "❌ 仍然失败,请手动检查 PostgreSQL 日志:"
|
||||
echo " journalctl -u postgresql -n 50"
|
||||
echo " cat /var/log/postgresql/*.log | tail -50"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 6. 重启应用服务
|
||||
echo "[6/6] 重启应用服务..."
|
||||
systemctl restart stock-app
|
||||
systemctl restart stock-data-service
|
||||
sleep 3
|
||||
|
||||
# 验证应用是否正常
|
||||
echo ""
|
||||
echo "验证应用状态..."
|
||||
systemctl status stock-app --no-pager | head -5
|
||||
echo ""
|
||||
|
||||
# 用 Python 测试应用级 DB 连接
|
||||
${APP_DIR}/venv/bin/python -c "
|
||||
import sys
|
||||
sys.path.insert(0, '${APP_DIR}')
|
||||
import os
|
||||
os.environ['DB_HOST'] = 'localhost'
|
||||
os.environ['DB_PORT'] = '5432'
|
||||
os.environ['DB_NAME'] = 'stock_app'
|
||||
os.environ['DB_USER'] = 'postgres'
|
||||
os.environ['DB_PASSWORD'] = '${DB_PASS}'
|
||||
from db import get_db
|
||||
conn = get_db()
|
||||
if conn:
|
||||
cur = conn.cursor()
|
||||
cur.execute('SELECT COUNT(*) FROM users')
|
||||
count = cur.fetchone()[0]
|
||||
print(f'✅ Python 应用级 DB 连接成功!用户数: {count}')
|
||||
conn.close()
|
||||
else:
|
||||
print('❌ Python 应用级 DB 连接失败')
|
||||
sys.exit(1)
|
||||
" 2>&1
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "修复完成!请访问 https://stock.allbyai.cn 验证"
|
||||
echo "=========================================="
|
||||
@@ -0,0 +1,49 @@
|
||||
# Nginx配置 - stock.allbyai.cn (HTTPS)
|
||||
# 部署路径: /etc/nginx/sites-available/stock.allbyai.cn
|
||||
# SSL证书由 acme.sh 管理,自动续期
|
||||
|
||||
# HTTP 重定向到 HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name stock.allbyai.cn;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
# HTTPS 配置
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name stock.allbyai.cn;
|
||||
|
||||
# SSL 证书
|
||||
ssl_certificate /etc/nginx/ssl/stock.allbyai.cn.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/stock.allbyai.cn.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# 日志
|
||||
access_log /var/log/nginx/stock.allbyai.cn.access.log;
|
||||
error_log /var/log/nginx/stock.allbyai.cn.error.log;
|
||||
|
||||
# 代理到Flask应用
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3333;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
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_cache_bypass $http_upgrade;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_connect_timeout 75s;
|
||||
}
|
||||
|
||||
# 静态文件缓存
|
||||
location /static/ {
|
||||
alias /opt/stock-app/static/;
|
||||
expires 7d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
# 从本地执行:同步修复脚本到服务器并执行
|
||||
# 用法: ./deploy/run-fix-db.sh
|
||||
|
||||
set -e
|
||||
|
||||
NEW_SERVER="ubuntu@152.136.182.184"
|
||||
APP_DIR="/opt/stock-app"
|
||||
LOCAL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
echo "=========================================="
|
||||
echo "修复 stock.allbyai.cn 数据库连接"
|
||||
echo "=========================================="
|
||||
|
||||
echo "[1/2] 同步修复脚本到服务器..."
|
||||
rsync -avz "${LOCAL_DIR}/deploy/fix-db-connection.sh" ${NEW_SERVER}:${APP_DIR}/deploy/
|
||||
|
||||
echo "[2/2] 在服务器上执行修复..."
|
||||
ssh ${NEW_SERVER} "sudo bash ${APP_DIR}/deploy/fix-db-connection.sh"
|
||||
|
||||
echo ""
|
||||
echo "验证: curl -s https://stock.allbyai.cn/api/db/data_status"
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
# 新服务器初始化脚本 - 152.136.182.184 (stock.allbyai.cn)
|
||||
# 在服务器上执行此脚本完成环境配置
|
||||
|
||||
set -e
|
||||
|
||||
echo "=========================================="
|
||||
echo "股票投资分析系统 - 服务器初始化"
|
||||
echo "服务器: 152.136.182.184"
|
||||
echo "域名: stock.allbyai.cn"
|
||||
echo "=========================================="
|
||||
|
||||
# 更新系统
|
||||
echo "[1/8] 更新系统包..."
|
||||
apt-get update && apt-get upgrade -y
|
||||
|
||||
# 安装依赖
|
||||
echo "[2/8] 安装系统依赖..."
|
||||
apt-get install -y python3 python3-pip python3-venv nginx postgresql postgresql-contrib
|
||||
|
||||
# 配置PostgreSQL
|
||||
echo "[3/8] 配置PostgreSQL..."
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'stock_password_2025';" || true
|
||||
sudo -u postgres createdb stock_app || echo "数据库已存在"
|
||||
|
||||
# 创建应用目录
|
||||
echo "[4/8] 创建应用目录..."
|
||||
mkdir -p /opt/stock-app
|
||||
chown -R root:root /opt/stock-app
|
||||
|
||||
# 创建Python虚拟环境
|
||||
echo "[5/8] 创建Python虚拟环境..."
|
||||
cd /opt/stock-app
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install --upgrade pip
|
||||
|
||||
# 安装Python依赖
|
||||
echo "[6/8] 安装Python依赖..."
|
||||
if [ -f requirements.txt ]; then
|
||||
pip install -r requirements.txt
|
||||
else
|
||||
pip install flask flask-cors akshare pandas numpy schedule psycopg2-binary
|
||||
fi
|
||||
|
||||
# 初始化数据库
|
||||
echo "[7/8] 初始化数据库..."
|
||||
if [ -f init_db.sql ]; then
|
||||
sudo -u postgres psql -d stock_app -f init_db.sql || true
|
||||
fi
|
||||
if [ -f init_sim_trade.sql ]; then
|
||||
sudo -u postgres psql -d stock_app -f init_sim_trade.sql || true
|
||||
fi
|
||||
if [ -f init_smart_trade.sql ]; then
|
||||
sudo -u postgres psql -d stock_app -f init_smart_trade.sql || true
|
||||
fi
|
||||
if [ -f init_stock_data_db.sql ]; then
|
||||
sudo -u postgres psql -d stock_app -f init_stock_data_db.sql || true
|
||||
fi
|
||||
|
||||
# 配置systemd服务
|
||||
echo "[8/8] 配置systemd服务..."
|
||||
cat > /etc/systemd/system/stock-app.service << 'EOF'
|
||||
[Unit]
|
||||
Description=Stock Investment Analysis Web Application
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/stock-app
|
||||
Environment="DB_HOST=localhost"
|
||||
Environment="DB_PORT=5432"
|
||||
Environment="DB_NAME=stock_app"
|
||||
Environment="DB_USER=postgres"
|
||||
Environment="DB_PASSWORD=stock_password_2025"
|
||||
ExecStart=/opt/stock-app/venv/bin/python app.py
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/stock-data-service.service << 'EOF'
|
||||
[Unit]
|
||||
Description=Stock Data Collection Service
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/stock-app
|
||||
Environment="DB_HOST=localhost"
|
||||
Environment="DB_PORT=5432"
|
||||
Environment="DB_NAME=stock_app"
|
||||
Environment="DB_USER=postgres"
|
||||
Environment="DB_PASSWORD=stock_password_2025"
|
||||
ExecStart=/opt/stock-app/venv/bin/python stock_data_service.py daemon
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable stock-app
|
||||
systemctl enable stock-data-service
|
||||
|
||||
echo "=========================================="
|
||||
echo "初始化完成!"
|
||||
echo ""
|
||||
echo "后续步骤:"
|
||||
echo "1. 从本地同步代码到服务器"
|
||||
echo "2. 配置Nginx反向代理"
|
||||
echo "3. 启动服务"
|
||||
echo "=========================================="
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/bin/bash
|
||||
# SSL证书申请脚本 - stock.allbyai.cn
|
||||
# 使用 acme.sh + DNS 验证方式申请免费SSL证书
|
||||
# 适用于 DNSPod 有 Web 防护导致 HTTP 验证失败的情况
|
||||
# 在服务器上执行此脚本
|
||||
|
||||
set -e
|
||||
|
||||
DOMAIN="stock.allbyai.cn"
|
||||
SSL_DIR="/etc/nginx/ssl"
|
||||
ACME_HOME="/home/ubuntu/.acme.sh"
|
||||
|
||||
echo "=========================================="
|
||||
echo "为 ${DOMAIN} 完成SSL证书安装"
|
||||
echo "=========================================="
|
||||
|
||||
# 检查 acme.sh 是否已安装
|
||||
if [ ! -f "${ACME_HOME}/acme.sh" ]; then
|
||||
echo "错误: acme.sh 未安装,请先运行初始化"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查 DNS TXT 记录
|
||||
echo "[1/4] 检查 DNS TXT 记录..."
|
||||
TXT_RECORD=$(dig +short TXT _acme-challenge.stock.allbyai.cn 2>/dev/null || echo "")
|
||||
if [ -z "$TXT_RECORD" ]; then
|
||||
echo ""
|
||||
echo "错误: DNS TXT 记录未找到!"
|
||||
echo ""
|
||||
echo "请在 DNSPod 添加以下 TXT 记录:"
|
||||
echo " 主机记录: _acme-challenge.stock"
|
||||
echo " 记录值: cM9lSA4-uKk-yjrvA38HYtmA1h7E3DzgIXVJq8IsSNo"
|
||||
echo ""
|
||||
echo "添加后等待 1-2 分钟,然后重新运行此脚本"
|
||||
exit 1
|
||||
fi
|
||||
echo "DNS TXT 记录已找到: $TXT_RECORD"
|
||||
|
||||
# 创建 SSL 目录
|
||||
echo "[2/4] 创建 SSL 目录..."
|
||||
mkdir -p ${SSL_DIR}
|
||||
|
||||
# 完成证书申请
|
||||
echo "[3/4] 完成证书申请..."
|
||||
${ACME_HOME}/acme.sh --renew -d ${DOMAIN} --yes-I-know-dns-manual-mode-enough-go-ahead-please
|
||||
|
||||
# 安装证书
|
||||
echo "[4/4] 安装证书到 Nginx..."
|
||||
${ACME_HOME}/acme.sh --install-cert -d ${DOMAIN} \
|
||||
--key-file ${SSL_DIR}/${DOMAIN}.key \
|
||||
--fullchain-file ${SSL_DIR}/${DOMAIN}.crt \
|
||||
--reloadcmd "systemctl reload nginx"
|
||||
|
||||
# 更新 Nginx 配置
|
||||
echo "[5/5] 更新 Nginx 配置..."
|
||||
cat > /etc/nginx/sites-available/${DOMAIN} << 'NGINX_CONF'
|
||||
# Nginx配置 - stock.allbyai.cn (HTTPS)
|
||||
server {
|
||||
listen 80;
|
||||
server_name stock.allbyai.cn;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name stock.allbyai.cn;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/stock.allbyai.cn.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/stock.allbyai.cn.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
access_log /var/log/nginx/stock.allbyai.cn.access.log;
|
||||
error_log /var/log/nginx/stock.allbyai.cn.error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3333;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
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_cache_bypass $http_upgrade;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_connect_timeout 75s;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /opt/stock-app/static/;
|
||||
expires 7d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
}
|
||||
NGINX_CONF
|
||||
|
||||
# 重载 Nginx
|
||||
nginx -t && systemctl reload nginx
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "SSL证书安装完成!"
|
||||
echo ""
|
||||
echo "访问地址: https://${DOMAIN}"
|
||||
echo ""
|
||||
echo "证书信息:"
|
||||
echo " - 证书路径: ${SSL_DIR}/${DOMAIN}.crt"
|
||||
echo " - 密钥路径: ${SSL_DIR}/${DOMAIN}.key"
|
||||
echo " - 有效期: 90天"
|
||||
echo " - 自动续期: 已配置 (acme.sh cron)"
|
||||
echo ""
|
||||
echo "手动续期命令: ${ACME_HOME}/acme.sh --renew -d ${DOMAIN} --force"
|
||||
echo "=========================================="
|
||||
@@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=Stock Investment Analysis Web Application
|
||||
After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/stock-app
|
||||
Environment="DB_HOST=localhost"
|
||||
Environment="DB_PORT=5432"
|
||||
Environment="DB_NAME=stock_app"
|
||||
Environment="DB_USER=postgres"
|
||||
Environment="DB_PASSWORD=stock_password_2025"
|
||||
ExecStart=/opt/stock-app/venv/bin/python app.py
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# 快速同步代码到新服务器并重启 - 152.136.182.184 (stock.allbyai.cn)
|
||||
# 用于日常代码更新
|
||||
|
||||
set -e
|
||||
|
||||
NEW_SERVER="ubuntu@152.136.182.184"
|
||||
APP_DIR="/opt/stock-app"
|
||||
LOCAL_DIR="/Users/freedak/Documents/go-new/stock/stock-html"
|
||||
|
||||
echo "同步代码到 stock.allbyai.cn (152.136.182.184)..."
|
||||
|
||||
rsync -avz ${LOCAL_DIR}/ ${NEW_SERVER}:${APP_DIR}/ \
|
||||
--exclude='.git' \
|
||||
--exclude='venv' \
|
||||
--exclude='__pycache__' \
|
||||
--exclude='stock_data_cache' \
|
||||
--exclude='*.pyc' \
|
||||
--exclude='.DS_Store' \
|
||||
--exclude='stock_names.json' \
|
||||
--exclude='alerts_cache.json' \
|
||||
--exclude='trades.json' \
|
||||
--exclude='watchlist.json' \
|
||||
--exclude='*.log' \
|
||||
--exclude='.playwright-mcp' \
|
||||
--exclude='/app.js' \
|
||||
--exclude='/index.html' \
|
||||
--exclude='/main.css' \
|
||||
--exclude='/css' \
|
||||
--exclude='/js' \
|
||||
--exclude='/.windsurfrules'
|
||||
|
||||
ssh ${NEW_SERVER} "systemctl restart stock-app && echo '✅ 服务已重启'"
|
||||
|
||||
echo ""
|
||||
echo "访问: http://stock.allbyai.cn"
|
||||
Reference in New Issue
Block a user