2012-02-18 14 views
6

Tengo varios procesos diferentes y me gustaría que todos logren el mismo archivo. Estos procesos se ejecutan en un sistema Windows 7. Algunos son scripts de Python y otros son archivos de proceso por lotes cmd.¿Cómo se han compartido los archivos de registro en Windows?

En Unix, todo el mundo tiene que abrir el archivo en el modo de agregar y escribir. Siempre que cada proceso haya escrito menos de PIPE_BUF bytes en un solo mensaje, se garantizará que cada llamada write no se intercale con ninguna otra.

¿Hay alguna manera de que esto ocurra en Windows? El enfoque ingenuo tipo Unix falla porque a Windows no le gusta que más de un proceso tenga un archivo abierto para escribir a la vez de forma predeterminada.

Respuesta

9

Es posible tener varios procesos por lotes para escribir de forma segura en un único archivo de registro. No sé nada de Python, pero imagino que los conceptos en esta respuesta podrían integrarse con Python.

Windows permite a lo sumo un proceso tener un archivo específico abierto para el acceso de escritura en cualquier momento. Esto se puede usar para implementar un mecanismo de bloqueo basado en archivos que garantiza que los eventos se serialicen en múltiples procesos. Ver https://stackoverflow.com/a/9048097/1012053 y http://www.dostips.com/forum/viewtopic.php?p=12454 para algunos ejemplos.

Dado que todo lo que intenta hacer es escribir en un registro, puede usar el archivo de registro como el candado. La operación de registro está encapsulada en una subrutina que intenta abrir el archivo de registro en modo de adición. Si el abierto falla, la rutina regresa e intenta nuevamente. Una vez que la apertura es exitosa, el registro se escribe y luego se cierra, y la rutina regresa a la persona que llama. La rutina ejecuta cualquier comando que se le pase, y todo lo escrito en stdout dentro de la rutina se redirige al registro.

Aquí hay una secuencia de comandos de proceso por lotes de prueba que crea 5 procesos secundarios que cada uno escribe en el archivo de registro 20 veces. Las escrituras están intercaladas de forma segura.

@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 

Aquí está la salida que demuestra que los 20 escrituras tuvieron éxito para cada proceso

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 

Puede abrir el archivo resultante "myLog.log" para ver cómo se han intercalado con seguridad las escrituras. Pero la salida es demasiado grande para publicar aquí.

Es fácil demostrar que las escrituras simultáneas de múltiples procesos pueden fallar modificando la rutina de registro para que no vuelva a intentarse al producirse un error.

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

Éstos son algunos resultados de la muestra después de "romper" el: registro de rutina

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

Cuando abre un archivo en Windows (con CreateFile) puede elegir si otros procesos pueden leer y/o escribir en el mismo archivo, el segundo proceso tiene que especificar indicadores de compartir compatibles ... – Anders

+0

Lo suficiente. En general, estaba hablando sobre cómo funciona el lote de Windows con la redirección, no hay ninguna opción de la que tenga conocimiento. Múltiples procesos pueden leer, incluso mientras un proceso está escribiendo. (No estoy seguro si eso siempre es seguro). Pero nunca más de un proceso abierto para escritura. – dbenham

+0

@dbenham: Muchas gracias por esto. En realidad resuelve otro gran problema que tengo. También puede resolver mi problema de registro. ¿Está documentada la sintaxis '>> file (commands)' en cualquier lugar? – Omnifarious

2

le puede dar este módulo Python intentarlo: http://pypi.python.org/pypi/ConcurrentLogHandler

Proporciona una gota en el reemplazo del RotatingFileHandler que permite que múltiples procesos para conectarse simultáneamente a un único archivo sin que se caiga o clobbering eventos de registro.

No lo he usado, pero me enteré al leer un error relacionado (Issue 4749) en Python.

Si implementa su propio código para hacerlo en lugar de usar ese módulo, ¡asegúrese de leer el error!

Puede usar output redirection en Windows como lo hace en Bash. Transmita la salida de los archivos de proceso por lotes a un script de Python que se conecte a través del ConcurrentLogHandler.

+0

Eso parece útil. Sin embargo, no estoy seguro de cómo manejar el registro del archivo por lotes. En este momento solo tengo que escribir en un archivo diferente. – Omnifarious

+0

@Omnifarious Creo que debería ser capaz de manipular algo usando [redirección de salida] (http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr = verdadero). '|' funciona en Windows como lo hace en Bash. –

Cuestiones relacionadas