> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bash EXIT Trap

The Bash `EXIT` trap is a built-in shell mechanism that registers a command or function to execute automatically when the shell process terminates. It intercepts the shell-internal pseudo-signal `EXIT` (also represented as signal `0`), ensuring the specified code evaluates during the teardown phase of the shell execution lifecycle.

## Syntax

The `trap` builtin requires two primary arguments: the payload (a string containing the command or function to execute) and the signal specification (`EXIT` or `0`).

```bash theme={"dark"}

# Standard syntax using the EXIT pseudo-signal
trap 'command_or_function' EXIT


# Alternative syntax using the numeric equivalent
trap 'command_or_function' 0


# Clearing an existing EXIT trap
trap - EXIT
```

## Trigger Conditions

The `EXIT` trap is invoked under the following conditions:

* **Normal Termination:** The shell reaches the end of the script (EOF).
* **Explicit Termination:** An `exit` builtin is executed anywhere within the script.
* **Errexit Termination:** The script terminates prematurely due to the `set -e` (`errexit`) option encountering a non-zero exit status.

The `EXIT` trap will **not** trigger under these conditions:

* **Untrapped Fatal Signals:** The shell receives a termination signal such as `SIGINT` (Ctrl+C), `SIGTERM`, or `SIGHUP` that is not explicitly trapped. The shell terminates immediately and bypasses the `EXIT` trap.
* **Uncatchable Signals:** The process is terminated by `SIGKILL` (e.g., `kill -9`) or suspended by `SIGSTOP`, both of which bypass user-space signal handling entirely.
* **Process Replacement:** The shell process is replaced entirely using the `exec` builtin. The original shell ceases to exist, taking its trap registrations with it.
* **Hardware/System Faults:** A fatal segmentation fault or hardware-level interruption occurs.

## Interaction with Explicit Signal Traps

Because untrapped fatal signals bypass the `EXIT` trap, developers must explicitly trap signals like `INT` and `TERM` to ensure the `EXIT` payload executes during an interruption.

If a signal is explicitly trapped, the shell executes the trap payload and then *resumes execution* of the script from the point of interruption. To force termination, the signal trap payload must explicitly invoke the `exit` builtin. Invoking `exit` inside a signal trap immediately triggers the `EXIT` trap.

Binding the same function to both `EXIT` and termination signals is a common anti-pattern. It can lead to double-execution if the handler calls `exit`, or it can force a successful script to exit with a failure code if the handler hardcodes an error status. The correct pattern isolates the payload in the `EXIT` trap and binds termination signals to an `exit` command, which safely routes the termination through the `EXIT` trap.

```bash theme={"dark"}

# ANTI-PATTERN: Binds the same handler to EXIT and signals.

# If the script finishes successfully, it still exits with 130.
handler() {
    # ... payload logic ...
    exit 130 
}
trap 'handler' EXIT INT TERM


# CORRECT PATTERN: Bind the payload only to EXIT. 

# Bind signals to explicitly exit, which then triggers the EXIT trap.
handler() {
    # ... payload logic ...
}
trap 'handler' EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
```

## Execution Context and State

When the `EXIT` trap fires, it executes within the current shell environment, not a subshell. This means the trap payload retains full access to the script's global variables, functions, and file descriptors exactly as they existed at the moment of termination.

If multiple `EXIT` traps are defined sequentially in a script, the shell only honors the most recently defined trap. A new `trap ... EXIT` declaration silently overwrites the previous one.

## Exit Status Behavior

By default, a Bash script returns the exit status of the last command executed *before* the trap was triggered. The execution of the trap itself does not alter the script's final exit status, even if commands within the trap fail.

```bash theme={"dark"}
trap 'echo "Trap executed"' EXIT
false # Script will exit with status 1, despite the trap succeeding
```

To override this behavior, an explicit `exit <N>` command must be invoked *inside* the trap payload. This forces the shell to discard the original exit status and terminate with the status provided by the trap.

```bash theme={"dark"}
trap 'exit 0' EXIT
false # Script will exit with status 0, overridden by the trap
```

## Subshell Inheritance

`EXIT` traps are bound to the specific shell process in which they are defined. Subshells (created via command substitution `$(...)`, grouping `(...)`, or background processes `&`) do not inherit the `EXIT` trap from their parent shell. If an `EXIT` trap is required for a subshell's termination, it must be explicitly declared within that subshell's execution block.

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Bash Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
