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

# Startup loop

> How start.sh keeps the server running across crashes while respecting intentional stops.

`start.sh` is the process that actually runs inside the tmux session. Its
primary job is to run the Minecraft server and automatically restart it if it
crashes — unless the shutdown was intentional.

<Note>
  You do not normally invoke `start.sh` directly. Use `serv start` instead,
  which sets up the tmux session, exports the necessary environment variables,
  and runs `start.sh` inside it.
</Note>

## How the loop works

The script registers a `SIGINT`/`SIGTERM` signal trap and runs in a `while` loop that continues as long as a `keep_running` flag is `true`. Each iteration of the loop:

1. Checks for a `stop_signal` file before launching. If found, sets `keep_running=false` and removes the file — server does not start.
2. Launches the Java process and blocks until it exits.
3. Checks for `stop_signal` again immediately after the process exits.
4. If `keep_running` is still `true`, waits 5 seconds, checks `stop_signal` one final time, then restarts.

```bash theme={null}
# Trap SIGINT (Ctrl+C) and SIGTERM signals
trap handle_shutdown SIGINT SIGTERM

while $keep_running; do
    # Check for stop signal file
    if [ -f "stop_signal" ]; then
        echo "Stop signal file detected. Server will not restart after stopping."
        keep_running=false
        rm -f stop_signal
    fi

    java -Xmx3072M -Xms2048M -XX:+UseG1GC -XX:MaxGCPauseMillis=50 \
        -Dlog4j.configurationFile=log4j2.xml \
        -jar $SERVER_JAR nogui

    # Check again after server stops
    if [ -f "stop_signal" ]; then
        echo "Stop signal file detected. Server will not restart."
        keep_running=false
        rm -f stop_signal
    fi

    if $keep_running; then
        echo "Server restarting in 5 seconds..."
        echo "Press CTRL+C to prevent restart."
        sleep 5
        # Check one more time before restarting
        if [ -f "stop_signal" ]; then
            echo "Stop signal file detected. Server will not restart."
            keep_running=false
            rm -f stop_signal
        fi
    fi
done

echo "Server shutdown complete."
```

## The stop\_signal file

The `stop_signal` file is the mechanism that differentiates an intentional stop from a crash. The script also traps `SIGINT` and `SIGTERM` — pressing Ctrl+C inside the tmux session sets `keep_running=false` without needing the file.

| Event          | What happens                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------- |
| `serv stop`    | Creates `stop_signal`, sends `stop` to the console — loop exits cleanly, no restart                     |
| Server crash   | No `stop_signal` is created — loop detects the process exited, waits 5 seconds, restarts                |
| `serv restart` | Sends `stop` to the console **without** creating `stop_signal` — loop restarts the server automatically |
| Ctrl+C in tmux | `SIGINT` trap sets `keep_running=false` — loop exits after the current server run finishes              |

This means a crash at any time — including during a snapshot window — will
trigger an automatic restart within 5 seconds, unless `serv stop` was called
first.

## JVM flags

The server is launched with the following JVM arguments:

| Flag                        | Value        | Purpose                                              |
| --------------------------- | ------------ | ---------------------------------------------------- |
| `-Xmx`                      | `3072M`      | Maximum heap size (3 GB)                             |
| `-Xms`                      | `2048M`      | Initial heap size (2 GB)                             |
| `-XX:+UseG1GC`              | —            | Use the G1 garbage collector                         |
| `-XX:MaxGCPauseMillis`      | `50`         | Target maximum GC pause time of 50 ms                |
| `-Dlog4j.configurationFile` | `log4j2.xml` | Use the custom log4j config to suppress noisy output |

The jar is launched with the `nogui` flag, which disables the Swing GUI that
would otherwise fail in a headless environment.

## tmux session details

| Setting           | Value                                    |
| ----------------- | ---------------------------------------- |
| Session name      | `minecraft`                              |
| tmux socket       | `/tmp/minecraft-tmux`                    |
| Working directory | `/usr/local/games/minecraft_server/java` |
| Error log         | `/tmp/minecraft_error.log`               |

The socket is created with permissions `770` after the session is started, so
users in the owning group can attach without root.

## Graceful stop vs crash

**Graceful stop via `serv stop`:**

```text theme={null}
Stop signal file detected. Server will not restart after stopping.
Server shutdown complete.
```

**Crash recovery:**

```text theme={null}
Server restarting in 5 seconds...
Press CTRL+C to prevent restart.
```

The loop will then re-execute the `java` command and the server comes back up
automatically. The tmux session and the loop itself remain alive throughout,
so `serv console` continues to work even between restarts.
