Discussion:
[Help-bash] eval and set -e
Peng Yu
2017-05-16 01:04:12 UTC
Permalink
Hi,

I have the following code.

The exit code of the first eval is 1. The exit code of the second eval
is supposed to be 1 as well, so I'd expect the last echo to print the
exit code. But I don't see it.

Does anybody know how to understand this code?

$ cat main.sh
#!/usr/bin/env bash
# vim: set noexpandtab tabstop=2:

( eval 'set -e; false; echo xx' )
echo xxx "$?"
( eval 'set -e; false; echo xx' ) || echo "$?"
$ ./main.sh
xxx 1
xx
--
Regards,
Peng
Eduardo Bustamante
2017-05-16 03:43:08 UTC
Permalink
On Mon, May 15, 2017 at 8:04 PM, Peng Yu <***@gmail.com> wrote:
[...]
Post by Peng Yu
I have the following code.
[...]
Post by Peng Yu
( eval 'set -e; false; echo xx' )
echo xxx "$?"
( eval 'set -e; false; echo xx' ) || echo "$?"
Lets simplify. The above is equivalent to:

( set -e; false; echo xx )
echo xxx "$?"
( set -e; false; echo xx ) || echo "$?"

(i.e. the eval doesn't change the outcome).

Now, time to add some context from the relevant standard (emphasis
mine): http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set

-e

When this option is on, when any command fails (for any of the reasons listed
in Consequences of Shell Errors or by returning an exit status greater than
zero), the shell immediately shall exit, as if by executing the exit special
built-in utility with no arguments, with the following exceptions:

1. The failure of any individual command in a multi-command pipeline shall
not cause the shell to exit. Only the failure of the pipeline itself shall
be considered.

2. The -e setting shall be ignored when executing the compound list
following the while, until, if, or elif reserved word, a pipeline beginning
with the ! reserved word, or **any command of an AND-OR list other than the
last**.

3. If the exit status of a compound command other than a subshell command
was the result of a failure while -e was being ignored, then -e shall not
apply to this command.

So, in the first case (the "simple" subshell), errexit is NOT ignored,
and `false' triggers an error condition that exits the subshell with
the return code of 1.

In the second case (the AND-OR list), the list is composed of two
elements: a subshell and the echo, joined by an OR. According to
POSIX, errexit is ignored for every element of the list, other than
the last one, which means that errexit is ignored for the subshell,
the `false' does not trigger the subshell to exit, and the return
status is that of `echo xx', i.e. 0.
Greg Wooledge
2017-05-16 12:03:40 UTC
Permalink
Post by Eduardo Bustamante
Lets simplify.
Yup. Here's my simplification:

STOP USING set -e!

IT IS IRREPARABLY BROKEN.

IT DOES *NOT* GIVE YOU AUTOMATIC ERROR CHECKING.

BASH COMES FROM AN ERA AND CULTURE WHERE ERROR CHECKING HAD TO BE DONE
BY THE DEVELOPER AFTER EACH CALL.

set -e EXISTS IN CURRENT SHELLS ONLY FOR COMPATIBILTY WITH ANCIENT
SCRIPTS.

BASH IS NOT A MODERN HIGH-LEVEL SCRIPTING LANGUAGE.

I've tried everything. I don't know why people can't. get. the. god.
damned. message. I've tried writing wiki pages, posting on mailing
lists, responding in IRC, writing short stories....
Eduardo Bustamante
2017-05-17 00:30:31 UTC
Permalink
Post by Greg Wooledge
Post by Eduardo Bustamante
Lets simplify.
STOP USING set -e!
IT IS IRREPARABLY BROKEN.
I'm seriously wondering if it' be a good idea to show a warning
whenever errexit is enabled and you're not in POSIX mode.

Loading...