调用外部程序异步行为的Java程序?

时间:2013-11-07 11:53:59

标签: java shell asynchronous sql-loader

所有

我最初有一个名为SQLLoader的shell脚本(Oracles数据上传工具)。

问题是SQLLoader采用纯文本密码作为输入,因此我决定构建一个Java应用程序来调用SQLLoader,在内部将解密的密码传递给命令字符串。

e.g。

  

sqlldr user / pass @ DBServer control = .. / sqlloader.ctl log = sqlloader.log data = mydata.csv

因此,使用我的java包装器,它在我的shell脚本

中成为了这个
java -jar sqlloader.jar sqlloader.ctl mydata.csv

然而,当SQLLoader抱怨没有要加载的文件时,会出现一个新问题。经过一番搔痒后,发现当我的java应用程序仍在运行时,我的shell脚本中的后续命令似乎正在执行。因此它表现异步。

下一个命令是移动sqlloader使用的输入文件,然后才有机会使用它。所以我在20秒内放入一个sleep命令,让我的java应用程序有时间运行。

java -jar sqlloader.jar sqlloader.ctl mydata.csv
echo $?
sleep 20
if [ $? -ne 0 ]
    then
        echo "SQLLoader failed during execution, please check the log : " 
        mv mydata.csv

else
    echo "SQLLoader successfully processed file : "
    mv mydata.csv
fi

有没有人知道为什么unix的表现如此,Java是否将我的SQLLoader作为不同的用户/线程执行?

这是我的java代码:

    Runtime Rt;
Process Prc;
    Prc = Rt.exec("sqlldr user/decryptedpass@DBServer control=../sqlloader.ctl log=sqlloader.log data=mydata.csv);
system.exit(0);

我检查了运行时类有关它是异步但无法找到任何内容的任何内容

http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html

任何理论或建议?

由于

2 个答案:

答案 0 :(得分:3)

是。如果再次查看Runtime.exec,它会指定它将在指定环境中启动新进程(例如,独立于当前“环境”或异步放置)。您应该使用ProcessBuilder创建Process,然后在调用System.exit之前等待该进程完成 - 这当然不是强制性的。像这样的东西

public static void main(String[] args) {
    // String command = "/usr/bin/sleep 5";
    List<String> command = new ArrayList<String>();
    command.add("c:/cygwin/bin/sleep");
    command.add("5");
    ProcessBuilder pb = new ProcessBuilder(command);
    BufferedReader is = null;
    try {
        System.out.println("Starting command " + command);
        Process p = pb.start();

        int ret = p.waitFor();
        is = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        while ((line = is.readLine()) != null) {
            System.out.println(line);
        }
        if (ret == 0) {
            System.out.println("Command has completed.");
            System.exit(ret);
        } else {
            System.out.println("Command completed with return code " + ret);
            System.exit(ret);
        }
    } catch (Exception e) {
        System.out.println("Caught Exception " + e.getMessage()
                + " running command " + command);
        e.printStackTrace();
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
            }
        }
    }
    System.out.println("COMMAND FAILED");
    System.exit(1);
}

答案 1 :(得分:2)

您需要等待流程完成,您还应该从正在启动的流程中读取所有输出(stdout stderr)。

如果你在exec()之后调用exit(),Java就会这样做 - 立即退出。

这是一篇解释Runtime.exec陷阱的文章:http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4(也考虑其他页面)。