下面我将从基础用法到高级技巧,全面讲解如何在批处理中进行日志记录。

基础日志记录
最简单的方式就是使用 >> 操作符,将命令的输出(包括标准输出和错误输出)追加到一个文本文件中。
基本语法
>> 日志文件.txt echo [日志内容]
>>:追加操作符,如果日志文件不存在,会自动创建;如果存在,新的内容会添加到文件末尾,而不会覆盖原有内容。>:覆盖操作符,每次执行都会清空文件并写入新内容,通常用于初始化日志或只保留最后一次的运行结果。echo [日志内容]:要记录的文本信息。
示例
创建一个名为 test_log.bat 的文件,内容如下:
@echo off
:: 设置日志文件路径
set "logfile=app.log"
:: 初始化或覆盖日志文件
> %logfile% echo ================================
> %logfile% echo 程序启动于 %date% %time%
> %logfile% echo ================================
:: 追加一些操作日志
>> %logfile% echo 正在执行第一步:检查网络...
ping -n 1 8.8.8.8 > nul
>> %logfile% echo 网络检查完成。
>> %logfile% echo 正在执行第二步:创建目录...
if not exist "C:\temp_logs" (
mkdir "C:\temp_logs"
>> %logfile% echo 目录 C:\temp_logs 创建成功。
) else (
>> %logfile% echo 目录 C:\temp_logs 已存在。
)
:: 记录错误
>> %logfile% echo 正在执行第三步:尝试访问一个不存在的文件...
type "C:\non_existent_file.txt" 2>> %logfile%
>> %logfile% echo 上一步操作已结束,错误信息(如果有)已记录。
>> %logfile% echo ================================
>> %logfile% echo 程序结束于 %date% %time%
>> %logfile% echo ================================
echo 日志已写入 %logfile%
pause
运行 test_log.bat 后,你会得到一个 app.log 文件,内容如下:
===============================
程序启动于 2025/10/27 星期五 15:30:05.35
===============================
正在执行第一步:检查网络...
网络检查完成。
正在执行第二步:创建目录...
目录 C:\temp_logs 创建成功。
正在执行第三步:尝试访问一个不存在的文件...
系统找不到指定的文件。
上一步操作已结束,错误信息(如果有)已记录。
===============================
程序结束于 2025/10/27 星期五 15:30:06.12
===============================
进阶日志记录(带时间戳)
一个好的日志,每条记录都应该有时间戳,方便排查问题。

创建带时间戳的日志函数
将重复的代码封装成一个函数,是批处理脚本提高可读性和可维护性的关键。
@echo off
set "logfile=app_with_timestamp.log"
:: 调用函数,初始化日志
call :log "==============================="
call :log "程序启动"
call :log "==============================="
:: 执行一些操作
call :log "开始备份文件..."
xcopy "C:\source" "D:\backup" /E /I /H > nul
if %errorlevel% equ 0 (
call :log "文件备份成功!"
) else (
call :log "错误:文件备份失败!错误代码 %errorlevel%。"
)
call :log "程序结束"
call :log "==============================="
pause
exit /b
::---------------------------------------------------------------------------------
:: 日志函数
:: 参数: %1 - 要记录的日志内容
::---------------------------------------------------------------------------------
:log
:: >> 追加到日志文件
:: echo %date% %time% %~1 >> %logfile%
:: 为了更清晰的时间格式,我们可以使用 for /f 来格式化时间
for /f "tokens=1-4 delims=/ " %%a in ("%date%") do set "dt=%%c-%%a-%%b"
for /f "tokens=1-3 delims=:." %%a in ("%time%") do set "tt=%%a:%%b:%%c"
>> %logfile% echo [%dt% %tt%] %~1
goto :eof
运行后,app_with_timestamp.log 的内容会是这样:
[2025-10-27 15:32:10] ===============================
[2025-10-27 15:32:10] 程序启动
[2025-10-27 15:32:10] ===============================
[2025-10-27 15:32:10] 开始备份文件...
[2025-10-27 15:32:12] 文件备份成功!
[2025-10-27 15:32:12] 程序结束
[2025-10-27 15:32:12] ===============================
函数解析:
log:定义一个名为log的标签(函数)。%~1:这是函数的第一个参数。 会移除参数可能存在的引号。for /f "tokens=1-4 delims=/ " ...:这是一个非常强大的命令,用于解析字符串。delims=/:指定分隔符为 和空格。tokens=1-4:提取第1到第4个“块”。- 对于
2025/10/27 星期五,它会提取2025,10,27,星期五。 set "dt=%%c-%%a-%%b":将它们重新组合成年-月-日的格式。
goto :eof:跳转到当前脚本的结尾,相当于函数的return。
高级技巧与最佳实践
同时输出到屏幕和日志文件
在调试或需要实时查看进度时,我们既希望看到日志文件,也希望在控制台看到输出。

@echo off set "logfile=console_and_log.log" :: 定义一个函数,同时输出到屏幕和文件 :log_and_echo echo [%date% %time%] %~1 >> %logfile% echo [%date% %time%] %~1 goto :eof call :log_and_echo "程序开始运行" dir C:\ > nul call :log_and_echo "列出 C:\ 目录完成" pause
区分日志级别(INFO, ERROR, WARNING)
在复杂的脚本中,区分不同类型的日志非常有帮助,我们可以通过函数参数来实现。
@echo off set "logfile=level_log.log" :: 日志级别定义 set "level_info=[INFO]" set "level_warn=[WARN]" set "level_err=[ERROR]" :: 带级别的日志函数 :log_with_level set "log_content=%~1" set "log_message=%~2" >> %logfile% echo %log_content% %date% %time% - %log_message% goto :eof :: 使用示例 call :log_with_level "%level_info%" "应用程序正常启动。" call :log_with_level "%level_warn%" "磁盘空间不足,请及时清理。" call :log_with_level "%level_err%" "无法连接到数据库!" pause
记录命令本身及其输出
我们不仅想知道命令的结果,还想看到执行的命令本身。
@echo off set "logfile=command_log.log" :: 记录要执行的命令 >> %logfile% echo [CMD] ping -n 1 8.8.8.8 :: 执行命令并将输出重定向到日志文件 >> %logfile% echo [OUT] ping -n 1 8.8.8.8 >> %logfile% >> %logfile% echo. >> %logfile% echo [CMD] ipconfig /all >> %logfile% echo [OUT] ipconfig /all >> %logfile% echo 命令日志已生成。 pause
日志文件滚动(防止单个文件过大)
长时间运行的脚本会产生巨大的日志文件,一个简单的滚动策略是:当日志文件超过一定大小时,将其重命名备份,然后创建一个新的日志文件。
@echo off
set "logfile=rolling.log"
set "max_size=1024" :: 设置最大大小为 1KB (仅用于演示)
:: 检查日志文件是否存在
if exist "%logfile%" (
:: for %%A in ("%logfile%") do ... 获取文件大小(字节)
for %%A in ("%logfile%") do (
if %%~zA gtr %max_size% (
echo 日志文件过大,进行滚动...
ren "%logfile%" "rolling_old.log"
echo 已创建新的日志文件。
)
)
)
>> %logfile% echo [%date% %time%] 这是一条新的日志记录。
>> %logfile% echo [%date% %time%] 为了让日志文件变大,我们重复写很多次...
>> %logfile% echo [%date% %time%] 为了让日志文件变大,我们重复写很多次...
>> %logfile% echo [%date% %time%] 为了让日志文件变大,我们重复写很多次...
>> %logfile% echo [%date% %time%] 为了让日志文件变大,我们重复写很多次...
>> %logfile% echo [%date% %time%] 为了让日志文件变大,我们重复写很多次...
pause
日志记录中的重定向
这是批处理日志的核心,必须理解清楚。
| 命令 | 描述 | 示例 |
|---|---|---|
command >> file |
将 command 的标准输出追加到 file 末尾。 |
>> log.txt echo hello |
command > file |
将 command 的标准输出覆盖写入 file。 |
> log.txt echo hello |
command 2> file |
将 command 的错误输出**覆盖**写入 file。 |
copy missing.txt 2> error.log |
command 2>> file |
将 command 的错误输出**追加**到 file 末尾。 |
copy missing.txt 2>> error.log |
command > file 2>&1 |
关键技巧:将标准输出和错误输出都重定向到同一个文件(覆盖)。 | > all_output.log dir 2>&1 |
command >> file 2>&1 |
最常用:将标准输出和错误输出都追加到同一个文件末尾。 | >> app.log some_command 2>&1 |
解释 2>&1:
2:代表标准错误流。1:代表标准输出流。&:是连接符号,表示“与...相同”。2>&1的意思是:“将标准错误流(2)重定向到标准输出流(1)当前所指向的地方”。
>> app.log some_command 2>&1 的完整含义是:
>> app.log打开app.log文件用于追加,并将其分配给标准输出流(1)。2>&1命令标准错误流(2)也指向这个app.log文件。- 执行
some_command,无论它输出到标准输出还是标准错误,都会被写入到app.log文件的末尾。
| 场景 | 推荐方法 |
|---|---|
| 简单记录 | >> log.txt echo [内容] |
| 带时间戳的记录 | 使用 for /f 格式化时间,封装成 log 函数。 |
| 同时显示和记录 | echo [内容] 并 >> log.txt echo [内容],或封装成函数。 |
| 记录错误 | command 2>> error.log 或 command >> all.log 2>&1。 |
| 记录命令和输出 | 先 >> log.txt echo [CMD] ...,再执行 command >> log.txt。 |
| 健壮的日志系统 | 封装带时间戳、日志级别(INFO/WARN/ERROR)的函数,并使用 2>&1 捕获所有输出。 |
掌握这些技巧,你就可以编写出专业、可靠且易于维护的批处理脚本了。
