2015-08-30 59 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命令之前通過()定義整個塊在所有這將導致執行將相同的日期和時間寫入日誌文件的所有行。

相關問題