I'm writing a lot of manuals on how to accomplish things in bash. Often I'm showing people something that doesn't work, and then go on to show what works. When I'm showing something that doesn't work, the bash exit code is non-zero, and the result isn't captured by org. So as a general rule I just add "|| true" to most bash statements. But this is a bit ugly, is there a better way? so that after I do "org-publish" to html, my blog post is not littered with "|| true"

# -*- org-export-babel-evaluate: nil -*-
#+PROPERTY: header-args:sh :prologue exec 2>&1 :epilogue :

#+BEGIN_SRC sh :exports both :dir /ssh:ubuntu@
bundle exec rails server || true

: sh: 2: bundle: not found

Somewhat related http://kitchingroup.cheme.cmu.edu/blog/2015/01/04/Redirecting-stderr-in-org-mode-shell-blocks/


You're nearly there; you have a :prologue set, via exec 2>&1, to capture both stdout and stderr. To finish this, you just need two things:

  1. :results: output to inform Babel that you want the results from what gets written out, not by what the code returns; and
  2. :epilogue "true", to do what you're doing above with || true unilaterally and always without cluttering the code blocks.


#+BEGIN_SRC sh :exports both :dir /tmp :results output :prologue "exec 2>&1" :epilogue "true"
echo hi
echo 'echo "$@" 1>&2;' > echoerr
chmod +x echoerr
./echoerr this is an error
nonesuch cmd
echo bye
false # guarantee failure

: hi
: this is an error
: sh: 6: nonesuch: not found
: Tue Apr  9 18:41:00 EDT 2019
: bye

Above, we've captured program error, shell error, and syntax error, as well as stdout, of course, all into RESULTS. You can inject this into your ob-shell environment via your preferred systemwide or per-file method rather than in each individual #+BEGIN_SRC header (as you showed in your example above).

(Note, by the way, the quotes around the :prologue and :epilogue arguments; perhaps there's a versioning thing going on between us or something more subtle, but I couldn't get the effect you were getting with merely :prologue exec 2>&1 without quotes.)

p.s. One thing you mustn't do, though: return $NONZERO_VALUE. An explicit return in the code block will short-circuit the rest of the block including the epilogue, and you'll fail execution again.

  • 2
    faken genius mate, tested with tramp session too – american-ninja-warrior Apr 10 '19 at 1:04
  • This is brilliant, thank you! To get the exit code of the last command, you can use this as the epilogue: :epilogue "ret=$? ; [ 0 -eq $ret ] || echo \"exit code: $ret\"". – hraban May 24 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.