【问题标题】:batch - is there a way to synchronize-lock txt file in batch?批处理 - 有没有办法批量同步锁定 txt 文件?
【发布时间】:2016-04-01 21:20:38
【问题描述】:

我需要创建一个使用 tracert 命令一些 ip 跟踪的批处理文件,并将跟踪写入 txt 文件。我希望它很快,所以我想为每个跟踪启动一个新命令,以使所有跟踪请求立即启动。

有我的 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
    )
)

trace.bat 看起来像这样:

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

问题是,当我尝试使用它时,我遇到了这个问题:

该进程无法访问该文件,因为它正被另一个进程使用

我可以做些什么来解决这个问题?谢谢!

【问题讨论】:

    标签: file batch-file text cmd synchronization


    【解决方案1】:

    Windows 重定向不允许多个进程同时打开同一个文件以进行写访问。写操作必须是序列化的。这可以通过批处理来完成,如https://stackoverflow.com/a/9344547/1012053 所示。但是,我认为该解决方案对您的情况没有帮助。

    每个 tracert 过程都需要相当长的时间,并且必须始终重定向输出。但是您希望多个进程同时运行,所有输出都重定向到同一个文件。即使你让它工作,输出也会交错,你将无法弄清楚这一切意味着什么。

    我建议将每个 tracert 输出重定向到一个唯一的文件。您可以将 ip 地址合并到输出文件名中,您可以使用我展示的技术在每个过程完成后合并文件。

    注意没有必要传递输出位置。每个子进程都可以访问跟踪变量,因此可以轻松地重定向到正确的位置。

    ping.bat 改动概要

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

    修改后的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
    

    没有 cmets 的缩短形式可能如下所示:

    @echo off
    tracert %1 >%trace%_%1.txt
    :merge
    2>nul (>>%trace%.txt (type %trace%_%1.txt&(call )))||goto :merge
    del %trace%_%1.txt
    exit
    

    【讨论】:

    • 非常感谢您的回答!我不知道我可以像那样访问 trace var。只需 2 个简单的问题: 1. 跟踪器是指跟踪吗?因为我没有创建一个名为 tracer 2 的变量。我对编写批处理有点陌生,这一行在做什么? "2>nul(类型%tracer%_%1.txt >>%tracer%.txt)"
    • @Moshe9362 - 1) 哎呀!是的,我的意思是写“跟踪”变量,而不是跟踪器。 2)查看更新的答案。请注意%= This is a comment =%。我已经修复了一个语法错误错误,以及一个深奥的错误,如果临时文件由于某种原因不存在,可能会导致无限循环。
    • 实际上,它不起作用。它创建像tracertDB_10.0.0.1.txt 这样的文件,但在进程结束后它没有删除它们,它也没有将跟踪复制到 tracertDB.txt 并且没有退出 cmd-tracert 命令。有什么建议吗?
    • @Moshe9362 - 呃 - 是的,第一个带有 cmets 的 trace.bat 应该可以工作,但是第二个缩短的形式缺少右括号。现在都修好了。
    • 仍然存在问题。我试过你的修复,它没有好处。所以我会发布我的固定解决方案。它很相似,但批处理文件对“(”和“)”位置非常敏感。我将在新答案中发布我的修复,只需编辑并将我的小修复发布到您的代码中,我将删除我的答案。这是你的答案,但不同的空间哈哈。非常感谢:)
    【解决方案2】:

    这是基于 dbenham 答案的固定代码:

    @echo off
    tracert %1 >%trace%_%1.txt
    :merge
    2>nul (
        >>%trace%.txt ( 
            type %trace%_%1.txt
                (call )
        )
    ) ||goto :merge 
    del %trace%_%1.txt
    exit
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 2017-10-01
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      相关资源
      最近更新 更多