Blog

Terraria 联机服务器的 systemd 托管

Terraria 联机比 Minecraft 轻,朋友周末上来挖一会,不需要强主机。真正拖后腿的是进程怎么活:有人 SSH 里前台跑 ./TerrariaServer,会话断了服就没;有人 screen,机器重启后忘记 attach。目标应改成开机自启、崩溃拉起、备份可脚本化。下面把官方专服放进一个认真写过的 systemd 单元里,逐段解释每一节在守护什么。

单元之前:用户、目录与世界文件

SteamCMD 或官方专用服务器包放到例如 /opt/terraria。专用系统用户 terraria,家目录与数据目录权限归它,不要用 root 跑游戏服。serverconfig.txt 写清 world 路径与世界名、maxplayers、端口(默认 7777)、需要时的 password;autocreate 仅第一次生成世界时有用。路径尽量用绝对路径,减少 WorkingDirectory 与配置文件互相猜测的空间。

世界文件 *.wld 是核心资产,和二进制、配置同等重要却更脆弱——运行中拷贝可能不一致。单元文件写好之前,先保证路径稳定、用户可写、防火墙规则(TCP/UDP 按官方文档)已放行。公网映射时密码不要用 123456,日志里扫端口的人从不缺席。先手动以 terraria 用户成功启动一次,再写 systemd,能把「权限不对」和「单元写错」拆开排查。

[Unit]:它何时被认为「可以启动」

[Unit]
Description=Terraria Dedicated Server
Documentation=file:/opt/terraria/serverconfig.txt
After=network-online.target
Wants=network-online.target

After=network-online.target 比只写 network.target 更稳一点:避免网络栈尚未就绪时绑定失败再靠 Restart 空转。Description 会出现在 systemctl status 里,写清楚免得和主机上其它游戏服混淆。不在这里写 Requires= 绑定到数据库之类——原版 Terraria 专服没有这层依赖,加了只会制造虚假故障点。

[Service]:进程模型与崩溃策略

[Service]
Type=simple
User=terraria
Group=terraria
WorkingDirectory=/opt/terraria
ExecStart=/opt/terraria/TerrariaServer -config /opt/terraria/serverconfig.txt
Restart=on-failure
RestartSec=15
Nice=5
LimitNOFILE=8192

# 可选:把 stdout 留在 journal
StandardOutput=journal
StandardError=journal

Type=simple 适合前台常驻、不自行 double-fork 的专服。WorkingDirectory 必须设,否则相对路径的世界与日志会落到意料之外的位置。Restart=on-failure 在进程非零退出时拉起;若你手动 systemctl stop,不会被无限拉起打扰。RestartSec=15 给崩溃留喘息,避免配置错误时打满 CPU 狂重启。

Nice=5 略让出 CPU,同机还有更关键服务时有用。交互式控制台在 systemd 下不方便,改配置的标准路径是:停服 → 改 serverconfig.txt → 再启动。对小团体可接受;若强依赖控制台指令,需要额外的 wrapper 或 rcon 类方案,原版专服场景多数用不到。

不要把 ExecStart 包进无意义的 shell 循环里「自己实现守护」——那是和 systemd 抢职责,信号与退出码会乱。

[Install] 与启用方式

[Install]
WantedBy=multi-user.target

systemctl daemon-reload && systemctl enable --now terraria.service 之后,多用户目标达标即拉起。状态一眼看:

systemctl status terraria.service
journalctl -u terraria.service -f

日志进 journald 的好处是和轮转策略统一;若专服自己还写文件日志,记得权限与磁盘配额。

备份如何挂在单元生命周期上

运行中直接 cp *.wld 有抄到半截的风险。脚本应显式经过单元:

  1. 游戏内公告(若有人在线)
  2. systemctl stop terraria.service
  3. 拷贝世界、serverconfig.txt 与必要模组列表到备份盘 / restic
  4. systemctl start terraria.service

保留多个版本;同一块盘上的副本挡不住盘挂。异地或至少第二块介质。tModLoader 与纯净版分开目录、分开单元,世界不要混用;模组列表导出,换机时按列表装,避免「我能进你进不去」。

和朋友约定的运维面

大版本谁来更、密码是否轮换、谁有 SSH 与 systemctl 权限,写进同一份小笔记。单元文件本身也可以进 git(去掉密码),换机器时 daemon-reload 即可恢复托管方式。

还可以给单元加一层「维护窗口」习惯:升级二进制前 systemctl stop,替换文件并核对权限属主,再 start;若新版本启动即崩,journalctl -u terraria.service -n 100 通常比游戏内报错更早暴露缺库或路径问题。需要临时前台调试时,用 systemctl stop 释放端口后,以 terraria 用户手动跑同一条 ExecStart,确认无误再交还 systemd,避免两套启动参数长期分叉。

防火墙与端口映射也写进同一笔记:7777 的 TCP/UDP、是否仅对 VPN 网段开放、路由器转发规则的截图位置。公网暴露时密码轮换周期说清楚,比在群里口头约定可靠。

Terraria 服的复杂度不高,把进程模型交给 systemd、把世界当数据备份,就已经超过多数「周末临时开房间」的可靠性;真正省心的不是更炫的面板,而是 status 为 active、备份脚本停得干净、启得回来。

← Back to Blog