2012-02-18 42 views
6

我有幾個不同的進程,我希望他們都登錄到同一個文件。這些進程在Windows 7系統上運行。有些是python腳本,其他的是cmd批處理文件。你如何在Windows下共享日誌文件?

在Unix下,你只需讓每個人以附加模式打開文件並寫下。只要每個進程在單個消息中寫入小於PIPE_BUF字節,則每個調用將被保證不與其他任何其他進行交織。

有沒有辦法在Windows下做到這一點?天真的類Unix方法失敗了,因爲Windows不喜歡多個進程默認情況下一次打開一個文件進行寫入。

回答

9

可以將多個批處理過程安全地寫入單個日誌文件。我對Python一無所知,但我想象這個答案中的概念可以與Python集成。

Windows最多允許一個進程在任何時間點打開一個特定的文件以進行寫入訪問。這可以用來實現基於文件的鎖定機制,以確保事件在多個進程間串行化。一些示例參見https://stackoverflow.com/a/9048097/1012053http://www.dostips.com/forum/viewtopic.php?p=12454

由於您所要做的只是寫入日誌,因此可以將日誌文件本身用作鎖。日誌操作封裝在試圖以附加模式打開日誌文件的子例程中。如果打開失敗,例程會循環返回並再次嘗試。一旦打開成功,日誌就會被寫入並關閉,並且例程返回給調用者。例程執行傳遞給它的任何命令,寫入例程內的stdout的任何內容都會重定向到日誌。

這是一個測試批處理腳本,它創建5個子進程,每個進程向日志文件寫入20次。寫入是安全交錯的。

@echo off 
setlocal 
if "%~1" neq "" goto :test 

:: Initialize 
set log="myLog.log" 
2>nul del %log% 
2>nul del "test*.marker" 
set procCount=5 
set testCount=10 

:: Launch %procCount% processes that write to the same log 
for /l %%n in (1 1 %procCount%) do start "" /b "%~f0" %%n 

:wait for child processes to finish 
2>nul dir /b "test*.marker" | find /c "test" | >nul findstr /x "%procCount%" || goto :wait 

:: Verify log results 
for /l %%n in (1 1 %procCount%) do (
    <nul set /p "=Proc %%n log count = " 
    find /c "Proc %%n: " <%log% 
) 

:: Cleanup 
del "test*.marker" 
exit /b 

============================================================================== 
:: code below is the process that writes to the log file 

:test 
set instance=%1 
for /l %%n in (1 1 %testCount%) do (
    call :log echo Proc %instance% says hello! 
    call :log dir "%~f0" 
) 
echo done >"test%1.marker" 
exit 

:log command args... 
2>nul (
    >>%log% (
    echo *********************************************************** 
    echo Proc %instance%: %date% %time% 
    %* 
    (call) %= This odd syntax guarantees the inner block ends with success =% 
      %= We only want to loop back and try again if redirection failed =% 
) 
) || goto :log 
exit /b 

這裏是證明所有20個寫入成功爲每個進程

Proc 1 log count = 20 
Proc 2 log count = 20 
Proc 3 log count = 20 
Proc 4 log count = 20 
Proc 5 log count = 20 

您可以打開生成的「myLog.log」文件怎麼看已經被寫入安全地交錯輸出。但是輸出太大而無法在這裏發佈。

很容易證明,通過修改:日誌例程以避免多個進程同時寫入失敗時不會重試。

:log command args... 
>>%log% (
    echo *********************************************************** 
    echo Proc %instance%: %date% %time% 
    %* 
) 
exit /b 

這裏是 「破」 後,一些樣品的結果:記錄日常

The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
The process cannot access the file because it is being used by another process. 
Proc 1 log count = 12 
Proc 2 log count = 16 
Proc 3 log count = 13 
Proc 4 log count = 18 
Proc 5 log count = 14 
+0

當您在Windows上打開文件(使用CreateFile)時,您可以選擇其他進程是否可以讀取和/或寫入同一個文件,第二個進程必須指定兼容的共享標誌... – Anders 2012-02-19 02:46:48

+0

不夠公平。我主要是說Windows批處理如何與重定向一起工作 - 我沒有意識到的選項。即使在一個進程正在寫入時,也可以讀取多個進程。 (我不確定這是否安全)。但是從未有更多的流程開放寫入。 – dbenham 2012-02-19 03:21:01

+0

@dbenham:非常感謝你。它實際上解決了我的另一個大問題。它也可以解決我的日誌記錄問題。是否在任何地方記錄了'>>文件(命令)'語法? – Omnifarious 2012-02-19 08:24:57

2

你可以給這個Python模塊一試: http://pypi.python.org/pypi/ConcurrentLogHandler

它提供了一個簡易替換的RotatingFileHandler它允許多個進程同時登錄到一個單獨的文件不會丟失或重挫日誌事件。

我還沒有使用它,但在Python中閱讀相關錯誤(Issue 4749)時發現了它。

如果您實現自己的代碼來代替使用該模塊,請確保您閱讀了該錯誤!

你可以在Windows上使用output redirection,就像你在Bash中做的那樣。將批處理文件的輸出傳輸到一個Python腳本,該腳本通過ConcurrentLogHandler進行日誌記錄。

+0

這看起來非常有用。我不確定如何處理批處理文件執行的日誌記錄。現在我只是寫它到不同的文件。 – Omnifarious 2012-02-18 01:13:25

+0

@Omnifarious我認爲你應該能夠使用[輸出重定向]來安裝某些東西(http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr = TRUE)。 '''在Windows上工作就像在Bash中一樣。 – 2012-02-18 04:54:04

相關問題