Como evitar erros “em uso por outro processo” ao enviar saída por um programa?

3

Em um ambiente Windows, os programas executáveis que são usados para processar a saída canalizada garantem tarefas únicas se chamadas de diferentes ambientes CMD?

Por exemplo, suponha que o script1.cmd contenha esta linha:

echo "some logging information" | my_pipe_program >> logfile1.txt

Também há script2.cmd que contém esta linha:

echo "some other information" | my_pipe_program >> logfile2.txt

Se script1 e script2 forem executados ao mesmo tempo, o Windows chamará instâncias separadas de my_pipe_program.exe?

Estou recebendo erros esporádicos em que um script de comando falha com o erro "O processo não pode acessar o arquivo porque está sendo usado por outro processo" Esse erro sempre ocorre logo após uma linha que passa por my_pipe_program.exe.
Isso faz com que o script CMD pare nesse ponto, deixando a janela do CMD aberta.

O conflito pode estar em my_pipe_program.exe ou pode ser logfile2.txt. O programa my_pipe_program.exe é usado em vários arquivos CMD, que podem ser executados ao mesmo tempo. O arquivo de log é exclusivo do arquivo CMD, portanto, parece menos provável que seja o culpado, a menos que o Windows falhe ao fechá-lo depois que o arquivo CMD existir. Existe alguma abordagem para diagnosticar o problema e corrigir o erro?

Pergunta relacionada - existe alguma maneira de capturar e manipular o erro "... sendo usado por outro processo" e impedir que o arquivo CMD seja abortado?

    
por tim11g 27.11.2015 / 19:59

1 resposta

1

Parece que o problema pode estar com EXE e como ele é chamado na mesma máquina que está sendo executado simultaneamente na memória, talvez. Ativar o registro em log avançado nesse nível para capturar detalhes detalhados ou rastreamentos de pilha durante a emulação de execuções simultâneas na memória da mesma máquina, assim como quando o problema ocorre, pode ser melhor para a resposta mais precisa POR QUE está fazendo isso.

Veja minha resposta aqui ( SuperUser ) no SuperUser do outro dia como matar um processo com lote se o arquivo CMD ou BAT for COMO um determinado nome.

Você poderia incorporar algo assim para verificar se algo está sendo executado por um determinado período de tempo com esses nomes de arquivo em lote e matar, mas você teria que verificar outras opções em WMIC para ver se há um temporizador, etc., se isso funcionasse no seu caso. Corrigir a lógica EXE nesse nível e capturar o erro e o final pode ser melhor se você controlar nesse nível.

IDÉIAS ADICIONAIS

Uma solução simples pode ser criar um arquivo de bloqueio quando o arquivo CMD em lote é iniciado, para que todos os scripts que iniciem o mesmo EXE da mesma máquina verifiquem primeiro se o arquivo de bloqueio existe e terminem o script (ou talvez pause por tantos minutos e depois verifique novamente, etc.).

Você pode simplesmente terminar o script [ GOTO locked ] ou pausá-lo por tantos segundos, depois ir para a rotina [ GOTO lockedrecheck ] e verificar novamente se o outro processo estiver concluído e excluir o arquivo se isso for suficiente no seu caso.

Se o arquivo de bloqueio não existir, ele criaria o arquivo, depois executaria o processo e, quando terminasse, excluiria o arquivo de bloqueio para que outros processos pudessem ser executados (exemplo abaixo).

Você também pode adicionar o 2<&1 ao final do seu arquivo de log para obter mais detalhes se o EXE permitir que ele seja capturado dessa forma onde não seria diferente (exemplo de lógica de script abaixo).

EXEMPLO DE ARQUIVO DE BLOQUEIO (termine ou pause e verifique novamente)

<ABOVE LOGIC>
<ABOVE LOGIC>
<ABOVE LOGIC>
<ABOVE LOGIC>

:SetLockFile
::SET check for, and create lock file to ensure concurrent runs aren't possible
SET lockfile=\server\share\lockfiles\my_pipe_program.lck
IF EXIST %lockfile% GOTO locked
::IF EXIST %lockfile% GOTO lockedrecheck 
ECHO This file is locked until current %~nx0 script ends or finishes using the EXE >> %lockfile%

ECHO "some logging information" | my_pipe_program >> %logfile% 2<&1

<More Logic>
<More Logic>
<More Logic>
<More Logic>

:end
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> %logfile%
ECHO End: %date% at %time%                       >> %logfile%
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> %logfile%
DEL /Q /F "%lockfile%"
ENDLOCAL
GOTO EOF

:locked
:: Come here to end the script since the lock file does exist
ECHO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>> %logfile%
ECHO LOCKED FILE: %~nx0 - %date% at %time%: FILE IS IN USE AND LOCKED                             >> %logfile%
ECHO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +>> %logfile%
ENDLOCAL
GOTO EOF

:lockedrecheck
:: Come here to Pause the script with a loopback ping to nul for 3 minutes or roughly 180 seconds
PING 127.0.0.1 -n 180 > nul
GOTO :SetLockFile

2<&1 Exemplo

echo "some logging information" | my_pipe_program >> logfile1.txt 2<&1
    
por 28.11.2015 / 08:09