今天要写个远程重启服务的功能,为了开发速度,暂时定为Java代码+WMIC命令的方法,简单的说,就是利用Java调用本机应用程序的方法。涉及到的Java类有java.lang包里面的Runtime、Process、ProcessBuilder三个类,以及wmic中重启服务的命令。因为之前也写过这方面的东西,所以很习惯性的写出了代码:
创新互联公司网站建设公司是一家服务多年做网站建设策划设计制作的公司,为广大用户提供了网站建设、网站制作,成都网站设计,一元广告,成都做网站选创新互联公司,贴合企业需求,高性价比,满足客户不同层次的需求一站式服务欢迎致电。
- Process p = Runtime.getRuntime().exec("wmic ...");
- BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String tmp = null;
- while ((tmp = br.readline()) != null) {
- System.out.println(tmp);
- }
- int exitValue = p.waitfor();
运行,结果发现程序不能退出,Debug发现程序阻塞在br.readline()中了,强制结束程序,发现重启服务的命令正常下下去了,去掉程序中获得标准输出的地方和获得返回结果的地方,命令也能正常下去,而且正常退出。
为什么程序会阻塞呢?Google了一下,发现了大家的解释,应该也是比较权威的解释吧:每个进程都有自己的标准输入、标准输出、标准错误输出,对于某些依赖于OS的进程,可能其输出缓冲区很小,如果不能及时的读出(标准输出、标注错误输出),将导致进程不能正常退出。我的程序中标准输出已经读了,显然原因不是这个,难道是错误输出缓冲区中的数据没有读出导致的?带着这个疑问,对程序作了一些更改:
- ProcessBuilder pb = new ProcessBuilder("wmic",...);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String tmp = null;
- while ((tmp = br.readline()) != null) {
- System.out.println(tmp);
- }
- int exitValue = p.waitfor();
编译运行,发现还是有问题,依然还是阻塞。又google了一下,大家的评论大多还是关于标准输出和标准错误输出,那这程序应该是没有问题了。后来在cmd中敲入wmic的命令,发现wmic命令敲入以后会进入一个自有的提示符中,难道是因为标准输入的问题。后来又google了一下,验证了我的猜想,果然是因为wmic进程会等待标准输入,而程序中没有处理标准输入的地方,是标准输入阻塞了进程的退出,修改代码:
- ProcessBuilder pb = new ProcessBuilder("wmic",...);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.getOutputStream().close();
- BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String tmp = null;
- while ((tmp = br.readline()) != null) {
- System.out.println(tmp);
- }
- int exitValue = p.waitfor();
编译运行,程序成功执行。果然是标准输入的原因。
后来执行的过程中换了一个服务的名称,发现执行失败(能够正常退出,但是返回的结果是“无效动作”),但是同样的命令,在命令行中执行成功,而且直接适用Runtime.exec()方法中写入整个命令也能够执行成功,难道是ProcessBuilder的错误,ProcessBuilder构造函数有两个:
ProcessBuilder(List
利用指定的操作系统程序和参数构造一个进程生成器。
ProcessBuilder(String... command)
利用指定的操作系统程序和参数构造一个进程生成器。
找到ProcessBuilder的源代码,发现了对List
问题终于全都解决了,耗费了多半天的时间,不过收获总是有的,这里总结一下,在使用Java调用外部命令的时候,一定要注意对标准输出、标准输入和错误输出的处理。对于一般的命令,只需要将标准输出和错误输出合并,一起读出来或者在另外的线程中读出来,而对于一些特殊的命令,还有处理标准输入。建议即使不使用标准输入,先close了,总是不会出错了。另外,使用ProcessBuilder时要注意它的空格处理方式是否是你想要的,如果不是,就不能用ProcessBuilder了,直接使用Runtime.exec()就好了。
原文链接:http://blog.csdn.net/ragic/article/details/5583164
当前名称:Java调用WMIC命令的方法阻塞
链接分享:http://www.mswzjz.cn/qtweb/news7/114207.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能