ProcessBuilder中如何为命令行传参

项目中有个需求是备份数据库,备份数据库很自然的想到使用mysqldump进行转储,那么问题的关键就变成了如何在java中调用mysqldump命令,一搜才知道通过开启一个本地的进程,来执行该命令即可。
Process的产生有两种方式:Runtime.getRuntime.exec(cmd),另一种是通过ProcessBuilder builder,builder.start()。
Process是一个抽象类,只能通过这两种方式来获取一个Process对象。在获取到Process之后,可以通过getInputStream()获取子进程的输出流,注意,子进程没有console,因此,它的stdout\stdin\stderr都被重定向到父进程,也就是java进程中。

Runtime

起初采用Runtime来进行操作,方法如下:
String cmd = “mysqldump.exe -h ” + host + ” -u ” + username + ” -p” + password + ” ” + dbName;
Process process = Runtime.getRuntime().exec(cmd);

这个方法可以正常work,但是我查询JDK,发现官方推荐是使用ProcessBuilder,原因是
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.

其实我并没有太懂。。。。

不过有一点,当执行命令过程中发生错误时怎么办?当然可以使用getErrorStream()来获取错误信息。但是,但是,我懒,,如果能重定向到inputstream就可以了。于是ProcessBuilder来了。

ProcessBuilder

ProcessBulder是一个final类,可以直接实例化,通过为ProcessBuilder传入命令参数,然后start()就可以创建一个满足参数的Process,注意只有在start时才会创建一个新的进程。JDK上说大多数的错误都是在start时产生的。。。
果然,,,
起初,我是这样创建ProcessBuilder builder = new ProcessBuilder(cmd);//cmd为上面的命令行。
然后报错了,说是找不到文件,,,,
在网上找解决方案:http://blog.csdn.net/iaiti/article/details/45268991,上面说要为“指令中有空格的需要用不同的字符串分开。”
然后我写成这个样子

new ProcessBuilder("mysqldump.exe"," ","-h"," ",host," ","-u"," ",root," ","-p",password"," ",dbName);

然后它告诉我说找不到数据库名,然后我就把顺序来回倒,倒来倒去,最后琢磨过来,如果说我是程序设计者,我希望把option和值分开吗?就像”-h”,” “,host一样?这样感觉好傻,我希望做的应该是将这几个东西放在一起,然后对于多个参数的情况,分为多个字符串即可。即

new ProcessBuilder("mysqldump.exe",dbName,"-h"+host,"-u"+username,"-p"+password);

结果果然,再执行就没有错误了。然后通过builder.redirectErrorStream()重定向到错误流就达到我们之前的目的了。

当然,这里直接在命令行里传密码是不大安全的,但是,在Enter password:里面传参数怎么做???请知情者不吝赐教。

waitfor

这里还有一个坑,就是waitfor(),起初我以为waitfor是指阻塞在这样,然后等命令行读取完成之后就恢复运行,结果不是,,,waitfor()等待的是子进程的退出,,,之前程序里面加入了waitfor()直接死在这里了。当然了,加入一个超时时间是可以的。其实在通过process获取inputstream的时候,系统就已经阻塞了。所以,并不懂waitfor()的作用是什么。。

destroy

destroy是另外一个坑,当java中的方法执行完退出时,并不会使得子进程退出,子进程何时会退出完全取决于操作系统,那在这里,我认为子进程命令执行完毕之后,要显式将process.destroy()掉,防止消耗资源,特别是服务器系统而言。

你可能感兴趣的:(java)