Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

batch - is there a way to synchronize-lock txt file in batch?

I need to create a batch file that trace out using tracert command some ip, and write the trace to txt files. I want it to be fast so I want to start for each trace a new command to make all the trace request start at once.

there is my ping.bat:

@echo off
set saveUnrechableLocation=..\pingUnreachableInfo\pingUnrechableInfoDB.txt
set IpListLocation=..\ipInfo\all_DB_ip.txt
set reachableLocation=..\pingRechableInfo\RechableIp\pingRechableInfoDB.txt
set trace=..\pingRechableInfo\tracert\tracertDB.txt
set numberOfPings=1
@echo pinging DB > %saveUnrechableLocation%
copy /y NUL %reachableLocation% > NUL
copy /y NUL %trace% > NUL
for /F "tokens=*" %%A in (%IpListLocation%) do (
    ping -n %numberOfPings% %%A | find "TTL=" >nul 
    if errorlevel %numberOfPings% (
        @echo %%A not rechable >> %saveUnrechableLocation%
    ) 
    if not errorlevel %numberOfPings% (
    @echo %%A >> %reachableLocation%
    start trace.bat %trace% %%A
    )
)

and the trace.bat look like that:

@echo off
set saveLocation=%~1
set ip=%~2
tracert %ip% >> %saveLocation%
exit

the problem is that when I'm trying to use this I'm getting this problem:

the process cannot access the file because it is being used by another process

what can I do to resolve this problem? thanks!

like image 730
Moshe9362 Avatar asked Apr 01 '16 21:04

Moshe9362


1 Answers

Windows redirection does not allow multiple processes to have the same file open for write access at the same time. The write operations must be serialized. This can be done with batch processing, as demonstrated at https://stackoverflow.com/a/9344547/1012053. However, I don't think that solution will help in your case.

Each tracert process takes considerable time, and the output must be redirected the entire time. But you want multiple processes running at the same time, all output redirected to the same file. Even if you were to make it work, the output would be interleaved, and you wouldn't be able to figure out what it all means.

I recommend redirecting each tracert output to a unique file. You could incorporate the ip address into the output file name, you could use the technique I showed to merge the files after each process completes.

Note there is no need to pass the output location. Each child process has access to the trace variable, so it can easily redirect to the correct location.

outline of ping.bat changes

...
set trace=..\pingRechableInfo\tracert\tracertDB
...
start trace.bat %%A
...

modified trace.bat

@echo off
tracert %1 >%trace%_%1.txt  %= Redirect TRACERT to unique temp file =%
:merge
2>nul (  %= Hide error messages inside the outer parentheses =%
  >>%trace%.txt (  %= Attempt stdout redirection - Fails if already locked =%
    type %trace%_%1.txt  %= Write the temp file to the merge file =%
    (call )  %= Clear any error that TYPE may have generated =%
  )
) || goto :merge  %= Loop back and try again if stdout redirection failed =%
del %trace%_%1.txt  %= Delete the temporary file =%
exit

A shortened form without comments could look like:

@echo off
tracert %1 >%trace%_%1.txt
:merge
2>nul (>>%trace%.txt (type %trace%_%1.txt&(call )))||goto :merge
del %trace%_%1.txt
exit
like image 83
dbenham Avatar answered Sep 25 '22 16:09

dbenham