我有几个不同的进程,我希望他们都登录到同一个文件。这些进程在Windows 7系统上运行。一些是python脚本,另一些是cmd
批处理文件。
在Unix下,你只需让所有人以附加模式打开文件然后写下来。只要每个进程在单个消息中写入的PIPE_BUF
个字节少于write
个字节,就可以保证每个{{1}}调用不会与其他任何进行交错。
有没有办法在Windows下实现这一目标?天真的类Unix方法失败了,因为Windows不喜欢默认情况下一次打开文件的多个进程。
答案 0 :(得分:11)
可以让多个批处理过程安全地写入单个日志文件。我对Python一无所知,但我想这个答案中的概念可以与Python集成。
Windows允许最多一个进程在任何时间点打开特定文件以进行写访问。这可用于实现基于文件的锁定机制,以确保事件在多个进程中被序列化。有关示例,请参阅https://stackoverflow.com/a/9048097/1012053和http://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例程,多个进程的同时写入可能会失败,以便在失败时不会重试。
:log command args...
>>%log% (
echo ***********************************************************
echo Proc %instance%: %date% %time%
%*
)
exit /b
以下是“破解”:log例程
之后的一些示例结果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
答案 1 :(得分:2)
您可以尝试使用此Python模块: http://pypi.python.org/pypi/ConcurrentLogHandler
它提供了RotatingFileHandler
的替换,它允许多个进程同时记录到单个文件而不会丢弃或破坏日志事件。
我没有使用它,但我在阅读Python中的相关错误(Issue 4749)时发现了它。
如果您实现自己的代码而不是使用该模块,请务必阅读该错误!
您可以在Windows上使用output redirection,就像在Bash中一样。将批处理文件的输出通过管道传递到ConcurrentLogHandler
。