2015-08-30 56 views
1

我发现有一些类似于这个问题的话题,但不完全是我想要的,所以我提出这个话题。批处理文件日志功能,用于打印命令输出到日志文件和屏幕

我想创建一个日志功能,用于将消息打印到格式化日志文件和控制台输出。该功能如下:

:LOGDEBUG 
@echo DEBUG: %~1 
if NOT EXIST %LOG_FILE% exit /b 1 
@echo [%date - %time%] DEBUG: %~1 >> %LOG_FILE% 2>&1 
exit /b 0 

我尝试使用它打印命令执行的输出,如果输出包含类似特殊字符“<”和“>”,这个功能不能很好地工作,并提示“该系统找不到指定的文件”。我的用于执行命令代码如下:

for /f "usebackq delims=" %%a in (`dir c:\temp`) do (
    CALL :LOGDEBUG "%%a" 
) 

然而,当我使用“回声”命令,而不是直接对数函数,输出可以正确地在控制台上被打印。如下面的代码:

for /f "usebackq delims=" %%a in (`dir c:\temp`) do (
    echo %%a 
) 

我想知道是什么问题,以及如何我使用日志功能正确打印输出?谢谢

+0

检查此http://stackoverflow.com/a/10719322/388389 – npocmaka

+0

如何定义'%LOG_FILE%'变量?并尝试'echo CALL:LOGDEBUG“%% a”'而不是'CALL:LOGDEBUG“%% a”'来查看例如'CALL:LOGDEBUG“驱动器C中的卷是SysDisk”'(: – JosefZ

+0

嗨@npocmaka,我希望在打印前格式化日志文件和控制台输出,我想我不能直接使用tee.bat,对吗? – Elliott

回答

1

您已经通过自己回复你的问题:当我直接使用“回声”命令 ...

@ECHO OFF 
SETLOCAL EnableExtensions 
set "LOG_FILE=D:\tempx\program.log"  my testing value 
rem type NUL>"%LOG_FILE%" 
for /f "usebackq delims=" %%a in (`dir d:\temp 2^>NUL`) do (
    CALL :LOGDEBUG "%%a" 
) 
rem type "%LOG_FILE%" 
ENDLOCAL 
exit /b 

:LOGDEBUG 
FOR %%A in ("%~1") do (
    @echo DEBUG: %%~A 
    if NOT EXIST "%LOG_FILE%" exit /b 1 
    @echo [%date% - %time%] DEBUG: %%~A >> "%LOG_FILE%" 2>&1 
) 
exit /b 0 

资源(必读):

1

这是应该工作的批处理代码。

@echo off 
setlocal EnableDelayedExpansion 
set "LOG_FILE=C:\program.log" 
del "%LOG_FILE%" 2>nul 
for /F "delims=" %%a in ('dir "C:\temp\*" 2^>nul') do call :LOGDEBUG "%%a" 
endlocal 
goto :EOF 

:LOGDEBUG 
set "StringToOutput=%~1" 
echo DEBUG: !StringToOutput! 
echo [%DATE% - %TIME%] DEBUG: !StringToOutput!>>"%LOG_FILE%" 
goto :EOF 

启用首次延迟的环境变量扩展并创建现有环境表的副本。下面解释为什么这样做。

接下来将具有完整路径的日志文件的名称分配给局部变量表中的环境变量。此路径可以带有或不带有1个或更多空间。如果以前的运行已经存在,日志文件将被删除。如果您想将新行添加到已存在的文件中,则可以删除此代码。但在这种情况下,应该添加代码以避免日志文件永久增加,直到不再有空闲存储空间。

FOR命令执行命令DIR并处理DIR的输出写入到标准输出每一行。空白行被跳过。默认分隔符是空格,制表符和换行符。正如这里所要求的是DIR的全部行,默认分隔符列表被替换为空,这意味着只有换行符保留,并且循环变量%a总是被分配一个完整的非空行。

命令的输出DIR包含<>如果没有引用的线内发现由命令处理器,其被解释为redirection operators。因此,DIR输出的行通过引用子程序LOGDEBUG。在命令提示符窗口中执行cmd /?时,必须通常引用哪些字符列在打印到命令提示符窗口的最后一个帮助页面上。

当循环结束时,本地环境表被删除,这意味着LOG_FILEStringToOutput也被删除,并且以前的环境被恢复,这通常意味着在批量执行退出并跳转到预定义标签之前,延迟扩展会再次关闭到文件结尾。

该子程序LOGDEBUG首先将传递的字符串分配给一个环境变量,不需要使用周围的引号,因为行中的特殊字符如<>

接下来将该行写入控制台窗口,而不使用延迟扩展引号,否则<>将被解释为重定向运算符,而不是字面意思。

将同一行写入日志文件,并在行首插入日期和时间的差异。您错过代码中的date之后的百分号。再次延迟扩展用于将字符<>写入文件而不被解释为重定向操作符。

重要的是,在>>之前没有空格,否则日志文件中的每行都会有尾随空格。 2>&1在这里没用,作为命令echo没有写点东西给stderr

子程序退出时跳转到文件结尾,导致命令FOR处理下一行。

为了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • call /?
  • del /?
  • dir /?
  • for /?
  • goto /?
  • set /?

这将是当然可以做所有的输出可怕在命令主体FOR中可以不使用子程序。

@echo off 
setlocal EnableDelayedExpansion 
set "LOG_FILE=C:\program.log" 
del "%LOG_FILE%" 2>nul 
for /F "delims=" %%a in ('dir "C:\temp\*" 2^>nul') do (
    echo DEBUG: %%a 
    echo [!DATE! - !TIME!] DEBUG: %%a>>"%LOG_FILE%" 
) 
endlocal 

延迟变量扩展然而这里需要另有%DATE%%TIME%将由命令处理器等​​扩大已经在解析FOR命令之前通过()定义整个块在所有这将导致执行将相同的日期和时间写入日志文件的所有行。

相关问题