7

We run the script script1 from the script script_main

script_main:

#!/bin/bash
/tmp/script1
echo $?

sleep 2
echo script ended 

script1:

#!/bin/bash
exit 1

As is obvious, script1 exits with exit code 1 but the main script will continue until end.

My question: is it possible when script1 does exit 1, then also the main_script will be stopped immediately?

2 Answers 2

12

The most straightforward way would be to explicitly have the first script exit if the other script failed. Put the script execution in a conditional, like

otherscript.sh || exit 1

or

if ! otherscript.sh ; then
      ret=$?
      echo "otherscript failed with exit code $ret. exit." >&2
      exit 1
fi

This would allow the main script to do any cleanup it wants, or just try some other solution, possibly depending on what the child's exit code was. In the first one, we could use just || exit, to pass the child's exit code along.

If you want to have the main script exit when any command it starts fails, then set -e.

set -e
otherscript.sh
echo "this will not run if otherscript fails"

set -e doesn't apply to programs that run inside conditional constructs so we can still test for particular codes or tail them with || true to ignore the failure. But with exit points everywhere now, we could use trap somecmd EXIT to do any cleanup before the shell exits, regardless of where it happens.


Having the inner script force the main script to exit is also possible, but a bit unfriendly, you wouldn't expect a usual application to do it. But, if you want to, just having the inner script plain old shoot its parent process is one way:

$ cat mainscript.sh
#!/bin/bash
./otherscript.sh
echo "$0 exiting normally"
$ cat otherscript.sh
#!/bin/bash
echo "$0 kill $PPID"
kill $PPID

$ bash mainscript.sh
./otherscript.sh kill 11825
Terminated

Here, if you run otherscript.sh from an interactive shell, it will try to shoot the interactive session. All shells I tested seem to ignore the SIGTERM in this case when running interactively, though. In any case, the main shell could again trap the SIGTERM.

Instead of shooting just the parent process, you could use kill 0 to kill all processes in the process group otherscript.sh runs in. If started from a noninteractive shell, that would usually include the parent.

1
  • +1 for writing logic that can trap the exit status of the child process and do some cleanup. I'd go further and explicitly capture ChildStatus=$? right after running the child, and if it's non-zero, do something like echo >&2 otherscript terminated with $ChildStatus status Commented Jan 16, 2018 at 19:08
2

You can source script 2. Like:

. /tmp/script1.sh

And exit code will be read from the script2 which will terminate the process.

➜  /tmp cat script.sh 
#!/bin/bash

echo "Running ${0} with pid $$"
. /tmp/script1.sh
echo $?
echo "This code won't execute"
sleep 2
echo "Script ${0} ended"
echo "This code won't execute"
sleep 2

echo "Script ${0} ended"



➜  /tmp cat script1.sh 
#!/bin/bash

echo "Running ${0} with pid $$"
exit 5

Running it:

➜  /tmp ./script.sh 
Running ./script.sh with pid 10306
Running ./script.sh with pid 10306
➜  /tmp echo $?
5

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .