令人讨厌的代码块如下。该代码几乎总是可以工作,但有时会永远挂起。该应用程序是一个EJB计时器bean。

实际上,它只挂了一次,我无法复制它。它的工作已经有将近两年没有任何问题。但是,在测试应用程序的更新版本时,计时器仅在运行几天后冻结,而从未从上次运行时释放数据库锁。日志清楚地表明它冻结在下面的代码块中的某个位置。它正在运行的命令是“ chmod”。

public void shellExec(String cmd, File workDir) {
    String s = null;
    try {
        Process p = Runtime.getRuntime().exec(cmd, null, workDir);
        int i = p.waitFor();
        if (i == 0){
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
            // read the output from the command
            while ((s = stdInput.readLine()) != null) {
                logger.debug(s);
            }
        }
        else {
            BufferedReader stdErr = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            // read the output from the command
            while ((s = stdErr.readLine()) != null) {
                logger.debug(s);
            }
        }
    } catch (Exception e) {
        logger.debug(e);
    }
}


我不愿意修改此代码,因为它已经过测试,并且已经正确运行了近两年。我也无法重现该问题,因此我不知道重写的版本是否更好。但是,很明显它可能会挂起,我不知道可能性是多少。

通过搜索问题,似乎该代码块是执行Shell命令的相当标准。该代码是否存在任何已知问题?考虑到我无法重现该问题,是否有人知道确保它会引发异常而不是挂起的好方法?

谢谢。

最佳答案

您需要同时执行stdout / err的使用。否则,您将获得看到的阻止行为。有关更多信息,请参见this answer

10-08 06:17
查看更多