从java运行shell脚本 - 无法完成任务

时间:2011-12-11 14:02:03

标签: java shell runtime

我有一个应该启动shell脚本的java程序。该脚本包含6个要按顺序执行的任务。 java程序启动脚本并启动(我看到日志)。但是在10-15秒之后,即使在shell脚本中的第一个任务完成之前,执行也会停止。奇怪的是,当我在终端中启动它时脚本运行正常。为了避免程序在执行脚本时挂起,我将在单独的线程中启动它。可能是什么原因?

Java代码 -

try {   
            log.info("run cmd - "+optionsRun);

            String[] cmdLine = (String[]) optionsRun.toArray(new     String[optionsRun.size()]);

            Process process = Runtime.getRuntime().exec(cmdLine);
            log.info("end run cmd " + this.getScriptPath());

//          
//          BufferedWriter writer = new BufferedWriter(new     OutputStreamWriter(process.getOutputStream()));
//          writer.write("mypwd");
//          writer.flush();
//          writer.close();


            InputStream is = process.getErrorStream();
            String error = inputStreamToStringValue(is);
            log.trace("Eventual error was : " + error);

            InputStream os = process.getInputStream();
        String output = inputStreamToStringValue(os);
            log.info("Eventual output was : " + output);

            if (error!=null & error.length()>0) {
                throw new ActionProcessingException("An error occurred when     running the script :'"+this.getScriptPath()+"' with following error message : "+error);    
            }else {
                log.info("Script run ended successfully.");
            }

shell脚本看起来就是这样 -

#!/bin/sh
# ./publish <path-to-publish-home-folder> <workspace_id> <start_date> <end_date>
# ./publish <path-to-publish-home-folder> 100011 2010-01-06-12:00:00-CET     2012-01-14-19:00:00-CET

rm -f $1/publish.log
echo 'Start publish' >> $1/publish.log
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 >> $1/publish.log

# lancement de l'export RDF du domaine
cd $1/1-export-domain
echo "Starting export domain with the command - ./export.sh $2" >> $1/publish.log
./export.sh $2

# lancement de l'export des translations du domaine
cd $1/2-export-trans
echo "Starting export domain(translated) with the command - ./export.sh $2" >>         $1/publish.log
./export.sh $2
.....
.....
a couple of more steps like 1 and 2
....

提前致谢,

2 个答案:

答案 0 :(得分:1)

我不确定,但我会推荐两个可能帮助您解决问题的链接。

第一个是关于Runtime.exec()的非常古老的:

http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

第二个约为ProcessBuilder,新类旨在取代Runtime.exec()

http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html

答案 1 :(得分:1)

我无法确定我的猜测是问题出在您的方法inputStreamToStringValue(is)中。它读取STDERR并且在读取时阻塞。当它没有从STDERR读取任何内容但该进程尚未终止时,您将永远被阻止。

我建议您使用ProcessBuilder:

    ProcessBuilder b = new ProcessBuilder();
    b.redirectErrorStream(true);

现在您可以一起阅读STDIN和STDERR。

如果您仍想单独阅读它们,您有2个解决方案。

首先按照您现在的操作进行,但不要阻止读取,即在每次读取调用之前调用in.available(),然后只读取以前可用的字节数。

第二种方法是使用shell重定向。运行脚本并将其STDOUT和STDERR重定向到临时文件。然后等待您的进程终止,然后从文件中读取。我个人认为这种解决方案更容易,更强大。

祝你好运。