如何在测试完成后杀死在后台运行的phantomjs进程

时间:2015-02-11 22:26:27

标签: java phantomjs integration-testing

在构建服务器上运行phatomjs / java集成测试后,phantomjs进程仍然在后台运行,必须手动终止。

有没有办法在java代码中执行此操作?我已经在测试清理部分使用了driver.quit()。还有其他什么还要包括在内吗?

2 个答案:

答案 0 :(得分:10)

处理这个问题的最简单方法(不一定是正式的方法)是从bash脚本中发出一个终止所有phantomjs进程的kill命令:

ps -ef | grep phantomjs | awk '{print $2}' | xargs sudo kill -9

在终端中运行的上述脚本将终止所有后台幻像,无论你是使用java还是python或ruby启动它们... 一个快速的解决方法,直到实际的bug得到解决,imo。

答案 1 :(得分:0)

这是一个着名的问题,自2012年12月以来一直存在 - UnreachableBrowserException

所以,我做了一些解决方法 - 创建了类,它使用重写方法“execute”扩展了PhantomJSDriver:

@Override
protected Response execute(String driverCommand, Map<String, ?> parameters) {
    int retryAttempt = 0;

    while (true) {
        try {
            return super.execute(driverCommand, parameters);
        } catch (WebDriverException e) {
            retryAttempt++;
            if (retryAttempt > retryCount) {
                throw e;
            }
        }
    }
}

这是有帮助的,但并非总是如此 - 有时phantomjs过程并没有停止工作。所以,我找到了一种通过PID(进程ID)

来终止进程的方法
@Override
protected Response execute(String driverCommand, Map<String, ?> parameters) {
    int retryAttempt = 0;

    while (true) {
        try {
            return super.execute(driverCommand, parameters);
        } catch (WebDriverException e) {
            retryAttempt++;
            if (retryAttempt > retryCount) {
                if(driverCommand.equalsIgnoreCase("quit")) {
                    int port = GetDriverPort();
                    try {
                        int processID = GetPIDByServerPort(port);
                        boolean processExist = processID != -1;
                        if(processExist) {
                            log.info("Killing phantomJS, of process id:" + processID + " that listen to port:" + port);
                            KillPhantomProcess(processID);
                        }
                        return null;
                    } catch (IOException | InterruptedException ignore) {
                        throw e;
                    }
                }

                throw e;
            }
        }
    }
}

private int GetDriverPort(){
    return  ((HttpCommandExecutor)(this).getCommandExecutor()).getAddressOfRemoteServer().getPort();
}

private int GetPIDByServerPort(int port) throws InterruptedException, IOException {
    int pid = -1;
    ProcessBuilder p = new ProcessBuilder("cmd.exe", "/C", "netstat -no | findstr :" + String.valueOf(port));
    p.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);

    Process netstat = p.start();
    netstat.waitFor();
    InputStream inputStream = netstat.getInputStream();

    int bytesRead;
    byte[] bytes = new byte[1024];
    String result = "";
    while ((bytesRead = inputStream.read(bytes)) > -1) {
        result = result + new String(bytes, 0, bytesRead);
    }

    String[] lines = result.split("\\n+");
    for (String line : lines) {
        if(!(line.toUpperCase().contains("ESTABLISHED") && line.contains("127.0.0.1:" + port))) continue;

        String[] str = line.trim().split("\\s+");
        if(str[1].contains(String.valueOf(port))) pid = Integer.parseInt(str[4]);
    }

    return pid;
}

private void KillPhantomProcess(int pid) throws IOException  {
    try {
        Runtime.getRuntime().exec(TASKKILL_COMMAND + pid);
    } catch (IOException e) {
        log.error("Failed to kill phantomJs process. PID: " + pid, e);
        throw e;
    }

    if(pid > 0) log.info("phantomJs process " + pid + " was interrupted");
}

我希望这会有所帮助