0

My shell script needs to get the result (exit status) and capture the log output from Java application, which writes to its standard output and standard error streas.

To get the status code of the Java application I can do this:

RESULT=$(java <My app>)

To get its output streams I can do this:

$java <My app> >> Mylog.txt 2>&1 || true;

But I can't find a way to get both.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Gonnix
  • 161
  • 1
  • 5

3 Answers3

1

The exit status of the most recently run program is available in the variable $?. Hence, you can do this:

 $java <My app> >> Mylog.txt 2>&1
 RESULT=$?
Raedwald
  • 46,613
  • 43
  • 151
  • 237
  • I have tried this one. It can record output log but can't catch result. "$?" is result of previous command, so I think in this case "RESULT" is result of ">>" not My app – Gonnix Nov 27 '13 at 03:57
  • ">>" is not a command or program. It tells the shell that when it does execute the program, the standard output stream of the program should be appended to the given file. In my code snippet, the entire first line is one command. – Raedwald Nov 27 '13 at 07:55
0

Best solution in standard unix way is to redirect stderr and/or stdout file descriptors:

Redirect stderr before your invokation, capture result and as soon as possible restore this:

Example:

#!/bin/bash
...
#Modify sdterr file descriptor

exec 6<&2
exec 2>$LOG_STDERR

#Your Java Invokation 
$("here invoke your java")
$RESULT = $?

#Restore sdterr file descriptor
exec 2<&6 6<&-
-1

You can use the tee command to both append your output and keep writing to stdout:

RESULT_STDOUT=$($java classname | tee -a Mylog.txt)

Here, the -a asks tee to append to Mylog.txt, if possible.

I'm not sure why you need the true there, so I excluded that. The main problem here is how to preserve the error log. If you do 2>&1 it will become part of Mylog.txt but also of the result. If storing the error log in a separate file is sufficient for you, you can redirect it with

RESULT_STDOUT=$($java classname 2>> Mylog.error.txt | tee -a Mylog.txt)

EDIT: The exit status you can get via $PIPESTATUS, as @Raedwald pointed out: Pipe output and capture exit status in Bash. The above solution captures stdout as RESULT_STDOUT only.

Community
  • 1
  • 1
creichen
  • 1,728
  • 9
  • 16
  • Your answer works nearly perfect for me, it need some modification. Your first command can't catch some part of java running log. I use "2>&1" because it can catch all output log from my java app, thank that "2 >>" in your second command resolve this issue for me . I use "|| true" because my script use "set -e" before calling this command and I want just record and non-stop if error occur. Your command will work for me if I use "java" instead of "$java" – Gonnix Nov 27 '13 at 04:20
  • So, if you do this, will `RESULT` have the exit code returned by the JVM, or the exit code returned by `tee`? – Raedwald Nov 27 '13 at 07:57
  • 1
    This answer is wrong. See also http://stackoverflow.com/questions/1221833/bash-pipe-output-and-capture-exit-status – Raedwald Nov 27 '13 at 08:00
  • My code as follow: RESULT=$(java | tee -a ); The RESULT is result of JVM. @Raedwald: Your link is useful – Gonnix Nov 27 '13 at 09:07