@echo off chcp 65001 >nul setlocal enabledelayedexpansion :: version: 0.13 :: ===================================================================== 主逻辑顺序 :: 初始化脚本. call :INITIALIZE :: 调用主函数. goto :main >nul exit /b 0 :INITIALIZE set "SCRIPT_PATH=%~dp0" set "SCRIPT_NAME=%~nx0" set "SCRIPT_NAME_WITHOUT_EXT=%~n0" set "LOG_LEVEL_THRESHOLD=DEBUG" call :get_current_time set "CALL_TIME=!CURRENT_TIME!" call :LOG_INFO "Startup %SCRIPT_NAME%: %CALL_TIME%" set "SHOW_TITLE=true" for %%a in (%*) do (if /i "%%a"=="/notitle" set set "SHOW_TITLE=false") if "!SHOW_TITLE!"=="true" (title %SCRIPT_NAME%) exit /b 0 :CHECK_IS_ADMIN net session >nul 2>&1 if %errorLevel% neq 0 ( exit /b 1 ) exit /b 0 :MD52String setlocal set "input=%~1" for /f "delims=" %%i in (' powershell -Command "[System.BitConverter]::ToString((New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash([System.Text.Encoding]::UTF8.GetBytes('!input!'))).Replace('-','').ToLower()" ') do set "md5=%%i" endlocal & set "md5=%md5%" exit /b 0 :MD5Hash2File setlocal set "input_text=%~1" set "return_var=%~2" where md5sum >nul 2>nul if errorlevel 1 ( echo Error: md5sum command not found in PATH endlocal exit /b 1 ) set "temp_file=%TEMP%\md5_%RANDOM%.txt" echo !input_text! > "!temp_file!" for /f "tokens=1" %%i in ('md5sum "!temp_file!" 2^>nul') do ( set "hash_result=%%i" ) if "!hash_result!"=="" ( echo Error: Failed to calculate MD5 hash del "!temp_file!" 2>nul endlocal exit /b 2 ) del "!temp_file!" 2>nul endlocal & set "%return_var%=%hash_result%" exit /b 0 :GET_TIME_STAMP setLocal set "level=%~1" if /i "%level%"=="ms" ( for /f %%i in ('powershell -command "[math]::Truncate([decimal]((Get-Date).ToUniversalTime() - [datetime]'1970-01-01').TotalMilliseconds)"') do set timestamp_ms=%%i if %errorlevel% == 0 ( set "timestamp=!timestamp_ms!" ) ) if /i "%level%"=="s" ( for /f %%i in ('powershell -command "[math]::Truncate([decimal]((Get-Date).ToUniversalTime() - [datetime]'1970-01-01').TotalSeconds)"') do set timestamp_s=%%i if %errorlevel% == 0 ( set "timestamp=!timestamp_s!" ) ) endLocal & set "timestamp=%timestamp%" exit /b 0 :GET_DATE_TIME for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set __date=%%a-%%b-%%c) for /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set __time=%%a%%b) set "CURRENT_DATE_TIME=%__date%_%__time%" exit /b 0 :GET_CURRENT_TIME for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "datetime=%%a" set "CURRENT_TIME=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2% %datetime:~8,2%:%datetime:~10,2%:%datetime:~12,2%" exit /b 0 :GET_CURRENT_DATE for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "datetime=%%a" set "CURRENT_DATE=%datetime:~0,4%%datetime:~4,2%%datetime:~6,2%" exit /b 0 :WAIT set /a "SECOND=%~1" timeout /t %SECOND% /nobreak >nul exit /b 0 :LOG setLocal set "LOG_LEVEL=%~1" set LOG_MESSAGE= shift :log__params_loop if not "%~1"=="" ( set "LOG_MESSAGE=%LOG_MESSAGE% %~1" shift goto log__params_loop ) call :get_log_level_num "%LOG_LEVEL%" "CALLER_LEVEL_NUM" call :get_log_level_num "%LOG_LEVEL_THRESHOLD%" "THRESHOLD_LEVEL_NUM" if %CALLER_LEVEL_NUM% lss %THRESHOLD_LEVEL_NUM% ( endLocal exit /b 0 ) call :GET_CURRENT_TIME if /i "%LOG_LEVEL%"=="GROUP" echo. echo [%CURRENT_TIME%] - [%LOG_LEVEL%] - %LOG_MESSAGE% endLocal exit /b 0 :get_log_level_num setLocal set "level=%~1" set "num=0" if /i "%level%"=="TRACE" set "num=1" if /i "%level%"=="DEBUG" set "num=2" if /i "%level%"=="INFO" set "num=3" if /i "%level%"=="WARN" set "num=4" if /i "%level%"=="GROUP" set "num=5" if /i "%level%"=="ERROR" set "num=6" endLocal & set "%~2=%num%" exit /b 0 :LOG_ERROR call :LOG ERROR %* && exit /b 0 :LOG_GROUP call :LOG GROUP "===============================" %* "===============================" exit /b 0 :LOG_WARN call :LOG WARN %* && exit /b 0 :LOG_INFO call :LOG INFO %* && exit /b 0 :LOG_DEBUG call :LOG DEBUG %* && exit /b 0 :LOG_DEBUG call :LOG DEBUG %* && exit /b 0 :LOG_TRACE call :LOG TRACE %* && exit /b 0 :GET_STRING_LENGTH setlocal set "input_str=%~1" set "str_length=%~2" :get_string_length_loop if defined input_str ( set /a str_length+=1 set "input_str=!input_str:~1!" goto get_string_length_loop ) endlocal & ( if not "%~2"=="" ( set "%~2=%str_length%" ) else ( exit /b %str_length% ) ) exit /b 0 :GET_STRING_LENGTH_WITHOUT_SPACES setlocal set "input_str=%~1" set "result_var=%~2" set "tmp_char=!input_str!" set /a str_length=0 for %%p in ( 4096 2048 1024 512 256 128 64 32 16 8 4 2 1 ) do ( if not "!tmp_char:~%%p!"=="" ( set "tmp_char=!tmp_char:~%%p!" set /a str_length+=%%p ) ) if not "!tmp_char!"=="" set /a str_length+=1 call :LOG_TRACE Length=%str_length% String=%input_str% endlocal & ( if not "%~2"=="" ( set "%~2=%str_length%" ) else ( exit /b %str_length% ) ) exit /b 0 :RANDOM_STR setlocal set "len=%~1" set "varname=%~2" if "!varname!"=="" set "varname=RAND_STR" set "chars=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" set "random_str=" call :GET_STRING_LENGTH "%chars%" "charts_length" for /l %%i in (1,1,!len!) do ( set /a rand_index=!random! %% !charts_length! call set "char=%%chars:~!rand_index!,1%%" set "random_str=!random_str!!char!" ) endlocal & set "%varname%=%random_str%" exit /b 0 :GET_SINGLE_PID_BY_PORT setlocal call :RandomStr single_pid_tmp call :LOG_INFO netstat -ano ^| grep -E ":%1 " ^| grep "LISTENING" ^| awk "{print $NF}" ^| head -n 1 netstat -ano | grep -E ":%1 " | grep "LISTENING" | awk "{print $NF}" | head -n 1 > %single_pid_tmp%.txt set /p pid=<%single_pid_tmp%.txt call :LOG_INFO pid: %pid% del %single_pid_tmp%.txt endlocal & set pid=%pid% exit /b 0 :GET_USED_PID_BY_PORT setlocal set "PORT=%~1" set /a "UNIQUE_COUNT=0" if "!PORT!"=="" ( call :log_error ERROR: Port number required endlocal & exit /b 0 ) set "TEMP_FILE=%TEMP%\port_%PORT%_%RANDOM%_%TIME::=_%.tmp" set "PID_LIST_FILE=%TEMP%\pids_%PORT%_%RANDOM%.tmp" call :LOG_INFO Checking for processes using port !PORT!... netstat -ano | grep -E ":!PORT! " > "!TEMP_FILE!" if !errorlevel! neq 0 ( call :LOG_INFO No process found using port !PORT! del "!TEMP_FILE!" 2>nul endlocal & exit /b 0 ) echo. > "!PID_LIST_FILE!" echo. call :LOG_GROUP Processes using port !PORT! for /f "tokens=5" %%a in (!TEMP_FILE!) do ( set "PID=%%a" :: grep -E "^^!PID! $" "!PID_LIST_FILE!" >nul findstr /x "!PID!" "!PID_LIST_FILE!" >nul if !errorlevel! neq 0 ( echo !PID! >> "!PID_LIST_FILE!" set /a "UNIQUE_COUNT+=1" call :LOG_INFO [!UNIQUE_COUNT!] PID: !PID! set "PROCESS_NAME=" set "SESSION_NAME=" set "SESSION_NUM=" set "MEM_USAGE=" for /f "tokens=1,2,3,4,5*" %%b in ('tasklist /fi "PID eq !PID!" /fo table ^| findstr /i "!PID!"') do ( if not "%%b"=="=" if not "%%b"=="Image" ( call :LOG_INFO "PROCESS_NAME=%%b" call :LOG_INFO "PID_VALUE=%%c" call :LOG_INFO "SESSION_NAME=%%d" call :LOG_INFO "SESSION_NUM=%%e" call :LOG_INFO "MEM_USAGE=%%f" ) ) if not "!PROCESS_NAME!"=="" ( call :LOG_INFO Process: !PROCESS_NAME! call :LOG_INFO Memory: !MEM_USAGE! ) echo. ) ) if !UNIQUE_COUNT! gtr 0 ( call :LOG_GROUP PIDs using port !PORT! :: type "!PID_LIST_FILE!" call :LOG_INFO Total: !UNIQUE_COUNT! process ) del "!TEMP_FILE!" 2>nul del "!PID_LIST_FILE!" 2>nul endlocal & exit /b %UNIQUE_COUNT% :LISTEN_PORT_LIST call :listen_port_list__default_set set all_ports_up=1 for %%i in (%PORT_LIST%) do ( for /f "tokens=1,2 delims=:" %%a in ("%%i") do ( set port=%%a set service=%%b netstat -an | find ":%%a" > nul if !errorlevel! neq 0 ( set all_ports_up=0 call :LOG_DEBUG "!service! Server (Port: %%a) isn't ready..." ) ) ) if !all_ports_up! equ 1 ( call :DISPLAY_SUCCESS && exit /b 0 ) set /a COUNTER+=CHECK_INTERVAL if !COUNTER! geq %MAX_WAIT% ( call :LOG_ERROR "Services did not start within !COUNTER! seconds" && exit /b 1 ) call :LOG_DEBUG "Waiting for services... (!COUNTER!/%MAX_WAIT% seconds)" echo. call :WAIT %CHECK_INTERVAL% goto LISTEN_PORT_LIST :listen_port_list__default_set set CHECK_INTERVAL=5 set MAX_WAIT=90 set COUNTER=0 exit /b 0 :DISPLAY_SUCCESS call :WAIT 3 echo. echo ======================================== echo %SERVER_HUMP% Services Successfully Started echo ======================================== for %%i in (%PORT_LIST%) do ( for /f "tokens=1,2 delims=:" %%a in ("%%i") do ( echo - %%b Server - Port %%a is listening ) ) echo ======================================== echo. exit /b 0 :AUTOSTART setlocal set DESCRIPTION=%~1 set SCRIPT_PATH=%~2 set SCRIPT_FILE=%~3 set PARAMS= shift /3 :autostart__params_loop if not "%~1"=="" ( set "PARAMS=%PARAMS% %~3" shift goto autostart__params_loop ) call :GET_STRING_LENGTH "%SCRIPT_PATH%" "len" set /a "last_pos=len-1" for /f "delims=" %%c in ("!SCRIPT_PATH:~%last_pos%,1!") do ( if not "%%c"=="\" ( set "SCRIPT_PATH=%SCRIPT_PATH%\" ) ) call :START "%DESCRIPTION%" "%SCRIPT_PATH%" "%SCRIPT_FILE%" %PARAMS% exit /b 0 :START setlocal set DESCRIPTION=%~1 set SCRIPT_PATH=%~2 set SCRIPT_FILE=%~3 set PARAMS= shift /3 :start__params_loop if not "%~1"=="" ( set "PARAMS=%PARAMS% %~3" shift goto start__params_loop ) call :LOG_DEBUG "%SCRIPT_PATH%%SCRIPT_FILE%" if exist "%SCRIPT_PATH%%SCRIPT_FILE%" ( echo. call :LOG_INFO "Starting %DESCRIPTION%..." cd /d "%SCRIPT_PATH%" start "%DESCRIPTION% Startup" /B cmd /c "%SCRIPT_FILE% %PARAMS%" if errorlevel 1 ( call :log_error %DESCRIPTION% start Failed. pause && exit /b 1 ) ) else ( call :log_error Startup file not found: %SCRIPT_PATH%\%SCRIPT_FILE% pause && exit /b 1 ) endlocal exit /b 0 :Exit set "exit_code=%~1" set "error_msg=%~2" if "!exit_code!"=="" set "exit_code=0" if not "!error_msg!"=="" ( call :LOG_ERROR An error occurred^(!exit_code!^): !error_msg! ) call :Cleanup exit /b !exit_code! :Cleanup call :LOG_INFO Cleaning up resources ... goto :EOF :: ===================================================================== 主逻辑起点 :: 主函数. :main setlocal call :LOG_INFO "脚本开始执行" :: nginx call :GET_USED_PID_BY_PORT 18080 if !ERRORLEVEL! neq 0 ( call :LOG_INFO Found !ERRORLEVEL! processes. call :GET_SINGLE_PID_BY_PORT 18080 call :LOG_GROUP Killing Process !pid! taskkill -f -im home-web.exe ) timeout /t 1 /nobreak >nul call :AUTOSTART "Nginx" "%SCRIPT_PATH%nginx" "home-web.exe" "-c" "conf/web.conf" :: redis timeout /t 3 /nobreak >nul call :AUTOSTART "Redis" "%SCRIPT_PATH%redis" "redis-server.exe" "redis.conf" :: minio timeout /t 3 /nobreak >nul call :AUTOSTART "MinIO" "%SCRIPT_PATH%io" "minio-server.bat" :: rocketmq timeout /t 3 /nobreak >nul call :AUTOSTART "RocketMQ" "%SCRIPT_PATH%rocketmq\sbin" "rocketmq.bat" set PORT_LIST=9876:RocketMQ-NameServer 10911:RocketMQ-Broker 8081:RocketMQ-Proxy 8088:RocketMQ-Dashboard set SERVER_HUMP=RocketMQ call :LISTEN_PORT_LIST endlocal goto :Exit 0