title: A good way to capture standard error and standard output
body: <p>This works well except it merges the standard error stream into the standard out stream of the sourcing script.  Any suggestions on how to fix it?</p>
  
  <pre><code>#!/usr/bin/env bash
  
  # Source this from a script to capture and `tee` standard error and standard 
  # out to a log file. Calling script must source this script.  For Example:
  #
  # . /usr/bin/logy /var/log/project/$0.log
  #
  # The logging uses &gt;(process substitution). Process substitution is supported 
  # in shells like bash and zsh but is not supported in sh.
  
  _LOG=${1?log file}
  test $# -eq 1 || exit 1
  
  mkdir -p "$(dirname "$_LOG")"
  
  # Append stdout and stderr to log file
  exec &gt; &gt;(
    echo -e "START\t$(date)" &gt;&gt; "$_LOG"
    tee -a "$_LOG"
    echo -e "END\t$(date)" &gt;&gt; "$_LOG"
  ) 2&gt;&amp;1
  </code></pre>
  
  <p>Here is an example:</p>
  
  <pre><code>. /usr/bin/logy $0.log
  echo stdout
  echo stderr &gt;&amp;2
  exit 1
  </code></pre>
  
  <p>Run the script:</p>
  
  <pre><code>$ ./t
  $ echo $?      # $? is the return value
  1
  </code></pre>
  
  <p>Good, the return value 1 was preserved...</p>
  
  <p>What was logged?</p>
  
  <pre><code>$ cat t.log
  START    Thu, Feb 07, 2013  2:58:57 PM
  stdout
  stderr
  END    Thu, Feb 07, 2013  2:58:57 PM
  </code></pre>
  
  <p>The idea is to make single log file and then use <code>logrotate</code> to maintain them.</p>
  
  <p>Here is the issue.  The standard out and error streams were merged.  This outputs noting showing that the standard error stream went to standard out:</p>
  
  <pre><code>./t &gt; /dev/null
  </code></pre>
  
  <p>This outputs both lines from the echo statements showing both went to standard out:</p>
  
  <pre><code>./t 2&gt; /dev/null
  </code></pre>
  
  <p>Is there a good way to preserve the streams while preserving the order in the log file of the stdout/err statements?  For that reason, I don't think two <code>exec</code> statements are an option.</p>