将退出代码从 Java 返回到 PL/SQL
Posted
技术标签:
【中文标题】将退出代码从 Java 返回到 PL/SQL【英文标题】:Getting exit code from Java back to PL/SQL 【发布时间】:2015-02-02 17:03:40 【问题描述】:我正在尝试将退出代码从 Java 方法返回到 PL/SQL。似乎总是有例外。我怎样才能找出异常 n 是。我在 12c 上跑步。
SQL> CREATE OR REPLACE JAVA SOURCE NAMED UTLCMD AS
2 import java.lang.Runtime;
3 public class UTLCMD
4
5 public static int execute(String command)
6
7 int exitCode = 0;
8
9 try
10
11 Runtime rt = java.lang.Runtime.getRuntime();
12 Process proc = rt.exec(command);
13 exitCode = proc.waitFor();
14
15 catch(Exception e)
16
17 System.out.println(e.getMessage());
18 exitCode = 12;
19
20
21 return exitCode;
22
23
24 /
Java created.
SQL> CREATE OR REPLACE FUNCTION JavaRunShellCommand(
2 command IN VARCHAR2)
3 RETURN NUMBER
4 AS LANGUAGE JAVA
5 NAME 'UTLCMD.execute(java.lang.String) return oracle.sql.NUMBER';
6 /
Function created.
这是尝试调用该方法的结果。
SQL> VARIABLE n NUMBER;
SQL> CALL JavaRunShellCommand('cmd.exe /C CALL C:\Users\pwatson\src\java\my.bat') INTO :n;
Call completed.
SQL> PRINT n
N
----------
12
SQL> CALL JavaRunShellCommand('cmd.exe /C EXIT /B 3') INTO :n;
Call completed.
SQL> PRINT n
N
----------
12
SQL> SELECT JavaRunShellCommand('cmd.exe /C CALL C:\Users\pwatson\src\java\my.bat') AS R FROM DUAL;
R
----------
12
SQL> SELECT JavaRunShellCommand('cmd.exe /C EXIT /B 3') AS R FROM DUAL;
R
----------
12
【问题讨论】:
您是否为cmd.exe
运行过dbms_java.grant_permission
?您正在将错误写入控制台,因此您需要检查跟踪文件以找到它。你为什么要捕捉异常,让它们冒泡到你的会话可能更简单。
将返回类型改为字符串,并返回异常信息。
【参考方案1】:
你得到了一个异常,因为你得到了 12 个,但是你捕获了所有异常并且只用System.out.println()
显示它们,并且 Java 控制台输出进入一个跟踪文件 - 你(或你的 DBA)需要找到正确的文件并提取实际故障。
让抛出异常会更简单:
CREATE OR REPLACE JAVA SOURCE NAMED UTLCMD AS
import java.lang.Runtime;
public class UTLCMD
public static int execute(String command)
throws java.lang.InterruptedException, java.io.IOException
int exitCode = 0;
Runtime rt = java.lang.Runtime.getRuntime();
Process proc = rt.exec(command);
exitCode = proc.waitFor();
return exitCode;
/
如果我使用命令(在我的情况下为 Unix-y)运行它,那么我会看到真正的问题:
exec :n := JavaRunShellCommand('/bin/ls /tmp');
ORA-29532: Java call terminated by uncaught Java exception: java.security.AccessControlException: the Permission (java.io.FilePermission /bin/ls execute) has not been granted to ***. The PL/SQL to grant this is dbms_java.grant_permission( '***', 'SYS:java.io.FilePermission', '/bin/ls', 'execute' )
ORA-06512: at "***.JAVARUNSHELLCOMMAND", line 1
ORA-06512: at line 1
29532. 00000 - "Java call terminated by uncaught Java exception: %s"
*Cause: A Java exception or error was signaled and could not be
resolved by the Java code.
*Action: Modify Java code, if this behavior is not intended.
这与我在按照您的方式尝试时在跟踪文件中看到的相同,但更容易访问。
如果我通过发出 dbms_java.grant_permission()
调用(作为 DBA)解决我的问题,因为错误告诉我有帮助,然后重新连接,它现在可以工作了:
exec :n := JavaRunShellCommand('/bin/ls /tmp');
anonymous block completed
print n
N
-
0
当然,您很可能会遇到不同的异常,但您需要先弄清楚它是什么,然后才能开始解决真正的问题。
【讨论】:
糟糕!我说得很快。 my.bat 脚本以退出代码 7 退出,但始终返回 1。我授予了 '>'.C:\Users\pwatson\src\java>type my.bat @echo off echo now exit /b 7 的“执行”权限 它返回 1,而不是 0?即使使用/c
开关?我可能希望cmd.exe
本身不会出错,但不会与开关有关。我认为。您是否必须运行cmd.exe
,或者您可以直接在exec 调用中调用my.bat
? (这真的不是我的区域... *8-)
是的,我必须运行 cmd.exe,因为它是 my.bat 文本的解释器。 Windows 没有用于指定解释器的 shebang。无论是否使用“CALL”,它都返回 1。您已经走得更远了,但我将取消选中答案图标,希望有人可能会通过退出代码。
@Paul - 我隐约认为你可以直接执行 bat 文件。当然取决于你,但我会问一个关于这种行为的新问题 - 使用你运行的单个特定命令和 bat 文件,如果你可以从运行相同的代码获得相同的行为,则无需 Oracle 位贝壳。并且可能标有 DOS-y *8-)
如果我在 Oracle 之外运行 Java 代码,则会返回正确的退出代码。这就是你所暗示的吗?【参考方案2】:
问题是 oracle.exe 以 machine\oracle 用户身份运行,并且在我的目录中没有权限。当我将所有内容移至 C:\app\oracle\product\12.1.0\dbhome_1\BIN 时,它开始按预期工作。该解决方案来自 Oracle 社区站点。 https://community.oracle.com/thread/3669270
非常感谢所有提出建议的人。
【讨论】:
以上是关于将退出代码从 Java 返回到 PL/SQL的主要内容,如果未能解决你的问题,请参考以下文章
我可以将退出代码 %errorlevel% 从 WSL Bash 返回到 Powershell 或命令提示符吗?