bash + 如何同时退出辅助脚本和主脚本

yae*_*ael 7 bash rhel shell-script exit

我们script1从脚本运行脚本script_main

script_main

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

sleep 2
echo script ended 
Run Code Online (Sandbox Code Playgroud)

script1

#!/bin/bash
exit 1
Run Code Online (Sandbox Code Playgroud)

很明显,script1以退出代码 1 退出,但主脚本将持续到结束。

我的问题是:什么时候script1可以exit 1,然后也会main_script立即停止?

ilk*_*chu 11

最直接的方法是exit在另一个脚本失败时显式地拥有第一个脚本。将脚本执行置于条件中,例如

otherscript.sh || exit 1
Run Code Online (Sandbox Code Playgroud)

或者

if ! otherscript.sh ; then
      ret=$?
      echo "otherscript failed with exit code $ret. exit." >&2
      exit 1
fi
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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.