文档章节

Java程序执行Linux命令

郑光宗
 郑光宗
发布于 2015/07/20 18:47
字数 1782
阅读 74
收藏 1

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

首先看一下Process类:

[plain] view plaincopy

<EMBED id=ZeroClipboardMovie_1 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,  

  2. 该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、  

  3. 检查进程的退出状态以及销毁(杀掉)进程的方法。  

  4. 创建进程的方法可能无法针对某些本机平台上的特定进程很好地工作,比如,本机窗口进程,守护进程,Microsoft Windows  

  5. 上的 Win16/DOS 进程,或者 shell 脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout 和 stderr)  

  6. 操作都将通过三个流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。  

  7. 父进程使用这些流来提供到子进程的输入和获得从子进程的输出。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,  

  8. 如果读写子进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁。  

  9. 当没有 Process 对象的更多引用时,不是删掉子进程,而是继续异步执行子进程。  

  10. 对于带有 Process 对象的 Java 进程,没有必要异步或并发执行由 Process 对象表示的进程。  

特别需要注意的是:

1,创建的子进程没有自己的终端控制台,所有标注操作都会通过三个流

(getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程(父进程可通过这些流判断子进程的执行情况

2,因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,

则可能导致子进程阻塞,甚至产生死锁

[plain] view plaincopy

<EMBED id=ZeroClipboardMovie_2 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. abstract  void destroy()   

  2.           杀掉子进程。   

  3. abstract  int exitValue()   

  4.           返回子进程的出口值。根据惯例,值0表示正常终止。   

  5. abstract  InputStream getErrorStream()   

  6.           获取子进程的错误流。   

  7. abstract  InputStream getInputStream()   

  8.           获取子进程的输入流。   

  9. abstract  OutputStream getOutputStream()   

  10.           获取子进程的输出流。   

  11. abstract  int waitFor()   

  12.           导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。  

  13.      如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。  

特别需要注意:如果子进程中的输入流,输出流或错误流中的内容比较多,最好使用缓存(注意上面的情况2)

再来看一下Runtime类:

[plain] view plaincopy

<EMBED id=ZeroClipboardMovie_3 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. 每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取当前运行时环境。   

  2. 应用程序不能创建自己的Runtime类实例。   

介绍几个主要方法:

[plain] view plaincopy

<EMBED id=ZeroClipboardMovie_4 name=ZeroClipboardMovie_4 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=4&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. Process exec(String command)   

  2.          在单独的进程中执行指定的字符串命令。  

  3. Process exec(String command, String[] envp)   

  4.          在指定环境的单独进程中执行指定的字符串命令。  

  5. Process exec(String command, String[] envp, File dir)   

  6.          在有指定环境和工作目录的独立进程中执行指定的字符串命令。  

  7. Process exec(String[] cmdarray)   

  8.          在单独的进程中执行指定命令和变量。   

  9. Process exec(String[] cmdarray, String[] envp)   

  10.          在指定环境的独立进程中执行指定命令和变量。   

  11. Process exec(String[] cmdarray, String[] envp, File dir)   

  12.          在指定环境和工作目录的独立进程中执行指定的命令和变量。   

command:一条指定的系统命令。

envp:环境变量字符串数组,其中每个环境变量的设置格式为name=value;如果子进程应该继承当前进程的环境,则该参数为null。

dir:子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为null。

cmdarray:包含所调用命令及其参数的数组。

以下为示例(要打成可执行jar包扔到linux下执行):

[java] view plaincopy

<EMBED id=ZeroClipboardMovie_5 name=ZeroClipboardMovie_5 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=5&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. public class test {  

  2.     public static void main(String[] args){  

  3.         InputStream in = null;  

  4.         try {  

  5.             Process pro = Runtime.getRuntime().exec(new String[]{"sh",  

  6.                                      "/home/test/test.sh","select admin from M_ADMIN",  

  7.                                      "/home/test/result.txt"});  

  8.             pro.waitFor();  

  9.             in = pro.getInputStream();  

  10.             BufferedReader read = new BufferedReader(new InputStreamReader(in));  

  11.             String result = read.readLine();  

  12.             System.out.println("INFO:"+result);  

  13.         } catch (Exception e) {  

  14.             e.printStackTrace();  

  15.         }  

  16.     }  

  17. }  

在这用的是Process exec(String[] cmdarray)这个方法

 /home/test/test.sh脚本如下:

[plain] view plaincopy

<EMBED id=ZeroClipboardMovie_6 name=ZeroClipboardMovie_6 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=6&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. #!/bin/sh  

  2.   

  3. #查询sql  

  4. SQL=$1  

  5. #查询结果保存文件  

  6. RESULT_FILE=$2  

  7. #数据库连接  

  8. DB_NAME=scott  

  9. DB_PWD=tiger  

  10. DB_SERVER=DB_TEST  

  11.   

  12. RESULT=`sqlplus -S ${DB_NAME}/${DB_PWD}@${DB_SERVER}<< !   

  13. set heading off  

  14. set echo off  

  15. set pages 0  

  16. set feed off  

  17. set linesize 3000  

  18. ${SQL}  

  19. /  

  20. commit  

  21. /  

  22. !`  

  23.       

  24. echo "${RESULT}" >> ${RESULT_FILE}  

  25. echo 0;  

特别需要注意的是,当需要执行的linux命令带有管道符时(例如:ps -ef|grep java),用上面的方法是不行的,解决方式是将需要执行的命令作为参数传给shell

[java] view plaincopy

<EMBED id=ZeroClipboardMovie_7 name=ZeroClipboardMovie_7 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=18 width=18 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=7&width=18&height=18" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. public class Test {  

  2.     public static void main(String[] args) throws Exception{  

  3.         String[] cmds = {"/bin/sh","-c","ps -ef|grep java"};  

  4.         Process pro = Runtime.getRuntime().exec(cmds);  

  5.         pro.waitFor();  

  6.         InputStream in = pro.getInputStream();  

  7.         BufferedReader read = new BufferedReader(new InputStreamReader(in));  

  8.         String line = null;  

  9.         while((line = read.readLine())!=null){  

  10.             System.out.println(line);  

  11.         }  

  12.     }  

  13. }  


PS:

Runtime.getRuntime().exec()这种调用方式在java虚拟机中是十分消耗资源的,即使命令可以很快的执行完毕,频繁的调用时创建进程消耗十分客观。

java虚拟机执行这个命令的过程是,首先克隆一条和当前虚拟机拥有一样环境变量的进程,再用这个新的进程执行外部命令,最后退出这个进程。频繁的创建对CPU和内存的消耗很大

本文转载自:http://blog.csdn.net/a19881029/article/details/8063758

郑光宗
粉丝 20
博文 117
码字总数 148900
作品 0
海淀
程序员
私信 提问
Linux下启动Java进程并获得进程ID(PID)

Linux 下启动Java程序一般是执行命令: java -cp ${CLASSPATH} org.self.test.Main 而停止一个程序需要执行命令: kill ${PID} 只有这个启动命令你不能直接得到这个Java进程的PID,但是可以通...

疯狂的艺术家
2012/04/17
0
0
Linux Centos6.0 在线安装搭建jdk环境【jdk-1.7.0.1】

预备工作: 卸载系统默认的老版本jdk,执行以下命令 1,下载jdk: wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://downlo......

岸芷汀兰
2015/06/16
0
0
Hadoop学习手册-在ubuntu12.04下配置JDK7

第一步:下载JDK 在oracle公司的官方网站下载JDK 网址: http://www.oracle.com/technetwork/indexes/downloads/index.html 下载最新版本:jdk-7u6-linux-i586.tar.gz 第二步:安装JDK 1.在usr...

毛祥溢
2012/08/22
0
0
玩转Linux之- JDK安装

一、安装 创建安装目录,在/usr/java下建立安装路径,并将文件考到该路径下: # mkdir /usr/java 1、jdk-6u11-linux-i586.bin 这个是自解压的文件,在linux上安装如下: # chmod 755 jdk-6u...

淡定的米哥
2014/09/25
0
0
linux下查看已经安装的jdk 并卸载jdk

一、查看Jdk的安装路径: whereis java which java (java执行路径) echo $JAVA_HOME echo $PATH 备注:如果是windows中,可以使用: set java_home:查看JDK安装路径 java -version:查看JDK...

五大三粗
2014/12/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

任务调度-第三方库Quartz实现分布式任务管理与调度

1. 为什么要用第三方库Quartz来实现分布式任务管理和调度? 首先管理的目的是通过集群多节点的管理提供容错,调度的目的是保证同一任务只会被完整执行一次;之前分享过的任务调度-单体应用定...

秋日芒草
16分钟前
0
0
Mysql Explain Type

前言 当我们执行sql,一般都会用Explain来查看sql的效率如何。今天在看sql执行效率的时候,忘记了其中Type的意思,现在在此记录一下。 效率 这里的type指的是访问类型,各个效率高低如下: ...

无敌小杰杰
24分钟前
0
0
外部浏览器网页复制公众号无法自动唤起微信并关注怎么办?

现在有很多用户在外部浏览器网页复制公众号时无法自动唤起微信并关注,这是因为第三方浏览器打开微信的接口,微信只给部分合作平台开放了接口权限,任何第三方想调用只能是通过一些技术手段来...

qjniop
29分钟前
0
0
建造者模式

建造者模式(Builder Pattern) 也叫生成器模式,其定义如下: Separate the construction of a complex object from its representation so that the same construction process can create d......

无知的小狼
34分钟前
0
0
距离计算方法

1、欧式距离(欧几里得距离) 欧式距离是最易理解的距离定义,即各坐标点的坐标之差的平方和相加,然后开根号。 二维平面上点 与点 之间的距离公式是: n维空间上点 和点 之间的距离公式是:...

城北徐公美
36分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部