bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: command substitution is stripping set -e from options


From: Eric Blake
Subject: Re: command substitution is stripping set -e from options
Date: Thu, 1 Oct 2015 13:04:58 -0600
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0

On 10/01/2015 04:24 AM, Christoph Gysin wrote:
> It seems that set -e is stripped from the options ($-) when executing
> commands with command substitution:
> 
> $ bash -euc 'echo $-; f(){ false; echo $->&2; }; x=$(f)'
> ehuBc
> huBc
> 
> I would expect the shell to exit as soon as it executes 'false'.

Your expectations may be noble, but that's not how 'set -e' works.

> 
> Is this intended? Is it documented somewhere?

Whether e disappears from $- may be unintended, but what IS documented
is that there are contexts in which set -e has no effect, and when in
one of those contexts, you cannot re-enable set -e.  One such context is
on the left side of && or ||.  Even more non-intuitively, if you have a
function that tries to use set -e, the effect of set -e depends on the
context of where the function is called (that is, 'f' may behave
differently than 'f || true').

> 
> I'm trying to catch errors in shellscripts by starting them with:
> 
>   set -euo pipefail

Sadly, it won't do what you think.  Using 'set -e' is almost NEVER a
good idea, because it forces code contortions for things that are meant
to have non-zero status, while simultaneously missing cases that you
intuitively want it to catch, and such behavior is mandated by POSIX for
compatibility.  Reading the archives of this list will find numerous
threads where we recommend against using 'set -e' - it exists only for
historical back-compat, and not for useful work.

> 
> It seems now that this is not enough, I would have to start every
> command substitution with set -e:
> 
>   var=$(set -e; command1; command2)

Won't do what you want, so don't expect it to.

> 
> It *seems* to work with only a single command, because the return
> value of the assignment is the last command executed inside the
> command substitution. But if there are multiple commands, or a
> function call, errors are not caught.

What's wrong with:
  var=$(command1 && command2) || exit
without having to rely on set -e?

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]