server-deploy.sh 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  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 "backend/sql/init.sql" ]; then
  296. PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -d ${DB_NAME} -h ${DB_HOST} -f backend/sql/init.sql 2>/dev/null || true
  297. log_info "init.sql 执行完成"
  298. fi
  299. # 执行 RAG 表脚本
  300. if [ -f "backend/sql/rag_tables.sql" ]; then
  301. PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -d ${DB_NAME} -h ${DB_HOST} -f backend/sql/rag_tables.sql 2>/dev/null || true
  302. log_info "rag_tables.sql 执行完成"
  303. fi
  304. # 执行补充表脚本
  305. if [ -f "backend/sql/supplement_tables.sql" ]; then
  306. PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -d ${DB_NAME} -h ${DB_HOST} -f backend/sql/supplement_tables.sql 2>/dev/null || true
  307. log_info "supplement_tables.sql 执行完成"
  308. fi
  309. }
  310. # 编译 Java 项目
  311. build_java_project() {
  312. log_step "编译 Java 项目..."
  313. cd ${PROJECT_DIR}/backend
  314. # 清理并编译
  315. mvn clean package -DskipTests -q
  316. if [ -f "lingyue-starter/target/lingyue-starter.jar" ]; then
  317. log_info "Java 项目编译成功"
  318. else
  319. log_error "Java 项目编译失败"
  320. exit 1
  321. fi
  322. }
  323. # 创建 Systemd 服务
  324. create_systemd_service() {
  325. log_title "创建 Systemd 服务"
  326. cat > /etc/systemd/system/lingyue.service <<EOF
  327. [Unit]
  328. Description=Lingyue Zhibao Application
  329. After=network.target postgresql.service redis-server.service rabbitmq-server.service
  330. [Service]
  331. Type=simple
  332. User=root
  333. WorkingDirectory=${PROJECT_DIR}/backend
  334. ExecStart=/usr/bin/java -Xms1g -Xmx2g -XX:+UseG1GC -jar lingyue-starter/target/lingyue-starter.jar
  335. Restart=always
  336. RestartSec=10
  337. StandardOutput=append:${LOG_DIR}/lingyue.log
  338. StandardError=append:${LOG_DIR}/lingyue-error.log
  339. # Java 环境
  340. Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
  341. Environment=SPRING_PROFILES_ACTIVE=prod
  342. # 数据库配置
  343. Environment=DB_HOST=${DB_HOST}
  344. Environment=DB_PORT=${DB_PORT}
  345. Environment=DB_NAME=${DB_NAME}
  346. Environment=DB_USERNAME=${DB_USER}
  347. Environment=DB_PASSWORD=${DB_PASS}
  348. # Redis 配置
  349. Environment=REDIS_HOST=localhost
  350. Environment=REDIS_PORT=6379
  351. # RabbitMQ 配置
  352. Environment=RABBITMQ_HOST=localhost
  353. Environment=RABBITMQ_PORT=5672
  354. Environment=RABBITMQ_USERNAME=${MQ_USER}
  355. Environment=RABBITMQ_PASSWORD=${MQ_PASS}
  356. # NER 服务配置
  357. Environment=NER_SERVICE_URL=http://${NER_SERVICE_HOST}:${NER_SERVICE_PORT}
  358. [Install]
  359. WantedBy=multi-user.target
  360. EOF
  361. systemctl daemon-reload
  362. log_info "Systemd 服务已创建"
  363. }
  364. # 启动应用
  365. start_app() {
  366. log_title "启动应用"
  367. systemctl enable lingyue
  368. systemctl restart lingyue
  369. sleep 10
  370. if systemctl is-active --quiet lingyue; then
  371. log_info "应用启动成功"
  372. log_info "访问地址: http://$(hostname -I | awk '{print $1}'):8000"
  373. else
  374. log_error "应用启动失败,查看日志: journalctl -u lingyue -f"
  375. fi
  376. }
  377. # 停止应用
  378. stop_app() {
  379. log_title "停止应用"
  380. systemctl stop lingyue
  381. log_info "应用已停止"
  382. }
  383. # 查看状态
  384. show_status() {
  385. log_title "服务状态"
  386. printf "%-20s %s\n" "服务" "状态"
  387. printf "%-20s %s\n" "--------------------" "----------"
  388. printf "%-20s %s\n" "PostgreSQL" "$(systemctl is-active postgresql 2>/dev/null || echo 'unknown')"
  389. printf "%-20s %s\n" "Redis" "$(systemctl is-active redis-server 2>/dev/null || echo 'unknown')"
  390. printf "%-20s %s\n" "RabbitMQ" "$(systemctl is-active rabbitmq-server 2>/dev/null || echo 'unknown')"
  391. printf "%-20s %s\n" "Lingyue (Java)" "$(systemctl is-active lingyue 2>/dev/null || echo 'unknown')"
  392. printf "%-20s %s\n" "Lingyue NER" "$(systemctl is-active lingyue-ner 2>/dev/null || echo 'unknown')"
  393. if command -v ollama &> /dev/null && curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then
  394. printf "%-20s %s\n" "Ollama" "active"
  395. else
  396. printf "%-20s %s\n" "Ollama" "inactive"
  397. fi
  398. echo ""
  399. local ip=$(hostname -I | awk '{print $1}')
  400. if systemctl is-active --quiet lingyue; then
  401. log_info "主应用: http://${ip}:8000"
  402. log_info "Swagger: http://${ip}:8000/swagger-ui.html"
  403. log_info "健康检查: http://${ip}:8000/actuator/health"
  404. fi
  405. if systemctl is-active --quiet lingyue-ner; then
  406. log_info "NER 服务: http://${ip}:${NER_SERVICE_PORT}"
  407. log_info "NER 健康检查: http://${ip}:${NER_SERVICE_PORT}/health"
  408. fi
  409. }
  410. # 查看日志
  411. show_logs() {
  412. journalctl -u lingyue -f
  413. }
  414. # 健康检查
  415. health_check() {
  416. log_title "健康检查"
  417. echo "=== Java 主应用 ==="
  418. local health=$(curl -s http://localhost:8000/actuator/health 2>/dev/null)
  419. if [ -n "$health" ]; then
  420. echo "$health" | python3 -m json.tool 2>/dev/null || echo "$health"
  421. else
  422. log_error "Java 应用未响应"
  423. fi
  424. echo ""
  425. echo "=== NER 服务 ==="
  426. local ner_health=$(curl -s http://localhost:${NER_SERVICE_PORT}/health 2>/dev/null)
  427. if [ -n "$ner_health" ]; then
  428. echo "$ner_health" | python3 -m json.tool 2>/dev/null || echo "$ner_health"
  429. else
  430. log_warn "NER 服务未响应(可能未部署)"
  431. fi
  432. }
  433. # 备份数据库
  434. backup_database() {
  435. log_title "备份数据库"
  436. ensure_directories
  437. local timestamp=$(date '+%Y%m%d_%H%M%S')
  438. local backup_file="${BACKUP_DIR}/db_backup_${timestamp}.sql"
  439. log_step "备份数据库到 ${backup_file}..."
  440. PGPASSWORD=${DB_PASS} pg_dump -U ${DB_USER} -h ${DB_HOST} -d ${DB_NAME} > ${backup_file}
  441. # 压缩备份
  442. gzip ${backup_file}
  443. log_info "数据库备份完成: ${backup_file}.gz"
  444. # 清理 7 天前的备份
  445. find ${BACKUP_DIR} -name "db_backup_*.sql.gz" -mtime +7 -delete
  446. log_info "已清理 7 天前的备份"
  447. # 显示备份列表
  448. echo ""
  449. echo "现有备份:"
  450. ls -lh ${BACKUP_DIR}/db_backup_*.sql.gz 2>/dev/null || echo "无备份文件"
  451. }
  452. # 恢复数据库
  453. restore_database() {
  454. log_title "恢复数据库"
  455. local backup_file=$1
  456. if [ -z "$backup_file" ]; then
  457. echo "可用的备份文件:"
  458. ls -1 ${BACKUP_DIR}/db_backup_*.sql.gz 2>/dev/null || echo "无备份文件"
  459. echo ""
  460. log_error "请指定备份文件: ./server-deploy.sh restore <backup_file>"
  461. return 1
  462. fi
  463. if [ ! -f "$backup_file" ]; then
  464. log_error "备份文件不存在: $backup_file"
  465. return 1
  466. fi
  467. log_warn "警告: 此操作将覆盖现有数据库!"
  468. read -p "确认恢复? (yes/no): " confirm
  469. if [ "$confirm" != "yes" ]; then
  470. log_info "操作已取消"
  471. return 0
  472. fi
  473. log_step "恢复数据库..."
  474. # 解压并恢复
  475. if [[ "$backup_file" == *.gz ]]; then
  476. gunzip -c "$backup_file" | PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -h ${DB_HOST} -d ${DB_NAME}
  477. else
  478. PGPASSWORD=${DB_PASS} psql -U ${DB_USER} -h ${DB_HOST} -d ${DB_NAME} < "$backup_file"
  479. fi
  480. log_info "数据库恢复完成"
  481. }
  482. # 清理日志
  483. clean_logs() {
  484. log_title "清理日志"
  485. # 清理 30 天前的日志
  486. find ${LOG_DIR} -name "*.log" -mtime +30 -delete 2>/dev/null || true
  487. # 截断当前日志文件(保留最后 10000 行)
  488. for logfile in ${LOG_DIR}/*.log; do
  489. if [ -f "$logfile" ]; then
  490. tail -n 10000 "$logfile" > "${logfile}.tmp" && mv "${logfile}.tmp" "$logfile"
  491. fi
  492. done
  493. log_info "日志清理完成"
  494. # 显示日志目录大小
  495. echo "日志目录大小:"
  496. du -sh ${LOG_DIR}
  497. }
  498. # 查看所有日志
  499. show_all_logs() {
  500. log_title "选择要查看的日志"
  501. echo "1) Java 主应用日志"
  502. echo "2) Java 错误日志"
  503. echo "3) NER 服务日志"
  504. echo "4) NER 错误日志"
  505. echo "5) Ollama 日志"
  506. echo "6) 全部日志 (tail)"
  507. read -p "选择 [1-6]: " choice
  508. case $choice in
  509. 1) tail -f ${LOG_DIR}/lingyue.log ;;
  510. 2) tail -f ${LOG_DIR}/lingyue-error.log ;;
  511. 3) tail -f ${LOG_DIR}/ner-service.log ;;
  512. 4) tail -f ${LOG_DIR}/ner-service-error.log ;;
  513. 5) tail -f /var/log/ollama.log ;;
  514. 6) tail -f ${LOG_DIR}/*.log ;;
  515. *) log_error "无效选择" ;;
  516. esac
  517. }
  518. # 完整安装
  519. full_install() {
  520. check_root
  521. ensure_directories
  522. install_dependencies
  523. install_python_env
  524. install_postgresql
  525. setup_database
  526. install_redis
  527. install_rabbitmq
  528. install_ollama
  529. deploy_project
  530. deploy_ner_service
  531. create_systemd_service
  532. create_ner_systemd_service
  533. start_app
  534. start_ner_service
  535. log_title "部署完成"
  536. show_status
  537. }
  538. # 仅安装基础设施(不部署应用)
  539. install_infra_only() {
  540. check_root
  541. ensure_directories
  542. install_dependencies
  543. install_python_env
  544. install_postgresql
  545. setup_database
  546. install_redis
  547. install_rabbitmq
  548. install_ollama
  549. log_title "基础设施安装完成"
  550. show_status
  551. }
  552. # 仅部署应用(假设基础设施已就绪)
  553. deploy_app_only() {
  554. check_root
  555. check_services || exit 1
  556. deploy_project
  557. deploy_ner_service
  558. create_systemd_service
  559. create_ner_systemd_service
  560. start_app
  561. start_ner_service
  562. log_title "应用部署完成"
  563. show_status
  564. }
  565. # 仅更新代码
  566. update_only() {
  567. log_title "更新代码"
  568. cd ${PROJECT_DIR}
  569. # 拉取最新代码
  570. log_step "拉取最新代码..."
  571. git fetch --all
  572. git pull origin dev || git pull origin main || git pull origin master || true
  573. # 编译 Java 项目
  574. build_java_project
  575. # 更新 NER 服务依赖
  576. if [ -d "python-services/ner-service" ]; then
  577. log_step "更新 NER 服务依赖..."
  578. source ${PYTHON_VENV_DIR}/bin/activate 2>/dev/null || true
  579. pip install -r python-services/ner-service/requirements.txt -q 2>/dev/null || true
  580. deactivate 2>/dev/null || true
  581. fi
  582. # 重启服务
  583. log_step "重启服务..."
  584. systemctl restart lingyue
  585. systemctl restart lingyue-ner 2>/dev/null || true
  586. sleep 10
  587. health_check
  588. }
  589. # 快速重启(不重新编译)
  590. quick_restart() {
  591. log_title "快速重启"
  592. systemctl restart lingyue
  593. systemctl restart lingyue-ner 2>/dev/null || true
  594. sleep 5
  595. health_check
  596. }
  597. # 停止所有服务
  598. stop_all() {
  599. log_title "停止所有服务"
  600. systemctl stop lingyue 2>/dev/null || true
  601. systemctl stop lingyue-ner 2>/dev/null || true
  602. log_info "所有应用服务已停止"
  603. }
  604. # 启动所有服务
  605. start_all() {
  606. log_title "启动所有服务"
  607. # 先检查基础服务
  608. check_services || {
  609. log_warn "部分基础服务未运行,尝试启动..."
  610. systemctl start postgresql 2>/dev/null || true
  611. systemctl start redis-server 2>/dev/null || true
  612. systemctl start rabbitmq-server 2>/dev/null || true
  613. sleep 3
  614. }
  615. start_app
  616. start_ner_service
  617. }
  618. # 显示帮助
  619. show_help() {
  620. cat <<EOF
  621. ${BLUE}灵越智报 2.0 - 服务器部署脚本${NC}
  622. ${CYAN}版本: 2.1.0${NC}
  623. ${GREEN}用法:${NC} ./server-deploy.sh [命令] [参数]
  624. ${YELLOW}部署命令:${NC}
  625. install 完整安装(首次部署,包含所有基础设施)
  626. install-infra 仅安装基础设施(PostgreSQL, Redis, RabbitMQ, Ollama)
  627. deploy 仅部署应用(假设基础设施已就绪)
  628. update 更新代码并重启(git pull + mvn package)
  629. ${YELLOW}服务控制:${NC}
  630. start 启动所有应用服务
  631. stop 停止所有应用服务
  632. restart 快速重启(不重新编译)
  633. status 查看所有服务状态
  634. ${YELLOW}日志与监控:${NC}
  635. logs 选择查看日志
  636. health 健康检查(Java + NER)
  637. ${YELLOW}数据库管理:${NC}
  638. backup 备份数据库
  639. restore <file> 恢复数据库(需指定备份文件)
  640. init-db 重新初始化数据库表
  641. ${YELLOW}维护命令:${NC}
  642. clean-logs 清理旧日志文件
  643. help 显示此帮助
  644. ${GREEN}示例:${NC}
  645. # 首次部署
  646. ./server-deploy.sh install
  647. # 更新代码并重启
  648. ./server-deploy.sh update
  649. # 备份数据库
  650. ./server-deploy.sh backup
  651. # 查看服务状态
  652. ./server-deploy.sh status
  653. ${YELLOW}目录说明:${NC}
  654. 项目目录: ${PROJECT_DIR}
  655. 日志目录: ${LOG_DIR}
  656. 数据目录: ${DATA_DIR}
  657. 备份目录: ${BACKUP_DIR}
  658. ${YELLOW}服务端口:${NC}
  659. Java 主应用: 8000
  660. NER 服务: ${NER_SERVICE_PORT}
  661. PostgreSQL: ${DB_PORT}
  662. Redis: 6379
  663. RabbitMQ: 5672 / 15672 (管理界面)
  664. Ollama: 11434
  665. EOF
  666. }
  667. # 主函数
  668. main() {
  669. case "${1:-help}" in
  670. install)
  671. full_install
  672. ;;
  673. install-infra)
  674. install_infra_only
  675. ;;
  676. deploy)
  677. deploy_app_only
  678. ;;
  679. update)
  680. update_only
  681. ;;
  682. start)
  683. start_all
  684. ;;
  685. stop)
  686. stop_all
  687. ;;
  688. restart)
  689. quick_restart
  690. ;;
  691. status)
  692. show_status
  693. ;;
  694. logs)
  695. show_all_logs
  696. ;;
  697. health)
  698. health_check
  699. ;;
  700. backup)
  701. backup_database
  702. ;;
  703. restore)
  704. restore_database "$2"
  705. ;;
  706. init-db)
  707. init_database_tables
  708. ;;
  709. clean-logs)
  710. clean_logs
  711. ;;
  712. help|--help|-h)
  713. show_help
  714. ;;
  715. *)
  716. log_error "未知命令: $1"
  717. show_help
  718. exit 1
  719. ;;
  720. esac
  721. }
  722. main "$@"