Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I am attempting to do the following in a bash script and am wondering if it is possible:

  • Time the output of a command (in this case, mysql) using time
  • Suppress the stdout output of the command
  • Capture the stderr output of the command in case of an error
  • Check the exit status code of the command after running it

This is a complex chain and I haven't had much luck getting it all to work together. I can get the status code to work if I cease using time.

This is what I had so far:

# the setup
TIMEFORMAT=%R
MYSQL=mysql <options>

# execute and time a query (does more than is listed here)
function executeQuery {

  TIME=$( time ( $MYSQL "$1" 2>&1 | tee /tmp/somefile.txt > /dev/null ) 2>&1 )

  # do something with $?

}

I am redirecting any error response from the command to a file using tee, and then sending the resulting stdout to /dev/null. I am then redirecting the time command's stderr to stdout, which should end up in $TIME.

Now if I change that line to something like:

  TIME=$( time ( $MYSQL "$1" 2>&1 | tee /tmp/somefile.txt > /dev/null; exit ${PIPESTATUS[0]} ) 2>&1 )

It correctly sends back the exit code from mysql, but breaks the time command.

Is this even possible? Have I missed something? Hopefully the goal is clear.

Thanks!

share|improve this question

1 Answer 1

up vote 2 down vote accepted

bash time is a major PITA. Its output isn't redirectable without nasty shell hacks like your multiple levels of subshells. http://mywiki.wooledge.org/BashFAQ/032 suggests that the correct answer is:

TIME = $( ( time $MYSQL "$1" 2>&1 | tee /tmp/somefile.txt > /dev/null; exit ${PIPESTATUS[0]} ) 2>&1 )

Note that bash time takes an entire pipeline as an argument, so placing the subshell after the time invocation is incorrect.

This was tested with

TIME = $( ( time ls /asdfasfdsfs 2>&1 | tee asdf 2>&1 >/dev/null ; exit ${PIPESTATUS[0]} ) 2>&1 );
echo $?;
echo $TIME

Which gave me

2
real 0m0.003s user 0m0.004s sys 0m0.004s
share|improve this answer
    
Worked perfectly -- many thanks! Looks like the only thing I was missing was moving time into the same subshell as the command chain. Makes sense now that I think about it. –  futureal Dec 5 '12 at 18:39

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.