sync-and-deploy.sh 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #!/bin/bash
  2. # ============================================
  3. # 灵越智报 - 同步代码并部署脚本
  4. # 从本地同步代码到服务器并重启应用
  5. # ============================================
  6. set -e
  7. # 颜色定义
  8. RED='\033[0;31m'
  9. GREEN='\033[0;32m'
  10. YELLOW='\033[1;33m'
  11. BLUE='\033[0;34m'
  12. NC='\033[0m'
  13. # ========== 配置区域 ==========
  14. # 服务器配置(根据实际情况修改)
  15. SERVER_USER="root"
  16. SERVER_HOST="${SERVER_HOST:-lanaipc}" # 可通过环境变量覆盖,或直接改为 IP
  17. SERVER_PORT="${SERVER_PORT:-22}"
  18. # 路径配置
  19. LOCAL_PROJECT_DIR="/home/hws/workspace/GitLab/ay/lingyue-zhibao"
  20. REMOTE_PROJECT_DIR="/mnt/win_home/lingyue-zhibao"
  21. REMOTE_MAVEN_REPO="/mnt/win_home/.m2/repository"
  22. # 应用配置
  23. APP_PORT=5232
  24. JAR_NAME="lingyue-starter.jar"
  25. # ==============================
  26. log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
  27. log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
  28. log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
  29. log_title() { echo -e "\n${BLUE}========== $1 ==========${NC}\n"; }
  30. # SSH 命令封装
  31. ssh_cmd() {
  32. ssh -p ${SERVER_PORT} ${SERVER_USER}@${SERVER_HOST} "$@"
  33. }
  34. # 检查服务器连接
  35. check_connection() {
  36. log_title "检查服务器连接"
  37. if ssh_cmd "echo 'OK'" > /dev/null 2>&1; then
  38. log_info "服务器连接成功: ${SERVER_USER}@${SERVER_HOST}"
  39. else
  40. log_error "无法连接服务器: ${SERVER_USER}@${SERVER_HOST}"
  41. log_warn "请检查:"
  42. log_warn " 1. 服务器地址是否正确"
  43. log_warn " 2. SSH 密钥是否配置"
  44. log_warn " 3. 可以通过 SERVER_HOST=<IP> ./sync-and-deploy.sh 指定服务器"
  45. exit 1
  46. fi
  47. }
  48. # 同步代码
  49. sync_code() {
  50. log_title "同步代码到服务器"
  51. cd ${LOCAL_PROJECT_DIR}
  52. log_info "正在同步..."
  53. rsync -avz --delete \
  54. --exclude '.git' \
  55. --exclude 'target' \
  56. --exclude 'node_modules' \
  57. --exclude '.idea' \
  58. --exclude '*.iml' \
  59. --exclude '.DS_Store' \
  60. --exclude 'frontend_flutter/build' \
  61. --exclude 'frontend_flutter/.dart_tool' \
  62. -e "ssh -p ${SERVER_PORT}" \
  63. ./ ${SERVER_USER}@${SERVER_HOST}:${REMOTE_PROJECT_DIR}/
  64. log_info "代码同步完成"
  65. }
  66. # 停止应用
  67. stop_app() {
  68. log_title "停止应用"
  69. ssh_cmd "pkill -f '${JAR_NAME}' 2>/dev/null || true"
  70. sleep 2
  71. # 确保进程已停止
  72. if ssh_cmd "pgrep -f '${JAR_NAME}'" > /dev/null 2>&1; then
  73. log_warn "进程仍在运行,强制终止..."
  74. ssh_cmd "pkill -9 -f '${JAR_NAME}' 2>/dev/null || true"
  75. sleep 2
  76. fi
  77. log_info "应用已停止"
  78. }
  79. # 编译项目
  80. build_project() {
  81. log_title "编译项目"
  82. ssh_cmd "cd ${REMOTE_PROJECT_DIR}/backend && \
  83. rm -rf lingyue-starter/target && \
  84. mvn clean package -DskipTests -q -Dmaven.repo.local=${REMOTE_MAVEN_REPO}"
  85. log_info "编译完成"
  86. }
  87. # 启动应用
  88. start_app() {
  89. log_title "启动应用"
  90. ssh_cmd "cd ${REMOTE_PROJECT_DIR}/backend && \
  91. nohup java -Xms1g -Xmx2g -XX:+UseG1GC \
  92. -jar lingyue-starter/target/${JAR_NAME} \
  93. > /var/log/lingyue.log 2>&1 &"
  94. log_info "应用启动中..."
  95. sleep 5
  96. # 检查应用是否启动
  97. if ssh_cmd "pgrep -f '${JAR_NAME}'" > /dev/null 2>&1; then
  98. log_info "应用启动成功"
  99. else
  100. log_error "应用启动失败,查看日志:"
  101. ssh_cmd "tail -50 /var/log/lingyue.log"
  102. exit 1
  103. fi
  104. }
  105. # 健康检查
  106. health_check() {
  107. log_title "健康检查"
  108. local max_attempts=10
  109. local attempt=1
  110. while [ $attempt -le $max_attempts ]; do
  111. log_info "尝试 $attempt/$max_attempts..."
  112. local response=$(ssh_cmd "curl -s -o /dev/null -w '%{http_code}' http://localhost:${APP_PORT}/actuator/health 2>/dev/null" || echo "000")
  113. if [ "$response" = "200" ]; then
  114. log_info "健康检查通过 ✓"
  115. ssh_cmd "curl -s http://localhost:${APP_PORT}/actuator/health"
  116. echo ""
  117. return 0
  118. fi
  119. sleep 3
  120. attempt=$((attempt + 1))
  121. done
  122. log_warn "健康检查超时,但应用可能仍在启动中"
  123. log_info "可以手动检查: curl http://${SERVER_HOST}:${APP_PORT}/actuator/health"
  124. }
  125. # 查看日志
  126. show_logs() {
  127. log_title "应用日志"
  128. ssh_cmd "tail -100 /var/log/lingyue.log"
  129. }
  130. # 查看实时日志
  131. tail_logs() {
  132. log_info "实时日志 (Ctrl+C 退出)"
  133. ssh_cmd "tail -f /var/log/lingyue.log"
  134. }
  135. # 查看状态
  136. show_status() {
  137. log_title "应用状态"
  138. if ssh_cmd "pgrep -f '${JAR_NAME}'" > /dev/null 2>&1; then
  139. local pid=$(ssh_cmd "pgrep -f '${JAR_NAME}'")
  140. log_info "应用运行中 (PID: $pid)"
  141. log_info "访问地址: http://${SERVER_HOST}:${APP_PORT}"
  142. else
  143. log_warn "应用未运行"
  144. fi
  145. }
  146. # 仅同步代码(不编译不重启)
  147. sync_only() {
  148. check_connection
  149. sync_code
  150. log_info "代码同步完成,未编译和重启"
  151. }
  152. # 完整部署
  153. full_deploy() {
  154. check_connection
  155. sync_code
  156. stop_app
  157. build_project
  158. start_app
  159. health_check
  160. log_title "部署完成"
  161. echo -e "${GREEN}访问地址: http://${SERVER_HOST}:${APP_PORT}${NC}"
  162. echo ""
  163. echo "测试命令:"
  164. echo " curl http://${SERVER_HOST}:${APP_PORT}/actuator/health"
  165. echo " curl -X POST http://${SERVER_HOST}:${APP_PORT}/auth/register -H 'Content-Type: application/json' -d '{\"username\":\"test\",\"email\":\"test@test.com\",\"password\":\"123456\"}'"
  166. }
  167. # 快速重启(不同步代码)
  168. quick_restart() {
  169. check_connection
  170. stop_app
  171. start_app
  172. health_check
  173. }
  174. # 显示帮助
  175. show_help() {
  176. cat <<EOF
  177. 灵越智报 - 同步代码并部署脚本
  178. 用法: ./sync-and-deploy.sh [命令]
  179. 命令:
  180. deploy 完整部署(同步 + 编译 + 重启)
  181. sync 仅同步代码(不编译不重启)
  182. restart 快速重启(不同步代码)
  183. stop 停止应用
  184. status 查看应用状态
  185. logs 查看最近日志
  186. tail 实时查看日志
  187. build 远程编译(不重启)
  188. help 显示此帮助
  189. 环境变量:
  190. SERVER_HOST 服务器地址(默认: lanaipc)
  191. SERVER_PORT SSH 端口(默认: 22)
  192. 示例:
  193. ./sync-and-deploy.sh deploy # 完整部署
  194. ./sync-and-deploy.sh sync # 仅同步
  195. ./sync-and-deploy.sh restart # 快速重启
  196. SERVER_HOST=192.168.1.100 ./sync-and-deploy.sh deploy # 指定服务器
  197. EOF
  198. }
  199. # 主函数
  200. main() {
  201. case "${1:-deploy}" in
  202. deploy)
  203. full_deploy
  204. ;;
  205. sync)
  206. sync_only
  207. ;;
  208. restart)
  209. quick_restart
  210. ;;
  211. stop)
  212. check_connection
  213. stop_app
  214. ;;
  215. status)
  216. check_connection
  217. show_status
  218. ;;
  219. logs)
  220. check_connection
  221. show_logs
  222. ;;
  223. tail)
  224. check_connection
  225. tail_logs
  226. ;;
  227. build)
  228. check_connection
  229. build_project
  230. ;;
  231. help|--help|-h)
  232. show_help
  233. ;;
  234. *)
  235. log_error "未知命令: $1"
  236. show_help
  237. exit 1
  238. ;;
  239. esac
  240. }
  241. main "$@"