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:
-
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".
-
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():
--- 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:
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
Relevant log output
# TelnetPassword is set in the server config:
$ grep TelnetPassword serverfiles/sdtdserver.xml
<property name="TelnetPassword" value="REDACTED"/>
# 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
- Install
sdtdserver on LinuxGSM v24.3.0 or newer (reproduced on v26.2.0).
- Set a non-empty
TelnetPassword and TelnetEnabled="true" in the server config.
- 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.
- Start the server, then run
./sdtdserver stop — graceful telnet shutdown fails to authenticate and LinuxGSM falls back to a tmux kill.
- Apply the two-line rename in
fn_info_game_sdtd() and repeat steps 3–4 — the password is read and graceful shutdown completes.
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()readsTelnetPasswordfrom the server config into${telnetpassword}— the variable thatcommand_stop.shandinfo_messages.shactually 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:
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 withTelnetPasswordset the login fails, graceful shutdown fails, and LinuxGSM falls back totmux kill— the path its own comment describes as "this risks loss of world save".Telnet IP is pinned to localhost.
info_game.sh:1980—if [ -z "${telnetpassword}" ]; then telnetip="127.0.0.1"; fialways fires, regardless of the configured IP.info_messages.sh:1497also prints an empty Telnet password indetails— 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.shandcommand_stop.shboth used${telnetpass}and were consistent. v24.3.0 renamed the consumers (command_stop.sh,info_messages.sh) to${telnetpassword}but left the producer ininfo_game.shas${telnetpass}.Confirmed present in v24.3.0 through v26.2.0, and in current
masteranddevelop.Note that
info_game.sh:1980already 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():The existing ordering stays correct once renamed: the
-zcheck on line 1980 runs before the"NOT SET"default on line 1983, andcommand_stop.shhandles both the empty and"NOT SET"cases.Use word-boundary matching when patching —
telnetpasswordcontainstelnetpassas a prefix:sed -i -E 's/\btelnetpass\b/telnetpassword/g' lgsm/modules/info_game.shgrep -w telnetpassacrosslgsm/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
Relevant log output
Steps to reproduce
sdtdserveron LinuxGSM v24.3.0 or newer (reproduced on v26.2.0).TelnetPasswordandTelnetEnabled="true"in the server config../sdtdserver detailsand look at the 7 Days To Die Telnet block — Telnet password is blank and Telnet address is forced to127.0.0.1../sdtdserver stop— graceful telnet shutdown fails to authenticate and LinuxGSM falls back to atmuxkill.fn_info_game_sdtd()and repeat steps 3–4 — the password is read and graceful shutdown completes.