并行执行shell命令,但限制了工作(Windows,没有Cygwin)

时间:2018-08-14 05:44:13

标签: windows batch-file cmd parallel-processing gnu-parallel

这就是我想要做的。假设我有一个名为myprogram.exe的程序,我必须执行1000次。

在Windows下,我通常可以做一些简单的事情:

for /L %n in (1,1,1000) do start /myfolder/myprogram.exe

但是,假设我只有5个CPU线程可以投入运行myprogram.exe的1000个实例,因此我仅启动5个,那么当其中一个完成时又启动另一个,依此类推,直到整个1000结束。

在Linux上并使用GNU Parallel,我可以简单地做到:

seq 1000 | parallel -N0 -j5 "nohup myprogram.exe"

如何在Windows命令行中实现类似的功能?请注意,在我的情况下,使用 Cygwin并不是一个选择,因此在Windows下使用xargs和GNU Parallel也不是一个选择。

2 个答案:

答案 0 :(得分:3)

这将并行运行五个进程。每次完成其中一个操作时,都会开始下一个过程(因此,一共有5个操作,直到全部完成)

@ECHO off
setlocal enabledelayedexpansion
set bunch=5

for /l %%a in (1,1,1000) do (
  call :loop 
  echo processing: %%a
  start "MyCommand" cmd /c timeout !random:~-1!
)
call :loop
goto :eof

:loop  REM waits for available slot
for /f %%x in ('tasklist /fi "windowtitle eq MyCommand"  ^| find /c "cmd.exe"') do set x=%%x
if %x% geq %bunch% goto :loop
goto :eof

/min开关添加到start,以最小化启动的进程。
给他们一个唯一的窗口标题(此处为MyCommand),以便能够对其进行计数。
cmd /c timeout !random:~-1!替换为您的实际命令。

编辑:经过稍微修改的脚本,如果myprogram是GUI,则可能会更好地工作(上述脚本在CLI应用程序中会更好地工作):

@ECHO off
setlocal enabledelayedexpansion
set bunch=5

for /l %%a in (1,1,100) do (
  call :loop 
  echo processing: %%a
  start notepad.exe
)
call :loop
goto :eof

:loop  REM waits for available slot
for /f %%x in ('tasklist /fi "imagename eq Notepad.exe"^|find /c "."') do set x=%%x
if %x% geq %bunch% goto :loop
goto :eof

答案 1 :(得分:3)

这是一种使用Powershell进行进程计数的方法。并使用简单的set /a作为计数器。

@echo off
setlocal enabledelayedexpansion
set /a cnt=0
:counter
if !cnt! lss 1000 (
for /F "tokens=*" %%i in ('powershell ^(Get-Process -Name 'myprogram'^).count') do set proc=%%i
             if !proc! lss 5 (
                          start "C:\myfolder\myprogram.exe"
                          set /a cnt+=1
              )
    goto :counter
   )

如果要查看计数,可以在echo !cnt!之前的行中添加goto :counter

无需使用delayedexpansion即可完成操作,但我更喜欢在这里使用。