4

I pipe the output of a long-running build process through sed for syntax-highlighting, implemented as a wrapper around "mvn".

Further I have a "monitor" script that notifies me on the desktop when the build is finished. The monitor script checks the exit state of its argument and reports "Success" or "Failure".

By piping the maven output through sed, the exit status is always "ok", even when the build fails.

How can I pipe the correct exit status through sed as well?

Are there alternatives ?

Bastl
  • 1,431
  • 3
  • 14
  • 15

6 Answers6

4

Maybe the PIPESTATUS variable can help.

Sjoerd
  • 74,049
  • 16
  • 131
  • 175
2

If you are using Bash, there's an option to use the set -o pipefail option, but since it's bash dependent, it's not portable, and won't work from a crontab, unless you wrap the whole thing in a bash env (bad solution).

http://bclary.com/blog/2006/07/20/pipefail-testing-pipeline-exit-codes/

Lee Hambley
  • 6,270
  • 5
  • 49
  • 81
1

This is a well known pain in the rear. If you are using bash (and probably many other modern sh variants), you can access the PIPESTATUS array to get the return value of a program earlier in the pipe. (Typically, the return value of the pipe is the return value of the last program in the pipe.) If you are using a shell that doesn't have PIPESTATUS (or if you want portability), you can do something like this:

#!/bin/sh

# run 'echo foo | false | sed s/f/t/', recording the status
# of false in RV
eval $( { { echo foo | false; printf RV=$? >&4; } |
     sed s/f/t/ >&3; } 4>&1; ) 3>&1
echo RV=$RV

# run 'echo foo | cat | sed s/f/t/', recording the status
# of cat in RV
eval $( { { echo foo | cat; printf RV=$? >&4; } |
     sed s/f/t/ >&3; } 4>&1; ) 3>&1
echo RV=$RV


In each case, RV will contain the return value of the false and the cat, respectively.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

Bastil, because the pipe doesn't care about the exit status, you can only know whether sed exits sanely or not. I would enhance the sed script (or perhaps consider using a 3-liner Perl script) to exit with a failure status if the expected text isn't found, something like in pseudocode:

read($stdin)
if blank
  exit(1) // output was blank, or on $stderr
else
  regular expression substitution here
end
// natural exit success here

You could do it as a perl one-liner, and the same can be done in sedscript (but not in a sed one-liner, as far as I know)

Lee Hambley
  • 6,270
  • 5
  • 49
  • 81
  • But that would do the regex-substituion only after the whole output is generated and not in a streamed "sed" fashion, right? My PERL knowledge is quite deprecated ... – Bastl Feb 11 '11 at 11:57
  • Entirely possible, you could also do it on a while() read loop in perl, reading lines as long as you have some, with a fall-back for incase there are no lines.. if that sounds reasonable, I can help you write something up (expect it to be less than a five-liner!) – Lee Hambley Feb 11 '11 at 13:13
0

Perhaps you could use a named pipe? Here's an example:

FIFODIR=`mktemp -d`
FIFO=$FIFODIR/fifo
mkfifo $FIFO

cat $FIFO &                # An arbitrary pipeline
if false > $FIFO
then
    echo "Build succeeded"
else
    echo "Build failed"    # This line WILL execute
fi

rm -r $FIFODIR
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
0

A week later I got a solution:

Originally I wwanted to do

monitor "mvn blah | sed -e SomeHighlightRegEx"

where monitor would reacts on exit status of sed (instead of mvn).

It's easier to do

monitor "mvn blah" | sed -e SomeHiglightRegEx

Note that this pipes the output of monitor through sed, while the monitor script reacts on status of mvn.

Thanks anyway for the other ideas.

Bastl
  • 1,431
  • 3
  • 14
  • 15