【问题标题】:timeout or close when process is finished进程完成时超时或关闭
【发布时间】:2017-10-21 00:27:10
【问题描述】:

我有一个X.exe 程序,大约需要 2-6 小时才能完成。确切时间未知,但我想实施 6.5 或 7 小时的阈值。如果这个程序在这段时间内没有返回任何值,它将被杀死。如何使用批处理 *.bat 文件实现此功能?

这是我目前所拥有的:一个计时器bat1.bat 和一个实际的bat2.bat。

bat1.bat:

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

bat2.bat:

cd blah
bat1.bat

这种方法的问题在于,只有在 25200 秒(或 7 小时)之后,计时器才会停止,并且不会在该限制之前终止。我如何告诉计算机如果程序X.exe 完成了就不要再等待了?

感谢任何帮助!

【问题讨论】:

  • 如果您将 x.exe 设置为作为计划任务运行,您可以告诉它在 8 小时后停止任务。不幸的是,您在任务调度程序中的唯一选择是 1、2、4、8 或 12 小时。您可以做的是使用TASKLIST 命令检查程序是否每 300 秒运行一次。如果它没有运行,那么 bat 文件可以退出。如果它仍在运行,请检查到目前为止已经运行了多少秒,如果是 25,200 秒,则终止它。
  • @Squashman 感谢您的想法和命令。我有一个简单的脚本tasklist /fi "imagename eq X.exe",但是你如何返回X.exe 已经运行的时间量?你能提供一个正式的答案,以便我也可以接受吗?谢谢!!!
  • 设置三个变量。 %checktime% %elapsedtime% 和 %killtime%。将 %checktime% 变量与 TIMEOUT 命令一起使用。然后使用TASKLIST 命令查看进程是否正在运行。如果它正在运行,则将 %checktime% 添加到 %elapsedtime%。然后检查 %elapsedtime% 是否大于或等于 %killtime%。如果没有满足终止时间条件,请使用GOTO 命令循环回到TIMEOUT 命令之前的标签。如果满足终止时间条件,则使用TASKKILL 命令停止该进程。
  • @Squashman 非常感谢,我想我根据您的上述评论想通了。祝你有美好的一天!

标签: windows batch-file timeout batch-processing kill


【解决方案1】:

我认为这是一个更简单的解决方案:

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

在这个方法中没有任何额外的代码同时运行;只是timeout命令的等待状态。

编辑:添加了一些解释

请注意,带有timeout 命令的“WaitingToKill”cmd.exe 进程和X.exe 程序是并行运行的。如果timeout命令在7小时后结束,则执行taskkill /im X.exe /f命令,杀死X.exe程序,两个cmd.exe进程结束。

如果X.exe 程序在 7 小时前结束,批处理文件照常执行下一行。这一行是taskkill /fi "WINDOWTITLE eq WaitingToKill" /f,所以带有timeout命令的窗口被杀死,两个cmd.exe进程都结束了。

【讨论】:

  • 感谢您的回答,但这就是提出问题的原因:X.exe 有时会在计时器之前完成,因此我想定期检查程序是否仍在运行。您提出的答案与我以前的解决方案几乎相同。我是不是在哪里弄错了?
  • 你不需要定期检查任何东西:两个进程都必须在另一个进程结束时结束,所以只需要等待一个进程结束并在那个时候杀死另一个进程。查看我的编辑...
  • 更清楚一点:什么时候杀死X.exe程序?当timeout 命令结束时。什么时候杀死timeout 命令?当X.exe 程序结束时(除非我误解了你的要求:/)...
  • 所以?这个简单得多的解决方案是否正常工作?
  • +1。好主意!但是taskkill /fi "WINDOWTITLE eq WaitingToKill" /f 不会杀死timeout.exe,因为它没有Window Title。我可以建议您将其替换为taskkill /im cmd.exe /fi "WINDOWTITLE eq WaitingToKill" /f /t。另外我有一个想法来扩展您的解决方案,如果您不介意,我可以将其作为替代答案发布为 Killer 进程没有单独的窗口。
【解决方案2】:

感谢@Squashman,我能够自己构建脚本。似乎工作正常

@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.
    )

经验教训: 1. 难以批量比较数值变量(将 diff 与 0 进行比较) 2. 第一次终止elaspedtime > killtime(可能比killtime长一点,取决于它检查的频率)

【讨论】:

    【解决方案3】:

    我尝试了各种解决方案,但最终批量处理确实很麻烦。 如果您愿意使用外部工具,最简单的方法是

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

    它正确地返回测试进程的退出代码,如果你同时产生多个测试进程并且不会一直弹出窗口,它也可以工作。

    【讨论】:

      猜你喜欢
      • 2011-10-08
      • 1970-01-01
      • 2020-09-08
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多