可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.