server-deploy.sh 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. #!/bin/bash
  2. # ============================================
  3. # 灵越智报 2.0 - 服务器一键部署脚本
  4. # 适用于: Ubuntu 22.04 LTS
  5. # 服务器: lanaipc
  6. # 版本: 2.1.0
  7. # 更新日期: 2026-01-19
  8. # ============================================
  9. set -e
  10. # 颜色定义
  11. RED='\033[0;31m'
  12. GREEN='\033[0;32m'
  13. YELLOW='\033[1;33m'
  14. BLUE='\033[0;34m'
  15. CYAN='\033[0;36m'
  16. NC='\033[0m'
  17. # 配置
  18. PROJECT_DIR="/mnt/win_home/lingyue-zhibao"
  19. LOG_DIR="/var/log/lingyue"
  20. DATA_DIR="/mnt/win_home/lingyue-data"
  21. BACKUP_DIR="/mnt/win_home/lingyue-backup"
  22. PYTHON_VENV_DIR="${PROJECT_DIR}/python-services/ner-service/venv"
  23. # 数据库配置
  24. DB_NAME="lingyue_zhibao"
  25. DB_USER="lingyue"
  26. DB_PASS="123123"
  27. DB_HOST="localhost"
  28. DB_PORT="5432"
  29. # RabbitMQ 配置
  30. MQ_USER="admin"
  31. MQ_PASS="admin123"
  32. # NER 服务配置
  33. NER_SERVICE_PORT="8001"
  34. NER_SERVICE_HOST="localhost"
  35. # 日志函数
  36. log_info() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
  37. log_warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
  38. log_error() { echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') $1"; }
  39. log_title() { echo -e "\n${BLUE}========== $1 ==========${NC}\n"; }
  40. log_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
  41. # 检查 root 权限
  42. check_root() {
  43. if [ "$EUID" -ne 0 ]; then
  44. log_error "请使用 root 用户运行此脚本"
  45. exit 1
  46. fi
  47. }
  48. # 检查必要的服务是否运行
  49. check_services() {
  50. log_title "检查服务状态"
  51. local all_ok=true
  52. if systemctl is-active --quiet postgresql; then
  53. log_info "PostgreSQL: 运行中"
  54. else
  55. log_warn "PostgreSQL: 未运行"
  56. all_ok=false
  57. fi
  58. if systemctl is-active --quiet redis-server; then
  59. log_info "Redis: 运行中"
  60. else
  61. log_warn "Redis: 未运行"
  62. all_ok=false
  63. fi
  64. if systemctl is-active --quiet rabbitmq-server; then
  65. log_info "RabbitMQ: 运行中"
  66. else
  67. log_warn "RabbitMQ: 未运行"
  68. all_ok=false
  69. fi
  70. if [ "$all_ok" = false ]; then
  71. log_error "部分服务未运行,请先启动依赖服务"
  72. return 1
  73. fi
  74. return 0
  75. }
  76. # 确保目录存在
  77. ensure_directories() {
  78. mkdir -p ${LOG_DIR}
  79. mkdir -p ${DATA_DIR}
  80. mkdir -p ${BACKUP_DIR}
  81. chmod 755 ${LOG_DIR} ${DATA_DIR} ${BACKUP_DIR}
  82. }
  83. # 安装基础依赖
  84. install_dependencies() {
  85. log_title "安装基础依赖"
  86. apt update
  87. apt install -y openjdk-17-jdk maven git curl wget
  88. log_info "Java 版本: $(java -version 2>&1 | head -1)"
  89. log_info "Maven 版本: $(mvn -version 2>&1 | head -1)"
  90. }
  91. # 安装 PostgreSQL + pgvector
  92. install_postgresql() {
  93. log_title "安装 PostgreSQL + pgvector"
  94. # 安装 PostgreSQL
  95. apt install -y postgresql postgresql-contrib postgresql-server-dev-all build-essential
  96. # 编译安装 pgvector
  97. if [ ! -d "/tmp/pgvector" ]; then
  98. cd /tmp
  99. git clone https://github.com/pgvector/pgvector.git
  100. fi
  101. cd /tmp/pgvector
  102. make clean || true
  103. make
  104. make install
  105. # 启动服务
  106. systemctl enable postgresql
  107. systemctl restart postgresql
  108. log_info "PostgreSQL 已安装并启动"
  109. }
  110. # 配置数据库
  111. setup_database() {
  112. log_title "配置数据库"
  113. # 创建用户和数据库
  114. sudo -u postgres psql <<EOF
  115. DO \$\$
  116. BEGIN
  117. IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${DB_USER}') THEN
  118. CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASS}';
  119. END IF;
  120. END
  121. \$\$;
  122. SELECT 'CREATE DATABASE ${DB_NAME} OWNER ${DB_USER}'
  123. WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_NAME}')\gexec
  124. GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};
  125. EOF
  126. # 创建扩展
  127. sudo -u postgres psql -d ${DB_NAME} <<EOF
  128. CREATE EXTENSION IF NOT EXISTS vector;
  129. CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  130. EOF
  131. log_info "数据库 ${DB_NAME} 配置完成"
  132. }
  133. # 安装 Redis
  134. install_redis() {
  135. log_title "安装 Redis"
  136. apt install -y redis-server
  137. systemctl enable redis-server
  138. systemctl restart redis-server
  139. log_info "Redis 已安装: $(redis-cli ping)"
  140. }
  141. # 安装 RabbitMQ
  142. install_rabbitmq() {
  143. log_title "安装 RabbitMQ"
  144. apt install -y rabbitmq-server
  145. systemctl enable rabbitmq-server
  146. systemctl restart rabbitmq-server
  147. # 启用管理插件
  148. rabbitmq-plugins enable rabbitmq_management
  149. # 创建用户
  150. rabbitmqctl add_user ${MQ_USER} ${MQ_PASS} 2>/dev/null || true
  151. rabbitmqctl set_user_tags ${MQ_USER} administrator
  152. rabbitmqctl set_permissions -p / ${MQ_USER} ".*" ".*" ".*"
  153. log_info "RabbitMQ 已安装,管理界面: http://localhost:15672"
  154. }
  155. # 安装 Ollama
  156. install_ollama() {
  157. log_title "安装 Ollama"
  158. if ! command -v ollama &> /dev/null; then
  159. curl -fsSL https://ollama.ai/install.sh | sh
  160. fi
  161. # 创建 Ollama systemd 服务
  162. if [ ! -f /etc/systemd/system/ollama.service ]; then
  163. cat > /etc/systemd/system/ollama.service <<EOF
  164. [Unit]
  165. Description=Ollama Service
  166. After=network.target
  167. [Service]
  168. Type=simple
  169. User=root
  170. ExecStart=/usr/local/bin/ollama serve
  171. Restart=always
  172. RestartSec=10
  173. StandardOutput=append:/var/log/ollama.log
  174. StandardError=append:/var/log/ollama-error.log
  175. [Install]
  176. WantedBy=multi-user.target
  177. EOF
  178. systemctl daemon-reload
  179. fi
  180. systemctl enable ollama
  181. systemctl restart ollama
  182. sleep 5
  183. # 下载 Embedding 模型
  184. if ! ollama list 2>/dev/null | grep -q "nomic-embed-text"; then
  185. log_info "下载 nomic-embed-text 模型..."
  186. ollama pull nomic-embed-text
  187. fi
  188. log_info "Ollama 已安装"
  189. }
  190. # 安装 Python 环境(用于 NER 服务)
  191. install_python_env() {
  192. log_title "安装 Python 环境"
  193. # 安装 Python 和 pip
  194. apt install -y python3 python3-pip python3-venv
  195. log_info "Python 版本: $(python3 --version)"
  196. }
  197. # 部署 NER Python 服务
  198. deploy_ner_service() {
  199. log_title "部署 NER Python 服务"
  200. local ner_dir="${PROJECT_DIR}/python-services/ner-service"
  201. if [ ! -d "${ner_dir}" ]; then
  202. log_warn "NER 服务目录不存在: ${ner_dir}"
  203. return 0
  204. fi
  205. cd ${ner_dir}
  206. # 创建虚拟环境
  207. if [ ! -d "${PYTHON_VENV_DIR}" ]; then
  208. log_step "创建 Python 虚拟环境..."
  209. python3 -m venv ${PYTHON_VENV_DIR}
  210. fi
  211. # 激活虚拟环境并安装依赖
  212. log_step "安装 Python 依赖..."
  213. source ${PYTHON_VENV_DIR}/bin/activate
  214. pip install --upgrade pip -q
  215. pip install -r requirements.txt -q
  216. deactivate
  217. log_info "NER 服务依赖安装完成"
  218. }
  219. # 创建 NER 服务的 Systemd 配置
  220. create_ner_systemd_service() {
  221. log_title "创建 NER Systemd 服务"
  222. local ner_dir="${PROJECT_DIR}/python-services/ner-service"
  223. if [ ! -d "${ner_dir}" ]; then
  224. log_warn "NER 服务目录不存在,跳过"
  225. return 0
  226. fi
  227. cat > /etc/systemd/system/lingyue-ner.service <<EOF
  228. [Unit]
  229. Description=Lingyue NER Service
  230. After=network.target
  231. [Service]
  232. Type=simple
  233. User=root
  234. WorkingDirectory=${ner_dir}
  235. ExecStart=${PYTHON_VENV_DIR}/bin/uvicorn app.main:app --host 0.0.0.0 --port ${NER_SERVICE_PORT}
  236. Restart=always
  237. RestartSec=10
  238. StandardOutput=append:${LOG_DIR}/ner-service.log
  239. StandardError=append:${LOG_DIR}/ner-service-error.log
  240. Environment=NER_MODEL=rule
  241. Environment=LOG_LEVEL=INFO
  242. Environment=MAX_TEXT_LENGTH=50000
  243. [Install]
  244. WantedBy=multi-user.target
  245. EOF
  246. systemctl daemon-reload
  247. log_info "NER Systemd 服务已创建"
  248. }
  249. # 启动 NER 服务
  250. start_ner_service() {
  251. log_title "启动 NER 服务"
  252. if [ ! -f /etc/systemd/system/lingyue-ner.service ]; then
  253. log_warn "NER 服务未配置,跳过"
  254. return 0
  255. fi
  256. systemctl enable lingyue-ner
  257. systemctl restart lingyue-ner
  258. sleep 5
  259. if systemctl is-active --quiet lingyue-ner; then
  260. log_info "NER 服务启动成功: http://localhost:${NER_SERVICE_PORT}"
  261. else
  262. log_warn "NER 服务启动失败,查看日志: journalctl -u lingyue-ner -f"
  263. fi
  264. }
  265. # 停止 NER 服务
  266. stop_ner_service() {
  267. if systemctl is-active --quiet lingyue-ner; then
  268. systemctl stop lingyue-ner
  269. log_info "NER 服务已停止"
  270. fi
  271. }
  272. # 部署项目
  273. deploy_project() {
  274. log_title "部署项目"
  275. # 创建目录
  276. ensure_directories
  277. # 进入项目目录
  278. if [ ! -d "${PROJECT_DIR}" ]; then
  279. log_error "项目目录不存在: ${PROJECT_DIR}"
  280. log_info "请先克隆项目到 ${PROJECT_DIR}"
  281. exit 1
  282. fi
  283. cd ${PROJECT_DIR}
  284. # 初始化数据库表
  285. init_database_tables
  286. # 编译项目
  287. build_java_project
  288. log_info "项目部署完成"
  289. }
  290. # 初始化数据库表
  291. init_database_tables() {
  292. log_step "初始化数据库表..."
  293. cd ${PROJECT_DIR}
  294. # 执行初始化脚本(单文件)
  295. if [ -f "database/init.sql" ]; then
  296. PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -d ${DB_NAME} -h ${DB_HOST} -f database/init.sql 2>/dev/null || true
  297. log_info "database/init.sql 执行完成"
  298. fi
  299. }
  300. # 编译 Java 项目
  301. build_java_project() {
  302. log_step "编译 Java 项目..."
  303. cd ${PROJECT_DIR}/backend
  304. # 清理并编译
  305. mvn clean package -DskipTests -q
  306. if [ -f "lingyue-starter/target/lingyue-starter.jar" ]; then
  307. log_info "Java 项目编译成功"
  308. else
  309. log_error "Java 项目编译失败"
  310. exit 1
  311. fi
  312. }
  313. # 创建 Systemd 服务
  314. create_systemd_service() {
  315. log_title "创建 Systemd 服务"
  316. cat > /etc/systemd/system/lingyue.service <<EOF
  317. [Unit]
  318. Description=Lingyue Zhibao Application
  319. After=network.target postgresql.service redis-server.service rabbitmq-server.service
  320. [Service]
  321. Type=simple
  322. User=root
  323. WorkingDirectory=${PROJECT_DIR}/backend
  324. ExecStart=/usr/bin/java -Xms1g -Xmx2g -XX:+UseG1GC -jar lingyue-starter/target/lingyue-starter.jar
  325. Restart=always
  326. RestartSec=10
  327. StandardOutput=append:${LOG_DIR}/lingyue.log
  328. StandardError=append:${LOG_DIR}/lingyue-error.log
  329. # Java 环境
  330. Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
  331. Environment=SPRING_PROFILES_ACTIVE=prod
  332. # 数据库配置
  333. Environment=DB_HOST=${DB_HOST}
  334. Environment=DB_PORT=${DB_PORT}
  335. Environment=DB_NAME=${DB_NAME}
  336. Environment=DB_USERNAME=${DB_USER}
  337. Environment=DB_PASSWORD=${DB_PASS}
  338. # Redis 配置
  339. Environment=REDIS_HOST=localhost
  340. Environment=REDIS_PORT=6379
  341. # RabbitMQ 配置
  342. Environment=RABBITMQ_HOST=localhost
  343. Environment=RABBITMQ_PORT=5672
  344. Environment=RABBITMQ_USERNAME=${MQ_USER}
  345. Environment=RABBITMQ_PASSWORD=${MQ_PASS}
  346. # NER 服务配置
  347. Environment=NER_SERVICE_URL=http://${NER_SERVICE_HOST}:${NER_SERVICE_PORT}
  348. [Install]
  349. WantedBy=multi-user.target
  350. EOF
  351. systemctl daemon-reload
  352. log_info "Systemd 服务已创建"
  353. }
  354. # 启动应用
  355. start_app() {
  356. log_title "启动应用"
  357. systemctl enable lingyue
  358. systemctl restart lingyue
  359. sleep 10
  360. if systemctl is-active --quiet lingyue; then
  361. log_info "应用启动成功"
  362. log_info "访问地址: http://$(hostname -I | awk '{print $1}'):8000"
  363. else
  364. log_error "应用启动失败,查看日志: journalctl -u lingyue -f"
  365. fi
  366. }
  367. # 停止应用
  368. stop_app() {
  369. log_title "停止应用"
  370. systemctl stop lingyue
  371. log_info "应用已停止"
  372. }
  373. # 查看状态
  374. show_status() {
  375. log_title "服务状态"
  376. printf "%-20s %s\n" "服务" "状态"
  377. printf "%-20s %s\n" "--------------------" "----------"
  378. printf "%-20s %s\n" "PostgreSQL" "$(systemctl is-active postgresql 2>/dev/null || echo 'unknown')"
  379. printf "%-20s %s\n" "Redis" "$(systemctl is-active redis-server 2>/dev/null || echo 'unknown')"
  380. printf "%-20s %s\n" "RabbitMQ" "$(systemctl is-active rabbitmq-server 2>/dev/null || echo 'unknown')"
  381. printf "%-20s %s\n" "Lingyue (Java)" "$(systemctl is-active lingyue 2>/dev/null || echo 'unknown')"
  382. printf "%-20s %s\n" "Lingyue NER" "$(systemctl is-active lingyue-ner 2>/dev/null || echo 'unknown')"
  383. if command -v ollama &> /dev/null && curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then
  384. printf "%-20s %s\n" "Ollama" "active"
  385. else
  386. printf "%-20s %s\n" "Ollama" "inactive"
  387. fi
  388. echo ""
  389. local ip=$(hostname -I | awk '{print $1}')
  390. if systemctl is-active --quiet lingyue; then
  391. log_info "主应用: http://${ip}:8000"
  392. log_info "Swagger: http://${ip}:8000/swagger-ui.html"
  393. log_info "健康检查: http://${ip}:8000/actuator/health"
  394. fi
  395. if systemctl is-active --quiet lingyue-ner; then
  396. log_info "NER 服务: http://${ip}:${NER_SERVICE_PORT}"
  397. log_info "NER 健康检查: http://${ip}:${NER_SERVICE_PORT}/health"
  398. fi
  399. }
  400. # 查看日志
  401. show_logs() {
  402. journalctl -u lingyue -f
  403. }
  404. # 健康检查
  405. health_check() {
  406. log_title "健康检查"
  407. echo "=== Java 主应用 ==="
  408. local health=$(curl -s http://localhost:8000/actuator/health 2>/dev/null)
  409. if [ -n "$health" ]; then
  410. echo "$health" | python3 -m json.tool 2>/dev/null || echo "$health"
  411. else
  412. log_error "Java 应用未响应"
  413. fi
  414. echo ""
  415. echo "=== NER 服务 ==="
  416. local ner_health=$(curl -s http://localhost:${NER_SERVICE_PORT}/health 2>/dev/null)
  417. if [ -n "$ner_health" ]; then
  418. echo "$ner_health" | python3 -m json.tool 2>/dev/null || echo "$ner_health"
  419. else
  420. log_warn "NER 服务未响应(可能未部署)"
  421. fi
  422. }
  423. # 备份数据库
  424. backup_database() {
  425. log_title "备份数据库"
  426. ensure_directories
  427. local timestamp=$(date '+%Y%m%d_%H%M%S')
  428. local backup_file="${BACKUP_DIR}/db_backup_${timestamp}.sql"
  429. log_step "备份数据库到 ${backup_file}..."
  430. PGPASSWORD=${DB_PASS} pg_dump -U ${DB_USER} -h ${DB_HOST} -d ${DB_NAME} > ${backup_file}
  431. # 压缩备份
  432. gzip ${backup_file}
  433. log_info "数据库备份完成: ${backup_file}.gz"
  434. # 清理 7 天前的备份
  435. find ${BACKUP_DIR} -name "db_backup_*.sql.gz" -mtime +7 -delete
  436. log_info "已清理 7 天前的备份"
  437. # 显示备份列表
  438. echo ""
  439. echo "现有备份:"
  440. ls -lh ${BACKUP_DIR}/db_backup_*.sql.gz 2>/dev/null || echo "无备份文件"
  441. }
  442. # 恢复数据库
  443. restore_database() {
  444. log_title "恢复数据库"
  445. local backup_file=$1
  446. if [ -z "$backup_file" ]; then
  447. echo "可用的备份文件:"
  448. ls -1 ${BACKUP_DIR}/db_backup_*.sql.gz 2>/dev/null || echo "无备份文件"
  449. echo ""
  450. log_error "请指定备份文件: ./server-deploy.sh restore <backup_file>"
  451. return 1
  452. fi
  453. if [ ! -f "$backup_file" ]; then
  454. log_error "备份文件不存在: $backup_file"
  455. return 1
  456. fi
  457. log_warn "警告: 此操作将覆盖现有数据库!"
  458. read -p "确认恢复? (yes/no): " confirm
  459. if [ "$confirm" != "yes" ]; then
  460. log_info "操作已取消"
  461. return 0
  462. fi
  463. log_step "恢复数据库..."
  464. # 解压并恢复
  465. if [[ "$backup_file" == *.gz ]]; then
  466. gunzip -c "$backup_file" | PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -h ${DB_HOST} -d ${DB_NAME}
  467. else
  468. PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -h ${DB_HOST} -d ${DB_NAME} < "$backup_file"
  469. fi
  470. log_info "数据库恢复完成"
  471. }
  472. # 清理日志
  473. clean_logs() {
  474. log_title "清理日志"
  475. # 清理 30 天前的日志
  476. find ${LOG_DIR} -name "*.log" -mtime +30 -delete 2>/dev/null || true
  477. # 截断当前日志文件(保留最后 10000 行)
  478. for logfile in ${LOG_DIR}/*.log; do
  479. if [ -f "$logfile" ]; then
  480. tail -n 10000 "$logfile" > "${logfile}.tmp" && mv "${logfile}.tmp" "$logfile"
  481. fi
  482. done
  483. log_info "日志清理完成"
  484. # 显示日志目录大小
  485. echo "日志目录大小:"
  486. du -sh ${LOG_DIR}
  487. }
  488. # 查看所有日志
  489. show_all_logs() {
  490. log_title "选择要查看的日志"
  491. echo "1) Java 主应用日志"
  492. echo "2) Java 错误日志"
  493. echo "3) NER 服务日志"
  494. echo "4) NER 错误日志"
  495. echo "5) Ollama 日志"
  496. echo "6) 全部日志 (tail)"
  497. read -p "选择 [1-6]: " choice
  498. case $choice in
  499. 1) tail -f ${LOG_DIR}/lingyue.log ;;
  500. 2) tail -f ${LOG_DIR}/lingyue-error.log ;;
  501. 3) tail -f ${LOG_DIR}/ner-service.log ;;
  502. 4) tail -f ${LOG_DIR}/ner-service-error.log ;;
  503. 5) tail -f /var/log/ollama.log ;;
  504. 6) tail -f ${LOG_DIR}/*.log ;;
  505. *) log_error "无效选择" ;;
  506. esac
  507. }
  508. # 完整安装
  509. full_install() {
  510. check_root
  511. ensure_directories
  512. install_dependencies
  513. install_python_env
  514. install_postgresql
  515. setup_database
  516. install_redis
  517. install_rabbitmq
  518. install_ollama
  519. deploy_project
  520. deploy_ner_service
  521. create_systemd_service
  522. create_ner_systemd_service
  523. start_app
  524. start_ner_service
  525. log_title "部署完成"
  526. show_status
  527. }
  528. # 仅安装基础设施(不部署应用)
  529. install_infra_only() {
  530. check_root
  531. ensure_directories
  532. install_dependencies
  533. install_python_env
  534. install_postgresql
  535. setup_database
  536. install_redis
  537. install_rabbitmq
  538. install_ollama
  539. log_title "基础设施安装完成"
  540. show_status
  541. }
  542. # 仅部署应用(假设基础设施已就绪)
  543. deploy_app_only() {
  544. check_root
  545. check_services || exit 1
  546. deploy_project
  547. deploy_ner_service
  548. create_systemd_service
  549. create_ner_systemd_service
  550. start_app
  551. start_ner_service
  552. log_title "应用部署完成"
  553. show_status
  554. }
  555. # 仅更新代码
  556. update_only() {
  557. log_title "更新代码"
  558. cd ${PROJECT_DIR}
  559. # 拉取最新代码
  560. log_step "拉取最新代码..."
  561. git fetch --all
  562. git pull origin dev || git pull origin main || git pull origin master || true
  563. # 编译 Java 项目
  564. build_java_project
  565. # 更新 NER 服务依赖
  566. if [ -d "python-services/ner-service" ]; then
  567. log_step "更新 NER 服务依赖..."
  568. source ${PYTHON_VENV_DIR}/bin/activate 2>/dev/null || true
  569. pip install -r python-services/ner-service/requirements.txt -q 2>/dev/null || true
  570. deactivate 2>/dev/null || true
  571. fi
  572. # 重启服务
  573. log_step "重启服务..."
  574. systemctl restart lingyue
  575. systemctl restart lingyue-ner 2>/dev/null || true
  576. sleep 10
  577. health_check
  578. }
  579. # 快速重启(不重新编译)
  580. quick_restart() {
  581. log_title "快速重启"
  582. systemctl restart lingyue
  583. systemctl restart lingyue-ner 2>/dev/null || true
  584. sleep 5
  585. health_check
  586. }
  587. # 停止所有服务
  588. stop_all() {
  589. log_title "停止所有服务"
  590. systemctl stop lingyue 2>/dev/null || true
  591. systemctl stop lingyue-ner 2>/dev/null || true
  592. log_info "所有应用服务已停止"
  593. }
  594. # 启动所有服务
  595. start_all() {
  596. log_title "启动所有服务"
  597. # 先检查基础服务
  598. check_services || {
  599. log_warn "部分基础服务未运行,尝试启动..."
  600. systemctl start postgresql 2>/dev/null || true
  601. systemctl start redis-server 2>/dev/null || true
  602. systemctl start rabbitmq-server 2>/dev/null || true
  603. sleep 3
  604. }
  605. start_app
  606. start_ner_service
  607. }
  608. # 显示帮助
  609. show_help() {
  610. cat <<EOF
  611. ${BLUE}灵越智报 2.0 - 服务器部署脚本${NC}
  612. ${CYAN}版本: 2.1.0${NC}
  613. ${GREEN}用法:${NC} ./server-deploy.sh [命令] [参数]
  614. ${YELLOW}部署命令:${NC}
  615. install 完整安装(首次部署,包含所有基础设施)
  616. install-infra 仅安装基础设施(PostgreSQL, Redis, RabbitMQ, Ollama)
  617. deploy 仅部署应用(假设基础设施已就绪)
  618. update 更新代码并重启(git pull + mvn package)
  619. ${YELLOW}服务控制:${NC}
  620. start 启动所有应用服务
  621. stop 停止所有应用服务
  622. restart 快速重启(不重新编译)
  623. status 查看所有服务状态
  624. ${YELLOW}日志与监控:${NC}
  625. logs 选择查看日志
  626. health 健康检查(Java + NER)
  627. ${YELLOW}数据库管理:${NC}
  628. backup 备份数据库
  629. restore <file> 恢复数据库(需指定备份文件)
  630. init-db 重新初始化数据库表
  631. ${YELLOW}维护命令:${NC}
  632. clean-logs 清理旧日志文件
  633. help 显示此帮助
  634. ${GREEN}示例:${NC}
  635. # 首次部署
  636. ./server-deploy.sh install
  637. # 更新代码并重启
  638. ./server-deploy.sh update
  639. # 备份数据库
  640. ./server-deploy.sh backup
  641. # 查看服务状态
  642. ./server-deploy.sh status
  643. ${YELLOW}目录说明:${NC}
  644. 项目目录: ${PROJECT_DIR}
  645. 日志目录: ${LOG_DIR}
  646. 数据目录: ${DATA_DIR}
  647. 备份目录: ${BACKUP_DIR}
  648. ${YELLOW}服务端口:${NC}
  649. Java 主应用: 8000
  650. NER 服务: ${NER_SERVICE_PORT}
  651. PostgreSQL: ${DB_PORT}
  652. Redis: 6379
  653. RabbitMQ: 5672 / 15672 (管理界面)
  654. Ollama: 11434
  655. EOF
  656. }
  657. # 主函数
  658. main() {
  659. case "${1:-help}" in
  660. install)
  661. full_install
  662. ;;
  663. install-infra)
  664. install_infra_only
  665. ;;
  666. deploy)
  667. deploy_app_only
  668. ;;
  669. update)
  670. update_only
  671. ;;
  672. start)
  673. start_all
  674. ;;
  675. stop)
  676. stop_all
  677. ;;
  678. restart)
  679. quick_restart
  680. ;;
  681. status)
  682. show_status
  683. ;;
  684. logs)
  685. show_all_logs
  686. ;;
  687. health)
  688. health_check
  689. ;;
  690. backup)
  691. backup_database
  692. ;;
  693. restore)
  694. restore_database "$2"
  695. ;;
  696. init-db)
  697. init_database_tables
  698. ;;
  699. clean-logs)
  700. clean_logs
  701. ;;
  702. help|--help|-h)
  703. show_help
  704. ;;
  705. *)
  706. log_error "未知命令: $1"
  707. show_help
  708. exit 1
  709. ;;
  710. esac
  711. }
  712. main "$@"