写在前面:
为了解决每次开发前繁琐的环境启动问题,我专门研究了 Windows 批处理脚本。本文将分享从基础语法到实战的全过程,实现项目的一键自动化部署。
1、echo
(1)@echo off 的作用
关闭命令回显。这意味着在脚本执行时,不会把每一条命令本身显示在窗口中,只会显示命令的执行结果,让输出界面更整洁。开头的 @ 符号是为了让 echo off 这条命令自身也不被显示。
(2)当你用 echo off 把命令隐藏后,想要展示在命令行信息可以用以下操作:
echo 文字内容:在屏幕上打印指定文字。
echo. :在屏幕上输出一个空行。
(3)echo on:重新打开命令回显。
2、chcp
chcp 65001 作用
将当前命令行窗口的字符编码设置为 UTF-8。这可以确保脚本和程序能够正确显示中文等多字节字符,避免出现乱码。
chcp 936:默认代码页(GBK 编码)。
chcp 950:繁体中文
3、set "PATH=%MYSQL_DIR%;%PATH%"
这里的意思是把PATH设为mysql路径+原有的PATH,如果 set "PATH=%MYSQL_DIR%;就是将当前命令行窗口系统路径设为只有mysql路径。
4、%errorlevel%
可以看到经常用到%errorlevel%
它是 Windows 命令提示符(CMD)中的一个特殊环境变量,用来存储上一条命令执行后的退出状态码。
5、>nul 2>&1
>nul:把正常的输出信息(比如 SELECT 1 查出来的结果)丢到空设备(nul)里,也就是不显示在屏幕上。
2>&1:把错误的输出信息(比如连接失败的报错)也重定向到正常输出里(最终一起被丢进 nul),这样即使报错了,屏幕上也不会弹出任何提示。
6、net start
net start:系统会列出当前所有正在运行的服务。
net start 服务名:启动某个具体的服务。
例如net start MySQL
启动MySQL服务,mysql -u -p只是登录,但MySQL不一定在后台是启动的所以可能登录失败,这个时候就要尝试启动服务。
7、pause
作用:暂停脚本的执行,并显示"请按任意键继续. . ."。
8、 timeout
timeout为等待命令
timeout /t 5 /nobreak >nul
/t 5 指等待时间长度为5秒(Window自带的timeout无其他时间单位)
/nobreak:强制等待,忽略用户的按键。如果不加这个参数,在等待期间你随便按一个键,等待就会立刻结束并继续执行后续操作。
9、exit
exit:直接关闭当前的命令提示符(CMD)窗口。
exit /b 仅退出当前的批处理脚本,不关闭 CMD 窗口,方便看上面的打印信息。
exit /b 0: 退出代码0表示程序成功执行。
exit /b 1:退出代码1程序遇到了错误或异常退出。
exit /b %errorlevel%:把当前脚本最后一条命令的执行结果作为退出代码。
10、pushd和popd
pushd :把你当前的目录保存到堆栈里。切换到新的目录。
例如: 当前目录为/home,则pushd /tmp,把你当前的目录 /home/user 保存到堆栈里。 把你切换到新的目录 /tmp。
popd: 回到pushd时候记住的位置。
把堆栈最上面的 /tmp 删掉。 把你切换到新的栈顶目录 /home。
dirs -v:查看堆栈里存了哪些目录带序号。
11、start
作用:单独开一个独立窗口执行命令,不阻塞当前窗口。
(1)start后面必须跟"标题名",因为它把命令后的第一个带双引号的字符串,默认当成是新窗口的"标题"。
(2)控制窗口"长相"的参数:
/min:启动后直接最小化到任务栏。
/max:启动后直接最大化窗口。
/b:不创建新窗口,直接在当前黑框框里启动程序(适合完全静默的后台任务)。
(3)控制程序"待遇"和"行为"的参数
"/wait:让当前的批处理脚本"死等 。它会暂停执行后面的代码,直到启动的这个新程序被关闭后,脚本才会继续往下走。
/high / /low / /realtime:指定程序的 CPU 优先级。比如 /high 就是高优先级启动;/low 则是低优先级,适合不紧急的后台任务。
/d "路径":指定程序的启动目录。有些程序必须要在它自己的文件夹里启动才能正常读取配置文件,这时就需要用到它。
(4)可以直接打开文件/网址
打开文件夹:start D:\MyFolder(会直接弹出一个资源管理器窗口打开该文件夹)。
打开文件:start test.txt 或 start report.pdf(它会自动调用电脑上默认的记事本或 PDF 阅读器来打开这个文件)。
打开网址:start https://www.example.com(会自动用默认浏览器打开这个网页)。
应用示例:start "Redis" /min redis-server.exe redis.windows.conf
正常redis-server.exe redis.windows.conf启动Redis,但是就不能够继续执行后面的命令,这里使用start可以单独开一个新窗口执行后面的命令,"Redis"则是新开窗口标题名,/min为自动最小化。
12、cmd
cmd /k:执行完后面的命令后,保持窗口打开,方便实时查看运行状态。
输入 cmd /k ipconfig:
系统会弹出一个新窗口(窗口B)来显示网络信息。但是,窗口A会被"阻塞"。也就是说,窗口A会一直等待窗口B关闭后,才会允许你继续输入下一条命令。
输入 start cmd /k ipconfig:
系统同样会弹出窗口B。但是,因为有 start 的存在,窗口A不会被阻塞。窗口A会立刻返回,允许你继续输入其他命令,窗口B则会在后台独立运行。
cmd /c :执行完后面的命令后立刻关闭窗口。
cmd /q :关闭命令回显。
cmd /v:on开启"延迟环境变量扩展"
具体来说:
set num=1
set /a num+=1 & echo %num%
输出1,因为 CMD 在执行这行命令前,就已经把 echo %num% 里的 %num% 替换成了旧值 1。
cmd /v:on
set num=1
set /a num+=1 & echo !num!
输出2,!变量名!表示CMD 在执行到那句话时,实时获取变量当下的最新状态。
13、setlocal enabledelayedexpansion
开启了延迟变量扩展(让你能用 !变量!)和cmd /v:on效果类似。
同时,在后台开启了一个"环境隔离区" ,此时set 设置环境变量是临时的,不会永久修改系统环境。
只在当前的脚本文件内生效,遇到endlocal时候恢复到原来的环境。
14、for 循环
for /l %%i in (1,1,60) do (
这是一个 for 循环,/l 代表按数字递增。
%%i 就是当前的秒数计数器(第1秒、第2秒...直到第60秒)。
(1,1,60) 的意思是:从 1 开始,每次增加 1,直到 60。
和timeout一起使用。满足条件可以通过goto跳出循环。
15、findstr
findstr:在一个或多个文件中查找包含特定字符串的行,然后把这一整行完整的内容打印出来 。
findstr :%BACKEND_PORT%:通过管道符,在上一步的结果中筛选包含"后端端口号"的行。
如果端口找到了,即后端启动成功,通过goto :backend_ok跳出循环。
在这里是查找:%BACKEND_PORT%,例如%BACKEND_PORT%为123的话,就是查找带有":123"这个字符串的端口号。
还可以加/i来不区分大小写,后面加文件名表示在指定文件(文件夹)查找。
例如findstr /i %BACKEND_PORT% log.txt 则是在log.txt内查找
findstr /S /i %BACKEND_PORT% D:\My\*.*是查找所有文件(/S代表该文件夹内的子文件夹也将一起搜 )
findstr /i %BACKEND_PORT% D:\My\*.txt是查找所有txt文件(不搜子文件夹内的文件)
对于netstat -ano | findstr :%BACKEND_PORT%
netstat -ano:查看当前电脑所有的网络连接和占用的端口。
|是管道符,作用是把前一个命令的输出结果直接输送给后一个命令作为输入内容。
16、color
color 命令通过一个两位的十六进制数字来改变颜色。
语法:color 背景色文字色。
第一个数字代表背景,第二个数字代表文字。如果只输入一个数字,则只改变文字颜色,背景保持默认。
全局生效:color 命令一旦执行,会改变之后整个窗口的所有输出颜色,直到再次使用 color 命令修改。
|---|----|---|-----|
| 0 | 黑色 | 8 | 灰色 |
| 1 | 蓝色 | 9 | 亮蓝色 |
| 2 | 绿色 | A | 亮绿色 |
| 3 | 青色 | B | 亮青色 |
| 4 | 红色 | C | 亮红色 |
| 5 | 紫色 | D | 亮紫色 |
| 6 | 黄色 | E | 亮黄色 |
| 7 | 白色 | F | 亮白色 |
17、:
以冒号 : 开头的单词就是一个标签。它本身不会被当作命令去执行,而是用来给 goto 或 call 命令提供跳转的目标位置。
脚本启动中间件和前后端项目示例:
这里启动了MySQL,Redis,前后端
@echo off
chcp 65001 >nul
title Project Launcher
set "MYSQL_USER=your_user"
set "MYSQL_PASS=your_password"
set "MYSQL_DIR=D:\mysql-8.0.34-winx64\bin"
set "REDIS_DIR=D:\Redis-x64-3.2.100"
set "BACKEND_DIR=d:\backend"
set "FRONTEND_DIR=d:\frontend"
set "BACKEND_PORT=8084"
color 0A
echo [1/4] Checking MySQL...
mysql -u%MYSQL_USER% -p%MYSQL_PASS% -e "SELECT 1" database_name >nul 2>&1
if %errorlevel% equ 0 (
echo OK MySQL is running
) else (
echo Starting MySQL...
set "PATH=%MYSQL_DIR%;%PATH%"
net start MySQL >nul 2>&1
if %errorlevel% equ 0 (
echo Waiting for MySQL...
timeout /t 5 /nobreak >nul
mysql -u%MYSQL_USER% -p%MYSQL_PASS% -e "SELECT 1" database_name >nul 2>&1
if %errorlevel% equ 0 (
echo OK MySQL started
) else (
echo ERROR MySQL start failed!
pause
exit /b 1
)
) else (
echo ERROR Cannot start MySQL service!
pause
exit /b 1
)
)
echo [2/4] Checking Redis...
if exist "%REDIS_DIR%\redis-cli.exe" (
"%REDIS_DIR%\redis-cli.exe" ping >nul 2>&1
if %errorlevel% equ 0 (
echo OK Redis is running
) else (
echo Starting Redis...
pushd "%REDIS_DIR%"
start "Redis" /min redis-server.exe redis.windows.conf
popd
echo Waiting for Redis...
timeout /t 5 /nobreak >nul
"%REDIS_DIR%\redis-cli.exe" ping >nul 2>&1
if %errorlevel% equ 0 (
echo OK Redis started
) else (
echo ERROR Redis start failed! Check path!
pause
exit /b 1
)
)
) else (
echo ERROR Redis-cli not found! Check REDIS_DIR!
pause
exit /b 1
)
echo [3/4] Starting Backend...
start "Backend" cmd /k "cd /d ""%BACKEND_DIR%"" && mvn spring-boot:run"
echo Waiting for backend (port %BACKEND_PORT%)...
setlocal enabledelayedexpansion
for /l %%i in (1,1,60) do (
netstat -ano | findstr :%BACKEND_PORT% >nul 2>&1
if !errorlevel! equ 0 (
echo OK Backend started!
goto :backend_end
)
timeout /t 1 /nobreak >nul
echo ... waiting (%%i/60s)
)
echo WARNING Backend timeout! Check logs manually.
:backend_end
endlocal
echo [4/4] Starting Frontend...
start "Frontend" cmd /k "cd /d ""%FRONTEND_DIR%"" && npm run dev"
echo.
echo ============================================================
echo Services Started Successfully!
echo ============================================================
echo.
echo Tip: This window can be closed, services run in separate windows.