服务器常用脚本汇总
2025/7/22
服务器常用脚本汇总
项目启停脚本
Tomcat运行项目
CentOS
#!/bin/bash
# ========================================
# SpringMVC 项目 Tomcat 启停管理脚本
# 支持默认命令为 restart
# 使用方式: ./tomcat-manager.sh [start|stop|restart|status] (不传参 = restart)
# ========================================
# 配置项
TOMCAT_HOME="/opt/tomcat"
PORT="8080"
SHUTDOWN_WAIT=5
LOG_FILE="$TOMCAT_HOME/logs/catalina.out"
# 函数:获取 Tomcat 进程 PID
get_pid() {
lsof -i :$PORT | grep LISTEN | awk '{print $2}' | head -n1
}
# 函数:检查进程是否存在
is_running() {
local pid=$(get_pid)
if [ -n "$pid" ]; then
if ps -p $pid > /dev/null 2>&1; then
echo $pid
else
echo ""
fi
else
echo ""
fi
}
# 启动 Tomcat
start() {
local pid=$(is_running)
if [ -n "$pid" ]; then
echo "⚠️ Tomcat 已在运行,PID: $pid,端口: $PORT"
echo "👉 请先停止服务,或使用 restart 命令。"
exit 1
fi
echo "🚀 正在启动 Tomcat..."
cd $TOMCAT_HOME/bin
./startup.sh
# 等待日志输出
sleep 3
tail -n 50 $LOG_FILE | grep -q "Server startup"
if [ $? -eq 0 ]; then
echo "✅ Tomcat 启动成功!"
else
echo "🟡 启动完成,但未检测到 'Server startup',请检查日志:$LOG_FILE"
fi
}
# 停止 Tomcat(暴力 kill)
stop() {
local pid=$(is_running)
if [ -z "$pid" ]; then
echo "🟢 Tomcat 未运行(端口 $PORT)"
return 0
fi
echo "🛑 检测到 Tomcat 进程 PID: $pid,正在尝试强制关闭..."
kill -9 $pid
# 等待进程结束
sleep $SHUTDOWN_WAIT
# 再次检查是否存活
if ps -p $pid > /dev/null 2>&1; then
echo "❌ kill -9 失败,进程仍存在 PID: $pid"
else
echo "✅ 进程 $pid 已被成功终止"
fi
}
# 重启
restart() {
echo "🔄 开始重启服务..."
stop
sleep 3
start
}
# 主逻辑:如果无参数,默认为 restart
ACTION="${1:-restart}"
case "$ACTION" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
pid=$(is_running)
if [ -n "$pid" ]; then
echo "🟢 Tomcat 正在运行,PID: $pid,端口: $PORT"
else
echo "🔴 Tomcat 未运行"
fi
;;
*)
echo "📌 用法: $0 {start|stop|restart|status}"
echo "💡 提示:不传参数时将自动执行 restart"
exit 1
;;
esac
exit 0SpringBoot项目
项目升级脚本
SPringBoot Jar包项目
CentOS
#!/bin/bash
set -e
BASE_DIR=/home/jdmeet
# 项目部署文件目录
PROJECT_PATH_PREFIX=${BASE_DIR}/projects
# 更新文件目录
UPDATE_PATH_PREFIX=${BASE_DIR}/updates
# 日志文件目录
ADMIN_LOGS_FILE_PATH=${BASE_DIR}/logs
# 备份文件目录
BAK_PATH_PREFIX=${BASE_DIR}/bak
NEWLY_SUFFIX="_new"
DATE=$(date +%Y%m%d%H%M)
# 基础路径
ADMIN_BASE_PATH=${PROJECT_PATH_PREFIX}/jdmeet-admin
# 服务名称。同时约定部署服务的 jar 包名字也为它。
ADMIN_SERVER_NAME=jdmeet-admin
# 环境
ADMIN_PROFILES_ACTIVE=prod
# heapError 存放路径
HEAP_ERROR_PATH=$ADMIN_BASE_PATH/heapError
# JVM 参数
JAVA_OPS="-Xms2048m -Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$HEAP_ERROR_PATH"
# 定义更新函数
update_jdmeet_admin() {
echo "开始更新 jdmeet-admin 项目..."
do_backup jdmeet-admin
echo ""
echo ""
}
update_jdmeet_ui() {
echo "开始更新 jdmeet-ui 项目..."
do_backup jdmeet-ui
echo ""
echo ""
}
update_jdmeet_uniapp() {
echo "开始更新 jdmeet-uniapp 项目..."
do_backup jdmeet-uniapp
echo ""
echo ""
}
update_jdmeet_goview() {
echo "开始更新 jdmeet-goview 项目..."
do_backup jdmeet-goview
echo ""
echo ""
}
#版本发布及备份
do_backup(){
# 当前时间
local CURRENT_TIME=$(date "+%Y%m%d_%H%M%S")
# 需要备份的项目文件夹名称
local CURRENT_SYSTEM_FLAG=$1
# 项目所在文件夹名称
local PROJECT_DEPLOY_PATH=${PROJECT_PATH_PREFIX}/${CURRENT_SYSTEM_FLAG}
# 更新文件所在目录
local UPDATE_FILE_PATH=${UPDATE_PATH_PREFIX}/${CURRENT_SYSTEM_FLAG}${NEWLY_SUFFIX}
# 备份文件夹
local BAK_PATH=${BAK_PATH_PREFIX}/${CURRENT_SYSTEM_FLAG}/${CURRENT_SYSTEM_FLAG}_${CURRENT_TIME}
echo ""
echo ""
echo "当前时间: $CURRENT_TIME"
echo "更新文件夹路径: ${UPDATE_FILE_PATH}"
echo "部署文件夹路径: ${PROJECT_DEPLOY_PATH}"
echo "备份文件夹路径: ${BAK_PATH}"
echo ""
echo "开始更新 ${CURRENT_SYSTEM_FLAG} 项目..."
echo ""
echo ""
if test -d "${UPDATE_FILE_PATH}"; then
echo "正在备份${CURRENT_SYSTEM_FLAG}文件夹..."
echo "备份文件夹路径: ${BAK_PATH}"
if mv ${PROJECT_DEPLOY_PATH}/ ${BAK_PATH}/; then
echo "备份成功,备份文件:${BAK_PATH}"
# 将更新文件夹重命名
if mv ${UPDATE_FILE_PATH} ${PROJECT_DEPLOY_PATH}; then
echo "新版本文件更新成功";
else
echo "Error: 新版本更新失败!"
fi
else
echo "Error: 文件夹备份失败!"
fi
else
echo "Error: 更新文件夹${UPDATE_FILE_PATH}不存在,请确认..."
fi
echo ""
echo ""
}
# 停止:优雅关闭之前已经启动的服务
function stop() {
echo "[stop] 开始停止 $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME"
PID=$(ps -ef | grep $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME | grep -v "grep" | awk '{print $2}')
# 如果 Java 服务启动中,则进行关闭
if [ -n "$PID" ]; then
# 正常关闭
echo "[stop] $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME 运行中,开始 kill [$PID]"
kill -15 $PID
# 等待最大 120 秒,直到关闭完成。
for ((i = 0; i < 120; i++))
do
sleep 1
PID=$(ps -ef | grep $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME | grep -v "grep" | awk '{print $2}')
if [ -n "$PID" ]; then
echo -e ".\c"
else
echo '[stop] 停止 $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME 成功'
break
fi
done
# 如果正常关闭失败,那么进行强制 kill -9 进行关闭
if [ -n "$PID" ]; then
echo "[stop] $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME 失败,强制 kill -9 $PID"
kill -9 $PID
fi
# 如果 Java 服务未启动,则无需关闭
else
echo "[stop] $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME 未启动,无需停止"
fi
}
# 启动:启动后端项目
function start() {
# 开启启动前,打印启动参数
echo "[start] 开始启动 $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME"
echo "[start] JAVA_OPS: $JAVA_OPS"
echo "[start] JAVA_AGENT: $JAVA_AGENT"
echo "[start] PROFILES: $ADMIN_PROFILES_ACTIVE"
# 开始启动
nohup java -server $JAVA_OPS $JAVA_AGENT -jar $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME.jar --spring.profiles.active=$ADMIN_PROFILES_ACTIVE > $ADMIN_LOGS_FILE_PATH/nohup.out 2>&1 &
echo "[start] 启动 $ADMIN_BASE_PATH/$ADMIN_SERVER_NAME 完成"
}
# 部署
function deploy() {
cd $ADMIN_BASE_PATH
# 第一步:停止 Java 服务
stop
# 第二步:启动 Java 服务
start
}
# 显示菜单并处理用户输入
while true; do
clear
echo "======================================"
echo "1. 启动jdmeet-admin项目"
echo "2. 更新jdmeet-admin项目"
echo "3. 更新jdmeet-ui项目"
echo "4. 更新jdmeet-uniapp项目"
echo "5. 更新jdmeet-goview项目"
echo "q. 退出"
echo "======================================"
read -p "请输入对应的选项: " choice
case $choice in
1)
deploy
;;
2)
do_backup jdmeet-admin
;;
3)
do_backup jdmeet-ui
;;
4)
do_backup jdmeet-uniapp
;;
5)
do_backup jdmeet-goview
;;
q|Q)
echo "退出脚本,返回命令行界面。"
exit 0
;;
*)
echo "无效输入,请输入 1-3 的数字或 'q' 退出!"
sleep 2
continue
;;
esac
read -p "按任意键继续..." any_key
doneWindows
@echo off
:: 设置代码页为 UTF-8(防止中文乱码)
:: chcp 65001 >nul
:: 检查是否以管理员身份运行
net session >nul 2>&1
if %errorLevel% NEQ 0 (
echo 请求管理员权限中...
timeout /t 1 >nul
powershell -Command "Start-Process '%cd%\%~nx0'" -Verb RunAs
exit /b
)
:: 设置日志文件路径
set "log_file=D:\zxt\data\logs\update\update_log.log"
set "BACKUP_PATH=D:\zxt\data\bak"
:: 获取当前日期时间
call :get_datetime
echo [%full_time%] 脚本已启动 >> "%log_file%"
call :main_menu
exit /b
:: ========== 获取标准化日期时间函数 ==========
:get_datetime
for /f "tokens=2 delims==" %%I in ('"wmic os get localdatetime /value"') do set datetime=%%I
set "ymd=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%"
set "hms=%datetime:~8,2%:%datetime:~10,2%:%datetime:~12,2%"
set "full_time=%ymd% %hms%"
exit /b
:: ============ 主菜单 ============
:main_menu
cls
echo.
echo ========================
echo 系统升级管理工具
echo ========================
echo.
echo 【0】 自动检测并升级
echo 【1】 后台服务升级
echo 【2】 前端服务升级
echo 【3】 数据库脚本升级
echo 【4】 退出
echo.
:: 输入处理(支持 0)
choice /c 12340 /n /m "请选择操作编号 (0-4): "
set choice=%errorlevel%
if %choice% == 1 goto backend_update
if %choice% == 2 goto frontend_update
if %choice% == 3 goto database_update
if %choice% == 4 goto exit_program
if %choice% == 5 goto auto_update
echo [错误] 输入无效,请重新输入。
timeout /t 2 >nul
goto main_menu
:: ========== 自动升级 ==========
:auto_update
cls
echo 自动检测升级开始
echo.
set "do_backend=0"
set "do_frontend=0"
set "do_database=0"
if exist "D:\zxt\updates\jar" set do_backend=1
if exist "D:\zxt\updates\html" set do_frontend=1
if exist "D:\zxt\updates\sql" set do_database=1
if %do_backend% == 0 if %do_frontend% == 0 if %do_database% == 0 (
echo 未检测到任何更新包,请放入更新文件夹后再运行。
echo.
echo.
echo 按任意键返回主菜单...
pause >nul
goto main_menu
)
if %do_backend% == 1 (
call :backend_update_auto
)
if %do_frontend% == 1 (
echo.
echo.
call :frontend_update_auto
)
if %do_database% == 1 (
echo.
echo.
call :database_update_auto
)
echo.
echo.
echo 自动升级结束
echo.
echo.
echo 按任意键返回主菜单...
pause >nul
goto main_menu
:: ========== 后台服务升级(带分隔符)==========
:backend_update_auto
echo --------------------------- 后端服务 升级开始 ---------------------------
call :get_datetime
set "jar_dir=D:\zxt\jar"
set "bak_jar_dir=%BACKUP_PATH%\jar"
set "update_jar=D:\zxt\updates\jar\inventory-admin.jar"
set "current_jar=%jar_dir%\inventory-admin.jar"
set "service_name=inventory_admin"
echo [%full_time%] 开始执行后台服务升级... >> "%log_file%"
if not exist "%update_jar%" (
echo [ERROR] 升级文件不存在:%update_jar%
echo [ERROR] 升级文件不存在 >> "%log_file%"
echo.
goto end_backend
)
echo 正在停止服务 %service_name% ...
nssm stop %service_name%
if errorlevel 1 (
echo [ERROR] 无法停止服务 %service_name%
echo [ERROR] 无法停止服务 >> "%log_file%"
)
timeout /t 3 >nul
call :get_timestamp
set "backup_dir=%bak_jar_dir%\%timestamp%"
echo 正在备份当前jar文件到 %backup_dir% ...
md "%backup_dir%" 2>nul
copy "%current_jar%" "%backup_dir%\inventory_admin.jar"
if errorlevel 1 (
echo [ERROR] 备份失败!
echo [ERROR] JAR文件备份失败 >> "%log_file%"
)
echo 正在替换为新版本jar文件 ...
del /q "%current_jar%"
move "%update_jar%" "%current_jar%"
if errorlevel 1 (
echo [ERROR] 文件移动失败,请检查权限或文件是否被占用。
echo [ERROR] 文件移动失败 >> "%log_file%"
)
echo 正在启动服务 %service_name% ...
nssm start %service_name%
if errorlevel 1 (
echo [ERROR] 无法启动服务 %service_name%
echo [ERROR] 服务启动失败 >> "%log_file%"
)
:: 删除升级文件夹
if exist "D:\zxt\updates\jar" rd /s /q "D:\zxt\updates\jar" >nul 2>&1
echo 后台服务升级完成。
echo [%full_time%] 后台服务升级成功完成 >> "%log_file%"
:end_backend
echo --------------------------- 后端服务 升级结束 ---------------------------
exit /b
:: ========== 前端服务升级(带分隔符)==========
:frontend_update_auto
echo --------------------------- 前端服务 升级开始 ---------------------------
call :get_datetime
set "html_dir=D:\zxt\html"
set "bak_html_dir=%BACKUP_PATH%\html"
set "update_html=D:\zxt\updates\html"
echo [%full_time%] 开始执行前端服务升级... >> "%log_file%"
if not exist "%update_html%" (
echo [ERROR] 前端更新文件夹不存在:%update_html%
echo [ERROR] 前端更新目录不存在 >> "%log_file%"
echo.
goto end_frontend
)
call :get_timestamp
set "backup_dir=%bak_html_dir%\%timestamp%"
echo 正在备份前端文件到 %backup_dir% ...
xcopy "%html_dir%" "%backup_dir%" /E /H /C /I >nul
if errorlevel 1 (
echo [ERROR] 前端文件备份失败!
echo [ERROR] 前端文件备份失败 >> "%log_file%"
)
echo 正在清理并更新前端文件 ...
:: 清理只读属性 + 删除目录
if exist "%html_dir%" attrib -r -h -s "%html_dir%\*" /s /d >nul 2>&1
rd /s /q "%html_dir%" >nul 2>&1
:: 创建新目录
md "%html_dir%" >nul 2>&1
xcopy "%update_html%" "%html_dir%" /E /H /C /I >nul
if errorlevel 1 (
echo [ERROR] 前端文件更新失败!
echo [ERROR] 前端文件更新失败 >> "%log_file%"
)
:: 删除更新文件夹
if exist "D:\zxt\updates\html" rd /s /q "D:\zxt\updates\html" >nul 2>&1
echo 前端服务更新完成。
echo [%full_time%] 前端服务更新完成 >> "%log_file%"
:end_frontend
echo --------------------------- 前端服务 升级结束 ---------------------------
exit /b
:: ========== 数据库升级(带分隔符)==========
:database_update_auto
echo --------------------------- 数据库脚本 升级开始 ---------------------------
call :get_datetime
set "sql_file=D:\zxt\sql\inventory_state_grid_prod.sql"
set "db_name=inventory_state_grid_prod"
set "mysql_user=root"
echo [%full_time%] 开始执行数据库升级... >> "%log_file%"
if not exist "%sql_file%" (
echo [ERROR] SQL 文件不存在:%sql_file%
echo [ERROR] SQL文件不存在 >> "%log_file%"
echo.
goto end_database
)
echo 正在执行数据库升级...
echo 注意:请输入MySQL root用户的密码以继续。
mysql -u %mysql_user% -p %db_name% < "%sql_file%"
if errorlevel 1 (
echo [ERROR] 数据库升级失败,请检查SQL语法或连接。
echo [ERROR] 数据库升级失败 >> "%log_file%"
)
:: 删除 SQL 文件夹
if exist "D:\zxt\updates\sql" rd /s /q "D:\zxt\updates\sql" >nul 2>&1
echo 数据库升级完成。
echo [%full_time%] 数据库升级完成 >> "%log_file%"
:end_database
echo --------------------------- 数据库脚本 升级结束 ---------------------------
exit /b
:: ========== 获取时间戳函数 ==========
:get_timestamp
for /f "tokens=2 delims==" %%I in ('"wmic os get localdatetime /value"') do set datetime=%%I
set timestamp=%datetime:~0,8%_%datetime:~8,2%
exit /b
:: ========== 退出程序 ==========
:exit_program
call :get_datetime
echo [%full_time%] 用户选择退出程序。 >> "%log_file%"
echo.
echo.
echo 再见!按任意键退出...
pause >nul
exit