Java ProcessBuilder无法使用sqlplus执行sql脚本文件,而在Linux可以正常执行
问题
在 linux 执行 sqlplus 跑sql脚本文件时能够正常执行,当Java ProcessBuilder向Linux Server发送指令时抛出错误
Cannot run program "sqlplus" (in directory "/test/scripts"): error=2, No such file or directory;
解决思路
- 如果我们在 linux 环境下能够正常执行sqlplus指令,就说明我们的Server已经正确安装并配置了Oracle相关的环境。
而我们这时需要找出的是 从 Linux Server 执行 sqlplus 指令 与 从 Java ProcessBuilder 执行 sqlplus 指令 之间的区别 - 如果我们从在1)中消耗了很多时间都找不到解决方法时,可能会尝试换一种方式执行sql脚本文件,比如 Spring的ScriptUtils 或者 自定义的工具类
我曾经在 1) 中花费了很多时间并转而使用 2) 中的Spring的ScriptUtils方法,但是Spring的ScriptUtils并没有想象中的适合,更像是读取sql脚本文件然后逐行执行SQL而已,由于我的sql脚本文件中包含了例如 set colsep ',' , spool c:\temp\test.txt; 之类的sqlplus专用关键词,导致使用ScriptUtils.executeSqlScript无法执行,并抛出"missing or invalid option"异常如下:
没办法,只能接着死磕 1) 的解决方法,我开始考虑是否Java ProcessBuilder使用的进程的环境变量与linux server user的环境变量不同导致的。
最终发现是只需要正确设置ORACLE_HOME和PATH即可,要实现这一步需要将qlplus指令改写成shell文件
解决过程
- 使用Java ProcessBuilder向Linux Server发送指令,代码如下:
public String test() throws Exception {
//String cmd = "sqlplus TEST/TEST123@test < /test/scripts/TEST_TXT.sql";
//Build command
List<String> commands = new ArrayList<String>();
commands.add("sqlplus");
//Add arguments
commands.add(dbUsername + "/" + dbPassword + "@ctccbs");
commands.add("<");
commands.add("/test/scripts/TEST_TXT.sql");
//Run macro on target
ProcessBuilder pb = new ProcessBuilder(commands);
pb.directory(new File("/test/scripts"));
pb.redirectErrorStream(true);
Map<String, String> environment = pb.environment();
Process process = pb.start();
//Read output
StringBuilder out = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
String line = null;
String previous = null;
while ((line = br.readLine()) != null) {
/* if (!line.equals(previous)) {
previous = line;
out.append(line).append('\n');
}*/
}
//Check result
int statusCode = process.waitFor();
if (statusCode != 0) {
return "Failed to run sql file with status code: " + statusCode;
}
} catch (Exception e) {
return e.getMessage();
} finally {
if (br != null) {
br.close();
}
if (process != null) {
process.destroy();
}
}
return "Successful";
}
- 结果失败,抛出以下错误信息
Cannot run program "sqlplus" (in directory "/test/scripts"): error=2, No such file or directory;
- 创建shell文件,将sqlplus指令写入shell文件中,b并且查看并参照 ~/.bash_profile 文件,重新配置ORACLE_HOME和PATH
- 执行成功,数据库中数据成功发生改变,statusCode 为 0 即代表正常执行