process.waitFor()卡死和process.exitValue()进程未退出

用Process process = Runtime.getRuntime().exec(cmd);执行mysqldump的还原命令,程序没报错也没抛异常,但还原不生效,将命令粘贴出来到控制台单独执行就能够生效,process.waitFor()会卡死,process.exitValue()报:process has not exited。
不明白为什么业务层执行命令就不生效。
源码:


```java
//Runtime runtime = Runtime.getRuntime();
            // 第一步,获取登录命令语句,指向mysql安装目录 
            String loginCommand = new StringBuffer().append("mysql -u").append(user).append(" -p").append(password).append(" -h").append(ip)
                    .append(" -P").append(port).toString();
            // 第二步,获取切换数据库到目标数据库的命令语句
            String switchCommand = new StringBuffer("use ").append(databaseName).toString();
            // 第三步,获取导入的命令语句
            String importCommand = new StringBuffer("source ").append(savePath + fileName).toString();
            // 需要返回的命令语句数组
            String[] commands = new String[] {loginCommand, switchCommand, importCommand};

            Process process = Runtime.getRuntime().exec(commands[0]);
            //执行了第一条命令以后已经登录到mysql了,所以之后就是利用mysql的命令窗口  
            //进程执行后面的代码  
            OutputStream os = process.getOutputStream();  
            OutputStreamWriter writer = new OutputStreamWriter(os);  
            //命令1和命令2要放在一起执行
            writer.write(commands[1] + "\r\n" + commands[2]);
            writer.flush();
            writer.close();
            os.close();
            System.out.println(process.exitValue());
            process.destroy();

```

你现在应该是执行的异步进程,exitValue报没结束很正常啊,你代码执行那么快,外部进程还没彻底起来你主进程都结束了,主进程结束了被它启动的子进程也跟着结束了,dump就中断了呀
你执行waitFor卡死就对了,还原不要时间吗,只要不是一直卡死就是正常现象
如果你不想程序假死,那应该写个循环,输出进程打印的结果,判断进程结束了再执行destroy(),否则进程被你杀死了肯定不干活了呀

可以尝试:

1、在执行命令之前,可以使用 ProcessBuilder 类来构建执行命令的进程,并设置命令的输出流和错误流的处理方式。这样可以避免命令输出流和错误流没有被正确处理导致的问题。

2、在执行命令之后,可以使用 process.waitFor() 方法等待命令执行完成,同时使用 process.exitValue() 方法来获取命令的退出码,如果退出码不为 0,则表示命令执行失败,可以通过读取命令的输出流和错误流来获取详细的错误信息。

例如:

ProcessBuilder pb = new ProcessBuilder(commands);
pb.redirectErrorStream(true); // 将错误流和输出流合并
Process process = pb.start();
int exitCode = process.waitFor();
if (exitCode == 0)
{
    // 命令执行成功
}
else
{
    // 命令执行失败
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while ((line = reader.readLine()) != null)
    {
        System.out.println(line); // 输出命令的输出信息
    }
}
process.destroy();

您的代码中使用了 Runtime.getRuntime().exec() 方法来执行 MySQL 的还原命令,但是这种方法存在一些局限性,如无法等待命令执行结束,无法获取命令执行的输出等。


我建议您使用另一种方式来执行命令,即使用 ProcessBuilder 类。这个类能够更好地控制命令的执行,例如能够等待命令执行结束,也能够获取命令的输出。


下面是一个例子,展示了如何使用 ProcessBuilder 类来执行 MySQL 的还原命令:

// 构建还原命令
List<String> command = new ArrayList<>();
command.add("mysql");
command.add("-u" + user);
command.add("-p" + password);
command.add("-h" + ip);
command.add("-P" + port);
command.add(databaseName);
command.add("<");
command.add(savePath + fileName);

// 使用 ProcessBuilder 执行命令
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();

// 等待命令执行结束
int exitCode = process.waitFor();
if (exitCode == 0) {
    // 命令执行成功
} else {
    // 命令执行失败
}

注意,在构建命令时,您需要将命令参数拆分成单独的字符串,并将它们添加到命令列表中。这样可以避免在执行命令时出现问题。

提供参考实例【Process.waitFor() 死锁问题了解和解决】,链接:http://t.zoukankan.com/muzhongjiang-p-13390606.html