2012-02-18 20 views
6

Ho diversi processi diversi e vorrei che tutti si collegassero allo stesso file. Questi processi sono in esecuzione su un sistema Windows 7. Alcuni sono script Python e altri sono file batch cmd.Come si hanno file di registro condivisi in Windows?

Sotto Unix, tutti dovrebbero aprire il file in modalità append e scrivere via. Fintanto che ogni processo ha scritto meno di PIPE_BUF byte in un singolo messaggio, ogni chiamata write sarebbe garantita per non interlacciare con nessun altro.

C'è un modo per farlo accadere in Windows? L'approccio ingenuo tipo Unix fallisce perché a Windows non piace più di un processo con un file aperto per la scrittura in un momento predefinito.

risposta

9

È possibile che più processi batch scrivano in modo sicuro in un singolo file di registro. Non so nulla di Python, ma immagino che i concetti di questa risposta possano essere integrati con Python.

Windows consente al massimo un processo di aprire un file specifico per l'accesso in scrittura in qualsiasi momento. Questo può essere utilizzato per implementare un meccanismo di blocco basato su file che garantisce che gli eventi siano serializzati su più processi. Vedere https://stackoverflow.com/a/9048097/1012053 e http://www.dostips.com/forum/viewtopic.php?p=12454 per alcuni esempi.

Poiché tutto ciò che si sta tentando di fare è scrivere su un registro, è possibile utilizzare il file di registro stesso come blocco. L'operazione di registro è incapsulata in una subroutine che tenta di aprire il file di registro in modalità append. Se l'open fallisce, la routine torna indietro e ci riprova. Una volta aperto, il log viene scritto e quindi chiuso e la routine ritorna al chiamante. La routine esegue qualunque comando gli venga passato e qualsiasi cosa scritta sullo stdout all'interno della routine viene reindirizzato al log.

Ecco uno script batch di test che crea 5 processi figlio che ciascuno scrive nel file di registro 20 volte. Le scritture sono intercalate in modo sicuro.

@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 

Ecco l'output che dimostra che tutte le 20 operazioni di scrittura hanno avuto successo per ogni processo

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 

È possibile aprire il file risultante "myLog.log" per vedere come le scritture sono state in modo sicuro interlacciati. Ma l'output è troppo grande per postare qui.

È facile dimostrare che le scritture simultanee da più processi possono fallire modificando la routine: log in modo che non torni in errore.

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

Ecco alcuni risultati del campione dopo "rompere" il: log di routine

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

Quando apri un file su Windows (con CreateFile) puoi scegliere se altri processi possono leggere e/o scrivere sullo stesso file, il secondo processo deve specificare flag di condivisione compatibili ... – Anders

+0

Abbastanza corretto. Stavo principalmente parlando di come il batch di Windows funziona con il reindirizzamento - nessuna opzione di cui sono a conoscenza. Più processi possono leggere, anche mentre un processo sta scrivendo. (Non sono sicuro che sia sempre sicuro). Ma mai più di un processo aperto per scrivere. – dbenham

+0

@dbenham: Grazie mille per questo. In realtà risolve un altro grosso problema che ho. Potrebbe anche risolvere il mio problema di registrazione. La sintassi '>> file (comandi)' è documentata ovunque? – Omnifarious

2

si può dare questo modulo Python una prova: http://pypi.python.org/pypi/ConcurrentLogHandler

Esso fornisce un rimpiazzo nel RotatingFileHandler che consente a più processi di accedere contemporaneamente a un singolo file, senza cadute o sovrascrivere eventi del registro.

Non l'ho usato, ma l'ho scoperto leggendo un bug correlato (Issue 4749) in Python.

Se si implementa il proprio codice per farlo invece di utilizzare quel modulo, assicurarsi di aver letto sull'errore!

È possibile utilizzare output redirection su Windows come si fa in Bash. Esegui il pipe dell'output dei file batch su uno script Python che registra attraverso lo ConcurrentLogHandler.

+0

che sembra utile. Non sono sicuro di come gestire la registrazione che il file batch fa però. In questo momento ho appena scritto su un file diverso. – Omnifarious

+0

@Omnifarious Penso che dovresti essere in grado di configurare qualcosa usando [redirezione dell'output] (http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr = true). '|' funziona su Windows molto come fa in Bash. –

Problemi correlati