Welcome to ZaiZheLe Developer Zone-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
912 views
in Technique[技术] by (71.8m points)

sh - Posix Shell test non zero exit code script termination when set -e

Reading the manual of the test shell command:

man test

Description states:

Exit with the status determined by EXPRESSION.

But this conflicts with my POSIX sh test script examples, where I use set -eu that should terminate a script if a command's exit status is not zero:

#!/bin/sh

set -eu

status=1
test "$status" -ne 0 && echo "Status not eq 0"
echo "(A) Exit code for "$status" = $?"

echo ""

status=0
test "$status" -ne 0 && echo "Status not eq 0"
echo "(B) Exit code for "$status" = $?"

echo ""

status=1
test "$status" -ne 0
echo "(C) Exit code for "$status" = $?"

echo ""

status=0
test "$status" -ne 0
echo "(D) Exit code for "$status" = $?"

running that script provides the output:

Status not eq 0
(A) Exit code for 1 = 0

(B) Exit code for 0 = 1

(C) Exit code for 1 = 0

This is how I understand flow of a execution for:

status=1
test "$status" -ne 0 && echo "Status not eq 0"
echo "(A) Exit code for "$status" = $?"

with output:

Status not eq 0
(A) Exit code for 1 = 0

test "$status" -ne 0 evaluates to true so its exit code is zero therefore an expression after boolean && is executed and since it is just an echo it returns also zero exit code so the script does not brake and echoes next line (A) Exit code for 1 = 0

but for the

status=0
test "$status" -ne 0 && echo "Status not eq 0"
echo "(B) Exit code for "$status" = $?"

with the output:

(B) Exit code for 0 = 1

Following previous reasoning the test should return non zero therefore an expression after && should not be executed (and it is not) but the script executes even the test returned non zero exit code (B) Exit code for 0 = 1.

Why does the script continue execution? It should brake due to non zero exit status.

There is no output for the case:

status=0
test "$status" -ne 0
echo "(D) Exit code for "$status" = $?"

that suggests to me the script execution was terminated at the line test "$status" -ne 0 and if you run echo $? after running the script you'll get in fact 1.

But how come the script is terminated when the test returns non zero exit status for the example (D) but it is not for the example (B)?

The only difference between (D) and (B) is that (B) has && echo "Status not eq 0" after the test but that is not executed and the exit status is 1 so in case of (B) the script should be terminated but it wasn't and if an exit status of a test is treated somehow so specially so it does not terminate a script having a set -e then why it terminates script for the (D) example?

EDIT

Similarly to test behaves ls

for the script:

#!/bin/sh

set -eu

ls notexitingfile && echo "File exists"
echo "Exit code for ls = $?"

ls notexitingfile
echo "Exit code for ls = $?"

the output is:

ls: cannot access 'notexitingfile': No such file or directory
Exit code for ls = 2
ls: cannot access 'notexitingfile': No such file or directory

note Exit code for ls = 2 for the first example and lack of it for the second.

I think the cause of the unexpected behavior may be my misunderstanding of the script termination (set -e) due to non zero exit code when using && operator.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The set -e option applies only to a single command. It does not apply for commands combined with || or &&.

man bash says:

The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to ZaiZheLe Developer Zone-Open, Learning and Share
...