服务器之家

服务器之家 > 正文

调用java.lang.Runtime.exec的正确姿势分享

时间:2022-03-10 00:44     来源/作者:Morpheus丶

 

调用java.lang.Runtime.exec的正确姿势

今天写一个用到编译的程序,遇到了问题。

在调用

?
1
runtime.exec("javac HelloWorld.java");

运行完美,也就是有生成.class。

而到了

?
1
runtime.exec("java HelloWorld >> output.txt");

却怎么也无法重定向输出,连output.txt文件也生成不了。

测试"echo hello >> 1.txt" 也是不可以,甚是头疼,于是乎翻阅资料,这才发现了

一个认识上的误区,就是exec(str)中 不能把str完全看作命令行执行的command。尤其是str中不可包含重定向 ' < ' ' > ' 和管道符' | ' 。

那么,遇到这样的指令怎么办呢?我们接着往下看:

 

两种方法

一种是将指令写到脚本中,在runtime.exec()中调用脚本。这种方法避过了使用exec(),也是一种思路。

还有一种方法,就是调用exec()的重载方法:我们来重点看这种方法:

我们先看一下官方doc[>link<]给我们提供的重载方法:

?
1
2
3
4
5
6
public Process exec(String command) throws IOExecption
public Process exec(String command,String [] envp) throws IOExecption
public Process exec(String command,String [] envp,File dir) throws IOExecption
public Process exec(String[] cmdarray) throws IOExecption
public Process exec(String[] cmdarray,String [] envp) throws IOExecption
public Process exec(String[] cmdarray,String [] envp,File dir) throws IOExecption

翻阅其文档,发现其重载方法4.exec(String []cmdarray) 最简便适合我们,官方说4.exec() 与执行6.exec(cmdarray,null,null) 效果是一样的。那么5.exec.(cmdarray,null)也是一样的咯?

于是乎,我们可以这样写:

?
1
2
3
runtime.exec( new String[]{"/bin/bash", "-c", "java HelloWorld >> output.txt"} );
runtime.exec( new String[]{"/bin/bash", "-c", "java HelloWorld >> output.txt"} ,null );
runtime.exec( new String[]{"/bin/bash", "-c", "java HelloWorld >> output.txt"} ,null,null );

不过要注意,如果使用java /home/path/HelloWorld 时,' / '会被解析成 " . ",从而报出 “错误: 找不到或无法加载主类 .home.path.HelloWorld ”.

所以,无法使用全路径的时候,我们需要更改一下策略,把 路径 改到工作目录dir 中去,比如:

?
1
File dir = new File("/home/path/");

然后用其第6种重载方法,把dir作为第三个参数传入即可:

?
1
2
String []cmdarry ={"/bin/bash", "-c", "java HelloWorld >> output.txt"}
runtime.exec(cmdarry,null.dir);

当然echo , ls 等命令便不受' / '限制了。

*BTW,exec()取得返回值的标准用法详见:runtime.exec()的左膀右臂

 

小结一下

当命令中包含重定向 ' < ' ' > ' 和管道符' | ' 时,exec(String command)方法便不适用了,需要使用exec(String [] cmdArray) 或者exec(String []cmdarray,String []envp,File dir)来执行。

例如:

?
1
2
exec("echo hello >> ouput.txt");
exec("history | grep -i mvn");

应改为:

?
1
2
exec( new String[]{"/bin/sh","-c","echo hello >> ouput.txt"});
exec( new String[]{"/bin/bash","-c","history | grep -i mvn"},null);

 

Java Runtime.exec()注意事项

  • Runtime.exec()用来执行外部程序或命令

 

1.Runtime.exec() 有四种调用方法

?
1
2
3
4
* public Process exec(String command);
* public Process exec(String [] cmdArray);
* public Process exec(String command, String [] envp);
* public Process exec(String [] cmdArray, String [] envp);

 

2.得到程序执行返回值, 0为success

需要用waitFor()函数,比如

?
1
2
3
Process p = Runtime.getRuntime().exec("javac");
(处理.....)
int exitVal = p.waitFor();

 

3.得到程序执行的结果或错误信息

需要用BufferedInputStream 和 BufferReader来得到,否则程序会hang

比如得到错误信息用p.getErrorStream(),然后输出即可:

?
1
2
BufferedInputStream in = new BufferedInputStream(p.getErrorStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));

 

4.Runtime.exec()

不等同于直接执行command line命令

啊,我算是在这里吃了苦头了。Runtime.exec()很有局限性,对有些命令不能直接把command line里的内容当作String参数传给exec().

比如重定向等命令。举个例子:

?
1
javap -l xxx > output.txt

这时要用到exec的第二种重载,即input 参数为String[]:

?
1
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","javap -l xxx > output.txt"});

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/timo1160139211/article/details/75006938

相关文章

热门资讯

2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
暖暖日本高清免费中文 暖暖在线观看免费完整版韩国
暖暖日本高清免费中文 暖暖在线观看免费完整版韩国 2021-05-08
返回顶部