接着之前写的一篇文章,《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和内存的消耗很大
下面上几个例子:
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);
}
}
}
再如 :在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();
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()这个加上。