Java程序执行Linux命令

简介: java程序中要执行linux命令主要依赖2个类:Process和Runtime首先看一下Process类:[plain] view plaincopyprint?ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,  该实例可用来控制进程并获得相关信息。Process 类提供了执行从进程输入

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

目录
相关文章
|
3月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
423 1
二、Linux文本处理与文件操作核心命令
|
4月前
|
人工智能 监控 安全
智慧工地解决方案,java智慧工地程序代码
智慧工地系统融合物联网、AI、大数据等技术,实现对施工现场“人、机、料、法、环”的全面智能监控与管理,提升安全、效率与决策水平。
131 2
|
2月前
|
安全 Java
Java异常处理:程序世界的“交通规则
Java异常处理:程序世界的“交通规则
318 98
|
3月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
294 137
|
3月前
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
684 57
|
2月前
|
安全 Linux iOS开发
Nessus Professional 10.10 Auto Installer for RHEL 10, AlmaLinux 10, Rocky Linux 10 - Nessus 自动化安装程序
Nessus Professional 10.10 Auto Installer for RHEL 10, AlmaLinux 10, Rocky Linux 10 - Nessus 自动化安装程序
149 6
Nessus Professional 10.10 Auto Installer for RHEL 10, AlmaLinux 10, Rocky Linux 10 - Nessus 自动化安装程序
|
2月前
|
存储 安全 Linux
Linux卡在emergency mode怎么办?xfs_repair 命令轻松解决
Linux虚拟机遇紧急模式?别慌!多因磁盘挂载失败。本文教你通过日志定位问题,用`xfs_repair`等工具修复文件系统,三步快速恢复。掌握查日志、修磁盘、验重启,轻松应对紧急模式,保障系统稳定运行。
410 2
|
3月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
275 0
Linux内存问题排查命令详解
|
3月前
|
Unix Linux 程序员
Linux文本搜索工具grep命令使用指南
以上就是对Linux环境下强大工具 `grep` 的基础到进阶功能介绍。它不仅能够执行简单文字查询任务还能够处理复杂文字处理任务,并且支持强大而灵活地正则表达规范来增加查询精度与效率。无论您是程序员、数据分析师还是系统管理员,在日常工作中熟练运用该命令都将极大提升您处理和分析数据效率。
277 16