将退出代码从 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的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL 编译失败时如何让 SQL*Plus 退出

发生错误时退出执行 PL/SQL

我可以将退出代码 %errorlevel% 从 WSL Bash 返回到 Powershell 或命令提示符吗?

Oracle PL/SQL - 如果不满足条件,则退出开始结束块

Java已启动但​​返回退出代码13 [重复]

STS 启动错误 - Java 已启动但返回退出代码 = 13