Java中如何执⾏多条shellbat命令
java调⽤process执⾏命令
public class ShellUtil {
public static String runShell (String shStr) throws Exception {
Process process;
process = Runtime().exec( new String[]{ "/bin/sh" , "-c" ,shStr});
process.waitFor();
BufferedReader read = new BufferedReader( new InputStream()));
String line = null ;
String result = "" ;
while ((line = adLine())!= null ){
result+=line;
}
return result;
}
}
注意:如果是windows操作系统要改为
1.当要执⾏多条时且不依赖事务,可以分开多次调⽤
public class ExecuteShell {
public static void main (String[] args){
String command1 = "some command" ;
String command2 = "some command" ;
String message1 = ShellUtil.runShell(command1);
String message2 = ShellUtil.runShell(command2);
System. out .println(message1);
System. out .println(message2);
}
}
2.但是当命令之间有事务依赖时
⽐如⼀条命令是登录数据库,第⼆条执⾏查询语句,上⾯分开多次调⽤的⽅式就不⾏。需要做改动如下
public class ExecuteShell {
public static void main (String[] args){
String command1 = "some command" ;
String command2 = "some command" ;
String command = command1 + " && " + command2;
String message = ShellUtil.runShell(command);
System. out .println(message);
}
}
Java执⾏shell遇到的各种问题
1、判断⼦进程是否执⾏结束
有的时候我们⽤java调⽤shell之后,之后的操作要在Process⼦进程正常执⾏结束的情况下才可以继续,所以我们需要判断Process进程什么时候终⽌。
Process类提供了waitFor()⽅法。该⽅法导致当前线程等待,直到Process线程终⽌。
Process.waitFor()是有⼀个int类型返回值的,当返回值为0的时候表Process进程正常终⽌。否则⼀般是脚本执⾏出错了(我遇到的⼀般是这种情况)。
2、Process.waitFor()导致当前线程阻塞
有的时候我们发现调⽤waitFor()⽅法后,java主线程会⼀直阻塞在waitFor()处,阻塞的原因是什么呢?
分析⼀下:
Java在执⾏Runtime().exec(jyName)之后,Linux会创建⼀个进程,该进程与JVM进程建⽴三个管道连接,标准输⼊流、标准输出流、标准错误流,假设linux进程不断向标准输出流和标准错误流写数据,⽽JVM却不读取,数据会暂存在linux缓存区,当缓存区存满之后导致该进程⽆法继续写数据,会僵死,导致java进程会卡死在waitFor()处,永远⽆法结束。
解决办法:
java进程在waitFor()前不断读取标准输出流和标准错误流:
//jyName  解压脚本路径
String (0).toString().(0).toString().lastIndexOf(File.separator)+1);
String  jyName="/etc/zxvf.sh "+fileName;
try {
Process p0 = Runtime().exec(jyName);
//读取标准输出流
BufferedReader bufferedReader =new BufferedReader(new InputStream()));
String line;
while ((adLine()) != null) {
System.out.println(line);
}
//读取标准错误流
BufferedReader brError = new BufferedReader(new ErrorStream(), "gb2312"));
String errline = null;
while ((errline = adLine()) != null) {
System.out.println(errline);
}
//waitFor()判断Process进程是否终⽌,通过返回值判断是否正常终⽌。0代表正常终⽌
int c=p0.waitFor();
if(c!=0){
baseRes.put("desc", "软件升级失败:执⾏zxvf.sh异常终⽌");
baseRes.setReturnFlag(false);
return baseRes;
}
} catch (IOException e1) {
baseRes.put("desc", "软件升级失败:⽂件解压失败");
baseRes.setReturnFlag(false);
return baseRes;
} catch (InterruptedException e1) {
baseRes.put("desc", "软件升级失败:⽂件解压失败");
baseRes.setReturnFlag(false);
return baseRes;
}
也可以在执⾏Runtime().exec(jyName)之后另外再启动两个线程分别读取标准错误流和标准输出流
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ExcuteThread extends Thread {
private String name;
public ExcuteThread(String name) {
this.name = name;
}
@Override
public void run() {
try {
Process p = Runtime().exec(name);
InputStream fis = p.getInputStream();
final BufferedReader brError = new BufferedReader(
new ErrorStream(), "gb2312"));
InputStreamReader isr = new InputStreamReader(fis, "gb2312");
final BufferedReader br = new BufferedReader(isr);
Thread t1 = new Thread() {
public void run() {
String line = null;
try {
while ((line = adLine()) != null) {
// System.out.println(line);
}
linux执行shell命令
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (brError != null)
brError.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Thread t2 = new Thread() {
public void run() {
String line = null;
try {
while ((line = br.readLine()) != null) {
// System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
t1.start();
t2.start();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
}
}
}
3、shell脚本中有关联脚本,注意路径
就是shell脚本中还要执⾏其他脚本,这时候就是注意⼀个路径的问题,这个问题也是我了好长时间的⼀个问题。Process Runtime().exec(“/etc/a.sh”)
在Test.java类调⽤了etc⽬录下的a.sh脚本, a.sh脚本中执⾏etc⽬录下的b.sh脚本,原来我在a.sh脚本中写的是./b.sh。其实这样linux是不到b.sh的,因为我们执⾏是在Test.class⽬录下调⽤的/etc/a.sh 所以当a.sh中执⾏./b.sh的时候他会在Test.class⽬录下寻,所以不到,所以a.sh中要写成/etc/b.sh
4、java连续调⽤多个脚本
String[] cmd = { "/bin/sh", "-c", "rm -rf /installation/upgrade/ ; mkdir /installation/upgrade/" };
Process p = Runtime().exec(cmd);
p.waitFor();
就是这种数组的⽅式。
5、java执⾏.sh脚本⽂件的时候直接写⽬录就⾏
例如这样:
java 直接执⾏语句的时候需要加上"/bin/sh" 例如这样:
String name="/bin/sh cd /installation/upgrade/ip89_install_packet";
Process p = Runtime().exec(name);
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。