getting status from first element of pipeline in Bourne shell

getting status from first element of pipeline in Bourne shell

Post by Dan DeJoh » Thu, 15 May 2003 05:35:07



I need to route the output of a command to both the terminal and a file,
but I still need access to the command status (because this is being
done in a makefile).

Suppose the command is blotz, then the make rule

A : B
         blotz -o A B

will run the blotz command on file B and produce file A. The messages
from blotz are sent to the terminal, and make properly stops if blotz
returns a non-zero exit status.

Now to log the output to a file I try this:

A : B
         blotz -o A B | tee make_output

The blotz messages now go to the terminal and into the make_output file,
but make gets the exit status of the tee command instead of the blotz
command. Make can't tell when the blotz command fails.

I can just redirect the blotz output

A : B
         blotz -o A B > make_output

but the blotz command takes a long time and prints progress messages
which I would like displayed as well as logged.

Is there a way to get the exit status from the first element of a
command pipeline? Or is there some other way to get the messages into a
file and onto the terminal without piping the result through tee?

Thanks.

Dan

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Barry Margoli » Thu, 15 May 2003 05:44:27




Quote:>Is there a way to get the exit status from the first element of a
>command pipeline? Or is there some other way to get the messages into a
>file and onto the terminal without piping the result through tee?

Bourne shell doesn't provide any way to get the status of any but the last
command in a pipeline (bash has the $PIPESTATUS array for this).

Can you redirect the output to a file and then use "cat filename" to get it
to the terminal?

--

Genuity Managed Services, a Level(3) Company, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Ed Morto » Fri, 16 May 2003 01:13:58



> I need to route the output of a command to both the terminal and a file,
> but I still need access to the command status (because this is being
> done in a makefile).

<snip>

Quote:> Is there a way to get the exit status from the first element of a
> command pipeline? Or is there some other way to get the messages into a
> file and onto the terminal without piping the result through tee?

> Thanks.

> Dan

Here's a workaround that I think will do what you want:

Create an executable file called something like "teecmd" containing this script:

----------------------------
_log=$1                 # remember the log file name
shift                   # skip over it

Quote:> ${_log}               # create the empty log file

tail +0f ${_log} &      # start tailing the log file
_pid=$!                 # remember the PID for the tail process
${_cmd} > ${_log}       # execute the command
_ret=$?                 # remember the commands exit code
kill -9 ${_pid}         # kill the tail process
exit ${_ret}            # exit with the commands exit code
-----------------------------

Now modify your Makefile to:

A : B
         teecmd make_output blotz -o A B

and you'll see the blotz output as it's being produced, plus teecmd will return
the exit code from blotz to your Makefile.

Regards,

    Ed.

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Dan DeJoh » Fri, 16 May 2003 01:54:57


Thanks for the script, Ed. I was just about to write the equivalent in
C, because I'm more familiar with C than sh, but your script is a much
better solution.

Thanks again.

Dan



>>I need to route the output of a command to both the terminal and a file,
>>but I still need access to the command status (because this is being
>>done in a makefile).

> <snip>

>>Is there a way to get the exit status from the first element of a
>>command pipeline? Or is there some other way to get the messages into a
>>file and onto the terminal without piping the result through tee?

>>Thanks.

>>Dan

> Here's a workaround that I think will do what you want:

> Create an executable file called something like "teecmd" containing this script:

> ----------------------------
> _log=$1                 # remember the log file name
> shift                   # skip over it

>>${_log}               # create the empty log file

> tail +0f ${_log} &      # start tailing the log file
> _pid=$!                 # remember the PID for the tail process
> ${_cmd} > ${_log}       # execute the command
> _ret=$?                 # remember the commands exit code
> kill -9 ${_pid}         # kill the tail process
> exit ${_ret}            # exit with the commands exit code
> -----------------------------

> Now modify your Makefile to:

> A : B
>          teecmd make_output blotz -o A B

> and you'll see the blotz output as it's being produced, plus teecmd will return
> the exit code from blotz to your Makefile.

> Regards,

>     Ed.

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Dan DeJoh » Fri, 16 May 2003 02:46:26


Ed,

I found one detail while testing your script. If the command (_cmd)
finishes quickly, then tail gets killed before it ever gets a chance to
write anything. For that matter, tail will fail to write everything that
cmd writes during the last second or so of its execution (since this is
how often tail checks for a file size change).

My inelegant solution is to put a "usleep 1500000" command before the
kill command, to give tail a chance to write cmd's final output. Any
better ideas?

Finally, sometimes running the script produces the message:

teecmd: line 13:  1563 Killed                  tail +0f ${_log}

and sometimes it doesn't. I assume this is a timing issue, involving
when the tail command actually dies and when the teecmd completes.
Anyway, it would be great if there were a way to ensure that the
"Killed" message never appeared. I don't want the users of this script
to become desensitized to seeing "Killed" messages.

Dan



>>I need to route the output of a command to both the terminal and a file,
>>but I still need access to the command status (because this is being
>>done in a makefile).

> <snip>

>>Is there a way to get the exit status from the first element of a
>>command pipeline? Or is there some other way to get the messages into a
>>file and onto the terminal without piping the result through tee?

>>Thanks.

>>Dan

> Here's a workaround that I think will do what you want:

> Create an executable file called something like "teecmd" containing this script:

> ----------------------------
> _log=$1                 # remember the log file name
> shift                   # skip over it

>>${_log}               # create the empty log file

> tail +0f ${_log} &      # start tailing the log file
> _pid=$!                 # remember the PID for the tail process
> ${_cmd} > ${_log}       # execute the command
> _ret=$?                 # remember the commands exit code
> kill -9 ${_pid}         # kill the tail process
> exit ${_ret}            # exit with the commands exit code
> -----------------------------

> Now modify your Makefile to:

> A : B
>          teecmd make_output blotz -o A B

> and you'll see the blotz output as it's being produced, plus teecmd will return
> the exit code from blotz to your Makefile.

> Regards,

>     Ed.

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Ed Morto » Fri, 16 May 2003 03:39:36


Dan -


> Ed,

> I found one detail while testing your script. If the command (_cmd)
> finishes quickly, then tail gets killed before it ever gets a chance to
> write anything.

<snip>

Quote:> Finally, sometimes running the script produces the message:

> teecmd: line 13:  1563 Killed                  tail +0f ${_log}

Some versions of tail (e.g the GNU version, I believe) support a "--pid=PID" option so
that tail itself will die when the specified process PID dies. You might be able to
remove the "kill" command by running "tail --pid=$$ ...". That'd solve both problems,
assuming that tail only handles it's death after checking for more to output.
Otherwise for the first problem you could consider the sleep you suggested (though I'd
have just done a "sleep 1" since I believe tail checks for output every 1 second so
this should be enough - you could check/test that) or additionally (if want to be sure
tail is caught up) tailing to tee into another file and killing the tail when that
other file is identical to your log file, and for the second problem you could try
redirecting stderr from the kill command (or from teecmd itself if that's not enough)
to /dev/null though then you'd lose other error messages too.

    Ed.

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Ed Morto » Fri, 16 May 2003 04:28:29


Dan - This seems to work for me with the GNU version of tail:

_log=$1                 # remember the log file name
shift                   # skip over it

Quote:> ${_log}               # create the empty log file

tail --pid=$$ -f ${_log} &   # start tailing the log file
${_cmd} > ${_log}       # execute the command
exit $?                 # exit with the commands exit code

Regards,

    Ed.

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Kevin Rodger » Fri, 16 May 2003 04:39:28



> I need to route the output of a command to both the terminal and a file,
> but I still need access to the command status (because this is being
> done in a makefile).

> Suppose the command is blotz, then the make rule

> A : B
>         blotz -o A B

> will run the blotz command on file B and produce file A. The messages
> from blotz are sent to the terminal, and make properly stops if blotz
> returns a non-zero exit status.

> Now to log the output to a file I try this:

> A : B
>         blotz -o A B | tee make_output

> The blotz messages now go to the terminal and into the make_output file,
> but make gets the exit status of the tee command instead of the blotz
> command. Make can't tell when the blotz command fails.

> I can just redirect the blotz output

> A : B
>         blotz -o A B > make_output

> but the blotz command takes a long time and prints progress messages
> which I would like displayed as well as logged.

Why don't you leave your Makefile alone and run make like this:

make 2>&1 | tee make_output

--

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Dan DeJoh » Fri, 16 May 2003 05:20:58


Kevin

Quote:

> Why don't you leave your Makefile alone and run make like this:

> make 2>&1 | tee make_output

Good question. The hidden information is that the blotz command whose
output I  want to collect is actually make! This is the command part of
a pattern rule in a master makefile.

The master makefile contains pattern rules that tell how to make various
directories' contents. In some cases, the command is a recursive make. I
want the _parent_ make to stop if the sub-make fails.

$R/%/c : FORCE

$R/%/bx : FORCE

Dan

 
 
 

getting status from first element of pipeline in Bourne shell

Post by Thomas Weidenfell » Sun, 18 May 2003 01:20:47



> Now to log the output to a file I try this:

> A : B
>          blotz -o A B | tee make_output

> The blotz messages now go to the terminal and into the make_output file,
> but make gets the exit status of the tee command instead of the blotz
> command. Make can't tell when the blotz command fails.

With a little bit of file descriptor messing:

A: B
        exit `{ { blotz -o A B; echo $? >&3; } | tee make_output; } 3>&1`

/Thomas

 
 
 

1. Getting at the first char of a string in Bourne shell

I am trying to peel off one at a time the letters from a variable
in the Bourne shell, ie from Bourne get B and ourne.
How can I do this?
Thanks in advance.

----------------------------------------------------------------------
Ken Braithwaite            | They couldn't hit an elephant at
                           |   this dist
These opinions are solely  |       last words, General Sedgwick
my own. I don't share.     |
----------------------------------------------------------------------

2. Passing options to remote Solaris printers

3. Bourne shell and variable substitution of pipelines

4. NTFS support?

5. Trying to run nohup from Korn shell but getting Bourne shell errors

6. HD geometry problems on PS/1

7. best practice for getting exit status of pipeline commands (bash, ksh, etc)

8. Problems setting PythonPath

9. getting environment variables from c shell using Bourne shell

10. Status from first process in a pipeline

11. Light Speed Bourne Shell! (was: Bourne shell tricks)

12. Having problems passing an exit() status to bourne shell

13. Capturing exit statuses in bourne shell...