title: Bash: Checking for exit status of multi-pipe command chain
body: <p>I have a problem checking whether a certain command in a multi-pipe command chain did throw an error. Usually this is not hard to check but neither <code>set -o pipefail</code> nor checking <code>${PIPESTATUS[@]}</code> works in my case. The setup is like this:</p>
  
  <pre><code>cmd="$snmpcmd $snmpargs $agent $oid | grep &lt;grepoptions&gt; for_stuff | cut -d',' f$fields | sed 's/ubstitute/some_other_stuff/g'"
  </code></pre>
  
  <p>Note-1: The command was tested thoroughly and works perfectly.</p>
  
  <p>Now, I want to store the output of that command in an array called <code>procdata</code>. Thus, I did:</p>
  
  <pre><code>declare -a procdata
  procdata=( $(eval $cmd) )
  </code></pre>
  
  <p>Note-2: <code>eval</code> is necessary because otherwise <code>$snmpcmd</code> throws up with an <code>invalid option -- &lt;grepoption&gt;</code> error which makes no sense because <code>&lt;grepoption&gt;</code> is not an <code>$snmpcmd</code> option obviously. At this stage I consider this a bug with <code>$snmpcmd</code> but that's another show...</p>
  
  <p>If an error occurres, <code>procdata</code> will be empty. However, it might be empty for two different reasons: either because an error occurred while executing the <code>$snmpcmd</code> (e.g. timeout) or because <code>grep</code> couldn't find what it was looking for. The problem is, I need to be able to distinguish between these two cases and handle them separately. </p>
  
  <p>Thus, <code>set -o pipefail</code> is not an option since it will propagate any error and I can't distinguish which part of the pipe failed. On the other hand <code>echo ${PIPESTATUS[@]}</code> is always <code>0</code> after <code>procdata=( $(eval $cmd) )</code> even though I have many pipes!?. Yet if I execute the whole command directly at the prompt and call <code>echo ${PIPESTATUS[@]}</code> immediately after, it returns the exit status of all the pipes correctly.</p>
  
  <p>I know I could bind the err stream to stdout but I would have to use heuristic methods to check whether the elements in <code>procdata</code> are valid or error messages and I run the risk of getting false positives. I could also pipe stdout to <code>/dev/null</code> and capture only the error stream and check whether <code>${#procdata[@]} -eq 0</code>. But I'd have to repeat the call to get the actual data and the whole command is time costly (ca. 3-5s). I wouldn't want to call it twice. Or I could use a temporary file to write errors to but I'd rather do it without the overhead of creating/deleting files.</p>
  
  <p>Any ideas how I can make this work in bash?</p>
  
  <p>Thanks</p>
  
  <p>P.S.:</p>
  
  <pre><code>$ echo $BASH_VERSION
  4.2.37(1)-release
  </code></pre>