在java中调用Linux命令/脚本

接着之前写的一篇文章,《Linux的cached和pagecache清除 解决缓存、内存不足、测试结果影响问题》说的缓存影响测试的问题。找到了解决方法,开始实施~

测试用例使用java写的,需要再两个不同的用例之间调用一次

sync && echo 3 > /proc/sys/vm/drop_caches

这就等同于:

Java程序运行时,调用系统提供的服务:Linux脚本或者命令


这里不得不提到java的Process类、Runtime类。


1、Process是一个抽象类,封装了一个进程(在调用Linux的命令或者shell脚本就是为了执行一个在Linux下执行的程序)。

Process类提供了执行从进程输入,执行输出到进程,等待进程完成,检查进程的推出状态,以及shut down掉进程。它的所有标准 io(即 stdin、stdout 和 stderr)操作都将通过三个流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。父进程使用这些流来提供到子进程的输入和获得从子进程的输出。


2、Runtime类,Runtime类是一个与JVM运行时环境有关的类,提供获取当前运行环境的接口,这个类是Singleton的。

其中的Runtime.getRuntime()方法作用是取得当前JVM的运行环境,也是java中唯一可以得到运行环境的方法。(另外,Runtime的大部分方法都是实例方法,也就是说每次运行调用的时候都需要调用到getRuntime方法)


再来说Runtime的exec()方法。

exec函数具体实现形式有以下几种:

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

注1:

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

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

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

cmdarray:包含所调用命令及其参数的数组。数组的第一个元素是要执行的命令往后依次都是命令的参数。

注2:

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

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


下面上几个例子:

  1. 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;  

特别注意:当需要执行的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. }  


再如 :在Linux下执行命令:sh test.sh 

1、shpath:是/test/test.sh也就是我们要执行的sh脚本的完整路径+脚本名称

2、var是一个参数,可以有也可以没有,当然这个参数取决于你的sh脚本中是否使用到了这个参数,因为我的脚本中使用到了这个var参数,在Linux下面执行的时候是 sh test.sh  a.tar


这个var参数就是a.tar这个tar包的名字。


String command1 = “chmod 777 ” + shpath;
    process= Runtime.getRuntime().exec(command1);
    process.waitFor();
    Stringvar= “a.tar”;
    Stringcommand2 = “/bin/sh ” + shpath + ” ” + var;
    Runtime.getRuntime().exec(command2).waitFor();

String command1 = “chmod 777 ” + shpath;

    process= Runtime.getRuntime().exec(command1);

    process.waitFor();

    Stringvar= “a.tar”;

    Stringcommand2 = “/bin/sh ” + shpath + ” ” + var;

    Runtime.getRuntime().exec(command2).waitFor();


注:

如果没有给这个sh文件添加权限(chmod777),就会执行到Runtime.getRuntime().exec的时侯会出现Permission denied错误。

waitFor()这个也是必不可缺的,等待进程执行完毕。如果你需要执行多行命令的话,把waitFor()这个加上。

你可能感兴趣的:(Java)