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
exitin your script, or terminate with CTRL+C. You can later resume that same process with thefgorbgcommands.
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
exitto 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
returnto 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
exitonly closes the script, not your terminal or parent shell (unless the script was run withexec).- In functions or sourced scripts, use
returnto 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:
exitin 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
jobsandkillor bring them to the foreground withfgand terminate them properly. - Don’t use
exitinside a function that’s sourced in your.bashrc—you might close your terminal! exitin 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 withsudoprivileges (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
trapfor more robust error and signal handling. - Learn about bash
set -eand 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/bgto resume it. - Use
exitto end a Bash script, orreturnin 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
exitin 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.