72

I am currently exploring Debian packages, and I have been reading some code samples. And on every line in, for example, the postinst script is a pattern.

some command || true
another command || true

So if some command fails, then the line returns true but I don't see how this affects the output of the program.

  • 3
    FYI, ||: is another idiomatic way of writing this (: being another entry in the builtin table pointing to true -- but guaranteed to be a builtin even back to Bourne; that said, for POSIX sh, true is likewise guaranteed to be a builtin -- so it's more terseness than efficiency in even-remotely-modern times). – Charles Duffy Nov 26 '16 at 6:09
138

The reason for this pattern is that maintainer scripts in Debian packages tend to start with set -e, which causes the shell to exit as soon as any command (strictly speaking, pipeline, list or compound command) exits with a non-zero status. This ensures that errors don't accumulate: as soon as something goes wrong, the script aborts.

In cases where a command in the script is allowed to fail, adding || true ensures that the resulting compound command always exits with status zero, so the script doesn't abort. For example, removing a directory shouldn't be a fatal error (preventing a package from being removed); so we'd use

rmdir ... || true

since rmdir doesn't have an option to tell it to ignore errors.

  • 4
    Well, without set -e there's no need for || true at all, I thought it important to provide the context. If you notice odd things on POWER, I strongly encourage you to file bugs (reportbug)! – Stephen Kitt Nov 24 '16 at 12:34
  • 15
    @MichaelFelt, actually set -e is not only "Debian convention", but a good programming pattern one should always use. See. e.g. davidpashley.com/articles/writing-robust-shell-scripts – kay Nov 24 '16 at 13:57
  • 2
    per the question here - why use || true set -e is the likely context and likely the most common. I bow to this answer! Literally though, it is useful anytime exit status is deemed irrelevant AND (as you article link adds) I am not using exit status as part of my script control. I see utility (in set -e) but would not go so far as the article does and say "Every script you write should include set -e at the top". It is a style of programming. "ALWAYS | Every" includes it own set of traps - aka - absolutes re: wild-card solutions will ALWAYS backfire eventually aka - no free rides. – Michael Felt Nov 24 '16 at 14:58
  • 1
    @Kay That's a currently popular perspective but is ultimately mired with numerous assumptions which limit the script's portability. There are historical inconsistencies with set -e behavior. It might not matter to you, if your only targets are bash and the other relatively recent shells that live at /bin/sh, but the situation is more nuanced when you want to support old shells/systems. – mtraceur Nov 25 '16 at 19:58
  • 2
    @StephenKitt Sure thing. There is a very thorough page documenting different shells' set -e behaviors by Sven Mascheck, though this page also documents a lot of historical/ancient shells irrelevant today. There's also these two pages with a narrower modern focus (search for "set -e"): "lintsh" page, autoconf's portable shell documentation -> Limitation of Builtins subpage – mtraceur Nov 26 '16 at 22:50
31

While it does not affect the output of the program just run - it permits the caller to proceed as if all is okay aka affects future logic.

Rephrased: it masks the error status of the previous command.

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0
  • 6
    That's true, but it doesn't answer why masking a command's exit status is useful. – moopet Nov 24 '16 at 15:47
  • 4
    set -e means that the script will instantly terminate upon a non-zero return. You might, in that localized spot, not want that happening! – rackandboneman Nov 24 '16 at 16:33
  • I am a simple person - and for me the only reason to mask the error status is because it is "in the way". set -e makes any error "in the way" if before you did not care. I like the discussion because I see it as a nice way to help me debug my scripts and write additional logic to respond to an error (e.g., || print -- "xxx existed non-zero here". More likely though I have a shell function 'fatal' and I have "something || fatal "unhappy me". imho a script should report a failed status, or not care. -e plus || true is masking errors. If that is what I want - fine, if not, I am missing errors – Michael Felt Nov 24 '16 at 16:48
  • what I have to ask myself is: is || true - a coding crutch (lazy way to get around/past an error I do not want to deal with now; a debug tool (-e but no || true) or just someone's dogma about what good coding practice is. In other words - I see it as a feature - with potential benefit. I do not see it as a magic wand to cure all. In short - just as beauty is in the eye of the beholder - set -e and || true utility will be defined by the traits and goals of the programmer. – Michael Felt Nov 24 '16 at 16:53
  • 6
    @MichaelFelt Consider: git remote remove foo || true git remote add foo http://blah - we want to ignore the error if the remote doesn't exist. – immibis Nov 25 '16 at 2:04

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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