111

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.

2
  • 7
    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). Commented Nov 26, 2016 at 6:09
  • 1
    Read more about ||: in unix.stackexchange.com/questions/78408/… Commented Jun 6, 2021 at 0:20

2 Answers 2

190

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.

10
  • 5
    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)! Commented Nov 24, 2016 at 12:34
  • 21
    @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
    – Kijewski
    Commented Nov 24, 2016 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. Commented Nov 24, 2016 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
    Commented Nov 25, 2016 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
    Commented Nov 26, 2016 at 22:50
37

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
5
  • 7
    That's true, but it doesn't answer why masking a command's exit status is useful.
    – moopet
    Commented Nov 24, 2016 at 15:47
  • 5
    set -e means that the script will instantly terminate upon a non-zero return. You might, in that localized spot, not want that happening! Commented Nov 24, 2016 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 Commented Nov 24, 2016 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. Commented Nov 24, 2016 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. Commented Nov 25, 2016 at 2:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .