I have a Bash script that is sourced. When this script is sourced, it runs a function in the Bash script. This function should terminate the script if a certain condition is matched. How can this be done without terminating the shell in which the script is sourced?
To be clear: I want the termination action to be completed by the function in the sourced shell script, not in the main body of the sourced shell script. The problems that I can see are that return
simply returns from the function to the main of the script while exit 1
terminated the calling shell.
The following minimal example illustrates the problem:
main(){
echo "starting test of environment..."
ensure_environment
echo "environment safe -- starting other procedures..."
}
ensure_environment(){
if [ 1 == 1 ]; then
echo "environment problemm -- terminating..."
# exit 1 # <-- terminates calling shell
return # <-- returns only from function, not from sourced script
fi
}
main
This is a recipe how you can achieve your goal with your approach. I will not write your code for you, just describe how it can be done.
Your goal is to set/alter environment variables in the current bash shell by, effectively, sourcing a possibly complex shell script. Some component of this script may decide that execution of this sourced script should stop. What makes this complicated is that this decision is not necessarily top-level, but may be located in a nested function invocation. return
, then, does not help, and exit
would terminate the sourcing shell, which is not desired.
Your task is made easier by this statement of yours:
additional complexity that I can't really include in a minimal example makes it very desirable to centralise the termination procedure in a function.
This is how you do it:
Instead of sourcing your real script that decides which environment to set to what ("realscript.bash
"), you source another script "ipcscript.bash
".
ipcscript.bash
will setup some interprocess communication. This may be a pipe on some extra file descriptor that you open with exec, it may be a temporary file, it may be something else.
ipcscript.bash
will then start realscript.bash
as a child process. That means, the environment changes that realscript.bash
does first only affect the environment of that child process instance of bash. Starting realscript.bash
as a childprocess, you gain the capability of terminating the execution at any nested level with exit without terminating the sourcing shell.
Your call to exit will live, as you write, in a centralised function that is called from any level when a decision is made to terminate execution. Your terminating function now needs, before exiting, to write the current environment to the IPC mechanism in a suitable format.
ipcscript.bash
will read environment settings from the IPC mechanism and reproduce all settings in the process of the sourcing shell.