`

Java程序执行Linux命令

 
阅读更多

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

首先看一下Process类:

  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 对象表示的进程。  
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,因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流迅速出现失败,

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

  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.      如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。  
abstract  void destroy() 
          杀掉子进程。 
abstract  int exitValue() 
          返回子进程的出口值。根据惯例,值0表示正常终止。 
abstract  InputStream getErrorStream() 
          获取子进程的错误流。 
abstract  InputStream getInputStream() 
          获取子进程的输入流。 
abstract  OutputStream getOutputStream() 
          获取子进程的输出流。 
abstract  int waitFor() 
          导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
 	 如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程。

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

再来看一下Runtime类:

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

介绍几个主要方法:

  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.          在指定环境和工作目录的独立进程中执行指定的命令和变量。   
 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下执行):

  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. }  
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脚本如下:

  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;  
#!/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

  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. }  
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调用linux命令、脚本工具类.zip

    Java程序调用linux命令、脚本,支持程序在服务器上使用linux命令。工具类为:ProcessUtil,支持单个命令和批量命令执行函数,同时在工具类中添加了getFileLineNumByCmd函数支持通过linux命令获取文件行数的样例。

    java通过代码登录远程linux服务器并执行linux命令源码以及jar包

    3. 执行Linux命令 连接成功后,可以通过Session对象创建一个Channel,通常使用`session.openChannel("exec")`创建一个执行命令的通道。设置命令,然后打开并读取输出流。 ```java public void executeCommand...

    在Linux系统下用java执行系统命令实例讲解

    本文将深入讲解如何在Java程序中调用Linux命令,并通过实例来阐述这一过程。 一、Runtime类 `Runtime`类是每个Java应用程序都有的一个单例对象,它提供了执行外部进程的能力。通过`getRuntime()`方法可以获得`...

    java连接linux,执行shell命令的工具类 sshxcute.jar

    在Java开发中,有时我们需要远程连接到Linux服务器执行shell命令,比如进行系统管理、自动化运维或者数据处理等任务。...SSHXCUTE.jar简化了Java开发中的SSH操作,使得远程执行Linux命令变得更加便捷和安全。

    Java调用Linux命令

    虽然`Runtime.exec()`提供了一种非常方便的方式来执行Linux命令,但是在实际应用中还需要注意以下几点: - **安全性**:直接执行外部命令可能会引入安全风险,特别是当命令字符串包含来自不可信源的数据时。 - **...

    java执行远程linux服务器命令

    在实际情况中,这个文件可能包含一个简单的Java程序,展示了如何使用JSch或其他工具来执行远程Linux命令。如果能查看到具体的代码内容,我们将能够更深入地了解其实现细节。 总结,通过Java执行远程Linux服务器命令...

    java应用程序远程登录linux并执行其命令

    接下来,我们将编写一个简单的Java程序来演示如何使用Ganymed SSH2库实现远程登录Linux服务器并执行命令。 #### 1. 创建Connection对象 ```java // 创建Connection实例 Connection conn = new Connection(hostname...

    java开发的swing客户端,远程执行linux命令.zip

    本项目“java开发的swing客户端,远程执行linux命令”显然旨在利用Swing构建一个桌面应用,该应用的核心功能是远程控制Linux服务器,执行命令。这涉及到Java中的网络编程和Linux系统的交互。具体来说,开发者可能使用...

    Java 调用 Linux 命令实战(含完整代码)1

    如果需要直接执行Linux命令,而不是通过shell脚本,可以使用`ProcessBuilder`类来实现。例如,重启keepalived服务的命令`systemctl restart keepalived`可以通过以下Java代码执行: ```java public class ...

    登录linux执行命令

    通过监听特定的队列,当有新消息到达时,程序将被动地接收并解析这些消息,这些消息可能是执行Linux命令的指示。 其次,"expect4j"是一个Java库,它允许程序模拟用户交互,尤其是用于自动化SSH登录。SSH(Secure ...

    java执行Linux命令的方法

    在Java编程中,有时我们需要在运行Java程序时执行Linux命令,例如进行文件操作、系统管理等。这可以通过Java内置的`Runtime.exec()`方法实现。本文将深入探讨如何使用`Runtime.exec()`来执行Linux命令以及相关的注意...

    14-Java操作Linux命令分割合并文本文件1

    标题中的“14-Java操作Linux命令分割合并文本文件1”指的是使用Java编程语言来执行Linux命令,以实现对文本文件的分割和合并操作。在处理大文件时,由于内存限制,不能一次性将整个文件读入,因此需要采用分块处理的...

    Java语言编写的Linux简单命令解释器

    在本项目中,Java被用来解析和执行Linux命令,展示了其强大的系统交互能力。 2. **Linux命令解释器**:在Linux中,命令解释器(如bash)负责接收用户的输入并执行相应的系统调用。这个简单的Java命令解释器模拟了这...

    java执行linux的SH文件

    - **Runtime类**:Java的标准库提供了Runtime类,它允许Java程序执行系统命令。通过`Runtime.getRuntime().exec(command)`方法,可以执行一个系统命令,如我们的SH文件。 - **ProcessBuilder类**:ProcessBuilder...

    linux安装 java 8版

    本篇文章将详细讲解如何在Linux环境下安装Java Development Kit(JDK)8,以满足开发和运行Java程序的需求。 首先,我们需要下载Java 8的Linux版本。这里提供的是`jdk-8u261-linux-x64.tar.gz`文件,这是一个适用于...

    linux 通过脚本执行java程序

    在Linux环境中,通过脚本执行Java程序是一种常见的实践,尤其对于服务器端应用或者自动化任务来说。这使得我们能够更方便地管理和控制Java应用程序的启动、停止以及监控。下面将详细介绍如何编写一个简单的bash脚本...

    java执行系统命令

    本文将详细介绍如何使用Java来执行系统命令,并给出具体的示例代码,特别是针对Linux系统的操作。 #### 二、基本原理 在Java中执行系统命令主要通过`java.lang.Runtime`类来实现。具体来说,可以通过调用`Runtime....

    linux下运行java程序

    这篇博文将深入探讨如何在Linux系统中配置Java环境并执行Java程序。 首先,确保你的Linux系统已经安装了Java Development Kit (JDK)。JDK包含了运行和开发Java应用程序所需的所有工具,包括Java虚拟机(JVM)。你...

    Java应用程序远程登录linux并执行其命令.pdf

    Java应用程序远程登录Linux并执行命令的实现原理和实践 Java应用程序远程登录Linux并执行命令是Java开发中一个常见的需求,例如在自动化运维、云计算、DevOps等领域都需要使用远程登录和命令执行技术。下面我们将...

Global site tag (gtag.js) - Google Analytics