Bash: How to Exit a Script or Function Gracefully
Problem
- How do you exit or stop a running Bash script (or function) without closing your terminal session?
- Sometimes you need to halt execution early due to errors, user requests, or special conditions, but you want to keep the shell open.
Solutions
In a Linux or macOS terminal:
- Press CTRL+C to terminate (kill) a running script or command, and it will gracefully send a signal (
SIGINT
) to terminate the process. - Press CTRL+Z to pause/suspend the process (it keeps running, but is stopped and detached). You can later resume it with
fg
(foreground) orbg
(background).
Note: Pressing CTRL+Z does not exit or stop the script for good—it only “pauses” it, leaving it suspended. To actually exit, use
exit
in your script, or terminate with CTRL+C. You can later resume that same process with thefg
orbg
commands.
What Are fg
and bg
Commands?
fg
(foreground) resumes the most recently suspended job, running it in the foreground (terminal regains direct control).bg
(background) resumes the most recently suspended job, but lets it run in the background (you get your prompt back).
Examples of Suspending and Resuming a Bash Process
Let’s walk through a classic example:
# Example: Start a long-running script
$ bash myscript.sh
Suppose myscript.sh
contains:
#!/bin/bash
echo "Start sleeping"
sleep 120
echo "Done"
Now, while it’s running (sleep 120
), do:
- Suspend with CTRL+Z:
^Z
[1]+ Stopped bash myscript.sh
You get your shell prompt back. The script is “paused” (state: Stopped).
- Check jobs (optional):
$ jobs
[1]+ Stopped bash myscript.sh
- Resume in foreground:
$ fg
bash myscript.sh
Now it continues running in the foreground.
- Resume in background:
$ bg
[1]+ bash myscript.sh &
Script continues in the background; you get your shell prompt back immediately.
How to Stop Bash Programmatically
Here are a few ways you can stop a bash script, or bash process, programmatically:
- Use
exit
to stop the script immediately:
#!/bin/bash
if [[ "$SOMETHING_WENT_WRONG" == "yes" ]]; then
echo "Error: Something went wrong"
exit 1 # Use a non-zero code for errors
fi
- Exit with a custom status code (for error handling or automation):
exit 2 # Any non-zero value can indicate a specific failure
- Use
return
to exit a sourced script or function programatically:
my_func() {
echo "Exiting function early"
return 1
}
my_func
echo "Script still running after function"
- Trap signals for clean-up on exit:
trap 'echo "Cleaning up..."; exit 1' SIGINT
- Graceful conditional exit anywhere in the script:
[[ -z "$REQUIRED_VAR" ]] && { echo "Missing var"; exit 1; }
- Prompt user to exit interactively:
read -p "Continue? (y/n) " yn
[[ $yn != "y" ]] && exit 0
- Kill script from another shell (advanced):
kill <pid_of_script>
Things to Consider
exit
only closes the script, not your terminal or parent shell (unless the script was run withexec
).- In functions or sourced scripts, use
return
to avoid killing the whole shell. - Use meaningful exit codes (convention:
0
=success,1-255
=different errors). - Signal handling (using
trap
) can be useful for cleaning up temp files or resources. - Be aware of subshells:
exit
in a subshell affects only that subshell.
Gotchas
- Repeatedly suspending scripts with CTRL+Z, instead of killing them with CTRL+C, leaves processes running in the background, eating up system resources and potentially causing port conflicts. Clean up suspended jobs with
jobs
andkill
or bring them to the foreground withfg
and terminate them properly. - Don’t use
exit
inside a function that’s sourced in your.bashrc
—you might close your terminal! exit
in a sourced script exits the current shell, not just the script—preferreturn
.- Forgetting to check exit codes may result in silent failures.
kill
-ing a script with kill -9 skips clean-up and traps, and often requires you to execute it withsudo
privileges (which can be dangerous).
Sources
- Bash Manual: exit builtin
- StackOverflow: How to exit script gracefully
- Reddit: Quitting a script without exiting the shell
- Reddit: How to exit/return sourced bash script/function
- StackOverflow: What is the difference between kill and kill -9?
Further Investigation
- Explore using
trap
for more robust error and signal handling. - Learn about bash
set -e
and its effect on script exit behavior. - Advanced Bash-Scripting Guide
Bash trap
Command
trap
is a Bash builtin that lets your script react, or do something, when it comes across signals or events. For example, you can run cleanup code (or any code) automatically before the script exits, or when it receives certain signals (like CTRL+C or script errors).
Here’s a practical example:
trap 'echo "Caught CTRL+C! Cleaning up..."; rm -f /tmp/myfile' SIGINT
Now, if you press CTRL+C while the script is running, it’ll print a message and remove the temp file (before exiting).
TL;DR
- Press CTRL+C to terminate (kill) the running process.
- Press CTRL+Z to pause/suspend a process, and use
fg
/bg
to resume it. - Use
exit
to end a Bash script, orreturn
in a function or sourced script.
Example:
exit 1 # exits script with error code 1
Note: Pressing CTRL+Z does not exit or stop the script for good—it only “pauses” it, leaving it suspended. To actually exit, use
exit
in your script, or terminate with CTRL+C. Pressing^Z
, when it’s a foreground process, truly “pauses” it wherever it is—mid-loop, mid-system call, or even in the middle of I/O.