2012-02-18 19 views
6

Mam kilka różnych procesów i chciałbym, aby wszystkie logowały się do tego samego pliku. Te procesy działają w systemie Windows 7. Niektóre z nich to skrypty Pythona, a inne to pliki wsadowe cmd.W jaki sposób udostępniasz pliki dziennika w systemie Windows?

W systemie Unix każdy powinien otworzyć plik w trybie dołączania i odpisać. Tak długo, jak każdy proces zapisuje mniej niż PIPE_BUF bajtów w pojedynczej wiadomości, każde wywołanie write będzie gwarantowane, aby nie przeplatało się z żadnym innym.

Czy istnieje sposób, aby tak się stało w systemie Windows? Naiwne podejście podobne do Uniksa nie działa, ponieważ system Windows nie lubi więcej niż jednego procesu, który domyślnie ma otwarty plik do zapisu.

Odpowiedz

9

Istnieje możliwość wielokrotnego tworzenia wielu procesów wsadowych w jednym pliku dziennika. Nic nie wiem o Pythonie, ale wyobrażam sobie, że koncepcje w tej odpowiedzi można zintegrować z Pythonem.

System Windows pozwala maksymalnie jednemu procesowi na otwarcie określonego pliku w celu uzyskania dostępu do zapisu w dowolnym momencie. Można to wykorzystać do zaimplementowania mechanizmu blokowania plików, który gwarantuje, że zdarzenia są szeregowane w wielu procesach. Zobacz https://stackoverflow.com/a/9048097/1012053 i http://www.dostips.com/forum/viewtopic.php?p=12454 dla niektórych przykładów.

Ponieważ wszystko, co próbujesz zrobić, to zapisać w dzienniku, możesz użyć samego pliku dziennika jako blokady. Operacja dziennika jest enkapsulowana w podprogramie, który próbuje otworzyć plik dziennika w trybie dołączania. Jeśli procedura się nie powiedzie, procedura powróci do poprzedniej procedury i spróbuje ponownie. Po pomyślnym otwarciu rejestr jest zapisywany, a następnie zamykany, a procedura powraca do wywołującego. Procedura rutynowa wykonuje wszystkie polecenia przekazywane do niej, a wszystko, co zapisano na standardowe wyjście w ramach procedury, jest przekierowywane do dziennika.

Oto skrypt testu wsadowego, który tworzy 5 procesów potomnych, z których każdy zapisuje do pliku dziennika 20 razy. Napisy są bezpiecznie przeplatane.

@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 

Oto wynik, który pokazuje, że wszystkie 20 zapisy były udane dla każdego procesu

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 

Można otworzyć wynikowy plik „myLog.log”, aby zobaczyć, w jaki sposób zapisy zostały bezpiecznie przeplatane. Ale wynik jest zbyt duży, aby opublikować go tutaj.

Łatwo udowodnić, że jednoczesne zapisy z wielu procesów mogą zakończyć się niepowodzeniem, modyfikując procedurę: log tak, aby nie była ponawiana po awarii.

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

Oto przykładowe wyniki po "łamanie" THE: log rutynowe

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

Po otwarciu pliku w systemie Windows (za pomocą CreateFile) można wybrać, czy inne procesy mogą czytać i/lub zapisywać do tego samego pliku, drugi proces musi określić zgodne flagi udziału ... – Anders

+0

Wystarczająco sprawiedliwe. Mówiłem głównie o tym, jak partia Windows działa z przekierowaniem - nie mam tam żadnej opcji. Wiele procesów może czytać, nawet podczas pisania jednego procesu. (Nie jestem pewien, czy to zawsze jest bezpieczne). Ale nigdy więcej niż jeden proces otwarty na zapis. – dbenham

+0

@dbenham: Bardzo dziękuję za to. To rozwiązuje kolejny duży problem, jaki mam. Może to również rozwiązać mój problem z logowaniem. Czy składnia '>> file (commands)' jest udokumentowana w dowolnym miejscu? – Omnifarious

2

Można dać ten moduł Pythona spróbować: http://pypi.python.org/pypi/ConcurrentLogHandler

Zapewnia zastąpienie drop-in, który pozwala wielu RotatingFileHandler procesy jednocześnie zalogować się do pojedynczego pliku bez pomijania lub przebijania zdarzeń.

Nie użyłem go, ale dowiedziałem się o tym podczas czytania na temat powiązanego błędu (Issue 4749) w Pythonie.

Jeśli zaimplementujesz własny kod zamiast tego modułu, koniecznie przeczytaj o błędzie!

Możesz używać output redirection w systemie Windows, tak jak w Bash. Przetwarzaj dane wyjściowe plików wsadowych do skryptu w języku Python, który loguje się przez ConcurrentLogHandler.

+0

To wygląda użyteczne. Nie wiem jednak, jak sobie poradzić z rejestrowaniem pliku wsadowego. Właśnie teraz po prostu zapisuję go w innym pliku. – Omnifarious

+0

@Omnifarious Myślę, że powinieneś być w stanie obsłużyć coś za pomocą [przekierowania wyjścia] (http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr = true). '|' działa na systemie Windows podobnie jak w Bash. –

Powiązane problemy