0

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.

4
  • 2
    the while loop is spawned in another subshell due to the pipe (|). the exit command exits this. you can try this out with this minimal script: sh -c 'exit;echo hi' vs sh -c ':|exit;echo hi' Commented Dec 8, 2022 at 17:49
  • Instead of print ... | while read ..., you can do while read ... <<< $(printf ...) (or use a heredoc) Commented Dec 8, 2022 at 18:01
  • 1
    Note that in order to use herestring, OP needs to change the shebang of test1 to use bash or zsh... instead of sh Commented Dec 8, 2022 at 18:05
  • restricted to /bin/sh... thx Commented Dec 8, 2022 at 18:56

2 Answers 2

2

I change the code to this:

bring_data() { zombies_are "${MY_DATA}" || exit 2 }

Sign up to request clarification or add additional context in comments.

Comments

1

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}")
}

1 Comment

Process substitution works in bash script... Unfortunately, not whith shell script. Thx, it helped clarifying the problem (shellcheck.net/wiki/SC3001)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.