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和内存的消耗很大

java执行Shell命令的更多相关文章

  1. Android Java执行Shell命令

    最新内容建议直接访问原文:http://www.trinea.cn/android/android-java-execute-shell-commands/ 主要介绍Android或Java应用中如何 ...

  2. java 执行shell命令及日志收集避坑指南

    有时候我们需要调用系统命令执行一些东西,可能是为了方便,也可能是没有办法必须要调用.涉及执行系统命令的东西,则就不能做跨平台了,这和java语言的初衷是相背的. 废话不多说,java如何执行shell ...

  3. java 执行shell命令遇到的坑

    正常来说java调用shell命令就是用 String[] cmdAry = new String[]{"/bin/bash","-c",cmd} Runtim ...

  4. [Java] Java执行Shell命令

    Methods ProcessBuilder.start() 和 Runtime.exec() 方法都被用来创建一个操作系统进程(执行命令行操作),并返回 Process 子类的一个实例,该实例可用来 ...

  5. java 执行shell命令

    Runtime.getRuntime().exec http://blog.csdn.net/heyetina/article/details/6555746

  6. 第3节 sqoop:7、通过java代码远程连接linux执行shell命令

    数据库的数据同步软件sqoop 数据同步 关系型数据库到大数据平台 任务:sqoop 是批量导入数据太慢,如何做到实时的数据同步 实时的数据同步工具: canal 阿里开源的一个数据库数据实时同步的软 ...

  7. Android 用java语言执行Shell命令

    最近项目中需要用到java语言来执行shell命令,在网上查了资料, 把自己在项目里用到的命令整理成了工具类开放给大家,希望对大家有用.功能不全,后期我会慢慢添加整合. public class Sh ...

  8. Java 实现 ssh命令 登录主机执行shell命令

    Java 实现 ssh命令 登录主机执行shell命令 1.SSH命令 SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定:SS ...

  9. 【Hadoop离线基础总结】通过Java代码执行Shell命令

    通过Java代码执行Shell命令 需求 在实际工作中,总会有些时候需要我们通过java代码通过远程连接去linux服务器上面执行一些shell命令,包括一些集群的状态管理,执行任务,集群的可视化界面 ...

随机推荐

  1. PHP 使用 Memcached

    PHP 想往 Memcached 中增删查改数据,需要先安装 memcache 扩展模块: cd /usr/local/src wget http://www.apelearn.com/bbs/dat ...

  2. (转载)Java反射机制

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  3. windows 命令行下 简单好用的查看端口占用情况的方法

    在windows命令行窗口下执行: C:\>netstat -aon|findstr "4444" TCP 127.0.0.1:4444 0.0.0.0:0 LISTENIN ...

  4. Android学习之Handler消息

    Android系统规定,一些耗时的操作不能放在UI线程中去执行,这样会报一个ANR错误.所以为了避免该问题,我们需要开启一个新的线程去执行一些耗时操作:开启新的线程,将耗时的操作在新线程里面去执行, ...

  5. Makefile中的MAKECMDGOALS

      make 在执行时会设置一个特殊变量 -- "MAKECMDGOALS" ,该变量记录了命令行参数指定的终极目标列表,没有通过参数指定终极目标时此变量为空.该变量仅限于用在特殊 ...

  6. Python Tkinter 学习成果:点歌软件music

    笔者工作业余时间也没什么爱好,社交圈子也小,主要娱乐就是背着自己带电瓶的卖唱音响到住地附近找个人多的位置唱唱KtV. 硬件上点歌就用笔记本电脑,歌曲都是网上下载的mkv格式的含有两个音轨的视频.因此点 ...

  7. 编译内核时出现__bad_udelay错误

    今天编译内核时候遇到了__bad_udelay错误,然后编不过去了,仔细一看发现是udelay函数的参数太大,内核不允许延时这么多.于是换成了mdelay函数,以毫秒为单位延时,问题解决.

  8. minix中时间转换的实现(asctime.c)

    在minix2.0源代码中,有相当经典的时间转换函数实现(src\ src\ lib\ ansi\ asctime.c),今天我们就来分析一下asctime.c中的源码 首先引入几个相关的头文件: 1 ...

  9. jquery.fn.extend与jquery.extend用法与区别

    jQuery为开发插件提拱了两个方法,分别是:  代码如下 复制代码 jQuery.fn.extend(object);  和   jQuery.extend(object); jQuery.exte ...

  10. [图书] C++

    作者 书名 Bjarne Stroustrup    The Design and Evolution of C++Stanley B. Lippman    C++ PrimerStanley B. ...