112

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

195

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.

12
  • 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
  • 22
    @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 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
  • 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 Commented Nov 26, 2016 at 22:50
  • 2
    @400theCat I don't think so. The idea here is that by default (with set -e), non-zero exit codes cause the script to stop (remember, we're in the context of package maintainer scripts, so it's important to stop early when errors are detected). Then if you add a command without thinking too much about it, you're "protected"; you can special-case commands whose exit code is ignored using || true, and that jumps out at you when you read the script. With your approach, we'd end up with || exit everywhere. (The OP was exaggerating, you don't see || true everywhere in these scripts.) Commented Dec 23, 2016 at 10:21
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. 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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.