【问题标题】:Kill Selenium Browser by PID Process [Java]通过 PID 进程杀死 Selenium 浏览器 [Java]
【发布时间】:2020-01-07 15:32:15
【问题描述】:

Selenium 有时在调用driver.quit() 后无法关闭,当它卡在“与服务器的连接已重置”或只是“停止响应”时。发生这种情况时,不可能直接使用WebDriver杀死进程(浏览器),我能想到的唯一方法是检索浏览器的PID并通过以下方式销毁进程:

String cmd = "taskkill /F /PID " + pidOfBrowser;
Runtime.getRuntime().exec(cmd);

我知道this response 建议检索当前正在运行的进程列表并将其过滤到 Firefox 浏览器。但是,正如有人在其中一个 cmets 中指出的那样,如果用户有许多并发会话正在运行并且只希望杀死少数几个,这将不起作用。

该线程的评论部分建议的另一个解决方案是在开始之前从浏览器获取 PID 列表,并且只关闭在测试开始之前未运行的那些(因此在测试开始之前手动启动的任何浏览器都不会关闭)

但是,这不适用于我的情况,因为我从我的程序(不是手动)一次启动多个浏览器,并且只想关闭一些启动的浏览器(那些挂起且未响应 @987654329 的浏览器@ 了)。

如何获取特定 Firefox WebDriver 会话的 PID(最好是在创建时),以便稍后在进程挂起或“卡住”时终止该进程?

谢谢!

【问题讨论】:

  • 这个来自herefrom selenium import webdriver driver = webdriver.Firefox() print(driver.service.process.pid) 怎么样。关闭时,请确保将窗口置于焦点并使用 driver.close() 作为 driver.quit()` 将关闭所有窗口
  • 我们不清理中间运行...我们等到运行完成然后杀死所有进程(或在运行开始前杀死所有进程)。为什么你需要清理中期运行?
  • @JeffC 我在浏览器之后启动浏览器 - 只要系统检测到内存足够,下一个浏览器就会自动启动,因此启动之间没有延迟。如果我必须等到所有浏览器完成工作才能启动下一组浏览器,它会减慢系统速度。因为每个浏览器可能需要不同的时间来完成工作。这就是为什么我需要在检测到浏览器“卡住”后立即终止浏览器,以便立即启动替换..
  • @user1207289 该线程在 Python 中。我不明白如何用 Java 做到这一点。如果可以在 Java 中获取 Firefox 会话/浏览器的 PID,请作为解决方案发布,我会接受。谢谢!

标签: java windows selenium selenium-webdriver pid


【解决方案1】:

在 Java 9+ 版本中,您可以这样做。取自here

public static void main(String[] args) {
    ProcessHandle.allProcesses()
            .forEach(process -> System.out.println(processDetails(process)));
}

private static String processDetails(ProcessHandle process) {
    return String.format("%8d %8s %10s %26s %-40s",
            process.pid(),
            text(process.parent().map(ProcessHandle::pid)),
            text(process.info().user()),
            text(process.info().startInstant()),
            text(process.info().commandLine()));
}

private static String text(Optional<?> optional) {
    return optional.map(Object::toString).orElse("-");
}

然后像上面那样得到info的过程。 ProcessHandle.Info 类中有一个 totalCpuDuration​() 方法。使用它来查看哪个过程需要很长时间,然后采取相应的行动。该类中还有其他方法可以在您的场景中受益。希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您可以终止使用 Seleniumcapabilities 对象检索 PID 启动的 Browser 实例,然后使用 taskkill /PID 调用 getRuntime(),如下所示:

    • 代码块:

      import java.io.IOException;
      import org.openqa.selenium.Capabilities;
      import org.openqa.selenium.WebDriver;
      import org.openqa.selenium.firefox.FirefoxDriver;
      import org.openqa.selenium.remote.RemoteWebDriver;
      
      public class Kill_Firefox_PID {
      
          public static void main(String[] args) throws IOException {
      
              System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
              WebDriver driver = new FirefoxDriver();
              Capabilities cap = ((RemoteWebDriver) driver).getCapabilities();
              System.out.println("moz:processID value is : "+cap.getCapability("moz:processID"));
              Runtime.getRuntime().exec("taskkill /PID "+cap.getCapability("moz:processID"));
          }
      }
      
    • 控制台输出:

      moz:processID value is : 8492
      

    【讨论】:

    • 赞成。谢谢。今天晚些时候将接受作为最终解决方案。只有一个问题:是否可以在不强制转换为 RemoteWebDriver 的情况下实现这一目标?因为我目前不依赖 RemoteWebDriver,但我想投射到 RemoteWebDriver 不会受到伤害..
    • @S.O.S 是的,可以通过操作系统级别的客户端调用,但相对使用getCapabilities(),事情要简单得多。
    • @DebanjanB 是否可以使用功能获取与驱动程序实例关联的 geckodriver 进程?
    • @AlanCook 是的,这是可能的,但这是一个单独的问题,您可能需要提出新的问题。
    猜你喜欢
    • 2020-03-02
    • 2014-11-24
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 2017-08-04
    • 2014-09-07
    相关资源
    最近更新 更多