从事java开发已经有了大半年的时间,一直没有在java里面调用shell脚本,以前在c语言里面用过system、popen或者execl等函数来调用过shell脚本,感觉非常好用,其实java里面也可以调用shell脚本,用两种调用shell脚本的方法。
1.使用ProcessBuilder
ProcessBuilder pb=new ProcessBuilder(cmd);
pb.start();
代码如下:
import java.io.File;
import java.io.IOException;
public class JavaShellUtil1 {
public static void main(String[] args) {
ProcessBuilder builder=new ProcessBuilder("/bin/sh","-c","/home/songjy.sh a b >/home/songjy.log 2>&1");
builder.directory(new File("/home/"));
int runningStatus = 0;
String s = null;
try {
Process pro=builder.start();
System.out.println("the shell script running");
try {
runningStatus=pro.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(runningStatus!=0){
System.out.println("脚本执行失败");
}else{
System.out.println("脚本执行成功");
}
System.out.println("11111111111");
}
}
但是这个两种方法都有个问题,执行诸如
:ps -ef | grep -v grep或者 /home/songjy.sh a b >/home/songjy.log 2>&1"
带有管道或重定向的命令就会出错。我们都知道使用以上两种方法执行命令时,如果带有参数就要把命令分割成数组或者List传入,不然会被当成一个整体执行(会出错,比如执行"ps -e")。对于|,号来说,这样做也不行。对于Linux系统,解决方法就是把整个命令都当成sh的参数传入,用sh来执行命令。
ProcessBuilder builder=new ProcessBuilder("/bin/sh","-c","/home/songjy.sh a b >/home/songjy.log 2>&1");
Windows下把sh换成cmd.exe就行了。
这儿其实还做了另外的一个处理,就是将标准输入和标准出错打印重定向到日志里面,就要就不用用pid.getInputStream 和pid.getErrorStream 去将其读出来了(防止会一直阻塞,java一直等待shell的返回
这个问题估计更加经常遇到。 原因是, shell脚本中有echo或者print输出, 导致缓冲区被用完了! 为了避免这种情况, 一定要把缓冲区读一下, 好处就是,可以对shell的具体运行状态进行log出来)
2.使用Runtime
Runtime.getRuntime().exec(cmd)
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
//http://kongcod