Java程序执行Linux命令

java程序中要执行linux命令主要依赖2个类:Process和Runtime

首先看一下Process类:

ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

操作都将通过三个流 (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下执行或者在linux下编译运行):

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class test {

    public static void main(String[] args) {

        test test = new test();
        final String[] command1 = { "/bin/sh", "-c", "ps -ef | grep tomcat | grep -v grep" };
        String[] content = test.execCont(command1);
        System.out.println("ps -ef | grep tomcat | grep -v grep   执行结果:" + content[0]);
        System.out.println("执行内容:" + content[1]);

        final String[] command2 = { "/bin/sh", "-c", "./shutdown_tomcat.sh" };
        String result = test.execRes(command2);
        System.out.println("./shutdown_tomcat.sh   执行结果:" + result);
    }

    /**
     * 执行语句方法(返回结果和内容)
     * 
     * @param 操作语句String[]
     */
    public String[] execCont(final String[] execute) {
        // 结果数组,第一个值存放语句运行结果,第二个值存放语句输出结果
        final String[] result = new String[2];
        InputStream is = null;
        InputStreamReader ir = null;
        BufferedReader br = null;
        String line = null;
        try {
            final Process p = Runtime.getRuntime().exec(execute);
            result[0] = String.valueOf(p.waitFor());
            is = p.getInputStream();
            ir = new InputStreamReader(is);
            br = new BufferedReader(ir);
            while ((line = br.readLine()) != null) {
                result[1] = line;
            }
        } catch (final Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (ir != null) {
                    ir.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 执行语句方法(返回结果)
     * 
     * @param 操作语句String[]
     */
    public String execRes(final String[] execute) {
        String result = null;

        try {
            final Process p = Runtime.getRuntime().exec(execute);
            result = String.valueOf(p.waitFor());

        } catch (final Exception e) {
            e.printStackTrace();
        }

        return result;
    }

}

测试结果:
Java程序执行Linux命令_第1张图片

注:Runtime.getRuntime().exec()这种调用方式在java虚拟机中是十分消耗资源的,即使命令可以很快的执行完毕,频繁的调用时创建进程消耗十分客观。java虚拟机执行这个命令的过程是,首先克隆一条和当前虚拟机拥有一样环境变量的进程,再用这个新的进程执行外部命令,最后退出这个进程。频繁的创建对CPU和内存的消耗很大。

你可能感兴趣的:(Linux,Java)