ProcessBuilder中如何为命令行传参

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

Runtime

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

这个方法能够正常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.web

其实我并无太懂。。。。sql

不过有一点,当执行命令过程当中发生错误时怎么办?固然可使用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()重定向到错误流就达到咱们以前的目的了。ide

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

waitfor

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

destroy

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