Java语言以其跨平台性和简易性而着称,在Java里面的lang包里(java.lang.Runtime)提供了一个允许Java程序与该程序所运
行的环境交互的接口,这就是Runtime类,在Runtime类里提供了获取当前运行环境的接口。
其中的exec函数返回一个执行shell命令的子进程。exec函数的具体实现形式有以下几种:
public Process exec(String command) throws IOException
public Process exec(String command,String[] envp) throws
IOException
public Process exec(String command,String[] envp,File dir) throws
IOException
public Process exec(String[] cmdarray) throws IOException
public Process exec(String[] cmdarray, String[] envp) throws
IOException
public Process exec(String[] cmdarray, String[] envp,File dir)
throws IOException
我们在这里主要用到的是第一个和第四个函数,具体方法很简单,就是在exec函数中传递一个代表命令的字符串。exec函数返回的是一个Process类
型的类的实例。Process类主要用来控制进程,获取进程信息等作用。(具体信息及其用法请参看Java doc)。
1)执行简单的命令的方法:
代码如下:
② 运行在linux下的java程序,调用了命令行,如何让java线程等待命令行结束再执行
Process prc = runtime.exec(.....);
prc.waitFor();//这行就能阻塞后续代码的执行,直到你执行的命令结束。
③ java程序执行linux命令
首先确保Linux开启sshd服务,并支持远程SSH连接。java程序使用jsch框架登录Linux,执行命令。
protected void creation() throws Exception {
JSch jsch = new JSch();
session = jsch.getSession(userName, host, port);
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(CONNECT_TIMEOUT);
session.setConfig("PreferredAuthentications", "password,keyboard-interactive");
session.setServerAliveInterval(1000 * 60 * 2);
session.connect();
}
public String sendCommand(String command) throws Exception {
if(!isConnected())
throw new JSchException("Session is not connected, command exec faild.");
final ChannelExec exec = (ChannelExec)session.openChannel("exec");
ByteArrayOutputStream out = new ByteArrayOutputStream();
exec.setCommand(command);
exec.setOutputStream(out);
exec.setExtOutputStream(out);
exec.connect();
final Thread thread = new Thread() {
public void run() {
while(!exec.isEOF()) {
try { Thread.sleep(500L); } catch(Exception e) {}
}
}
};
thread.setDaemon(true);
thread.start();
thread.join(EXEC_TIMEOUT);
thread.interrupt();
if(thread.isAlive()) {
throw new JSchException("Exec Time Out Error");
} else {
try {
exec.disconnect();
out.close();
} catch (Exception e) {
}
byte[] lens = out.toByteArray();
String result = new String(lens, charset);
if(result.startsWith("bash") && result.indexOf("command not found") != -1)
return "";
return result;
}
}
④ java运行linux命令获得返回值的问题
inputStream = Runtime.getRuntime().exec(cmd);
java的这个方式,得到的是控制台的输出流,
也就是linux命令运行完,显示在屏幕上的东西,都以流的方式传递给java了,
可以通过下边的方式
InputStreamReader insr = new InputStreamReader(inputStream, “GBK”);
BufferedReader br = new BufferedReader(insr);
while (br.ready()) {
String line = br.readLine();
}
得到屏幕上显示的一行行内容,解析得到你想要的结果。
InputStreamReader 最后一个参数,是设置显示流是什么字符集的,如果不正确,请自行调整一下。
⑤ java程序里如何调用linux命令
Java 可以通过 Runtime 调用Linux命令,形式如下:
Runtime.getRuntime().exec(command)
但是这样执行时没有任何输出,因为调用 Runtime.exec 方法将产生一个本地的进程,并返回一个Process子类的实例(注意:Runtime.getRuntime().exec(command)返回的是一个Process类的实例)该实例可用于控制进程或取得进程的相关信息。
由于调用 Runtime.exec 方法所创建的子进程没有自己的终端或控制台,因此该子进程的标准IO(如stdin,stdou,stderr)都通过 Process.getOutputStream(),Process.getInputStream(), Process.getErrorStream() 方法重定向给它的父进程了。
用户需要用这些stream来向子进程输入数据或获取子进程的输出,下面的代码可以取到 linux 命令的执行结果:
try {
String[] cmd = new String[]{”/bin/sh”, “-c”, ” ls “};
Process ps = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append(” ”);
}
String result = sb.toString();
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
⑥ linux 如何实现java守护进程编程开发
可以通过GuardServer实现,具体代码如下;
1publicclassGuardServer{
2privateStringservername;
3
4publicGuardServer(Stringservername){
5this.servername=servername;
6}
7
8publicvoidstartServer(Stringcmd)throwsException{
9System.out.println("StartServer:"+cmd);
10//将命令分开
11//String[]cmds=cmd.split("");
12//ProcessBuilderbuilder=newProcessBuilder(cmds);
13
14//
15ProcessBuilderbuilder=newProcessBuilder(newString[]{"/bin/sh","-c",cmd});
16//将服务器程序的输出定位到/dev/tty
17builder.redirectOutput(newFile("/dev/tty"));
18builder.redirectError(newFile("/dev/tty"));
19builder.start();//throwsIOException
20Thread.sleep(10000);
21}
22
23/**
24*检测服务是否存在
25*
26*@return返回配置的java程序的pid
27*@returnpid>0返回的是pid<=0代表指定java程序未运行
28***/
29publicintcheckServer()throwsException{
30intpid=-1;
31Processprocess=null;
32BufferedReaderreader=null;
33process=Runtime.getRuntime().exec("jps-l");
34reader=newBufferedReader(newInputStreamReader(process.getInputStream()));
35Stringline;
36while((line=reader.readLine())!=null){
37String[]strings=line.split("\s{1,}");
38if(strings.length<2)
39continue;
40if(strings[1].contains(servername)){
41pid=Integer.parseInt(strings[0]);
42break;
43}
44}
45reader.close();
46process.destroy();
47returnpid;
48}
49}
⑦ Java创建exec通道执行Linux命令时 程序卡在 su - oracle 程序阻塞,那位大神帮忙看看,非常感谢!!
是root方式运行的吗
如果是非root运行,su需要输入密码,所以就阻塞了
⑧ 如何在java程序中调用linux命令或者shell脚本
做到这,主要依赖2个类:Process和Runtime。
首先看一下Process类:
ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,
该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、
检查进程的退出状态以及销毁(杀掉)进程的方法。
创建进程的方法可能无法针对某些本机平台上的特定进程很好地工作,比如,本机窗口进程,守护进程,Microsoft Windows
上的 Win16/DOS 进程,或者 shell 脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout 和 stderr)
操作都将通过三个流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。
父进程使用这些流来提供到子进程的输入和获得从子进程的输出。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,
如果读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁。
当没有 Process 对象的更多引用时,不是删掉子进程,而是继续异步执行子进程。
对于带有 Process 对象的 Java 进程,没有必要异步或并发执行由 Process 对象表示的进程。
特别需要注意的是:
1,创建的子进程没有自己的终端控制台,所有标注操作都会通过三个流
(getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程(父进程可通过这些流判断子进程的执行情况)
2,因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,
则可能导致子进程阻塞,甚至产生死锁
abstract void destroy()
杀掉子进程。
abstract int exitValue()
返回子进程的出口值。根据惯例,值0表示正常终止。
abstract InputStream getErrorStream()
获取子进程的错误流。
abstract InputStream getInputStream()
获取子进程的输入流。
abstract OutputStream getOutputStream()
获取子进程的输出流。
abstract int waitFor()
导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。
特别需要注意:如果子进程中的输入流,输出流或错误流中的内容比较多,最好使用缓存(注意上面的情况2)
再来看一下Runtime类:
每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取当前运行时环境。
应用程序不能创建自己的Runtime类实例。
介绍几个主要方法:
Process exec(String command)
在单独的进程中执行指定的字符串命令。
Process exec(String command, String[] envp)
在指定环境的单独进程中执行指定的字符串命令。
Process exec(String command, String[] envp, File dir)
在有指定环境和工作目录的独立进程中执行指定的字符串命令。
Process exec(String[] cmdarray)
在单独的进程中执行指定命令和变量。
Process exec(String[] cmdarray, String[] envp)
在指定环境的独立进程中执行指定命令和变量。
Process exec(String[] cmdarray, String[] envp, File dir)
在指定环境和工作目录的独立进程中执行指定的命令和变量。
command:一条指定的系统命令。
envp:环境变量字符串数组,其中每个环境变量的设置格式为name=value;如果子进程应该继承当前进程的环境,则该参数为null。
dir:子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为null。
cmdarray:包含所调用命令及其参数的数组。
以下为示例(要打成可执行jar包扔到linux下执行):
public class test {
public static void main(String[] args){
InputStream in = null;
try {
Process pro = Runtime.getRuntime().exec(new String[]{"sh",
"/home/test/test.sh","select admin from M_ADMIN",
"/home/test/result.txt"});
pro.waitFor();
in = pro.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in));
String result = read.readLine();
System.out.println("INFO:"+result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在这用的是Process exec(String[] cmdarray)这个方法
/home/test/test.sh脚本如下:
#!/bin/sh
#查询sql
SQL=$1
#查询结果保存文件
RESULT_FILE=$2
#数据库连接
DB_NAME=scott
DB_PWD=tiger
DB_SERVER=DB_TEST
RESULT=`sqlplus -S ${DB_NAME}/${DB_PWD}@${DB_SERVER}<< !
set heading off
set echo off
set pages 0
set feed off
set linesize 3000
${SQL}
/
commit
/
!`
echo "${RESULT}" >> ${RESULT_FILE}
echo 0;
特别需要注意的是,当需要执行的linux命令带有管道符时(例如:ps -ef|grep java),用上面的方法是不行的,解决方式是将需要执行的命令作为参数传给shell
public class Test {
public static void main(String[] args) throws Exception{
String[] cmds = {"/bin/sh","-c","ps -ef|grep java"};
Process pro = Runtime.getRuntime().exec(cmds);
pro.waitFor();
InputStream in = pro.getInputStream();
BufferedReader read = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line = read.readLine())!=null){
System.out.println(line);
}
}
}
PS:
Runtime.getRuntime().exec()这种调用方式在java虚拟机中是十分消耗资源的,即使命令可以很快的执行完毕,频繁的调用时创建进程消耗十分客观。
java虚拟机执行这个命令的过程是,首先克隆一条和当前虚拟机拥有一样环境变量的进程,再用这个新的进程执行外部命令,最后退出这个进程。频繁的创建对CPU和内存的消耗很大。
⑨ linux环境下java调用.sh文件带参数
试试另一种方法
String[] cmd = {"/home/xiang/start.sh", "参数1", "参数2"};
Runtime.getRuntime().exec(cmd);
⑩ java中如何执行linux命令
执行linux命令基,基本思路是从控制台获得输入的指令,启动命令行执行命令,捕捉异常,示例如下:
publicclassTestRunTime{
publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{
Stringcmd="";
if(args==null||args.length==0){
System.out.println("请输入命令行参数");
}else{
for(inti=0;i<args.length;i++){//获得输入的命令
cmd+=args[i]+"";
}
}
try{
Processprocess=Runtime.getRuntime().exec(cmd);//执行命令
InputStreamReaderir=newInputStreamReader(process.getInputStream());
LineNumberReaderinput=newLineNumberReader(ir);
Stringline;
while((line=input.readLine())!=null){//输出结果
System.out.println(line);
}
}catch(java.io.IOExceptione){
System.err.println("IOException"+e.getMessage());//捕捉异常
}
}
}