简体   繁体   中英

How to return the error from a sourced bash script

I'm fairly new to bash scripting. I have 4 nested bash scripts, and i'm having trouble propogating the error from the 4th script appropriately. eg:

script1.sh:
  source script2.sh
  <check for error and display appropriate message>
script2.sh:
  source script3.sh param_1
  <return to script1 on error>
  source script3.sh param_2
  <return to script1 on error>
  source script3.sh param_n
  <return to script1 on error>
script3.sh
  <some processing>
  script4.sh
  echo "this statement is not reached"
  return $?
script4.sh
  <some processing>
  exit $?

My requirements are:

  1. I need to define an associative array in script1, which is populated in script2 and available in scope of script3. I think the only way to do this is source script2 and script3
  2. script4 is executed not sourced, as this script can also be executed independantly of these parent scripts

This thread talked about using the return statement to return from a sourced bash script, but as script4 is executed i need to exit. I don't understand why the exit statement in script4 causes both the original shell and the sub shell to terminate? Surely it should only exit the sub shell?

Do i need to look at signals and traps?

Thanks for any help

You can keep set -e enabled if you want. Then you'll have to be more careful about invoking a script where you know the exit status may be non-zero:

script3.sh
  <some processing>
  if script4.sh; then
    rc=0
  else
    rc=$?
  fi
  echo "script4 complete"
  return $rc

See https://www.gnu.org/software/bash/manual/bashref.html#index-set

IMO, using set -e is appropriate if you truly want to abort your program for any error. Here, where you want to <check for error and display appropriate message> , that's clearly not the case.

Best practice is to be explicit. If your code is always going to be sourced, and thus return will be valid, simply::

source foo || return

return uses the exit status of the immediately prior command as its default value, so there's no need to capture and then pass it through.


If you don't know if you'll be sourced or executed, this gets a bit more complicated:

source foo || { rc=$?; return "$rc" 2>/dev/null || exit "$rc" }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM