【问题标题】:Execute multiple batch files concurrently and monitor if their process is completed同时执行多个批处理文件并监控其进程是否完成
【发布时间】:2020-08-12 21:04:14
【问题描述】:

我有一个调用多个批处理文件的主批处理文件。我希望能够同时执行所有这些批处理文件。全部完成后,我需要在主批处理文件中进行进一步的处理。

当我使用“开始”调用多个批处理文件时,我可以同时启动所有批处理文件,但我无法跟踪它们。 (主批处理文件认为他们的进程在执行其他批处理文件的那一刻就完成了)。

当我使用“调用”时,我可以监控批处理文件进程,但它会按顺序而不是同时启动批处理文件。

有没有办法解决这个问题?我在这台电脑上的权限有限,我正在尝试仅使用 Batch 来完成此操作。

主批处理文件

call first.bat
call second.bat
call third.bat
:: echo only after all batch process done
echo done!

first.bat

timeout /t 10

second.bat

timeout /t 10

第三个.bat

timeout /t 10

【问题讨论】:

    标签: windows batch-file cmd parallel-processing


    【解决方案1】:

    这是解决这个问题最简单、最有效的方法:

    (
    start first.bat
    start second.bat
    start third.bat
    ) | pause
    
    echo done!
    

    在这个方法中,主文件中的等待状态是事件驱动,所以它不消耗任何CPU时间。当( block ) 中的任何命令输出字符时,pause 命令将终止,但start 命令在此 cmd.exe 中不显示任何输出。这样,pause 会一直等待一个字符,直到所有由start 命令启动的进程结束。此时与( block ) 关联的管道已关闭,因此pause 标准输入已关闭,命令由cmd.exe 终止。

    【讨论】:

    • 很好,我忘记了这个(又一次!)。请注意,这种方法与我的代码存在相同的问题:从继承句柄的批处理文件开始并且在批处理文件结束后仍然运行的任何内容都将保持管道打开并暂停主批处理文件。
    • 不知道我怎么从来没有见过这种技术 - 但我喜欢它!
    • 这也适用于开始 /B 开关吗?你能解释一下这里的理论吗?
    • @BikerDude:见 Eryk Sun 的 cmets 下面this answer
    【解决方案2】:

    这将生成一个临时文件并通过创建对它的重定向来锁定它,在此重定向中启动批处理子进程。当所有子进程结束时,重定向关闭并删除临时文件。

    当子进程运行时,文件被锁定,我们可以尝试重命名文件进行测试。如果我们可以重命名文件,则子进程已经结束,否则一些进程仍在运行。

    @echo off
        setlocal enableextensions disabledelayedexpansion
    
        for %%t in ("%temp%\%~nx0.%random%%random%%random%.tmp") do (
    
            echo Starting subprocesses
            9> "%%~ft" (
                start "" cmd /c subprocess.bat
                start "" cmd /c subprocess.bat
                start "" cmd /c subprocess.bat
                start "" cmd /c subprocess.bat
                start "" cmd /c subprocess.bat
            )
    
            echo Waiting for subprocesses to end
            break | >nul 2>nul (
                for /l %%a in (0) do @(ren "%%~ft" "%%~nxt" && exit || ping -n 2 "")
            )
            echo Done    
    
        ) & del "%%~ft"
    

    注意:在子进程内启动的任何进程也将持有重定向和锁定。如果您的代码让某些东西运行,则无法使用。

    【讨论】:

      【解决方案3】:
      @ECHO Off
      SETLOCAL
      :: set batchnames to run
      SET "batches=first second third"
      :: make a tempdir
      :maketemp
      SET /a tempnum=%random%
      SET "tempdir=%temp%\%tempnum%"
      IF EXIST "%tempdir%*" (GOTO maketemp) ELSE (MD "%tempdir%")
      
      FOR %%a IN (%batches%) DO START "%%a" %%a "%tempdir%\%%a"
      
      :wait
      timeout /t 1 >nul
      FOR %%a IN (%batches%) DO IF exist "%tempdir%\%%a" GOTO wait
      
      RD "%tempdir%" /S /Q
      
      GOTO :EOF
      

      批次的构造方式

      @ECHO OFF
      :: just delay for 5..14 seconds after creating a file "%1", then delete it and exit
      SETLOCAL
      ECHO.>"%~1"
      SET /a timeout=5+(%RANDOM% %% 10)
      timeout /t %timeout% >NUL
      DEL /F /Q "%~1"
      EXIT
      

      即每个被调用的批处理首先在临时目录中创建一个文件,然后在运行所需的进程后将其删除。要创建/删除的文件名作为批处理的第一个参数提供并“引用”,因为temp 目录名通常包含分隔符。

      主线只是创建一个临时目录并调用子过程,然后反复等待 1 秒并检查子过程的标志文件是否已全部删除。只有当它们都被删除时,程序才继续删除临时目录

      【讨论】:

        【解决方案4】:

        Aacini 补充答案。我也在寻找类似的任务。目标是并行运行多个命令并提取所有并行进程的输出(标准输出和错误)。然后等待所有并行进程完成并执行另一个命令。以下是BAT文件的示例代码,可以在CMD中执行:

        (
        start "" /B cmd /c ping localhost -n 6 ^>nul
        timeout /t 5 /nobreak
        start "" /B /D "C:\users\username\Desktop" cmd /c dir ^> dr.txt ^2^>^&^1
        start "" /B cmd /c ping localhost -n 11 ^>nul
        timeout /t 10 /nobreak
        ) | pause
        Echo waited
        timeout /t 12 /nobreak
        

        () 里面的所有语句都先执行,等待它们完成,然后执行最后两行。所有以start 开头的命令同时执行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-01-12
          • 1970-01-01
          • 2011-02-04
          • 2021-11-21
          • 1970-01-01
          • 2021-09-28
          • 2015-05-03
          • 2014-12-17
          相关资源
          最近更新 更多