title: How to get the real line number of a failing Bash command?
body: <p>In the process of coming up with a way to catch errors in my Bash scripts, I've been experimenting with "set -e", "set -E", and the "trap" command. In the process, I've discovered some strange behavior in how <code>$LINENO</code> is evaluated in the context of functions. First, here's a stripped down version of how I'm trying to log errors:</p>
  
  <pre class="lang-bash prettyprint-override"><code>#!/bin/bash
  
  set -E
  trap 'echo Failed on line: $LINENO at command: $BASH_COMMAND &amp;&amp; exit $?' ERR
  </code></pre>
  
  <p>Now, the behavior is different based on where the failure occurs. For example, if I follow the above with:</p>
  
  <pre class="lang-bash prettyprint-override"><code>echo "Should fail at: $((LINENO + 1))"
  false
  </code></pre>
  
  <p>I get the following output:</p>
  
  <pre class="lang-none prettyprint-override"><code>Should fail at: 6
  Failed on line: 6 at command: false
  </code></pre>
  
  <p>Everything is as expected. Line 6 is the line containing the single command "false". But if I wrap up my failing command in a function and call it like this:</p>
  
  <pre class="lang-bash prettyprint-override"><code>function failure {
      echo "Should fail at $((LINENO + 1))"
      false
  }
  failure
  </code></pre>
  
  <p>Then I get the following output:</p>
  
  <pre class="lang-none prettyprint-override"><code>Should fail at 7
  Failed on line: 5 at command: false
  </code></pre>
  
  <p>As you can see, <code>$BASH_COMMAND</code> contains the correct failing command: "false", but <code>$LINENO</code> is reporting the first line of the "failure" function definition as the current command. That makes no sense to me. Is there a way to get the line number of the line referenced in <code>$BASH_COMMAND</code>?</p>
  
  <p>It's possible this behavior is specific to older versions of Bash. I'm stuck on 3.2.51 for the time being. If the behavior has changed in later releases, it would still be nice to know if there's a workaround to get the value I want on 3.2.51.</p>
  
  <p><strong>EDIT:</strong> I'm afraid some people are confused because I broke up my example into chunks. Let me try to clarify what I have, what I'm getting, and what I want.</p>
  
  <p>This is my script:</p>
  
  <pre><code>#!/bin/bash
  
  set -E
  function handle_error {
      local retval=$?
      local line=$1
      echo "Failed at $line: $BASH_COMMAND"
      exit $retval
  }
  trap 'handle_error $LINENO' ERR
  
  function fail {
      echo "I expect the next line to be the failing line: $((LINENO + 1))"
      command_that_fails
  }
  
  fail
  </code></pre>
  
  <p>Now, what I expect is the following output:</p>
  
  <pre class="lang-none prettyprint-override"><code>I expect the next line to be the failing line: 14
  Failed at 14: command_that_fails
  </code></pre>
  
  <p>Now, what I <em>get</em> is the following output:</p>
  
  <pre class="lang-none prettyprint-override"><code>I expect the next line to be the failing line: 14
  Failed at 12: command_that_fails
  </code></pre>
  
  <p><strong>BUT</strong> line 12 is <em>not</em> <code>command_that_fails</code>. Line 12 is <code>function fail {</code>, which is somewhat less helpful. I have also examined the <code>${BASH_LINENO[@]}</code> array, and it does <em>not</em> have an entry for line 14.</p>