Java程序执行Linux命令(JSP运行其他程序)

java程序中要执行linux命令主要依赖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和内存的消耗很大。

From:

http://blog.csdn.net/a19881029/article/details/8063758

http://www.avajava.com/tutorials/lessons/how-do-i-run-another-application-from-java.html

http://stackoverflow.com/questions/13991007/execute-external-program-in-java

http://stackoverflow.com/questions/15218892/running-a-java-program-from-another-java-program

http://www.rgagnon.com/javadetails/java-0014.html

http://www.javacoffeebreak.com/faq/faq0030.html

http://www.youtube.com/watch?v=AiVpzFH9zRc

时间: 2024-10-08 09:30:07

Java程序执行Linux命令(JSP运行其他程序)的相关文章

Java程序执行Linux命令

java程序中要执行linux命令主要依赖2个类:Process和Runtime http://blog.csdn.net/a19881029/article/details/8063758 java连接centos服务器,并执行命令 java连接需要用到ganymed-ssh2. 将 ganymed-ssh2-build210.jar 加入到项目的lib中

使用java代码执行linux命令

前提: java代码是在windows下面写的,要打包放到linux下面运行,并且执行某个脚本. java代码: try { // 起作用的代码其实就下面这一行, 参数是linux中要执行的代码 Runtime.getRuntime().exec("sh generator.sh").waitFor(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printSt

java程序执行linux命令,并线程阻塞,执行完才走下面代码

Process process;                //String rsync="/usr/bin/rsync -arp "+imageSaveTrue+" "+imageRead;                String rsync="cp "+imageSave+SMALL_IMAGE_SIGN+fileNameAll+" "+imageRead+"/upload/"; logger.

Java 执行linux命令(转)

转自 http://blog.csdn.net/a19881029/article/details/8063758 java程序中要执行linux命令主要依赖2个类:Process和Runtime 首先看一下Process类: ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例, 该实例可用来控制进程并获得相关信息.Process 类提供了执行从进程输入.执行输出到进程.等待进程完成. 检查进程的退出状态以及销

Java中通过jsch来连接远程服务器执行linux命令

有时候你可能需要通过代码来控制执行linux命令实现某些功能. 针对这类问题可以使用JSCH来实现,具体代码如下: public class CogradientImgFileManager{ private static final Logger log = LoggerFactory.getLogger(CogradientImgFileManager.class); private static ChannelExec channelExec; private static Session

java通过ssh2远程连接计算机并执行linux命令的方法(转)

java通过ch.ethz.ssh2远程连接计算机并执行linux命令的方法实现 API详情:  http://www.ganymed.ethz.ch/ssh2/javadoc/ch/ethz/ssh2/package-summary.html jar包:  ganymed-ssh2-build210.jar    下载地址: http://www.ganymed.ethz.ch/ssh2/ 代码实现: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1

java执行linux命令

public class LinuxUtils { static Logger logger = Logger.getLogger(LinuxUtils.class); public static String exeCmd(String cmd) { logger.info(cmd); String returnString = ""; Runtime runTime = Runtime.getRuntime(); Process pro = null; StringBuffer s

java项目在linux上的运行

之前一直在windows下开发java项目,现如今在项目组主要是spring + mybatis +maven + git +MySQL来开发项目,最近碰到将项目移植到linux上去跑,遇到了一系列的问题,比如java程序在linux下的运行,由于接触java不长,对java的运行机制还不是很了解,最后先用maven 对项目进行了编译后,再在maven自动生成的target的class文件中直接执行main.class 文件运行,具体的命令是:java -classpath [jar包目录][配

如何在Java中执行Hive命令或HiveQL

这里所说的在Java中执行Hive命令或HiveQL并不是指Hive Client通过JDBC的方式连接HiveServer(or HiveServer2)执行查询,而是简单的在部署了HiveServer的服务器上执行Hive命令.当然这是一个简单的事情,平常我们通过Hive做简单的数据分析实验的时候,都是直接进入Hive执行HiveQL,那我们为什么还要在程序中执行呢? 这里涉及到了一个问题,通过进入Hive执行HiveQL,我们只能将分析结果打印到屏幕或是存入临时表,那如果我们想吧分析结果写