Reputation: 1144
Today, I find that my shell script occasionally exits early. After checking the code, I find out that it is because I have a set -e
in the head of my shell script and I use the built-in function RANDOM
to generate a random number.
With set -e
, if any command in the script return non-zero, the script would exit immediately. So I write a snippet of testing code like this:
set -u
#set -e
for (( i=0; i < 100; i++ ))
do
index=$(expr ${RANDOM} % 16)
echo "RANDOM return $? , index is $index"
done
Pay attention to the commented set -e
, I do that so as to show 100 output line, in which some RANDOM return 1
really exists. For example, I get a result like this:
RANDOM return 0 , index is 2
RANDOM return 0 , index is 10
RANDOM return 1 , index is 0
RANDOM return 0 , index is 9
RANDOM return 0 , index is 5
RANDOM return 0 , index is 9
RANDOM return 0 , index is 4
RANDOM return 0 , index is 6
RANDOM return 0 , index is 2
RANDOM return 0 , index is 4
RANDOM return 0 , index is 14
RANDOM return 0 , index is 6
RANDOM return 0 , index is 2
RANDOM return 1 , index is 0
RANDOM return 0 , index is 1
RANDOM return 0 , index is 8
...(more line)
See? RANDOM returns 1 but it generates the random number correctly, and that is why my shell script exits early. After switching to python's random-number-generating code, my script is back to normal.
Why would RANDOM
return 1?
Upvotes: 0
Views: 238
Reputation: 263337
$?
is the status of the last command you executed. $RANDOM
is not a command, so evaluating it doesn't affect $?
. ($RANDOM
is a "shell parameter" or variable that yields a random integer between 0 and 32767 when it's evaluated.)
The $?
value you're seeing is the result of executing the command expr ${RANDOM} % 16
.
The expr
command returns a status of 1
if the result of evaluating the expression is null or 0
, so you'll get a status of 1
whenever $RANDOM % 16
is 0 (6.25% of the time).
% expr 1 % 16 ; echo "\$?=$?"
1
$?=0
% expr 0 % 16 ; echo "\$?=$?"
0
$?=1
If you've done set -e
and you want to execute a command that might fail without terminating the shell, you can append something like || true
. Since the prefix to ||
is used as a condition, failure just makes the condition false.
index=$(expr ${RANDOM} % 16) || true
echo "Status of expr is $?, index is $index"
Upvotes: 7