SpringBoot利用可視化服務(wù)管理腳本部署應(yīng)用
在SpringBoot應(yīng)用的生產(chǎn)環(huán)境部署中,傳統(tǒng)的手動(dòng)啟停服務(wù)方式不僅效率低下,還容易出錯(cuò)。
今天分享一個(gè)功能強(qiáng)大的可視化服務(wù)管理腳本,讓SpringBoot應(yīng)用的部署和運(yùn)維變得簡(jiǎn)單高效。
痛點(diǎn)分析:傳統(tǒng)部署方式的困擾
相信很多開(kāi)發(fā)者都遇到過(guò)這些問(wèn)題:
- 操作繁瑣:每次部署都要手動(dòng)執(zhí)行一堆命令
- 狀態(tài)不明:不知道服務(wù)是否真正啟動(dòng)成功
- 日志分散:查看日志需要記住各種路徑
- 回滾困難:出問(wèn)題時(shí)手忙腳亂找備份
- 多服務(wù)管理:微服務(wù)架構(gòu)下管理復(fù)雜度倍增
這些問(wèn)題不僅影響開(kāi)發(fā)效率,還增加了生產(chǎn)環(huán)境的風(fēng)險(xiǎn)。
解決方案:可視化服務(wù)管理器
為了解決這些痛點(diǎn),我開(kāi)發(fā)了一套完整的SpringBoot服務(wù)管理解決方案,核心特性包括:
可視化操作界面
告別枯燥的命令行操作,采用彩色終端界面:
#################### SpringBoot服務(wù)管理器 ####################
當(dāng)前時(shí)間: 2024-01-15 14:30:25
配置文件: /path/to/services.conf
日志目錄: /path/to/logs
================== 服務(wù)列表 ==================
序號(hào) 服務(wù)名稱 端口 狀態(tài)
-----------------------------------------------
1 user-service 8080 運(yùn)行中 (PID: 1234, Port: 8080)
2 order-service 8081 已停止
3 payment-service 8082 啟動(dòng)中 (PID: 5678)
===============================================
界面直觀清晰,服務(wù)狀態(tài)一目了然,支持實(shí)時(shí)狀態(tài)更新和彩色狀態(tài)標(biāo)識(shí)。
智能服務(wù)管理
1. 配置驅(qū)動(dòng)的服務(wù)管理
通過(guò)簡(jiǎn)單的配置文件管理所有服務(wù):
# services.conf 配置格式
# 服務(wù)名稱|JAR路徑|端口|環(huán)境|JVM參數(shù)
user-service|/opt/apps/user-service.jar|8080|prod|-Xms512m -Xmx1024m
order-service|/opt/apps/order-service.jar|8081|prod|-Xms256m -Xmx512m
這種配置方式的優(yōu)勢(shì):
- 統(tǒng)一管理:所有服務(wù)配置集中管理
- 靈活配置:支持不同JVM參數(shù)和環(huán)境配置
- 易于維護(hù):修改配置無(wú)需改動(dòng)腳本
2. 智能啟停機(jī)制
優(yōu)雅啟動(dòng)流程:
檢查JAR文件 → 驗(yàn)證端口可用性 → 構(gòu)建啟動(dòng)命令
→ 后臺(tái)啟動(dòng)服務(wù) → 健康檢查 → 狀態(tài)確認(rèn)
安全停止流程:
發(fā)送TERM信號(hào) → 等待優(yōu)雅停止 → 超時(shí)強(qiáng)制終止 → 狀態(tài)確認(rèn)
這種機(jī)制確保服務(wù)啟停的可靠性,避免了常見(jiàn)的端口占用和進(jìn)程殘留問(wèn)題。
全方位監(jiān)控功能
1. 實(shí)時(shí)狀態(tài)監(jiān)控
==================== 服務(wù)詳細(xì)信息 ====================
服務(wù)名稱: user-service
運(yùn)行狀態(tài): 運(yùn)行中 (PID: 1234, Port: 8080)
內(nèi)存使用: 345.6 MB
CPU使用: 12.5%
啟動(dòng)時(shí)間: Dec 15 14:30
日志大小: 25.3M
======================================================
2. 系統(tǒng)資源監(jiān)控
==================== 系統(tǒng)資源信息 ====================
CPU使用率: 15.2%
內(nèi)存使用: 4.2G / 8.0G
磁盤使用: 25G / 50G (52%)
Java進(jìn)程: 3個(gè)運(yùn)行中
======================================================
這些監(jiān)控信息幫助運(yùn)維人員及時(shí)發(fā)現(xiàn)性能瓶頸和資源問(wèn)題。
智能日志管理
支持多種日志查看方式:
- 實(shí)時(shí)跟蹤:
tail -f實(shí)時(shí)查看最新日志 - 歷史查看:查看指定行數(shù)的歷史日志
- 全文瀏覽:使用less命令瀏覽完整日志
- 日志輪轉(zhuǎn):自動(dòng)管理日志文件大小
日志管理界面:
請(qǐng)選擇查看方式:
1) 查看最后50行
2) 查看最后100行
3) 實(shí)時(shí)跟蹤日志
4) 查看全部日志
批量操作支持
微服務(wù)架構(gòu)下,批量操作必不可少:
==================== 批量操作菜單 ====================
1) 啟動(dòng)所有服務(wù)
2) 停止所有服務(wù)
3) 重啟所有服務(wù)
4) 查看所有服務(wù)狀態(tài)
======================================================
批量操作特別適用于: 系統(tǒng)重啟后的服務(wù)恢復(fù) 版本發(fā)布時(shí)的服務(wù)更新 故障處理時(shí)的快速響應(yīng)
自動(dòng)化部署解決方案
除了服務(wù)管理,還提供了完整的自動(dòng)化部署腳本:
一鍵部署流程
./deploy.sh deploy app-1.0.0.jar
部署流程包括:
1. 環(huán)境檢查:驗(yàn)證部署環(huán)境和依賴
2. 版本備份:自動(dòng)備份當(dāng)前運(yùn)行版本
3. 服務(wù)停止:優(yōu)雅停止當(dāng)前服務(wù)
4. 文件部署:復(fù)制新版本到部署目錄
5. 服務(wù)啟動(dòng):?jiǎn)?dòng)新版本服務(wù)
6. 健康檢查:驗(yàn)證服務(wù)是否正常運(yùn)行
7. 清理備份:保留最近5個(gè)版本備份
安全回滾機(jī)制
當(dāng)部署出現(xiàn)問(wèn)題時(shí):
./deploy.sh rollback
回滾流程:
- 自動(dòng)查找最新備份版本
- 停止問(wèn)題版本服務(wù)
- 恢復(fù)備份文件
- 重啟服務(wù)并驗(yàn)證
這種設(shè)計(jì)確保了部署過(guò)程的安全性,即使出現(xiàn)問(wèn)題也能快速恢復(fù)。
實(shí)戰(zhàn)應(yīng)用場(chǎng)景
場(chǎng)景1:微服務(wù)集群管理
某電商公司有用戶服務(wù)、訂單服務(wù)、支付服務(wù)等10個(gè)微服務(wù):
傳統(tǒng)方式:
- 需要登錄到每臺(tái)服務(wù)器
- 手動(dòng)執(zhí)行啟停命令
- 分別查看各服務(wù)日志
- 耗時(shí)30分鐘+
使用腳本后:
- 一個(gè)界面管理所有服務(wù)
- 批量操作3分鐘完成
- 狀態(tài)監(jiān)控一目了然
- 效率提升10倍
場(chǎng)景2:版本發(fā)布管理
發(fā)布前:
# 查看當(dāng)前所有服務(wù)狀態(tài) 選擇批量操作 → 查看所有服務(wù)狀態(tài)
發(fā)布過(guò)程:
# 逐個(gè)服務(wù)更新 ./deploy.sh deploy user-service-v2.0.jar ./deploy.sh deploy order-service-v2.0.jar
發(fā)布驗(yàn)證:
# 健康檢查和監(jiān)控 ./deploy.sh health
場(chǎng)景3:故障應(yīng)急處理
當(dāng)生產(chǎn)環(huán)境出現(xiàn)問(wèn)題:
1. 快速定位:通過(guò)狀態(tài)監(jiān)控快速識(shí)別問(wèn)題服務(wù)
2. 日志分析:實(shí)時(shí)查看相關(guān)服務(wù)日志
3. 緊急處理:重啟問(wèn)題服務(wù)或快速回滾
4. 影響評(píng)估:查看系統(tǒng)資源使用情況
最佳實(shí)踐建議
1. 配置管理
使用版本控制管理配置文件
不同環(huán)境使用不同的配置
定期備份配置文件
2. 監(jiān)控告警
配合監(jiān)控系統(tǒng)使用
設(shè)置關(guān)鍵指標(biāo)告警
建立故障處理流程
3. 安全考慮
限制腳本執(zhí)行權(quán)限
使用非root用戶運(yùn)行
定期清理敏感日志
4. 性能優(yōu)化
合理配置JVM參數(shù)
監(jiān)控服務(wù)資源使用
定期優(yōu)化配置參數(shù)
總結(jié)
這套基于SHELL的SpringBoot服務(wù)管理解決方案通過(guò)可視化界面、智能管理機(jī)制、資源監(jiān)控和自動(dòng)化部署,可以極大提供服務(wù)管理效率。
它不僅大大提升了運(yùn)維效率,還降低了操作風(fēng)險(xiǎn),特別適合單機(jī)多服務(wù)和小規(guī)模微服務(wù)架構(gòu)的部署場(chǎng)景。
如果你也在為SpringBoot應(yīng)用的部署和管理而煩惱,不妨試試這套解決方案。相信它會(huì)讓你的運(yùn)維工作變得更加輕松高效!
腳本附錄
springboot-service-manager
#!/bin/bash
# SpringBoot服務(wù)管理腳本 - 可視化版本
# 支持多個(gè)服務(wù)的啟動(dòng)、停止、重啟、狀態(tài)查看等功能
# 配置目錄
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_FILE="$SCRIPT_DIR/services.conf"
LOG_DIR="$SCRIPT_DIR/logs"
# 創(chuàng)建必要目錄
mkdir -p "$LOG_DIR"
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color
# 加載服務(wù)配置
load_services() {
if [[ ! -f "$CONFIG_FILE" ]]; then
echo -e "${RED}配置文件不存在: $CONFIG_FILE${NC}"
echo "請(qǐng)先創(chuàng)建配置文件,參考 services.conf.example"
exit 1
fi
# 清空服務(wù)數(shù)組
unset SERVICE_NAMES
unset SERVICE_PATHS
unset SERVICE_PORTS
unset SERVICE_PROFILES
unset SERVICE_JVM_OPTS
declare -g -a SERVICE_NAMES=()
declare -g -a SERVICE_PATHS=()
declare -g -a SERVICE_PORTS=()
declare -g -a SERVICE_PROFILES=()
declare -g -a SERVICE_JVM_OPTS=()
# 讀取配置文件
while IFS='|' read -r name path port profile jvm_opts; do
# 跳過(guò)注釋和空行
[[ $name =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
SERVICE_NAMES+=("$name")
SERVICE_PATHS+=("$path")
SERVICE_PORTS+=("$port")
SERVICE_PROFILES+=("$profile")
SERVICE_JVM_OPTS+=("$jvm_opts")
done < "$CONFIG_FILE"
}
# 獲取服務(wù)PID
get_service_pid() {
local service_name=$1
local port=$2
# 先通過(guò)端口查找
if [[ -n "$port" ]]; then
pid=$(lsof -ti:$port 2>/dev/null)
if [[ -n "$pid" ]]; then
echo $pid
return
fi
fi
# 通過(guò)jar文件名查找
pid=$(ps aux | grep java | grep -v grep | grep "$service_name" | awk '{print $2}')
echo $pid
}
# 檢查服務(wù)狀態(tài)
check_service_status() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
local port=${SERVICE_PORTS[$index]}
local pid=$(get_service_pid "$service_name" "$port")
if [[ -n "$pid" ]]; then
# 檢查端口是否可訪問(wèn)
if [[ -n "$port" ]] && nc -z localhost $port 2>/dev/null; then
echo -e "${GREEN}運(yùn)行中${NC} (PID: $pid, Port: $port)"
else
echo -e "${YELLOW}啟動(dòng)中${NC} (PID: $pid)"
fi
return 0
else
echo -e "${RED}已停止${NC}"
return 1
fi
}
# 啟動(dòng)服務(wù)
start_service() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
local jar_path=${SERVICE_PATHS[$index]}
local port=${SERVICE_PORTS[$index]}
local profile=${SERVICE_PROFILES[$index]}
local jvm_opts=${SERVICE_JVM_OPTS[$index]}
echo -e "${BLUE}正在啟動(dòng)服務(wù): $service_name${NC}"
# 檢查jar文件是否存在
if [[ ! -f "$jar_path" ]]; then
echo -e "${RED}錯(cuò)誤: JAR文件不存在 - $jar_path${NC}"
return 1
fi
# 檢查服務(wù)是否已經(jīng)運(yùn)行
local pid=$(get_service_pid "$service_name" "$port")
if [[ -n "$pid" ]]; then
echo -e "${YELLOW}服務(wù)已經(jīng)在運(yùn)行中 (PID: $pid)${NC}"
return 0
fi
# 構(gòu)建啟動(dòng)命令
local cmd="java"
[[ -n "$jvm_opts" ]] && cmd="$cmd $jvm_opts"
[[ -n "$profile" ]] && cmd="$cmd -Dspring.profiles.active=$profile"
cmd="$cmd -jar $jar_path"
# 啟動(dòng)服務(wù)
local log_file="$LOG_DIR/${service_name}.log"
nohup $cmd > "$log_file" 2>&1 &
local new_pid=$!
echo "啟動(dòng)命令: $cmd" >> "$log_file"
echo "啟動(dòng)時(shí)間: $(date)" >> "$log_file"
echo "進(jìn)程PID: $new_pid" >> "$log_file"
echo "----------------------------------------" >> "$log_file"
# 等待服務(wù)啟動(dòng)
echo -n "等待服務(wù)啟動(dòng)"
for i in {1..30}; do
sleep 1
echo -n "."
if [[ -n "$port" ]] && nc -z localhost $port 2>/dev/null; then
echo
echo -e "${GREEN}服務(wù)啟動(dòng)成功!${NC} (PID: $new_pid, Port: $port)"
return 0
fi
done
echo
echo -e "${YELLOW}服務(wù)已啟動(dòng),但端口檢查超時(shí)${NC} (PID: $new_pid)"
echo "請(qǐng)查看日志文件: $log_file"
return 0
}
# 停止服務(wù)
stop_service() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
local port=${SERVICE_PORTS[$index]}
echo -e "${BLUE}正在停止服務(wù): $service_name${NC}"
local pid=$(get_service_pid "$service_name" "$port")
if [[ -z "$pid" ]]; then
echo -e "${YELLOW}服務(wù)未運(yùn)行${NC}"
return 0
fi
# 優(yōu)雅停止
echo "發(fā)送TERM信號(hào)..."
kill -TERM $pid
# 等待服務(wù)停止
echo -n "等待服務(wù)停止"
for i in {1..15}; do
sleep 1
echo -n "."
if ! kill -0 $pid 2>/dev/null; then
echo
echo -e "${GREEN}服務(wù)已停止${NC}"
return 0
fi
done
# 強(qiáng)制停止
echo
echo "優(yōu)雅停止超時(shí),強(qiáng)制停止..."
kill -KILL $pid 2>/dev/null
sleep 2
if ! kill -0 $pid 2>/dev/null; then
echo -e "${GREEN}服務(wù)已強(qiáng)制停止${NC}"
return 0
else
echo -e "${RED}服務(wù)停止失敗${NC}"
return 1
fi
}
# 重啟服務(wù)
restart_service() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
echo -e "${BLUE}正在重啟服務(wù): $service_name${NC}"
stop_service $index
sleep 2
start_service $index
}
# 查看服務(wù)日志
view_service_log() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
local log_file="$LOG_DIR/${service_name}.log"
if [[ ! -f "$log_file" ]]; then
echo -e "${RED}日志文件不存在: $log_file${NC}"
return 1
fi
echo -e "${BLUE}查看服務(wù)日志: $service_name${NC}"
echo "日志文件: $log_file"
echo "----------------------------------------"
# 選擇查看方式
echo "請(qǐng)選擇查看方式:"
echo "1) 查看最后50行"
echo "2) 查看最后100行"
echo "3) 實(shí)時(shí)跟蹤日志"
echo "4) 查看全部日志"
echo "0) 返回主菜單"
read -p "請(qǐng)輸入選擇 [1-4]: " log_choice
case $log_choice in
1) tail -50 "$log_file" ;;
2) tail -100 "$log_file" ;;
3) echo "按 Ctrl+C 退出實(shí)時(shí)跟蹤"
sleep 2
tail -f "$log_file" ;;
4) less "$log_file" ;;
0) return ;;
*) echo -e "${RED}無(wú)效選擇${NC}" ;;
esac
}
# 顯示服務(wù)詳細(xì)信息
show_service_detail() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
local jar_path=${SERVICE_PATHS[$index]}
local port=${SERVICE_PORTS[$index]}
local profile=${SERVICE_PROFILES[$index]}
local jvm_opts=${SERVICE_JVM_OPTS[$index]}
clear
echo -e "${CYAN}==================== 服務(wù)詳細(xì)信息 ====================${NC}"
echo -e "${WHITE}服務(wù)名稱:${NC} $service_name"
echo -e "${WHITE}JAR路徑:${NC} $jar_path"
echo -e "${WHITE}端口號(hào):${NC} ${port:-未配置}"
echo -e "${WHITE}環(huán)境配置:${NC} ${profile:-默認(rèn)}"
echo -e "${WHITE}JVM參數(shù):${NC} ${jvm_opts:-默認(rèn)}"
local pid=$(get_service_pid "$service_name" "$port")
echo -e "${WHITE}運(yùn)行狀態(tài):${NC} $(check_service_status $index)"
if [[ -n "$pid" ]]; then
echo -e "${WHITE}進(jìn)程PID:${NC} $pid"
echo -e "${WHITE}內(nèi)存使用:${NC} $(ps -p $pid -o rss= | awk '{printf "%.1f MB", $1/1024}')"
echo -e "${WHITE}CPU使用:${NC} $(ps -p $pid -o %cpu= | awk '{print $1"%"}')"
echo -e "${WHITE}啟動(dòng)時(shí)間:${NC} $(ps -p $pid -o lstart= | awk '{print $1" "$2" "$3" "$4}')"
fi
local log_file="$LOG_DIR/${service_name}.log"
if [[ -f "$log_file" ]]; then
echo -e "${WHITE}日志文件:${NC} $log_file"
echo -e "${WHITE}日志大小:${NC} $(du -h "$log_file" | awk '{print $1}')"
fi
echo -e "${CYAN}======================================================${NC}"
echo
read -p "按回車鍵返回主菜單..."
}
# 顯示系統(tǒng)資源使用情況
show_system_info() {
clear
echo -e "${CYAN}==================== 系統(tǒng)資源信息 ====================${NC}"
# CPU使用率
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//')
echo -e "${WHITE}CPU使用率:${NC} ${cpu_usage}%"
# 內(nèi)存使用情況
memory_info=$(free -h | grep Mem)
total_mem=$(echo $memory_info | awk '{print $2}')
used_mem=$(echo $memory_info | awk '{print $3}')
echo -e "${WHITE}內(nèi)存使用:${NC} $used_mem / $total_mem"
# 磁盤使用情況
echo -e "${WHITE}磁盤使用:${NC}"
df -h | grep -E '^/dev/' | awk '{printf " %s: %s / %s (%s)\n", $1, $3, $2, $5}'
# Java進(jìn)程信息
echo -e "${WHITE}Java進(jìn)程:${NC}"
ps aux | grep java | grep -v grep | while read line; do
pid=$(echo $line | awk '{print $2}')
mem=$(echo $line | awk '{print $4}')
cmd=$(echo $line | awk '{for(i=11;i<=NF;i++) printf "%s ", $i; print ""}')
echo " PID: $pid, MEM: ${mem}%, CMD: ${cmd:0:50}..."
done
echo -e "${CYAN}======================================================${NC}"
echo
read -p "按回車鍵返回主菜單..."
}
# 批量操作菜單
batch_operations_menu() {
while true; do
clear
echo -e "${PURPLE}==================== 批量操作菜單 ====================${NC}"
echo "1) 啟動(dòng)所有服務(wù)"
echo "2) 停止所有服務(wù)"
echo "3) 重啟所有服務(wù)"
echo "4) 查看所有服務(wù)狀態(tài)"
echo "0) 返回主菜單"
echo -e "${PURPLE}======================================================${NC}"
read -p "請(qǐng)輸入選擇 [0-4]: " batch_choice
case $batch_choice in
1)
echo -e "${BLUE}正在啟動(dòng)所有服務(wù)...${NC}"
for ((i=0; i<${#SERVICE_NAMES[@]}; i++)); do
start_service $i
echo
done
read -p "按回車鍵繼續(xù)..."
;;
2)
echo -e "${BLUE}正在停止所有服務(wù)...${NC}"
for ((i=0; i<${#SERVICE_NAMES[@]}; i++)); do
stop_service $i
echo
done
read -p "按回車鍵繼續(xù)..."
;;
3)
echo -e "${BLUE}正在重啟所有服務(wù)...${NC}"
for ((i=0; i<${#SERVICE_NAMES[@]}; i++)); do
restart_service $i
echo
done
read -p "按回車鍵繼續(xù)..."
;;
4)
clear
echo -e "${CYAN}==================== 所有服務(wù)狀態(tài) ====================${NC}"
printf "%-20s %-10s %-15s\n" "服務(wù)名稱" "端口" "狀態(tài)"
echo "------------------------------------------------------"
for ((i=0; i<${#SERVICE_NAMES[@]}; i++)); do
status=$(check_service_status $i)
printf "%-20s %-10s %s\n" "${SERVICE_NAMES[$i]}" "${SERVICE_PORTS[$i]}" "$status"
done
echo -e "${CYAN}======================================================${NC}"
read -p "按回車鍵繼續(xù)..."
;;
0)
break
;;
*)
echo -e "${RED}無(wú)效選擇,請(qǐng)重新輸入${NC}"
sleep 1
;;
esac
done
}
# 服務(wù)管理菜單
service_management_menu() {
local index=$1
local service_name=${SERVICE_NAMES[$index]}
while true; do
clear
echo -e "${CYAN}==================== 服務(wù)管理: $service_name ====================${NC}"
echo -e "當(dāng)前狀態(tài): $(check_service_status $index)"
echo
echo "1) 啟動(dòng)服務(wù)"
echo "2) 停止服務(wù)"
echo "3) 重啟服務(wù)"
echo "4) 查看日志"
echo "5) 服務(wù)詳情"
echo "0) 返回主菜單"
echo -e "${CYAN}================================================================${NC}"
read -p "請(qǐng)輸入選擇 [0-5]: " service_choice
case $service_choice in
1)
start_service $index
read -p "按回車鍵繼續(xù)..."
;;
2)
stop_service $index
read -p "按回車鍵繼續(xù)..."
;;
3)
restart_service $index
read -p "按回車鍵繼續(xù)..."
;;
4)
view_service_log $index
;;
5)
show_service_detail $index
;;
0)
break
;;
*)
echo -e "${RED}無(wú)效選擇,請(qǐng)重新輸入${NC}"
sleep 1
;;
esac
done
}
# 主菜單
main_menu() {
while true; do
clear
echo -e "${GREEN}#################### SpringBoot服務(wù)管理器 ####################${NC}"
echo -e "${WHITE}當(dāng)前時(shí)間: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
echo -e "${WHITE}配置文件: $CONFIG_FILE${NC}"
echo -e "${WHITE}日志目錄: $LOG_DIR${NC}"
echo
# 顯示服務(wù)列表和狀態(tài)
if [[ ${#SERVICE_NAMES[@]} -eq 0 ]]; then
echo -e "${RED}未找到任何服務(wù)配置${NC}"
else
echo -e "${CYAN}================== 服務(wù)列表 ==================${NC}"
printf "%-3s %-20s %-10s %-15s\n" "序號(hào)" "服務(wù)名稱" "端口" "狀態(tài)"
echo "-----------------------------------------------"
for ((i=0; i<${#SERVICE_NAMES[@]}; i++)); do
status=$(check_service_status $i)
printf "%-3s %-20s %-10s %s\n" "$((i+1))" "${SERVICE_NAMES[$i]}" "${SERVICE_PORTS[$i]}" "$status"
done
echo -e "${CYAN}===============================================${NC}"
fi
echo
echo "操作選項(xiàng):"
echo "1-${#SERVICE_NAMES[@]}) 管理對(duì)應(yīng)服務(wù)"
echo "b) 批量操作"
echo "s) 系統(tǒng)信息"
echo "r) 重新加載配置"
echo "q) 退出程序"
echo -e "${GREEN}#########################################################${NC}"
read -p "請(qǐng)輸入選擇: " main_choice
case $main_choice in
[1-9]|[1-9][0-9])
index=$((main_choice-1))
if [[ $index -ge 0 && $index -lt ${#SERVICE_NAMES[@]} ]]; then
service_management_menu $index
else
echo -e "${RED}無(wú)效的服務(wù)序號(hào)${NC}"
sleep 1
fi
;;
b|B)
batch_operations_menu
;;
s|S)
show_system_info
;;
r|R)
echo -e "${BLUE}重新加載配置文件...${NC}"
load_services
echo -e "${GREEN}配置加載完成${NC}"
sleep 1
;;
q|Q)
echo -e "${GREEN}感謝使用SpringBoot服務(wù)管理器!${NC}"
exit 0
;;
*)
echo -e "${RED}無(wú)效選擇,請(qǐng)重新輸入${NC}"
sleep 1
;;
esac
done
}
# 檢查依賴命令
check_dependencies() {
local missing_deps=()
command -v java >/dev/null 2>&1 || missing_deps+=("java")
command -v lsof >/dev/null 2>&1 || missing_deps+=("lsof")
command -v nc >/dev/null 2>&1 || missing_deps+=("netcat")
if [[ ${#missing_deps[@]} -ne 0 ]]; then
echo -e "${RED}錯(cuò)誤: 缺少必要的命令工具${NC}"
echo "請(qǐng)安裝以下工具: ${missing_deps[*]}"
echo
echo "Ubuntu/Debian: sudo apt-get install openjdk-8-jdk lsof netcat"
echo "CentOS/RHEL: sudo yum install java-1.8.0-openjdk lsof nc"
exit 1
fi
}
# 主程序入口
main() {
# 檢查依賴
check_dependencies
# 加載服務(wù)配置
load_services
# 顯示歡迎信息
clear
echo -e "${GREEN}"
echo "########################################################"
echo "# #"
echo "# SpringBoot服務(wù)管理器 v1.0 #"
echo "# #"
echo "# 支持多服務(wù)管理、日志查看、狀態(tài)監(jiān)控 #"
echo "# #"
echo "########################################################"
echo -e "${NC}"
sleep 2
# 啟動(dòng)主菜單
main_menu
}
# 腳本執(zhí)行入口
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi
services.conf
# SpringBoot服務(wù)配置文件 # 格式: 服務(wù)名稱|JAR文件路徑|端口號(hào)|Profile環(huán)境|JVM參數(shù) # 示例配置,請(qǐng)根據(jù)實(shí)際情況修改 # 測(cè)試服務(wù) serveless-core|/opt/apps/serverless-core-1.0.0.jar|8080|prod|-Xms512m -Xmx1024m -XX:+UseG1GC # 注意事項(xiàng): # 1. 每行一個(gè)服務(wù)配置 # 2. 使用 | 分隔各個(gè)字段 # 3. JAR文件路徑必須是絕對(duì)路徑 # 4. 端口號(hào)用于健康檢查 # 5. Profile環(huán)境可以為空,默認(rèn)使用default # 6. JVM參數(shù)可以為空,使用默認(rèn)配置 # 7. 以#開(kāi)頭的行為注釋行
deploy.sh
# SpringBoot服務(wù)部署腳本
# 自動(dòng)化部署和管理SpringBoot應(yīng)用
#!/bin/bash
# 部署配置
APP_NAME="serverless-core"
APP_VERSION="1.0.0"
JAR_NAME="${APP_NAME}-${APP_VERSION}.jar"
DEPLOY_DIR="/opt/apps"
BACKUP_DIR="/opt/backups"
SERVICE_PORT="8080"
PROFILE="prod"
# JVM參數(shù)配置
JVM_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
JVM_OPTS="$JVM_OPTS -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
JVM_OPTS="$JVM_OPTS -Xloggc:$DEPLOY_DIR/logs/gc.log -XX:+UseGCLogFileRotation"
JVM_OPTS="$JVM_OPTS -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M"
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 創(chuàng)建必要目錄
setup_directories() {
echo -e "${BLUE}創(chuàng)建部署目錄...${NC}"
mkdir -p "$DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR/logs"
mkdir -p "$BACKUP_DIR"
echo -e "${GREEN}目錄創(chuàng)建完成${NC}"
}
# 備份當(dāng)前版本
backup_current_version() {
if [[ -f "$DEPLOY_DIR/$JAR_NAME" ]]; then
echo -e "${BLUE}備份當(dāng)前版本...${NC}"
local backup_file="$BACKUP_DIR/${JAR_NAME}.$(date +%Y%m%d_%H%M%S).bak"
cp "$DEPLOY_DIR/$JAR_NAME" "$backup_file"
echo -e "${GREEN}備份完成: $backup_file${NC}"
fi
}
# 部署新版本
deploy_new_version() {
local jar_file=$1
if [[ ! -f "$jar_file" ]]; then
echo -e "${RED}錯(cuò)誤: JAR文件不存在 - $jar_file${NC}"
return 1
fi
echo -e "${BLUE}部署新版本...${NC}"
# 停止當(dāng)前服務(wù)
./springboot-service-manager.sh stop "$APP_NAME" 2>/dev/null || true
# 等待服務(wù)完全停止
sleep 3
# 復(fù)制新版本
cp "$jar_file" "$DEPLOY_DIR/$JAR_NAME"
chmod +x "$DEPLOY_DIR/$JAR_NAME"
echo -e "${GREEN}部署完成${NC}"
}
# 健康檢查
health_check() {
local max_attempts=30
local attempt=0
echo -e "${BLUE}進(jìn)行健康檢查...${NC}"
while [[ $attempt -lt $max_attempts ]]; do
if curl -s -f "http://localhost:$SERVICE_PORT/actuator/health" >/dev/null 2>&1; then
echo -e "${GREEN}健康檢查通過(guò)!${NC}"
return 0
fi
attempt=$((attempt + 1))
echo -n "."
sleep 2
done
echo
echo -e "${RED}健康檢查失?。?{NC}"
return 1
}
# 回滾到上一版本
rollback() {
echo -e "${YELLOW}開(kāi)始回滾...${NC}"
# 查找最新的備份文件
local latest_backup=$(ls -t "$BACKUP_DIR"/${JAR_NAME}.*.bak 2>/dev/null | head -1)
if [[ -z "$latest_backup" ]]; then
echo -e "${RED}沒(méi)有找到備份文件${NC}"
return 1
fi
echo -e "${BLUE}回滾到: $latest_backup${NC}"
# 停止當(dāng)前服務(wù)
./springboot-service-manager.sh stop "$APP_NAME" 2>/dev/null || true
sleep 3
# 恢復(fù)備份
cp "$latest_backup" "$DEPLOY_DIR/$JAR_NAME"
# 啟動(dòng)服務(wù)
./springboot-service-manager.sh start "$APP_NAME"
# 健康檢查
if health_check; then
echo -e "${GREEN}回滾成功!${NC}"
else
echo -e "${RED}回滾后健康檢查失敗${NC}"
return 1
fi
}
# 完整部署流程
full_deploy() {
local jar_file=$1
echo -e "${GREEN}開(kāi)始部署 $APP_NAME${NC}"
echo "JAR文件: $jar_file"
echo "部署目錄: $DEPLOY_DIR"
echo "服務(wù)端口: $SERVICE_PORT"
echo "環(huán)境配置: $PROFILE"
echo "----------------------------------------"
# 創(chuàng)建目錄
setup_directories
# 備份當(dāng)前版本
backup_current_version
# 部署新版本
if ! deploy_new_version "$jar_file"; then
echo -e "${RED}部署失敗${NC}"
return 1
fi
# 啟動(dòng)服務(wù)
echo -e "${BLUE}啟動(dòng)服務(wù)...${NC}"
./springboot-service-manager.sh start "$APP_NAME"
# 健康檢查
if health_check; then
echo -e "${GREEN}部署成功!${NC}"
# 清理舊備份(保留最近5個(gè))
echo -e "${BLUE}清理舊備份...${NC}"
ls -t "$BACKUP_DIR"/${JAR_NAME}.*.bak 2>/dev/null | tail -n +6 | xargs rm -f
echo -e "${GREEN}清理完成${NC}"
else
echo -e "${RED}部署失敗,開(kāi)始回滾...${NC}"
rollback
return 1
fi
}
# 顯示使用幫助
show_help() {
echo "SpringBoot應(yīng)用部署腳本"
echo
echo "用法:"
echo " $0 deploy <jar-file> - 部署新版本"
echo " $0 rollback - 回滾到上一版本"
echo " $0 health - 健康檢查"
echo " $0 setup - 初始化部署環(huán)境"
echo
echo "示例:"
echo " $0 deploy app-1.0.0.jar"
echo " $0 rollback"
}
# 主程序
main() {
case "${1:-}" in
deploy)
if [[ -z "${2:-}" ]]; then
echo -e "${RED}錯(cuò)誤: 請(qǐng)指定JAR文件${NC}"
show_help
exit 1
fi
full_deploy "$2"
;;
rollback)
rollback
;;
health)
health_check
;;
setup)
setup_directories
;;
*)
show_help
;;
esac
}
main "$@"
以上就是SpringBoot利用可視化服務(wù)管理腳本部署應(yīng)用的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot部署應(yīng)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring?boot項(xiàng)目使用@Async注解的坑
這篇文章主要為大家介紹了spring?boot項(xiàng)目中使用@Async注解遇到的坑示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Springboot3整合Mybatis-plus3.5.3報(bào)錯(cuò)問(wèn)題解決
在日常學(xué)習(xí)springboot3相關(guān)的代碼時(shí),在使用 SpringBoot3 整合 MyBatisplus 時(shí)出現(xiàn)了一些問(wèn)題,花了不少時(shí)間處理,這篇文章主要介紹了Springboot3整合Mybatis-plus3.5.3報(bào)錯(cuò)問(wèn)題解決,需要的朋友可以參考下2023-11-11
SpringBoot中@Value注入失敗問(wèn)題解決步驟
本文給大家介紹SpringBoot中@Value注入失敗問(wèn)題解決步驟,本文分步驟結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-09-09
Spring中的Eureka服務(wù)過(guò)期詳細(xì)解析
這篇文章主要介紹了Spring中的Eureka服務(wù)過(guò)期詳細(xì)解析,如果有一些服務(wù)過(guò)期了,或者宕機(jī)了,就不會(huì)調(diào)用shutdown()方法,也不會(huì)去發(fā)送請(qǐng)求下線服務(wù)實(shí)例,需要的朋友可以參考下2023-11-11
Spring零基礎(chǔ)到進(jìn)階之鴻蒙開(kāi)篇
Spring框架是一個(gè)開(kāi)放源代碼的J2EE應(yīng)用程序框架,由Rod Johnson發(fā)起,是針對(duì)bean的生命周期進(jìn)行管理的輕量級(jí)容器(lightweight container)。 Spring解決了開(kāi)發(fā)者在J2EE開(kāi)發(fā)中遇到的許多常見(jiàn)的問(wèn)題,提供了功能強(qiáng)大IOC、AOP及Web MVC等功能2022-07-07

