| Date: Tue, 7 Oct 2008 12:03:38 +0100
| From: Darragh Bailey <felix at compsoc.nuigalway.ie>
|[ ... ]
| make macro
| log = $(if $(filter 2,$(V)),2>&1 | tee -a $1,>> $1 2>&1)
|
| Problem occurs that if V=2, tee is used which results in the wrong exit
| code being received by the make rule.
|
| i.e.
| rule:
|
| somerule:
| @some_command $(call log,mylog.log)
|
| With V=1, this becomes:
| somerule:
| @some_command >> mylog.log 2>&1
|
| With V=2, this becomes:
| somerule:
| @some_command 2>&1 | tee -a mylog.log
|
| Problem is that when there is an error executing some_command and V=2,
| then make only receives the exit code of tee, which barring some problem
| in tee itself is always going to be 0.
|
| Any suggestions on how to get the output to go to the log file in all
| three cases while still resulting in the correct exit code being given
| to make?
well, I'd tell the user to run:
make V=1 RULE 2>&1 | tee -a FILE
but I do understand people don't do that when they should.
(there's numerous variations on the idea, such as using
script(1) or other session-logging commands.)
so, continuing with yer basic approach, and assuming the
underlying shell is a fairly modern version of GNU bash(1),
then try changing the rule's expansion from:
some_command 2>&1 | tee -a mylog.log
to:
set -o pipefail; some_command 2>&1 | tee -a mylog.log
from the bash(1) 3.2 man page:
If [`pipefail' is] set, the return value of a
pipeline is the value of the last (rightmost)
command to exit with a non-zero status, or zero
if all commands in the pipeline exit successfully.
This option is disabled by default.
an older trick, albeit still GNU `bash'-only, is
(I'm omitting all the spurious backslashes (\),
semicolons (;), &tc used in make(1)'s baroque syntax):
some_command 2>&1 | tee -a mylog.log
for sts in ${PIPESTATUS[*]}; do
[ $sts -eq 0 ] || exit $sts
done
WARNING: there must NOT be any commands between the pipe
and the `for'-loop. every command changes `PIPESTATUS'.
the oldest(?) trick of all, which works in most(? all?)
Bourne-ish shells (excepting the obvious trick of using
a temporary file instead of piping to tee(1)) is:
( some_command; echo $? >ERR ) 2>&1 | tee -a mylog.log
read sts <ERR && [ "$sts" -eq 0 ] || exit 1
(there's numerous variations on using a temporary file
to communicate the exit status, such as using a FIFO.)
hope this helps. (all of the examples above were just
typed in without testing. apologies for any mistakes.)
cheers!
-blf-
--
“How many surrealists does it take to | Brian Foster
change a lightbulb? Three. One calms | somewhere in south of France
the warthog, and two fill the bathtub | Stop E$$o (ExxonMobil)!
with brightly-coloured machine tools.” | http://www.stopesso.com
Maintained by the ILUG website team. The aim of Linux.ie is to
support and help commercial and private users of Linux in Ireland. You can
display ILUG news in your own webpages, read backend
information to find out how. Networking services kindly provided by HEAnet, server kindly donated by
Dell. Linux is a trademark of Linus Torvalds,
used with permission. No penguins were harmed in the production or maintenance
of this highly praised website. Looking for the
Indian Linux Users' Group? Try here. If you've read all this and aren't a lawyer: you should be!