Как у вас есть общие файлы журналов под Windows?
У меня есть несколько разных процессов, и я хотел бы, чтобы они все записывали в один файл. Эти процессы выполняются в системе Windows 7. Некоторые из них являются сценариями Python, а другие cmd
командные файлы.
В Unix вы бы просто открыли файл в режиме добавления и записали его. Пока каждый процесс написал меньше, чем PIPE_BUF
байтов в одном сообщении, каждый write
вызов будет гарантированно не перемежаться с любым другим.
Есть ли способ сделать это под Windows? Наивный Unix-подобный подход терпит неудачу, потому что Windows не нравится больше чем одному процессу, имеющему файл, открытый для записи за один раз по умолчанию.
2 ответа
Можно иметь несколько пакетных процессов для безопасной записи в один файл журнала. Я ничего не знаю о Python, но я думаю, что концепции в этом ответе могут быть интегрированы с Python.
Windows позволяет не более одного процесса иметь определенный файл, открытый для доступа на запись в любой момент времени. Это может быть использовано для реализации механизма блокировки на основе файлов, который гарантирует сериализацию событий между несколькими процессами. См. /questions/25664458/tsikl-batch-for-ne-obnovlyaet-fajl-iz-kotorogo-izvlekaetsya/25664470#25664470 и http://www.dostips.com/forum/viewtopic.php?p=12454 для некоторых примеров.
Поскольку все, что вы пытаетесь сделать, это записывать в журнал, вы можете использовать сам файл журнала в качестве блокировки. Операция журнала инкапсулируется в подпрограмму, которая пытается открыть файл журнала в режиме добавления. Если открытие не удается, процедура возвращается назад и пытается снова. После успешного открытия журнал записывается, а затем закрывается, и процедура возвращается к вызывающей стороне. Подпрограмма выполняет любую команду, переданную ей, и все, что записано на стандартный вывод в подпрограмме, перенаправляется в журнал.
Вот тестовый пакетный скрипт, который создает 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
Вы можете попробовать этот модуль Python: http://pypi.python.org/pypi/ConcurrentLogHandler
Это обеспечивает замену RotatingFileHandler
что позволяет нескольким процессам одновременно регистрироваться в одном файле, не удаляя и не блокируя события журнала.
Я не использовал его, но узнал об этом во время чтения связанной ошибки ( выпуск 4749) в Python.
Если вы реализуете свой собственный код, чтобы сделать это вместо того, чтобы использовать этот модуль, обязательно прочитайте об ошибке!
Вы можете использовать перенаправление вывода в Windows, как в Bash. Передайте выходные данные пакетных файлов в скрипт Python, который регистрирует через ConcurrentLogHandler
,