How to ping an ip and get only the ms on MS-DOS - dos

I can normally type
ping 8.8.8.8 -n 1
and i see output:
Pinging 8.8.8.8 with 32 bytes of data:
Reply from 8.8.8.8: bytes=32 time=84ms TTL=46
Ping statistics for 8.8.8.8:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 84ms, Maximum = 84ms, Average = 84ms
Is there anyway that I can see only 84 as output?

Here is one way:
#echo off
for /f "tokens=2 delims=mu= " %%a in ('ping 8.8.8.8 -n 1 ^|find "mum"') do echo %%a

Related

How to batch multiple commands such that exactly two are being executed at all times [duplicate]

Is there a tool available to execute several process in parallel in a Windows batch file? I have found some interesting tools for Linux (parallel and PPSS), however, I would need a tool for Windows platforms.
Bonus: It would be great if the tool also allowed to distribute processes in an easy way among several machines, running the processes remotely a la PsExec.
Example: I would like that in the following for loop
for %F in (*.*) do processFile.exe %F
a limited amount of instances of processFile.exe are running in parallel to take advantage of multi-core CPUs.
Edit - I modified the script to optionally display the output of each process
Here is a native batch solution that reliably runs a list of commands in parallel, never launching more than n processes at a time.
It even has a mechanism built in to distribute the processes to specific CPUs or remote machines via PSEXEC, but I haven't tested that feature.
The trick to make this work is to START each command through a CMD process that redirects either stdout or an undefined handle to a lock file. The process will maintain an exclusive lock on the file until it terminates. It doesn't matter how the process terminates (normal exit, crash, killed process), the lock will be released as soon as it does.
The master script can test if the process is still active by attempting to redirect to the same lock file. The redirection will fail if the process is still active, succeed if it has terminated.
By default, the script ignores the output of each process. If started with the /O option as the 1st parameter, then it displays the output of each process, without interleaving.
My demo sets the process limit to 4, and simply runs a series of PING commands of varying length.
I've tested this on XP, Vista, and Windows 7.
#echo off
setlocal enableDelayedExpansion
:: Display the output of each process if the /O option is used
:: else ignore the output of each process
if /i "%~1" equ "/O" (
set "lockHandle=1"
set "showOutput=1"
) else (
set "lockHandle=1^>nul 9"
set "showOutput="
)
:: The list of commands could come from anywhere such as another file
:: or the output of another command. For this demo I will list the
:: commands within this script - Each command is prefixed with :::
::: ping /n 05 ::1
::: ping /n 20 ::1
::: ping /n 10 ::1
::: ping /n 15 ::1
::: ping /n 07 ::1
::: ping /n 05 ::1
::: ping /n 20 ::1
::: ping /n 10 ::1
::: ping /n 15 ::1
::: ping /n 07 ::1
:: Define the maximum number of parallel processes to run.
:: Each process number can optionally be assigned to a particular server
:: and/or cpu via psexec specs (untested).
set "maxProc=4"
:: Optional - Define CPU targets in terms of PSEXEC specs
:: (everything but the command)
::
:: If a CPU is not defined for a proc, then it will be run on the local machine.
:: I haven't tested this feature, but it seems like it should work.
::
:: set cpu1=psexec \\server1 ...
:: set cpu2=psexec \\server1 ...
:: set cpu3=psexec \\server2 ...
:: etc.
:: For this demo force all CPU specs to undefined (local machine)
for /l %%N in (1 1 %maxProc%) do set "cpu%%N="
:: Get a unique base lock name for this particular instantiation.
:: Incorporate a timestamp from WMIC if possible, but don't fail if
:: WMIC not available. Also incorporate a random number.
set "lock="
for /f "skip=1 delims=-+ " %%T in ('2^>nul wmic os get localdatetime') do (
set "lock=%%T"
goto :break
)
:break
set "lock=%temp%\lock%lock%_%random%_"
:: Initialize the counters
set /a "startCount=0, endCount=0"
:: Clear any existing end flags
for /l %%N in (1 1 %maxProc%) do set "endProc%%N="
:: Launch the commands in a loop
:: Modify the IN () clause as needed to retrieve the list of commands
set launch=1
for /f "tokens=* delims=:" %%A in ('findstr /b ":::" "%~f0"') do (
if !startCount! lss %maxProc% (
set /a "startCount+=1, nextProc=startCount"
) else (
call :wait
)
set cmd!nextProc!=%%A
if defined showOutput echo -------------------------------------------------------------------------------
echo !time! - proc!nextProc!: starting %%A
2>nul del %lock%!nextProc!
%= Redirect the lock handle to the lock file. The CMD process will =%
%= maintain an exclusive lock on the lock file until the process ends. =%
start /b "" cmd /c %lockHandle%^>"%lock%!nextProc!" 2^>^&1 !cpu%%N! %%A
)
set "launch="
:wait
:: Wait for procs to finish in a loop
:: If still launching then return as soon as a proc ends
:: else wait for all procs to finish
:: redirect stderr to null to suppress any error message if redirection
:: within the loop fails.
for /l %%N in (1 1 %startCount%) do 2>nul (
%= Redirect an unused file handle to the lock file. If the process is =%
%= still running then redirection will fail and the IF body will not run =%
if not defined endProc%%N if exist "%lock%%%N" 9>>"%lock%%%N" (
%= Made it inside the IF body so the process must have finished =%
if defined showOutput echo ===============================================================================
echo !time! - proc%%N: finished !cmd%%N!
if defined showOutput type "%lock%%%N"
if defined launch (
set nextProc=%%N
exit /b
)
set /a "endCount+=1, endProc%%N=1"
)
)
if %endCount% lss %startCount% (
1>nul 2>nul ping /n 2 ::1
goto :wait
)
2>nul del %lock%*
if defined showOutput echo ===============================================================================
echo Thats all folks^^!
Here is output from a sample run that ignores process output
12:24:07.52 - proc1: starting ping /n 05 ::1
12:24:07.52 - proc2: starting ping /n 20 ::1
12:24:07.53 - proc3: starting ping /n 10 ::1
12:24:07.54 - proc4: starting ping /n 15 ::1
12:24:11.60 - proc1: finished ping /n 05 ::1
12:24:11.60 - proc1: starting ping /n 07 ::1
12:24:16.66 - proc3: finished ping /n 10 ::1
12:24:16.66 - proc3: starting ping /n 05 ::1
12:24:17.68 - proc1: finished ping /n 07 ::1
12:24:17.68 - proc1: starting ping /n 20 ::1
12:24:20.72 - proc3: finished ping /n 05 ::1
12:24:20.72 - proc3: starting ping /n 10 ::1
12:24:21.75 - proc4: finished ping /n 15 ::1
12:24:21.75 - proc4: starting ping /n 15 ::1
12:24:26.82 - proc2: finished ping /n 20 ::1
12:24:26.82 - proc2: starting ping /n 07 ::1
12:24:29.86 - proc3: finished ping /n 10 ::1
12:24:32.89 - proc2: finished ping /n 07 ::1
12:24:35.92 - proc4: finished ping /n 15 ::1
12:24:36.93 - proc1: finished ping /n 20 ::1
Thats all folks!
Here is the output if run with the /O option showing process output
-------------------------------------------------------------------------------
12:24:51.02 - proc1: starting ping /n 05 ::1
-------------------------------------------------------------------------------
12:24:51.02 - proc2: starting ping /n 20 ::1
-------------------------------------------------------------------------------
12:24:51.03 - proc3: starting ping /n 10 ::1
-------------------------------------------------------------------------------
12:24:51.04 - proc4: starting ping /n 15 ::1
===============================================================================
12:24:55.10 - proc1: finished ping /n 05 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:24:55.10 - proc1: starting ping /n 07 ::1
===============================================================================
12:25:00.17 - proc3: finished ping /n 10 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:00.19 - proc3: starting ping /n 05 ::1
===============================================================================
12:25:01.22 - proc1: finished ping /n 07 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 7, Received = 7, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:01.23 - proc1: starting ping /n 20 ::1
===============================================================================
12:25:04.27 - proc3: finished ping /n 05 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:04.28 - proc3: starting ping /n 10 ::1
===============================================================================
12:25:05.30 - proc4: finished ping /n 15 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 15, Received = 15, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:05.32 - proc4: starting ping /n 15 ::1
===============================================================================
12:25:10.38 - proc2: finished ping /n 20 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 20, Received = 20, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:10.40 - proc2: starting ping /n 07 ::1
===============================================================================
12:25:13.44 - proc3: finished ping /n 10 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:16.48 - proc2: finished ping /n 07 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 7, Received = 7, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:19.52 - proc4: finished ping /n 15 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 15, Received = 15, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:20.54 - proc1: finished ping /n 20 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 20, Received = 20, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
Thats all folks!
Try start:
start "title of the process" "P:\ath\to.exe"
It opens a new window with the given title and executes the BAT, CMD or EXE file. You can also set the priority, set the same environment etc.
Files being not executeable are opened with the associated program.
Further reading: Start -> Run
cmd /k start /?
Start is available at least since WinME.
Good luck!
Sounds more like you want to use Powershell 2. However, you can spawn new cmd windows (or other processes) by using start, see also this answer. Although you probably have to use some other tools and a little trickery to create something like a "process pool" (to have only a maximum of n instances running at a time). You could achieve the latter by using tasklist /im and counting how many are already there (for loop or wc, if applicable) and simply wait (ping -n 2 ::1 >nul 2>&1) and re-check again whether you can spawn a new process.
I have cobbled together a little test batch for this:
#echo off
for /l %%i in (1,1,20) do call :loop %%i
goto :eof
:loop
call :checkinstances
if %INSTANCES% LSS 5 (
rem just a dummy program that waits instead of doing useful stuff
rem but suffices for now
echo Starting processing instance for %1
start /min wait.exe 5 sec
goto :eof
)
rem wait a second, can be adjusted with -w (-n 2 because the first ping returns immediately;
rem otherwise just use an address that's unused and -n 1)
echo Waiting for instances to close ...
ping -n 2 ::1 >nul 2>&1
rem jump back to see whether we can spawn a new process now
goto loop
goto :eof
:checkinstances
rem this could probably be done better. But INSTANCES should contain the number of running instances afterwards.
for /f "usebackq" %%t in (`tasklist /fo csv /fi "imagename eq wait.exe"^|find /c /v ""`) do set INSTANCES=%%t
goto :eof
It spawns a maximum of four new processes that execute in parallel and minimized. Wait time needs to be adjusted probably, depending on how much each process does and how long it is running. You probably also need to adjust the process name for which tasklist is looking if you're doing something else.
There is no way to properly count the processes that are spawned by this batch, though. One way would be to create a random number at the start of the batch (%RANDOM%) and create a helper batch that does the processing (or spawns the processing program) but which can set its window title to a parameter:
#echo off
title %1
"%2" "%3"
This would be a simple batch that sets its title to the first parameter and then runs the second parameter with the third as argument. You can then filter in tasklist by selecting only processes with the specified window title (tasklist /fi "windowtitle eq ..."). This should work fairly reliable and prevents too many false positives. Searching for cmd.exe would be a bad idea if you still have some instances running, as that limits your pool of worker processes.
You can use %NUMBER_OF_PROCESSORS% to create a sensible default of how many instances to spawn.
You can also easily adapt this to use psexec to spawn the processes remotely (but wouldn't be very viable as you have to have admin privileges on the other machine as well as provide the password in the batch). You would have to use process names for filtering then, though.
There is a basic Windows xargs-like-clone which does support the -P parallel processing option at http://www.pirosa.co.uk/demo/wxargs/wxargs.html
GNU xargs under Linux has a "-P n" switch to launch "n" processes in parallel.
Maybe cygwin/mingw build of xargs also supports this?
Then you can use:
xargs -P 4 processFile < fileList
No fancy multi-node process spawning, though.
I wrote a library which provides multithreading support (in a way that "emulates" the behavior of thread-pools)
MultiBat on github
Here is the inline version of that library but I'd suggest going to the link above for the latest version (and a version that doesn't require being inlined into your bat file.
REM ---------------------------------------------------------------------------
REM ---------------------------------------------------------------------------
REM ---------------------------------------------------------------------------
goto:EOF
REM Append this to the END of your batch-file [*.BAT] to get inline "Multi" support
REM "Multi" is a thread-pool emulation helper library for controlling multi-threaded windows batch [*.BAT] files
REM Copyright (c) 2020 Adisak Pochanayon
REM Contact: adisak#gmail.com
REM See Multi_License.txt for details
REM -----------------------------------
:Multi_Setup
call :Multi_SetName %1
if "%2"=="" (
if "%NUMBER_OF_PROCESSORS%"=="" call :Multi_SetLimitToMax
) else (
call :Multi_SetLimit %2
)
goto:EOF
REM -----------------------------------
:Multi_SetName
REM Returns: MULTI_CHILDPROC_WINNAME - name to use for child processes (the window title)
if "%1"=="" (
SET MULTI_CHILDPROC_WINNAME=Multi-CmdProc
) else (
SET MULTI_CHILDPROC_WINNAME=Multi-CmdProc-%1
)
goto:EOF
REM -----------------------------------
REM To Enable Hyperthreading, call Multi_SetHyperThread before calling Multi_Setup or Multi_SetLimitToMax
:Multi_SetHyperThread
REM Parameter 1: (optional)
REM value=1 (or unspecified) - Use Hyperthreading if available
REM value=0 (or other) - Do not use Hyperthreading to compute the max threads
REM Returns: NumberOfCores - number of real CPU cores
REM Returns: MULTI_HAS_HYPERTHREADING - 1 if the CPU has Hyperthreading
REM Returns: MULTI_USE_HYPERTHREADING - 1 if "Multi" should use Hyperthreading
REM Set variable NumberOfCores
if "%NumberOfCores%"=="" (
for /f "tokens=*" %%f in ('wmic cpu get NumberOfCores /value ^| find "="') do set %%f
)
REM Set variable MULTI_HAS_HYPERTHREADING
if "%MULTI_HAS_HYPERTHREADING%"=="" (
if "%NumberOfCores%"=="%NUMBER_OF_PROCESSORS%" (
REM Non-Hyperthreading
SET MULTI_HAS_HYPERTHREADING=0
) else (
REM Hyperthreading
SET MULTI_HAS_HYPERTHREADING=1
)
}
if "%1"=="" (
SET MULTI_USE_HYPERTHREADING=%MULTI_HAS_HYPERTHREADING%
) else (
SET MULTI_USE_HYPERTHREADING=%1
)
REM Set the max threads to the limit (respecting Hyperthreading options)
call :Multi_SetLimitToMax
goto:EOF
REM -----------------------------------
:Multi_SetLimit
REM Parameter 1:
REM value=N - Use N as the number of max threads
REM unspecified - Compute the default number of max threads
REM Returns: MULTI_MAXCHILDREN - the maximum number of child processes to run simultaneously
if "%1"=="" (
if "%MULTI_MAXCHILDREN%"=="" call :Multi_SetLimitToMax
goto:EOF
)
SET /A MULTI_MAXCHILDREN=%1
if %MULTI_MAXCHILDREN% LSS 1 SET MULTI_MAXCHILDREN=1
goto:EOF
REM -----------------------------------
:Multi_SetLimitToMax
REM Parameter 1: (optional)
REM Passed to Multi_SetHyperThread if present
REM Returns: MULTI_MAXCHILDREN - max number of "threads" in pool for "Multi"
if "%1"=="" (
REM Check if Hyperthreading support was initialized
if "%NumberOfCores%"=="" (
call :Multi_SetHyperThread 0
REM Multi_SetHyperThread calls back to this subroutine so exit to prevent recursion
goto:EOF
)
) else (
call :Multi_SetHyperThread %1
REM Multi_SetHyperThread calls back to this subroutine so exit to prevent recursion
goto:EOF
)
if %NUMBER_OF_PROCESSORS% LEQ 3 (
SET MULTI_MAXCHILDREN=1
) else (
if "%NumberOfCores%"=="%NUMBER_OF_PROCESSORS%" (
REM Non-Hyperthreading
SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%-2
) else if "%MULTI_USE_HYPERTHREADING%"=="1" (
REM Hyperthreading available and used
SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%/2 - 1
) else (
REM Hyperthreading available but not used
SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%-2
)
)
goto:EOF
REM -----------------------------------
:Multi_RunWin
if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName
call :Multi_WaitChildrenMax
start "%MULTI_CHILDPROC_WINNAME%" /BELOWNORMAL cmd /c %*
goto:EOF
REM -----------------------------------
:Multi_RunWinMin
if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName
call :Multi_WaitChildrenMax
start "%MULTI_CHILDPROC_WINNAME%" /MIN /BELOWNORMAL cmd /c %*
goto:EOF
REM -----------------------------------
:Multi_RunSyncMin
REM Use this command to run things that mess with the window title
REM and otherwise would screw up the "Multi" System
start "Multi-Sync" /MIN /WAIT cmd /c %*
goto:EOF
REM -----------------------------------
:Multi_WaitChildrenMax
REM Wait until less than MULTI_MAXCHILDREN children are running
if "%MULTI_MAXCHILDREN%"=="" call :Multi_SetLimitToMax
call :Multi_WaitChildren %MULTI_MAXCHILDREN%
goto:EOF
REM -----------------------------------
:Multi_WaitChildren
SETLOCAL
REM multi_WAITCOUNT is a local variable
SET multi_WAITCOUNT=1
if "%1"=="" GOTO :loop_WaitChildren
SET /A multi_WAITCOUNT=%1
if %multi_WAITCOUNT% LSS 1 set multi_WAITCOUNT=1
:loop_WaitChildren
call :Multi_GetNumChildren
if %MULTI_NUM_CHILDREN% LSS %multi_WAITCOUNT% GOTO :exit_WaitChildren
timeout /t 1 /nobreak > nul
GOTO :loop_WaitChildren
:exit_WaitChildren
ENDLOCAL
goto:EOF
REM -----------------------------------
:Multi_GetNumChildren
REM Returns: MULTI_NUM_CHILDREN - the number of "children" processes (Windows named MULTI_CHILDPROC_WINNAME)
if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName
REM MULTI_NUM_CHILDREN should contain the number of
REM running %MULTI_CHILDPROC_WINNAME% instances after this
for /f "usebackq" %%t in (`tasklist /fo csv /fi "WINDOWTITLE eq %MULTI_CHILDPROC_WINNAME%" ^| find /c "cmd"`) do (
SET MULTI_NUM_CHILDREN=%%t
)
goto:EOF
REM -----------------------------------

Network latency monitoring script windows

I'm trying to write script which will run ping command and from output it will get average latency and % of packet loss values, i tried with below command which works well
`ping -n 8 4.4.4.4 > D:\latency.txt
C:\Users\tnt5273>ping 4.2.2.2
Pinging 4.2.2.2 with 32 bytes of data:
Reply from 4.2.2.2: bytes=32 time=253ms TTL=54
Reply from 4.2.2.2: bytes=32 time=242ms TTL=54
Reply from 4.2.2.2: bytes=32 time=252ms TTL=54
Reply from 4.2.2.2: bytes=32 time=248ms TTL=54
Reply from 4.2.2.2: bytes=32 time=253ms TTL=54
Reply from 4.2.2.2: bytes=32 time=242ms TTL=54
Reply from 4.2.2.2: bytes=32 time=252ms TTL=54
Reply from 4.2.2.2: bytes=32 time=248ms TTL=54
Ping statistics for 4.2.2.2:
Packets: Sent = 8, Received = 8, Lost = 0 (**0% loss**),
Approximate round trip times in milli-seconds:
Minimum = 242ms, Maximum = 253ms, Average = **248ms** `
However challenge here is i want to somehow grab just numerical vales from output(so threshold can be set) and publish them in plain text file as
Loss value in% Average value in ms
0 248
, I'm not sure how to do it in windows, looking for help in VB or windows shell scripting which can help me to achieve my objective
TIA
I would suggest to use Test-Connection instead of ping.exe since it returns an object from which you can get the data you need easily.
Example:
$count= 8
$con = Test-Connection 4.2.2.2 -count $count
$average = ($con.ResponseTime | Measure-Object -Average).Average
$lost = $count-($con.count)
#echo off
setlocal enableextensions disabledelayedexpansion
rem Initialize variables to hold data
set "pct="
set "avg="
rem Run the ping and filter to only read the required lines
rem The first line will contain the loss percentage
rem The second line will contain the average roundtrip
for /f "delims=" %%a in ('
ping -n 8 4.4.4.4 ^| findstr /r /c:"= [0-9]*ms" /c:"([0-9]*%% "
') do if not defined pct (
rem Extract the % loss from the line
for /f "tokens=2 delims=(%%" %%b in ("%%a") do set "pct=%%b"
) else (
rem Retrieve the last element in the line (the average)
for %%b in (%%a) do set "avg=%%b"
)
rem Remove the ms literal from the average
for /f "delims=m" %%a in ("%avg%") do set "avg=%%a"
rem Echo the retrieved values
echo pct=[%pct%]
echo avg=[%avg%]
Maybe a little more code than expected, but in my system (spanish locale) the loss percentage is shown in a separate line and the literals are not the same.
#echo off
for /f "tokens=3 delims=," %%# in ('ping -n 8 173.194.44.131 2^>nul^| findstr /i "loss average"') do (
set "%%#"
)
for /f "tokens=1 delims= " %%a in ("%Average %") do echo average-%%a
for /f "tokens=2 delims=() " %%a in ("%Lost %") do echo loss-%%a
On the last two lines you can change the output - the %%a is the value loss and average are the clarification strings.And you can output the result to a file.

Ping with timestamp on Windows CLI

On the Windows command prompt cmd, I use ping -t to 10.21.11.81
Reply from 10.21.11.81: bytes=32 time=3889ms TTL=238
Reply from 10.21.11.81: bytes=32 time=3738ms TTL=238
Reply from 10.21.11.81: bytes=32 time=3379ms TTL=238
Are there any possibilities to get an output like this?
10:13:29.421875 Reply from 10.21.11.81: bytes=32 time=3889ms TTL=238
10:13:29.468750 Reply from 10.21.11.81: bytes=32 time=3738ms TTL=238
10:13:29.468751 Reply from 10.21.11.81: bytes=32 time=3379ms TTL=238
Please note that I wanna achieve this with only commands provided by CMD
WindowsPowershell:
option 1
ping.exe -t COMPUTERNAME|Foreach{"{0} - {1}" -f (Get-Date),$_}
option 2
Test-Connection -Count 9999 -ComputerName COMPUTERNAME | Format-Table #{Name='TimeStamp';Expression={Get-Date}},Address,ProtocolAddress,ResponseTime
#echo off
ping -t localhost|find /v ""|cmd /q /v:on /c "for /l %%a in (0) do (set "data="&set /p "data="&if defined data echo(!time! !data!)"
note: code to be used inside a batch file. To use from command line replace %%a with %a
Start the ping, force a correct line buffered output (find /v), and start a cmd process with delayed expansion enabled that will do an infinite loop reading the piped data that will be echoed to console prefixed with the current time.
2015-01-08 edited:
In faster/newer machines/os versions there is a synchronization problem in previous code, making the set /p read a line while the ping command is still writting it and the result are line cuts.
#echo off
ping -t localhost|cmd /q /v /c "(pause&pause)>nul & for /l %%a in () do (set /p "data=" && echo(!time! !data!)&ping -n 2 localhost>nul"
Two aditional pause commands are included at the start of the subshell (only one can be used, but as pause consumes a input character, a CRLF pair is broken and a line with a LF is readed) to wait for input data, and a ping -n 2 localhost is included to wait a second for each read in the inner loop. The result is a more stable behaviour and less CPU usage.
NOTE: The inner ping can be replaced with a pause, but then the first character of each readed line is consumed by the pause and not retrieved by the set /p
You can do this in Bash (e.g. Linux or WSL):
ping 10.0.0.1 | while read line; do echo `date` - $line; done
Although it doesn't give the statistics you usually get when you hit ^C at the end.
Batch script:
#echo off
set /p host=host Address:
set logfile=Log_%host%.log
echo Target Host = %host% >%logfile%
for /f "tokens=*" %%A in ('ping %host% -n 1 ') do (echo %%A>>%logfile% && GOTO Ping)
:Ping
for /f "tokens=* skip=2" %%A in ('ping %host% -n 1 ') do (
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2% %%A>>%logfile%
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2% %%A
timeout 1 >NUL
GOTO Ping)
This script will ask for which host to ping.
Ping output is output to screen and log file.
Example log file output:
Target Host = www.nu.nl
Pinging nu-nl.gslb.sanomaservices.nl [62.69.166.210] with 32 bytes of data:
24-Aug-2015 13:17:42 Reply from 62.69.166.210: bytes=32 time=1ms TTL=250
24-Aug-2015 13:17:43 Reply from 62.69.166.210: bytes=32 time=1ms TTL=250
24-Aug-2015 13:17:44 Reply from 62.69.166.210: bytes=32 time=1ms TTL=250
Log file is named LOG_[hostname].log and written to same folder as the script.
This might help someone : [Needs to be run in Windows PowerShell]
ping.exe -t 10.227.23.241 |Foreach{"{0} - {1}" -f (Get-Date),$_} >> Ping_IP.txt
-- Check for the Ping_IP.txt file at the current directory or user home path.
The above command gives you output in a file like the below ;
9/14/2018 8:58:48 AM - Pinging 10.227.23.241 with 32 bytes of data:
9/14/2018 8:58:48 AM - Reply from 10.227.23.241: bytes=32 time=29ms TTL=117
9/14/2018 8:58:49 AM - Reply from 10.227.23.241: bytes=32 time=29ms TTL=117
9/14/2018 8:58:50 AM - Reply from 10.227.23.241: bytes=32 time=28ms TTL=117
9/14/2018 8:58:51 AM - Reply from 10.227.23.241: bytes=32 time=27ms TTL=117
9/14/2018 8:58:52 AM - Reply from 10.227.23.241: bytes=32 time=28ms TTL=117
9/14/2018 8:58:53 AM - Reply from 10.227.23.241: bytes=32 time=27ms TTL=117
9/14/2018 8:58:54 AM - Reply from 10.227.23.241: bytes=32 time=28ms TTL=117
Good Luck !!!
On Windows
You can use one of the other answers.
On Unix/Linux
while :;do ping -n -w1 -W1 -c1 10.21.11.81| grep -E "rtt|100%"| sed -e "s/^/`date` /g"; sleep 1; done
Or as function pingt for your ~/.bashrc:
pingt() {
while :;do ping -n -w1 -W1 -c1 $1| grep -E "rtt|100%"| sed -e "s/^/`date` /g"; sleep 1; done
}
source: https://stackoverflow.com/a/26666549/1069083
This might fit the bill for later Windows versions:
for /l %i in (1,0,2) do #echo|cmd /v:on /c set /p=!time! & ping -n 1 10.21.11.81 | findstr "Reply timed" && timeout /t 2 > nul:
I think my code its what everyone need:
ping -w 5000 -t -l 4000 -4 localhost|cmd /q /v /c "(pause&pause)>nul &for /l %a in () do (for /f "delims=*" %a in ('powershell get-date -format "{ddd dd-MMM-yyyy HH:mm:ss}"') do (set datax=%a) && set /p "data=" && echo([!datax!] - !data!)&ping -n 2 localhost>nul"
to display:
[Fri 09-Feb-2018 11:55:03] - Pinging localhost [127.0.0.1] with 4000 bytes of data:
[Fri 09-Feb-2018 11:55:05] - Reply from 127.0.0.1: bytes=4000 time<1ms TTL=128
[Fri 09-Feb-2018 11:55:08] - Reply from 127.0.0.1: bytes=4000 time<1ms TTL=128
[Fri 09-Feb-2018 11:55:11] - Reply from 127.0.0.1: bytes=4000 time<1ms TTL=128
[Fri 09-Feb-2018 11:55:13] - Reply from 127.0.0.1: bytes=4000 time<1ms TTL=128
note: code to be used inside a command line, and you must have powershell preinstalled on os.
Try this:
Create a batch file with the following:
echo off
cd\
:start
echo %time% >> c:\somedirectory\pinghostname.txt
ping pinghostname >> c:\somedirectory\pinghostname.txt
goto start
You can add your own options to the ping command based on your requirements. This doesn't put the time stamp on the same line as the ping, but it still gets you the info you need.
An even better way is to use fping, go here http://www.kwakkelflap.com/fping.html to download it.
Use
ping -D 8.8.8.8
From the man page
-D Print timestamp (unix time + microseconds as in gettimeofday) before each line
Output
[1593014142.306704] 64 bytes from 8.8.8.8: icmp_seq=2 ttl=120 time=13.7 ms
[1593014143.307690] 64 bytes from 8.8.8.8: icmp_seq=3 ttl=120 time=13.8 ms
[1593014144.310229] 64 bytes from 8.8.8.8: icmp_seq=4 ttl=120 time=14.3 ms
[1593014145.311144] 64 bytes from 8.8.8.8: icmp_seq=5 ttl=120 time=14.2 ms
[1593014146.312641] 64 bytes from 8.8.8.8: icmp_seq=6 ttl=120 time=14.8 ms
I also need this to monitor the network issue for my database mirroring time out issue. I use the command code as below:
ping -t Google.com|cmd /q /v /c "(pause&pause)>nul & for /l %a in () do (set /p "data=" && echo(!date! !time! !data!)&ping -n 2 Google.com>nul" >C:\pingtest.txt
You just need to modify Google.com to your server name. It works perfectly for me. and remember to stop this when you finished. The pingtest.txt file will increase by 4.5 KB per min (around).
Thank for raymond.cc. https://www.raymond.cc/blog/timestamp-ping-with-hrping/
Try this instead:
ping -c2 -s16 sntdn | awk '{print NR " | " strftime("%Y-%m-%d_%H:%M:%S") " | " $0 }'
Check if it suits you
ping -t wwww.google.com|cmd /q /v /c “(pause&pause)>nul & for /l %a in () do (set /p “data=” && echo(!date! !time! !data!)&ping -n 2 wwww.google.com>nul”
Another powershell method (I only wanted failures)
$ping = new-object System.Net.NetworkInformation.Ping
$target="192.168.0.1"
Write-Host "$(Get-Date -format 's') Start ping to $target"
while($true){
$reply = $ping.send($target)
if ($reply.status -eq "Success"){
# ignore success
Start-Sleep -Seconds 1
}
else{
Write-Host "$(Get-Date -format 's') Destination unreachable" $target
}
}
An enhancement to MC ND's answer for Windows.
I needed a script to run in WinPE, so I did the following:
#echo off
SET TARGET=192.168.1.1
IF "%~1" NEQ "" SET TARGET=%~1
ping -t %TARGET%|cmd /q /v /c "(pause&pause)>nul & for /l %%a in () do (set /p "data=" && echo(!time! !data!)&ping -n 2 localhost >nul"
This can be hardcoded to a particular IP Address (192.168.1.1 in my example) or take a passed parameter.
And as in MC ND's answer, repeats the ping about every 1 second.
Simple 😎:
#echo off
set hostName=www.stackoverflow.com
set logfile=C:\Users\Dell\Desktop\PING_LOG\NetworkLog\Log_%hostName%.text
echo Network Loging Running %hostName%...
echo Ping Log %hostName% >>%logfile%
:Ping
for /f "tokens=* skip=2" %%A in ('ping %hostName% -n 1 ') do (
echo %date% %time:~0,2%:%time:~3,2%:%time:~6,2% %%A>>%logfile%
timeout 1 >NUL
GOTO Ping)
Instead of having the additional ping -n 2 localhost at the end of the loop, you can just add the character R before !data! since the only possibilities are Reply or Request. The first character is consumed from the pause>nul. So instead of having the following expression:
ping localhost -t -l 4|cmd /q /v /c "(pause&pause)>nul & for /l %%a in () do (set /p data=&echo(!date! !time! !data!)&ping -n 2 localhost>nul"
You can use this expression:
ping localhost -t -l 4|cmd /q /v /c "(pause&pause)>nul & for /l %%a in () do (set /p data=&echo(!date! !time! R!data!)&pause>nul"
Which produces the same output eg.:
22:34:49.49 Reply from 172.217.4.46: bytes=4 time=14ms TTL=116
22:34:50.49 Reply from 172.217.4.46: bytes=4 time=14ms TTL=116
22:34:55.47 Request timed out.
22:34:56.49 Reply from 172.217.4.46: bytes=4 time=14ms TTL=116
22:34:57.49 Reply from 172.217.4.46: bytes=4 time=14ms TTL=116

CMD Findstr with ping

I am writting a batch file that pings a website, for example:
Pinging youtube.com [173.194.70.91] with 32 bytes of data:
Reply from 173.194.70.91: bytes=32 time=187ms TTL=44
Ping statistics for 173.194.70.91:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 187ms, Maximum = 187ms, Average = 187ms
and my program must copy just the IP address and save it into a text file.
So it pings into a text file
ping youtube.com >> file.txt
Now I use the findstr command to find the IP address. And that's fine if I use this:
ping youtube.com -n 1 >nul >>C:\Users\Adrian\Desktop\IP.txt
findstr /i "Reply from 173.194.70.93: bytes=32 time=188ms TTL=43 C:\IP.txt
IF %ERRORLEVEL% EQU 0 (
echo You are winning
) else (
echo You are losing
)
pause
Now it says I'm winning and thats a good thing but my program must find the IP address without knowing it. So the findstr command must know to get the IP address in between here...
"Reply from 173.194.70.91: bytes=32 time=187ms TTL=44"
so it must findstr the IP from that string. But I have been Googling and found nothing.
Try this:
#echo off &setlocal
for /f "tokens=2delims=[]" %%i in ('ping -n 1 youtube.com^|find "["') do set "ip=%%i"
echo.%ip%>>file.txt
endlocal
If PowerShell is acceptable then you could try:
[System.Net.Dns]::GetHostAddresses("youtube.com") | foreach {echo $_.IPAddressToString }

Parallel execution of shell processes

Is there a tool available to execute several process in parallel in a Windows batch file? I have found some interesting tools for Linux (parallel and PPSS), however, I would need a tool for Windows platforms.
Bonus: It would be great if the tool also allowed to distribute processes in an easy way among several machines, running the processes remotely a la PsExec.
Example: I would like that in the following for loop
for %F in (*.*) do processFile.exe %F
a limited amount of instances of processFile.exe are running in parallel to take advantage of multi-core CPUs.
Edit - I modified the script to optionally display the output of each process
Here is a native batch solution that reliably runs a list of commands in parallel, never launching more than n processes at a time.
It even has a mechanism built in to distribute the processes to specific CPUs or remote machines via PSEXEC, but I haven't tested that feature.
The trick to make this work is to START each command through a CMD process that redirects either stdout or an undefined handle to a lock file. The process will maintain an exclusive lock on the file until it terminates. It doesn't matter how the process terminates (normal exit, crash, killed process), the lock will be released as soon as it does.
The master script can test if the process is still active by attempting to redirect to the same lock file. The redirection will fail if the process is still active, succeed if it has terminated.
By default, the script ignores the output of each process. If started with the /O option as the 1st parameter, then it displays the output of each process, without interleaving.
My demo sets the process limit to 4, and simply runs a series of PING commands of varying length.
I've tested this on XP, Vista, and Windows 7.
#echo off
setlocal enableDelayedExpansion
:: Display the output of each process if the /O option is used
:: else ignore the output of each process
if /i "%~1" equ "/O" (
set "lockHandle=1"
set "showOutput=1"
) else (
set "lockHandle=1^>nul 9"
set "showOutput="
)
:: The list of commands could come from anywhere such as another file
:: or the output of another command. For this demo I will list the
:: commands within this script - Each command is prefixed with :::
::: ping /n 05 ::1
::: ping /n 20 ::1
::: ping /n 10 ::1
::: ping /n 15 ::1
::: ping /n 07 ::1
::: ping /n 05 ::1
::: ping /n 20 ::1
::: ping /n 10 ::1
::: ping /n 15 ::1
::: ping /n 07 ::1
:: Define the maximum number of parallel processes to run.
:: Each process number can optionally be assigned to a particular server
:: and/or cpu via psexec specs (untested).
set "maxProc=4"
:: Optional - Define CPU targets in terms of PSEXEC specs
:: (everything but the command)
::
:: If a CPU is not defined for a proc, then it will be run on the local machine.
:: I haven't tested this feature, but it seems like it should work.
::
:: set cpu1=psexec \\server1 ...
:: set cpu2=psexec \\server1 ...
:: set cpu3=psexec \\server2 ...
:: etc.
:: For this demo force all CPU specs to undefined (local machine)
for /l %%N in (1 1 %maxProc%) do set "cpu%%N="
:: Get a unique base lock name for this particular instantiation.
:: Incorporate a timestamp from WMIC if possible, but don't fail if
:: WMIC not available. Also incorporate a random number.
set "lock="
for /f "skip=1 delims=-+ " %%T in ('2^>nul wmic os get localdatetime') do (
set "lock=%%T"
goto :break
)
:break
set "lock=%temp%\lock%lock%_%random%_"
:: Initialize the counters
set /a "startCount=0, endCount=0"
:: Clear any existing end flags
for /l %%N in (1 1 %maxProc%) do set "endProc%%N="
:: Launch the commands in a loop
:: Modify the IN () clause as needed to retrieve the list of commands
set launch=1
for /f "tokens=* delims=:" %%A in ('findstr /b ":::" "%~f0"') do (
if !startCount! lss %maxProc% (
set /a "startCount+=1, nextProc=startCount"
) else (
call :wait
)
set cmd!nextProc!=%%A
if defined showOutput echo -------------------------------------------------------------------------------
echo !time! - proc!nextProc!: starting %%A
2>nul del %lock%!nextProc!
%= Redirect the lock handle to the lock file. The CMD process will =%
%= maintain an exclusive lock on the lock file until the process ends. =%
start /b "" cmd /c %lockHandle%^>"%lock%!nextProc!" 2^>^&1 !cpu%%N! %%A
)
set "launch="
:wait
:: Wait for procs to finish in a loop
:: If still launching then return as soon as a proc ends
:: else wait for all procs to finish
:: redirect stderr to null to suppress any error message if redirection
:: within the loop fails.
for /l %%N in (1 1 %startCount%) do 2>nul (
%= Redirect an unused file handle to the lock file. If the process is =%
%= still running then redirection will fail and the IF body will not run =%
if not defined endProc%%N if exist "%lock%%%N" 9>>"%lock%%%N" (
%= Made it inside the IF body so the process must have finished =%
if defined showOutput echo ===============================================================================
echo !time! - proc%%N: finished !cmd%%N!
if defined showOutput type "%lock%%%N"
if defined launch (
set nextProc=%%N
exit /b
)
set /a "endCount+=1, endProc%%N=1"
)
)
if %endCount% lss %startCount% (
1>nul 2>nul ping /n 2 ::1
goto :wait
)
2>nul del %lock%*
if defined showOutput echo ===============================================================================
echo Thats all folks^^!
Here is output from a sample run that ignores process output
12:24:07.52 - proc1: starting ping /n 05 ::1
12:24:07.52 - proc2: starting ping /n 20 ::1
12:24:07.53 - proc3: starting ping /n 10 ::1
12:24:07.54 - proc4: starting ping /n 15 ::1
12:24:11.60 - proc1: finished ping /n 05 ::1
12:24:11.60 - proc1: starting ping /n 07 ::1
12:24:16.66 - proc3: finished ping /n 10 ::1
12:24:16.66 - proc3: starting ping /n 05 ::1
12:24:17.68 - proc1: finished ping /n 07 ::1
12:24:17.68 - proc1: starting ping /n 20 ::1
12:24:20.72 - proc3: finished ping /n 05 ::1
12:24:20.72 - proc3: starting ping /n 10 ::1
12:24:21.75 - proc4: finished ping /n 15 ::1
12:24:21.75 - proc4: starting ping /n 15 ::1
12:24:26.82 - proc2: finished ping /n 20 ::1
12:24:26.82 - proc2: starting ping /n 07 ::1
12:24:29.86 - proc3: finished ping /n 10 ::1
12:24:32.89 - proc2: finished ping /n 07 ::1
12:24:35.92 - proc4: finished ping /n 15 ::1
12:24:36.93 - proc1: finished ping /n 20 ::1
Thats all folks!
Here is the output if run with the /O option showing process output
-------------------------------------------------------------------------------
12:24:51.02 - proc1: starting ping /n 05 ::1
-------------------------------------------------------------------------------
12:24:51.02 - proc2: starting ping /n 20 ::1
-------------------------------------------------------------------------------
12:24:51.03 - proc3: starting ping /n 10 ::1
-------------------------------------------------------------------------------
12:24:51.04 - proc4: starting ping /n 15 ::1
===============================================================================
12:24:55.10 - proc1: finished ping /n 05 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:24:55.10 - proc1: starting ping /n 07 ::1
===============================================================================
12:25:00.17 - proc3: finished ping /n 10 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:00.19 - proc3: starting ping /n 05 ::1
===============================================================================
12:25:01.22 - proc1: finished ping /n 07 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 7, Received = 7, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:01.23 - proc1: starting ping /n 20 ::1
===============================================================================
12:25:04.27 - proc3: finished ping /n 05 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:04.28 - proc3: starting ping /n 10 ::1
===============================================================================
12:25:05.30 - proc4: finished ping /n 15 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 15, Received = 15, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:05.32 - proc4: starting ping /n 15 ::1
===============================================================================
12:25:10.38 - proc2: finished ping /n 20 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 20, Received = 20, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:10.40 - proc2: starting ping /n 07 ::1
===============================================================================
12:25:13.44 - proc3: finished ping /n 10 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:16.48 - proc2: finished ping /n 07 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 7, Received = 7, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:19.52 - proc4: finished ping /n 15 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 15, Received = 15, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:20.54 - proc1: finished ping /n 20 ::1
Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Ping statistics for ::1:
Packets: Sent = 20, Received = 20, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
Thats all folks!
Try start:
start "title of the process" "P:\ath\to.exe"
It opens a new window with the given title and executes the BAT, CMD or EXE file. You can also set the priority, set the same environment etc.
Files being not executeable are opened with the associated program.
Further reading: Start -> Run
cmd /k start /?
Start is available at least since WinME.
Good luck!
Sounds more like you want to use Powershell 2. However, you can spawn new cmd windows (or other processes) by using start, see also this answer. Although you probably have to use some other tools and a little trickery to create something like a "process pool" (to have only a maximum of n instances running at a time). You could achieve the latter by using tasklist /im and counting how many are already there (for loop or wc, if applicable) and simply wait (ping -n 2 ::1 >nul 2>&1) and re-check again whether you can spawn a new process.
I have cobbled together a little test batch for this:
#echo off
for /l %%i in (1,1,20) do call :loop %%i
goto :eof
:loop
call :checkinstances
if %INSTANCES% LSS 5 (
rem just a dummy program that waits instead of doing useful stuff
rem but suffices for now
echo Starting processing instance for %1
start /min wait.exe 5 sec
goto :eof
)
rem wait a second, can be adjusted with -w (-n 2 because the first ping returns immediately;
rem otherwise just use an address that's unused and -n 1)
echo Waiting for instances to close ...
ping -n 2 ::1 >nul 2>&1
rem jump back to see whether we can spawn a new process now
goto loop
goto :eof
:checkinstances
rem this could probably be done better. But INSTANCES should contain the number of running instances afterwards.
for /f "usebackq" %%t in (`tasklist /fo csv /fi "imagename eq wait.exe"^|find /c /v ""`) do set INSTANCES=%%t
goto :eof
It spawns a maximum of four new processes that execute in parallel and minimized. Wait time needs to be adjusted probably, depending on how much each process does and how long it is running. You probably also need to adjust the process name for which tasklist is looking if you're doing something else.
There is no way to properly count the processes that are spawned by this batch, though. One way would be to create a random number at the start of the batch (%RANDOM%) and create a helper batch that does the processing (or spawns the processing program) but which can set its window title to a parameter:
#echo off
title %1
"%2" "%3"
This would be a simple batch that sets its title to the first parameter and then runs the second parameter with the third as argument. You can then filter in tasklist by selecting only processes with the specified window title (tasklist /fi "windowtitle eq ..."). This should work fairly reliable and prevents too many false positives. Searching for cmd.exe would be a bad idea if you still have some instances running, as that limits your pool of worker processes.
You can use %NUMBER_OF_PROCESSORS% to create a sensible default of how many instances to spawn.
You can also easily adapt this to use psexec to spawn the processes remotely (but wouldn't be very viable as you have to have admin privileges on the other machine as well as provide the password in the batch). You would have to use process names for filtering then, though.
There is a basic Windows xargs-like-clone which does support the -P parallel processing option at http://www.pirosa.co.uk/demo/wxargs/wxargs.html
GNU xargs under Linux has a "-P n" switch to launch "n" processes in parallel.
Maybe cygwin/mingw build of xargs also supports this?
Then you can use:
xargs -P 4 processFile < fileList
No fancy multi-node process spawning, though.
I wrote a library which provides multithreading support (in a way that "emulates" the behavior of thread-pools)
MultiBat on github
Here is the inline version of that library but I'd suggest going to the link above for the latest version (and a version that doesn't require being inlined into your bat file.
REM ---------------------------------------------------------------------------
REM ---------------------------------------------------------------------------
REM ---------------------------------------------------------------------------
goto:EOF
REM Append this to the END of your batch-file [*.BAT] to get inline "Multi" support
REM "Multi" is a thread-pool emulation helper library for controlling multi-threaded windows batch [*.BAT] files
REM Copyright (c) 2020 Adisak Pochanayon
REM Contact: adisak#gmail.com
REM See Multi_License.txt for details
REM -----------------------------------
:Multi_Setup
call :Multi_SetName %1
if "%2"=="" (
if "%NUMBER_OF_PROCESSORS%"=="" call :Multi_SetLimitToMax
) else (
call :Multi_SetLimit %2
)
goto:EOF
REM -----------------------------------
:Multi_SetName
REM Returns: MULTI_CHILDPROC_WINNAME - name to use for child processes (the window title)
if "%1"=="" (
SET MULTI_CHILDPROC_WINNAME=Multi-CmdProc
) else (
SET MULTI_CHILDPROC_WINNAME=Multi-CmdProc-%1
)
goto:EOF
REM -----------------------------------
REM To Enable Hyperthreading, call Multi_SetHyperThread before calling Multi_Setup or Multi_SetLimitToMax
:Multi_SetHyperThread
REM Parameter 1: (optional)
REM value=1 (or unspecified) - Use Hyperthreading if available
REM value=0 (or other) - Do not use Hyperthreading to compute the max threads
REM Returns: NumberOfCores - number of real CPU cores
REM Returns: MULTI_HAS_HYPERTHREADING - 1 if the CPU has Hyperthreading
REM Returns: MULTI_USE_HYPERTHREADING - 1 if "Multi" should use Hyperthreading
REM Set variable NumberOfCores
if "%NumberOfCores%"=="" (
for /f "tokens=*" %%f in ('wmic cpu get NumberOfCores /value ^| find "="') do set %%f
)
REM Set variable MULTI_HAS_HYPERTHREADING
if "%MULTI_HAS_HYPERTHREADING%"=="" (
if "%NumberOfCores%"=="%NUMBER_OF_PROCESSORS%" (
REM Non-Hyperthreading
SET MULTI_HAS_HYPERTHREADING=0
) else (
REM Hyperthreading
SET MULTI_HAS_HYPERTHREADING=1
)
}
if "%1"=="" (
SET MULTI_USE_HYPERTHREADING=%MULTI_HAS_HYPERTHREADING%
) else (
SET MULTI_USE_HYPERTHREADING=%1
)
REM Set the max threads to the limit (respecting Hyperthreading options)
call :Multi_SetLimitToMax
goto:EOF
REM -----------------------------------
:Multi_SetLimit
REM Parameter 1:
REM value=N - Use N as the number of max threads
REM unspecified - Compute the default number of max threads
REM Returns: MULTI_MAXCHILDREN - the maximum number of child processes to run simultaneously
if "%1"=="" (
if "%MULTI_MAXCHILDREN%"=="" call :Multi_SetLimitToMax
goto:EOF
)
SET /A MULTI_MAXCHILDREN=%1
if %MULTI_MAXCHILDREN% LSS 1 SET MULTI_MAXCHILDREN=1
goto:EOF
REM -----------------------------------
:Multi_SetLimitToMax
REM Parameter 1: (optional)
REM Passed to Multi_SetHyperThread if present
REM Returns: MULTI_MAXCHILDREN - max number of "threads" in pool for "Multi"
if "%1"=="" (
REM Check if Hyperthreading support was initialized
if "%NumberOfCores%"=="" (
call :Multi_SetHyperThread 0
REM Multi_SetHyperThread calls back to this subroutine so exit to prevent recursion
goto:EOF
)
) else (
call :Multi_SetHyperThread %1
REM Multi_SetHyperThread calls back to this subroutine so exit to prevent recursion
goto:EOF
)
if %NUMBER_OF_PROCESSORS% LEQ 3 (
SET MULTI_MAXCHILDREN=1
) else (
if "%NumberOfCores%"=="%NUMBER_OF_PROCESSORS%" (
REM Non-Hyperthreading
SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%-2
) else if "%MULTI_USE_HYPERTHREADING%"=="1" (
REM Hyperthreading available and used
SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%/2 - 1
) else (
REM Hyperthreading available but not used
SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%-2
)
)
goto:EOF
REM -----------------------------------
:Multi_RunWin
if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName
call :Multi_WaitChildrenMax
start "%MULTI_CHILDPROC_WINNAME%" /BELOWNORMAL cmd /c %*
goto:EOF
REM -----------------------------------
:Multi_RunWinMin
if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName
call :Multi_WaitChildrenMax
start "%MULTI_CHILDPROC_WINNAME%" /MIN /BELOWNORMAL cmd /c %*
goto:EOF
REM -----------------------------------
:Multi_RunSyncMin
REM Use this command to run things that mess with the window title
REM and otherwise would screw up the "Multi" System
start "Multi-Sync" /MIN /WAIT cmd /c %*
goto:EOF
REM -----------------------------------
:Multi_WaitChildrenMax
REM Wait until less than MULTI_MAXCHILDREN children are running
if "%MULTI_MAXCHILDREN%"=="" call :Multi_SetLimitToMax
call :Multi_WaitChildren %MULTI_MAXCHILDREN%
goto:EOF
REM -----------------------------------
:Multi_WaitChildren
SETLOCAL
REM multi_WAITCOUNT is a local variable
SET multi_WAITCOUNT=1
if "%1"=="" GOTO :loop_WaitChildren
SET /A multi_WAITCOUNT=%1
if %multi_WAITCOUNT% LSS 1 set multi_WAITCOUNT=1
:loop_WaitChildren
call :Multi_GetNumChildren
if %MULTI_NUM_CHILDREN% LSS %multi_WAITCOUNT% GOTO :exit_WaitChildren
timeout /t 1 /nobreak > nul
GOTO :loop_WaitChildren
:exit_WaitChildren
ENDLOCAL
goto:EOF
REM -----------------------------------
:Multi_GetNumChildren
REM Returns: MULTI_NUM_CHILDREN - the number of "children" processes (Windows named MULTI_CHILDPROC_WINNAME)
if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName
REM MULTI_NUM_CHILDREN should contain the number of
REM running %MULTI_CHILDPROC_WINNAME% instances after this
for /f "usebackq" %%t in (`tasklist /fo csv /fi "WINDOWTITLE eq %MULTI_CHILDPROC_WINNAME%" ^| find /c "cmd"`) do (
SET MULTI_NUM_CHILDREN=%%t
)
goto:EOF
REM -----------------------------------

Resources