如何从Java程序返回一些值给shell?

8
我希望能够从shell脚本中运行Java程序。因此我做了以下操作:
我的测试Java文件如下:
public class EchoTest {
    public static void main (String args[]) {
    System.out.println ("scuccess ..!!");
}

我的测试shell脚本文件如下:

out=$(java EchoTest)    
echo $out

我已经编译了Java程序,然后运行了shell脚本(例如$sh Myscript.sh)。现在它将输出打印到控制台上。到目前为止,一切都很好。
如果我写了一个像下面这样的程序(会抛出一些异常):
  public class EchoTest {
        public static void main (String args[]) {
        System.out.println ("Value is "+(2/0));
    }

它只是将Java异常打印到控制台上。但我的要求是,我希望它在控制台上打印0或1,即当我的Java程序失败时,我想得到0(零),并且当Java程序成功执行时,我想得到1(一)。


错误信息不会显示在正常输出中,你尝试过使用 echo $err 吗? - Frederic Henri
1
如果你想返回一个类Unix风格的返回值,请查看System.exit(int)。 - chsh
不是这样的@chsh,我只想在Java程序失败时打印零或一些我自己的失败消息。 - prasad
1
2/0总是会抛出ArithemeticException,因为数学不允许你除以零。 - Powerlord
嗨@Powerlord,只是举个例子,我问了那个。 - prasad
显示剩余2条评论
4个回答

6

Java程序的文档说明如下:

退出状态

通常情况下,启动器返回以下退出值,当使用错误参数、重大错误或从Java虚拟机抛出异常时。然而,Java应用程序可以使用API调用System.exit(exitValue)来返回任何值。

  • 0:成功完成。
  • >0:发生错误。

因此,如果您不做任何操作,JVM会按照惯例在成功完成时向调用者返回0值,在出现错误时返回非空值。

因此,您的shell脚本应该是:

java EchoTest
if [ $? -eq 0]
then echo 1
else echo 0
fi

这意味着你可以忽略标准输出和标准错误,仅仅依赖于JVM的退出状态。

正如@alk所建议的那样,你甚至可以用out = $( java EchoTest )替换第一行,并在成功分支(当$?0时)中使用$out


这也可以与第一种方法相结合,通过执行 out=$(java EchoTest) 并仅在“成功”分支中打印出 out,即 $? 等于 0 时。 - alk
@prasad:通过将stdout重定向到错误文件,将错误消息发送到错误文件中,例如out=$(java EchoTest 2>error.log),并在“失败”分支中使用cat error.log或者如果您不感兴趣错误消息,只需将error.log替换为/dev/null - alk
嗨@alk,你的意思是这样吗? out=$(java EchoTest 2>error.log) if [ $? -eq 0 ] then echo "1" else cat error.log fi - prasad
@prasad:通过文件传递时有些细微差别: 你应该避免同时启动2个或更多的shell。但是只要您仅启动一个,它肯定是一个不错且简单的解决方案。不使用文件的替代方法需要专门的程序。 - Serge Ballesta
@SergeBallesta,你能提供一下脚本吗? - prasad
无论如何,非常感谢大家,特别感谢 @alk。 - prasad

4

在检测到错误/异常与否时,您需要使用带有所需代码的System.exit(code)

您将拥有

System.exit(0) // if you detect error, you need to handle exception
System.exit(1) // when no error

3
我在这里还要说明,大多数程序在成功运行时返回0,并返回大于0的数字来表示特定错误。 - Powerlord
3
他的意思很清楚,当我的Java程序执行失败时,他特别提到了0(零),而当Java程序成功执行时,他希望得到1(一)。 - Frederic Henri

1
一个更完整的处理程序从shell输出的示例可能是:
#!/bin/bash
#
# run.sh command
#
# Runs command and logs the outcome to log.<pid> and err.<pid>.
#

cmd=${1}

# Run cmd and log standard output (1) to log.<pid> and standard error (2) to err.<pid>.
$cmd 1>log.$$ 2>err.$$

# Copy the return code from cmd into result.
result=$?

# Test whether result is 0.
if [ $result -eq 0 ]; then
   echo "$cmd" succeeded.
   cat log.$$
else
   echo "$cmd" failed with result = $result!
   cat err.$$
fi

exit $result


# eof

$$ 评估了 shell 的 pid,因此代码可以与其自身的副本并行运行。

像这样调用上面的脚本:

$ run.sh "java myprogram"

嗨@alk,终于我从这个脚本中得到了期望的输出。 - prasad
嗨@alk,你能解释一下这行语句吗,cmd="java EchoTest"$cmd >log.$$ 2>err.$$result=$? - prasad
@prasad:要理解这行代码的含义,您需要阅读有关标准流的内容。您可以在此处进行阅读:https://en.wikipedia.org/wiki/Standard_streams - alk

0
非常感谢大家的回复。我用下面这个脚本解决了问题,但我不知道这里发生了什么事情,请您解释一下。

cmd="java EchoTest"

$cmd >log.$$ 2>err.$$

result=$?

if [ $result -eq 0 ]; then

   echo "1"

else

    echo "0"

   #echo $result

fi

rm log.$$ >/dev/null

rm err.$$ >/dev/null

1
@prasad:这并不是真正的答案,但我理解你无法在评论中放置代码 :-)。如果alk添加到其答案中的评论足够了,您应该删除它(并接受alk的答案...) - Serge Ballesta
是的@SergeBallesta,这个解决方案仅基于alk的评论,我只是稍微修改了一下。 - prasad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接