A Bourne shell irritation: piping just stderr

April 26, 2009

I generally like the Bourne shell, but I will easily admit that it has a number of things that are less than ideal. One of those less than ideal things is a peculiar omission: you cannot easily redirect just standard error into a pipeline.

This sounds like a peculiar thing to want, but there are situations where you do need to process stderr separately; for example, you might need to timestamp all stderr output and log it. In a hypothetical shell with this feature you could have a 'timestamper' program and just write:

process |[2] timestamper >>error-log

In the Bourne shell, not so much. You can do it, but it is what you would call intricate:

exec 3>&1
process 2>&1 >&3 3>&- | timestamper >>error-log

What's going on here is that first we save a copy of the real stdout on file descriptor 3, and then in the command itself we:

  • send stdout to the timestamper process (remember, pipelines are set up before redirection)
  • redirect stderr to stdout, which is the pipeline
  • redirect stdout to fd 3, which is our original stdout
  • close fd 3 so that process does not inherit a surprise file descriptor.

(We must save the original stdout separately via exec because of the pipeline vs redirection timing issue; if we wrote 'process 3>&1 ...' we would be capturing the pipe'd stdout, not the original stdout.)

(This incantation is not original to me; I've seen it written up elsewhere on the Internet, but I never really understood it until I wrote out everything here (sort of cf, especially the comment).)


Comments on this page:

If you have a shell with working process substitution then you can use that to make the incantation reasonable:

process 2> >( timestamper >> error-log )
Written on 26 April 2009.
« Lighttpd, CGIs, and standard error
The problems of over-documenting things »

Page tools: View Source, View Normal, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sun Apr 26 02:03:21 2009
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.