GameServerManagers / GameServerManagers/LinuxGSM
[Bug]: 7 Days to Die graceful stop always fails — telnetpass/telnetpassword variable mismatch in info_game.sh
- Dominant language
- Shell
- Stars
- 4.9k
- Forks
- 864
- PR merge metrics
- No merged PRs in 30d
Description
### Severity
severity: high
### Reproducibility
reproducible: always
### Regression
regression: yes
### Affects latest release
latest-release: yes
### User story
As a 7 Days to Die server admin, I want LinuxGSM to shut the server down gracefully over telnet so that the world save is flushed cleanly instead of the server being killed by tmux.
### Script name
sdtdserver
### Game
7 Days to Die
### Linux distro
Debian 13
### Command
command: stop
### Expected behavior
`fn_info_game_sdtd()` reads `TelnetPassword` from the server config into `${telnetpassword}` — the variable that `command_stop.sh` and `info_messages.sh` actually consume. Graceful telnet shutdown authenticates and completes.
### Actual behavior
`fn_info_game_sdtd()` stores the password in `${telnetpass}`, but every consumer reads `${telnetpassword}`, which stays empty.
**Two things break:**
1. **Graceful shutdown never authenticates.** `command_stop.sh:115` — `[ -z "${telnetpassword}" ] || [ "${telnetpassword}" == "NOT SET" ]` is always true, so the expect block that sends *no* password is used. On any server with `TelnetPassword` set the login fails, graceful shutdown fails, and LinuxGSM falls back to `tmux kill` — the path its own comment describes as *"this risks loss of world save"*.
2. **Telnet IP is pinned to localhost.** `info_game.sh:1980` — `if [ -z "${telnetpassword}" ]; then telnetip="127.0.0.1"; fi` always fires, regardless of the configured IP.
`info_messages.sh:1497` also prints an empty Telnet password in `details` — the quickest way to observe the bug without stopping a server.
### Further information
**Root cause: a partial variable rename.**
Up to and including **v24.2.4**, `info_game.sh` and `command_stop.sh` both used `${telnetpass}` and were consistent. **v24.3.0** renamed the consumers (`command_stop.sh`, `info_messages.sh`) to `${telnetpassword}` but left the producer in `info_game.sh` as `${telnetpass}`.
Confirmed present in **v24.3.0 through v26.2.0**, and in current `master` and `develop`.
Note that `info_game.sh:1980` already reads `${telnetpassword}` — the mismatch is internal to the same function, which suggests the rename was simply incomplete rather than intentional.
### Fix
Rename the two remaining occurrences in `fn_info_game_sdtd()`:
```diff
--- a/lgsm/modules/info_game.sh
+++ b/lgsm/modules/info_game.sh
@@ -1963 +1963 @@
- fn_info_game_xml "telnetpass" "/ServerSettings/property[@name='TelnetPassword']/@value"
+ fn_info_game_xml "telnetpassword" "/ServerSettings/property[@name='TelnetPassword']/@value"
@@ -1983 +1983 @@
- telnetpass="${telnetpass:-"NOT SET"}"
+ telnetpassword="${telnetpassword:-"NOT SET"}"
```
The existing ordering stays correct once renamed: the `-z` check on line 1980 runs before the `"NOT SET"` default on line 1983, and `command_stop.sh` handles both the empty and `"NOT SET"` cases.
Use **word-boundary matching** when patching — `telnetpassword` contains `telnetpass` as a prefix:
```bash
sed -i -E 's/\btelnetpass\b/telnetpassword/g' lgsm/modules/info_game.sh
```
`grep -w telnetpass` across `lgsm/modules/` returns no other hits, so these are the only two call sites.
Verified on two independent 7 Days to Die installs — LinuxGSM v26.2.0, Debian 13, 7DTD dedicated buildid `24911252`.
### Pre-checks
- [x] I ran update and validate before reporting this issue.
### Relevant log output
```shell
# TelnetPassword is set in the server config:
$ grep TelnetPassword serverfiles/sdtdserver.xml
# BEFORE — stock v26.2.0 info_game.sh
$ ./sdtdserver details
Telnet enabled: true
Telnet address: 127.0.0.1 8091
Telnet password:
# AFTER — the two-line rename above applied
$ ./sdtdserver details
Telnet enabled: true
Telnet address: 203.0.113.10 8091
Telnet password: REDACTED
# Variable state in stock v26.2.0 info_game.sh (producer vs consumers)
$ grep -n telnetpass lgsm/modules/info_game.sh
1963: fn_info_game_xml "telnetpass" "/ServerSettings/property[@name='TelnetPassword']/@value"
1980: if [ -z "${telnetpassword}" ]; then
1983: telnetpass="${telnetpass:-"NOT SET"}"
$ grep -n telnetpassword lgsm/modules/command_stop.sh
115: if [ -z "${telnetpassword}" ] || [ "${telnetpassword}" == "NOT SET" ]; then
137: "password:" { send "'"${telnetpassword}"'\r" }
```
### Steps to reproduce
1. Install `sdtdserver` on LinuxGSM **v24.3.0 or newer** (reproduced on v26.2.0).
2. Set a non-empty `TelnetPassword` and `TelnetEnabled="true"` in the server config.
3. Run `./sdtdserver details` and look at the **7 Days To Die Telnet** block — Telnet password is blank and Telnet address is forced to `127.0.0.1`.
4. Start the server, then run `./sdtdserver stop` — graceful telnet shutdown fails to authenticate and LinuxGSM falls back to a `tmux` kill.
5. Apply the two-line rename in `fn_info_game_sdtd()` and repeat steps 3–4 — the password is read and graceful shutdown completes.
Contributor guide
Research direction
Start in lgsm/modules/info_game.sh at fn_info_game_sdtd(), then compare its TelnetPassword assignments with the consumers in command_stop.sh and info_messages.sh. Rename the two remaining telnetpass occurrences using word-boundary matching, then run ./sdtdserver details and ./sdtdserver stop with TelnetPassword enabled; done means the password and configured address appear and graceful shutdown authenticates.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, shell
- Domain
- cli, devops
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 92/100