[OpenWrt-Devel] [PATCH] base-files: For sysfixtime use hwclock if RTC available

Lars Kruse lists at sumpfralle.de
Mon Jan 11 10:09:02 EST 2016


Hi,

short summary for the impatient readers: the following text dives into the
subtile differences between errexit (set -e) and exit status in shell scripting


Am Mon, 11 Jan 2016 05:14:18 -0500
schrieb Daniel Dickinson <openwrt at daniel.thecshore.com>:

> I did one other test I hadn't thought of originally:
> 
> #!/bin/sh
> 
> set -e
> 
> /bin/false && /bin/false
> 
> echo "not killed"
> 
> displays "not killed", so there still the issue that unlike if..then 
> with set -e, && fails to exit on error condition (for the purposes of 
> set -e it's like there is an implicit || /bin/true (really the exit 
> status just gets ignored for an AND-OR list in POSIX terms)).

The dash manpage describes "-e" (errexit) as follows:
 The exit status of a command is considered to be explicitly tested if the
 command is used to control an if, elif, while, or until; or if the command is
 the left hand operand of an ``&&'' or ``||'' operator.
The bash manual explains the same - just a bit more lengty. Busybox's ash works
in the same way, as far as I noticed.

Thus the manual implies that the following two lines behave identical with
regards to errexit:

  if [ -e /somefile ]; then action; fi
  [ -e /somefile ] && action

In fact they do. If the test fails then action is not executed.
If the test succeeds then the action is executed. The exit status of action
determines the overall exit status of this line and thus may trigger errexit.

The subtile difference between the above two lines is their exit status.
The "if" variation returns the exit status of "action" (test succeeds) or zero
(test fails).
The "&&" variation returns the exit status of the last executed command. Thus a
failed test returns a non-zero exit status. But due to the definition of
errexit, only the exit status of the last item in a compound statement
may trigger an errexit event.

Thus both statements on their own will behave in the same way regarding errexit
even if their exit status may differ.

But there is a final catch: if these statements are the last ones in any
while/for/if/case block, then their exit status determines the exit status
of the whole block. Thus the surrounding while/for/if/case block may cause an
errexit.

Look at these examples:

= example A =
 for a in foo bar; do
   [ -e "$a" ] && echo "$a"
 done

= example B =
 for a in foo bar; do
   if [ -e "$a" ]; then echo "$a"; fi
 done

In example (A) you will see a failure (followed by errexit) if the file "bar"
does not exist. The state of "foo" is not relevant. This is a bit surprising.
In example (B) there will never be an error. This is probably in line with the
expectation of most users.

Thus it is advisable to add a "true" statement at the end of a while/for/if/case
block if last statement is a "||" or "&&" compound. This additional
statement does not cover any errors. It just works around the subtile
differences between "exit code" and "errexit triggering" in this specific
situation.

Lars
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list