I have this simple dummy script called test1
#!/bin/sh
echo "Starting ..."
. ./test2.sh
bring_data
this_is_it
echo "...Done"`
`
It calls another script (note we are not spawning here, but sourcing)
#!/bin/sh
MY_DATA=\
"john road usa
adrian avenue nigeria
arthur street brazil
bill roads canada"
create_my_data() {
echo "name = ${1} type = ${2} country = ${3}"
if [ "${2}" = "avenue" ]; then
echo "failed... kick me out"
exit 2
fi
}
zombies_are() {
printf "%s" "${1}" | while read -r guy_name lives_on country; do
create_my_data "${guy_name}" "${lives_on}" "${country}"
done
}
bring_data() {
zombies_are "${MY_DATA}"
}
this_is_it() {
echo "... more work has to be done..."
sleep 1
echo "..."
}
Since test1.sh is sourcing test2.sh... I would expect that calling exit 2 would terminate the whole scripting call. I would expect that calling that_is_it... to not happen... yet it does.
Is there something specific about this line:
while read -r guy_name lives_on country; do
` which does not allow to exit completely from the call test1.sh ???
Here is the output at this point:
# ./test1.sh
Starting ...
name = john type = road country = usa
name = adrian type = avenue country = nigeria
failed... kick me out
... more work has to be done...
...
...Done
I changed the code to this...
`zombies_are "${MY_DATA}" || exit 2'
that works now.
CodePudding user response:
The while
loop is spawned in another subshell due to the pipe (|
). The exit
command exits this subshell. You can try this out with this minimal script: sh -c 'exit; echo hi'
, vs sh -c ': | exit; echo hi'
.
A solution is to use process substitution instead to keep the while loop in the same shell:
zombies_are() {
while read -r guy_name lives_on country; do
create_my_data "${guy_name}" "${lives_on}" "${country}"
done < <(printf "%s" "${1}")
}
CodePudding user response:
I change the code to this:
bring_data() { zombies_are "${MY_DATA}" || exit 2 }