Execute multiple batch files concurrently and moni

2019-01-15 23:17发布

问题:

I have a main batch file which calls multiple batch files. I want to be able to execute all these batch files at the same time. Once they are all done, I have further processes that needs to carry on in the main match file.

When I use 'Start' to call the multiple batch files, able to kick off all batch files concurrently but I lose tracking them. (Main batch file thinks their processes are done the moment it executes other batch files).

When I use 'Call', able to monitor the batch file process, but it kicks off the batch files sequentially instead of concurrently.

Is there a way around this? Have limited permissions on this PC and trying to accomplish this using Batch only.

Main Batch file

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

third.bat

timeout /t 10

回答1:

This is the simplest and most efficient way to solve this problem:

(
start first.bat
start second.bat
start third.bat
) | pause

echo done!

In this method the waiting state in the main file is event driven, so it does not consume any CPU time. The pause command would terminate when anyone of the commands in the ( block ) outputs a character, but start commands don't show any output in this cmd.exe. In this way, pause keeps waiting for a char until all processes started by start commands ends. At that point the pipe line associated to the ( block ) is closed, so the pause Stdin is closed and the command is terminated by cmd.exe.



回答2:

This will generate a temporary file and lock it by creating a redirection to it, starting the batch subprocesses inside this redirection. When all the subprocesses end the redirection is closed and the temporary file is deleted.

While the subprocesses are running, the file is locked, and we can test this trying to rename the file. If we can rename the file, subprocesses have ended, else some of the processes are still running.

@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"

note: any process started inside the subprocesses will also hold the redirection and the lock. If your code leaves something running, this can not be used.



回答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

Where the batches are constructed like

@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

That is, each called batch first creates a file in the temporary directory, then deletes it after the required process is run. The filename to create/delete is provided as the first parameter to the batch and "quoted" because the temp directoryname typically contains separators.

The mainline simply creates a temporary directory and invokes the subprocedures, then repeatedly waits 1 second and checks whether the subprocedures' flagfile have all been deleted. Only if they have all been deleted with the procedure continue to delete the temporary directory



回答4:

Adding to the answer by Aacini. I was also looking for similar task. Objective was to run multiple commands parallel and extract output (stdout & error) of all parallel processes. Then wait for all parallel processes to finish and execute another command. Following is a sample code for BAT file, can be executed in 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

All the statements inside () are executed first, wait for them to complete, then last two lines are executed. All commands begining with start are executed simultaneously.