timeout or close when process is finished

2019-03-01 12:11发布

问题:

I have a X.exe program that takes about 2-6 hours to finish. Exact time is unknown, but I'd like to implement a threshold of 6.5 or 7 hours. If this program does not return any value by this amount of time, it will be killed. How do I implement this using batch *.bat files?

Here is what I had so far: a timer bat1.bat and an actual bat2.bat.

bat1.bat:

start cmd /C bat2.bat & timeout /t 25200 & taskkill /im X.exe /f

bat2.bat:

cd blah
bat1.bat

The problem with this approach is that only after 25200 seconds (or 7 hours) the timer will be stopped, and it won't be terminated before that limit. How do I tell the computer that if the program X.exe is finished then don't wait anymore?

Any help is appreciated!

回答1:

I think this is a much simpler solution:

rem Start the process that will kill the X.exe program after 7 hours
start "WaitingToKill" cmd /C timeout /t 25200 ^& taskkill /im X.exe /f

rem Run the X.exe program and wait for it to terminate
X.exe

rem Kill the killer process and terminate
taskkill /fi "WINDOWTITLE eq WaitingToKill" /f

In this method there is not any additional code running at same time; just the waiting state of timeout command.

EDIT: Some explanations added

Note that both the "WaitingToKill" cmd.exe process with the timeout command and the X.exe program are running in parallel. If the timeout command ends after 7 hours, the taskkill /im X.exe /f command is executed, the X.exe program is killed and both cmd.exe processes ends.

If the X.exe program ends before the 7 hours, the Batch file execute the next line as usual. This line is taskkill /fi "WINDOWTITLE eq WaitingToKill" /f, so the window with the timeout command is killed and both cmd.exe processes ends.



回答2:

thanks to @Squashman i was able to build a script on my own. seem to work fine

@echo off
setlocal enableextensions enabledelayedexpansion
set /a "checktime=60"
set /a "elapsedtime=0"
set /a "killtime=150"
set XProg=X.exe
start cmd /C runTest.bat 
timeout /t 10
:while1
    echo Go to WHILE loop.
    echo elapsedtime = %elapsedtime% 
    echo killtime = %killtime%
    set /a "timeleft = %killtime% - %elapsedtime%"
    echo timeleft = %timeleft%
    if /i %timeleft% geq 0 (
        tasklist /fi "imagename eq %XProg%" 2>NUL | find /i /n "%XProg%">NUL
        if "%ERRORLEVEL%"=="0" (
            echo %XProg% is still running...
        ) else (
            echo %XProg% is finished before timer.
        )
        set /a "elapsedtime = elapsedtime + checktime"
        timeout /t %checktime%
        goto :while1
    ) else (
        taskkill /im %XProg% /f
        echo %XProg% is terminated.
    )

lessons learned: 1. hard to compare numeric variables in batch (compare diff with 0 instead) 2. terminated first time elaspedtime > killtime (might be a bit longer than killtime depending how often it checks)



回答3:

I've tried various solutions but in the end this is really cumbersome in batch. If you are willing to use an external tool the simplest way is

"C:\Program Files\Git\usr\bin\timeout.exe" 5 .\test.exe

It properly returns the exit code of the test process, also works if you spawn multiple test processes simultaneously and does not pop up windows all the time.