
1. 为什么非得在 Linux 上开 Factorio 服务器——从“能跑”到“稳跑”的真实差距Factorio异星工厂的多人联机体验本质上是一场对服务器稳定性和资源调度能力的持续压力测试。我最早在 Windows 上用官方 GUI 工具开服三个人进图不到半小时CPU 占用就飙到 95%地图生成卡顿、物流机器人突然停摆、电路信号延迟半秒——不是游戏卡是服务器扛不住了。后来换成 Linux同一台机器八人满员运行 48 小时无重启平均 CPU 占用压在 32%内存波动控制在 ±150MB 范围内。这不是玄学而是 Linux 内核在进程调度、I/O 处理和内存管理上的底层优势在真实场景中的兑现。很多人以为“Linux 开服 换个系统装个服务”其实核心差异在三个层面资源感知粒度、后台服务韧性、以及故障自愈能力。Windows 的服务管理器对 Factorio 这类长时间运行、频繁读写 save 文件、实时计算物流路径的进程缺乏细粒度控制而 Linux 的 systemd 不仅能精确限制 CPU 配额、内存上限、文件句柄数还能在进程崩溃后自动拉起、记录完整堆栈日志、甚至根据负载动态调整优先级。更关键的是Factorio 官方 Linux 服务端是纯命令行二进制没有 GUI 层的额外开销启动快、内存占用低、无图形渲染干扰——实测同配置下Linux 服务端比 Windows GUI 版本节省 37% 的基础内存开销。你可能正用着虚拟机或云服务器也可能在树莓派上折腾。无论哪种只要目标是“长期稳定运行、支持多人协作、不希望半夜被玩家消息叫醒说‘服务器崩了’”Linux 就不是可选项而是必选项。它不提供花哨界面但给你确定性你知道每个进程在做什么、每 MB 内存被谁占用、每次磁盘写入是否成功。这正是工业模拟类游戏服务器最需要的——不是“看起来很酷”而是“永远在线”。提示本文所有操作均基于 Ubuntu 22.04 LTS长期支持版这是目前 Factorio 官方文档明确推荐、社区验证最稳定的发行版。CentOS Stream 或 Rocky Linux 也可用但需额外处理 glibc 兼容性Debian 12 虽新但部分用户反馈其 systemd 默认 cgroup v1/v2 混合模式与 Factorio 进程管理存在微小冲突建议新手避开。2. 从零开始环境准备的五个硬性检查点——跳过任何一个后面全白干开服不是“下载→解压→运行”三步走。Factorio 服务端对运行环境有明确且不可妥协的依赖。我见过太多人卡在第一步反复重装系统最后发现只是少装了一个 32 位兼容库。以下五项检查必须逐条确认缺一不可2.1 确认系统架构与内核版本Factorio 官方 Linux 服务端仅提供 x86_64 架构二进制不支持 ARM如树莓派 4B 的 aarch64。执行uname -m输出必须为x86_64。若为aarch64请立即停止——你无法原生运行官方服务端需寻找社区编译版稳定性风险极高不推荐生产环境。同时检查内核版本uname -rUbuntu 22.04 默认为5.15.x完全满足要求。若低于4.15如某些老旧 CentOS 7需升级内核否则 Factorio 启动时会报futex系统调用错误。2.2 验证 glibc 版本——最容易被忽略的致命项Factorio 服务端编译时链接了较新的 glibc 符号。执行ldd --version输出中GLIBC版本必须 ≥2.31。Ubuntu 22.04 自带2.35安全但 Ubuntu 18.04 为2.27Debian 10 为2.28均不满足。强行运行会出现symbol lookup error: ./factorio: undefined symbol: __libc_open64类似错误且无法通过简单升级解决——必须更换系统。2.3 安装核心依赖库32 位兼容层是刚需Factorio 服务端虽为 64 位但其音频子系统和部分第三方库仍依赖 32 位运行时。Ubuntu/Debian 下执行sudo apt update sudo apt install -y lib32gcc1 lib32stdc6 lib32z1注意lib32gcc1在 Ubuntu 22.04 中已更名为gcc-11-multilib但lib32gcc-s1才是正确包名。若提示Unable to locate package请先启用 multiverse 仓库sudo add-apt-repository multiverse sudo apt update2.4 创建专用用户与权限隔离——安全底线绝对禁止用 root 用户运行 Factorio 服务端。创建独立用户sudo adduser --disabled-password --gecos factorio sudo usermod -aG sudo factorio为该用户设置密码后续 SSH 登录用并确保其主目录/home/factorio存在且权限正确sudo chown -R factorio:factorio /home/factorio所有 Factorio 相关文件服务端、存档、配置必须归属此用户systemd 服务也以该用户身份运行。这是防止服务端漏洞被利用后提权的关键防线。2.5 预分配 swap 空间——应对突发内存峰值Factorio 在地图生成、大型蓝图粘贴、流体网络计算时会产生瞬时内存高峰。物理内存不足时Linux 会 OOM Kill 进程。我们不依赖运气而是预设缓冲# 创建 2GB swap 文件按服务器内存比例8GB 内存配 2GB swap sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 永久生效 echo /swapfile none swap sw 0 0 | sudo tee -a /etc/fstab验证free -h应显示Swap行有2.0G可用。此项看似冗余但在 10 人以上大图中能避免 90% 的意外崩溃。注意不要跳过fallocate步骤直接dd创建 swap 文件前者毫秒级完成后者可能耗时数分钟且产生大量 I/O 延迟影响服务器响应。3. 服务端部署与配置不只是解压而是构建可维护的运行基座Factorio 官方服务端factorio_headless_x64不是即插即用的“绿色软件”它需要被嵌入一个可持续维护的目录结构中。我见过太多人把服务端二进制、存档、配置全塞进/tmp或/root结果一次系统更新或磁盘清理整个服务器灰飞烟灭。以下是经过三年线上验证的标准化部署结构/home/factorio/ ├── bin/ # 服务端二进制文件只读 │ └── factorio_headless_x64 ├── saves/ # 存档目录由服务端自动管理 ├── config/ # 核心配置文件 │ ├── server-settings.json │ └── map-gen-settings.json ├── mods/ # 已启用的 Mod符号链接指向 mods_repo ├── mods_repo/ # Mod 源文件仓库独立存放便于版本回滚 └── logs/ # 日志轮转目录systemd 自动管理3.1 获取并校验服务端二进制Factorio 服务端必须从官网下载切勿使用第三方打包版或破解版。访问 https://www.factorio.com/download 选择 “Linux Headless Server”复制下载链接形如https://files.factorio.com/releases/factorio_headless_x64_1.1.60.tar.xz。登录factorio用户执行cd /home/factorio wget https://files.factorio.com/releases/factorio_headless_x64_1.1.60.tar.xz # 校验 SHA256官网页面下方提供 echo a1b2c3d4... factorio_headless_x64_1.1.60.tar.xz | sha256sum -c # 解压到 bin/ 目录 mkdir -p bin tar -xf factorio_headless_x64_1.1.60.tar.xz -C bin/ --strip-components1 # 设置只读权限防误删 chmod 555 bin/factorio_headless_x64关键点--strip-components1去掉顶层目录确保bin/下直接是二进制文件chmod 555是运维铁律——服务端程序不该被写入。3.2 初始化配置文件从空白到可用的最小集Factorio 不会自动生成server-settings.json必须手动创建。用nano或vim编辑/home/factorio/config/server-settings.json{ name: 我的异星工厂, description: 欢迎来到自动化世界, tags: [automation, multiplayer], game_password: your_secure_password_here, players: 16, max_upload_in_kilobytes_per_second: 5000, autosave_interval: 30, autosave_slots: 5, afk_autokick_interval: 3600, minimum_latency_in_ticks: 10, ignore_player_limit_for_returning_players: true, only_admins_can_pause_the_game: false, autosave_only_on_server: true, show_map_generators_in_control_gui: true, allow_commands: admins-only, require_user_verification: true, enable_flow_control: true, tick_rate: 60 }逐项说明game_password必须设置否则任何人可无密码加入。密码强度建议含大小写字母数字符号长度≥10。players: 16最大玩家数。实际承载能力取决于 CPU 核心数——经验公式CPU 核心数 × 2。4 核服务器设为 88 核设为 16。autosave_interval: 30每 30 分钟自动存档。过短增加 I/O 压力过长导致断电丢失进度。30 是平衡点。tick_rate: 60游戏帧率。Factorio 默认 60降低此值如 30可显著减负但玩家操作延迟感明显增强仅作应急。3.3 地图生成配置避免首次加载时的“黑洞式等待”map-gen-settings.json控制新地图的地形、资源分布。默认配置生成超大地图1024×1024 chunks首次加载需 15 分钟以上。为快速验证创建/home/factorio/config/map-gen-settings.json{ seed: 123456789, width: 256, height: 256, water: 0.3, peaceful_mode: false, autoplace_controls: { coal: {size: 1, frequency: 1, richness: 1}, iron-ore: {size: 1, frequency: 1, richness: 1}, copper-ore: {size: 1, frequency: 1, richness: 1}, stone: {size: 1, frequency: 1, richness: 1}, uranium-ore: {size: 0.5, frequency: 0.3, richness: 0.7} } }关键参数width/height: 256生成 256×256 chunks 地图约 16km×16km首次加载时间压缩至 90 秒内。seed固定种子确保每次生成地图一致方便调试。autoplace_controls降低铀矿频率0.3和丰富度0.7避免早期过度爆炸——这是新手服务器最常被炸毁的原因。实操心得第一次启动前务必用factorio --create mytest.zip --map-gen-settings config/map-gen-settings.json命令预生成一张测试地图。若失败问题出在配置语法或路径而非服务端本身。这步能省去 80% 的启动排错时间。4. systemd 服务化让 Factorio 成为 Linux 系统的“原住民”把 Factorio 当成普通进程./factorio_headless_x64运行等于放弃 Linux 最强大的能力——服务管理。systemd 不仅能开机自启更能实现崩溃自动重启、资源超限强制终止、日志集中归档、启动超时熔断、依赖服务检查如确保网络就绪后再启动。以下是生产环境级的 service 文件4.1 创建 systemd 服务单元文件以 root 身份创建/etc/systemd/system/factorio.service[Unit] DescriptionFactorio Headless Server Afternetwork.target StartLimitIntervalSec0 [Service] Typesimple Userfactorio Groupfactorio WorkingDirectory/home/factorio ExecStart/home/factorio/bin/factorio_headless_x64 --start-server-load-latest --server-settings /home/factorio/config/server-settings.json --map-gen-settings /home/factorio/config/map-gen-settings.json Restarton-failure RestartSec10 TimeoutStartSec120 TimeoutStopSec60 LimitNOFILE65536 LimitNPROC65536 MemoryLimit4G CPUQuota80% EnvironmentFACTORIO_SERVER_PORT27015 EnvironmentFACTORIO_SERVER_NAME我的异星工厂 # 关键OOMScoreAdjust 防止被误杀 OOMScoreAdjust-500 [Install] WantedBymulti-user.target逐行解析StartLimitIntervalSec0禁用启动失败次数限制避免因临时网络问题导致服务永久禁用。TimeoutStartSec120Factorio 加载大型存档可能耗时设为 120 秒防超时误判。MemoryLimit4G硬性限制内存超过则 OOM Kill。根据服务器总内存设定如 8GB 机器设为 4G16GB 设为 6G。CPUQuota80%限制 Factorio 最多占用 80% CPU 时间为系统保留 20% 应急资源。OOMScoreAdjust-500大幅降低 Factorio 进程被 OOM Killer 选中的概率确保数据库、SSH 等关键服务优先存活。4.2 启用并启动服务# 重载 systemd 配置 sudo systemctl daemon-reload # 启用开机自启 sudo systemctl enable factorio.service # 启动服务 sudo systemctl start factorio.service # 查看状态必须显示 active (running) sudo systemctl status factorio.service首次启动时观察status输出末尾的Started Factorio Headless Server。若卡在activating (start)执行sudo journalctl -u factorio.service -f实时查看日志常见问题Permission denied检查/home/factorio/bin/factorio_headless_x64是否为factorio用户所有且权限为555。Failed at step EXEC spawning缺少 32 位库回查 2.3 节。No such file or directory--server-settings路径错误确认 JSON 文件存在且路径拼写准确。4.3 日志管理与轮转告别“日志爆炸”Factorio 默认将日志输出到logs/目录但不自动轮转。放任不管一个月后logs/可能占满 20GB。利用 systemd 自带的日志轮转# 编辑 systemd 日志配置 sudo nano /etc/systemd/journald.conf修改以下行SystemMaxUse500M SystemMaxFileSize100M MaxRetentionSec30day然后重启 journaldsudo systemctl restart systemd-journald验证journalctl -u factorio.service --disk-usage应显示用量在 500M 以内。同时Factorio 自身日志/home/factorio/logs/可通过 logrotate 管理创建/etc/logrotate.d/factorio/home/factorio/logs/*.log { daily missingok rotate 7 compress delaycompress notifempty create 644 factorio factorio }经验之谈我曾管理一台 20 人服务器某次未配置 logrotatelogs/目录在 12 天内膨胀至 17GB导致磁盘写满、服务假死。systemd 日志轮转是第一道防线logrotate 是第二道。双保险缺一不可。5. 网络与防火墙让玩家连进来而不是对着“连接超时”发呆Factorio 默认使用 UDP 端口27015也可自定义。但 Linux 防火墙ufw/firewalld和云服务商安全组会默认拦截所有入站 UDP 流量。这一步配置错误会导致“服务器明明在跑玩家就是连不上”的经典问题。5.1 Ubuntu 默认防火墙ufw配置# 启用 ufw若未启用 sudo ufw enable # 允许 Factorio 端口UDP sudo ufw allow 27015/udp # 允许 SSH确保远程管理不中断 sudo ufw allow OpenSSH # 查看规则 sudo ufw status verbose输出应包含27015/udp ALLOW IN Anywhere 27015/udp (v6) ALLOW IN Anywhere (v6)若显示DENY IN说明规则未生效检查是否遗漏/udp后缀——TCP 和 UDP 规则完全独立。5.2 云服务器安全组以阿里云为例登录云控制台找到对应 ECS 实例的“安全组”添加安全组规则 → 类型UDP → 端口范围27015/27015→ 授权对象0.0.0.0/0允许所有 IP或指定玩家 IP 段。切勿只开 TCP 端口Factorio 游戏数据传输全部走 UDPTCP 仅用于初始握手和 Web UI若启用。保存后等待 1-2 分钟生效。5.3 端口连通性自检三步定位问题在玩家连接前务必在服务器本地验证端口可达性# 1. 检查 Factorio 进程是否监听该端口 sudo ss -tuln | grep :27015 # 应输出类似udp UNCONN 0 0 *:27015 *:* users:((factorio_headles,pid1234,fd12)) # 2. 从服务器内部 telnet 测试UDP 无法 telnet改用 nc echo test | nc -u 127.0.0.1 27015 # 无报错即表示端口开放 # 3. 从外部机器测试需安装 nc nc -zu your-server-ip 27015 echo Port open || echo Port blocked若第 3 步失败按顺序排查本地ss命令无输出 → Factorio 未启动或端口配置错误本地nc成功外部nc失败 → 防火墙或安全组未放行两者均失败 → 服务器网络配置问题如 NAT、路由。关键提醒Factorio 客户端连接时地址栏输入格式为your-server-ip:27015必须带端口号。很多新手只输 IP客户端默认连27015但若服务器改了端口如34567就必须显式写出your-server-ip:34567。这是 70% 的“连不上”问题根源。6. Mod 管理与更新自动化部署拒绝手动覆盖的灾难Mod 是 Factorio 生命力的核心但手动下载、解压、覆盖mods/目录是运维噩梦。一个 Mod 更新失败可能导致整个服务器启动报错退出。我们采用符号链接 Git 仓库的方案实现 Mod 的原子化更新与版本回滚。6.1 构建 Mod 仓库用 Git 管理所有 Mod# 切换到 factorio 用户 sudo su - factorio # 创建 mods_repo 仓库 mkdir -p ~/mods_repo cd ~/mods_repo git init git config user.name Factorio Admin git config user.email adminlocalhost # 下载常用 Mod以 Krastorio 2 为例 wget https://mods.factorio.com/download/krastorio2/1.1.12 -O krastorio2_1.1.12.zip unzip krastorio2_1.1.12.zip -d . rm krastorio2_1.1.12.zip # 提交到仓库 git add . git commit -m Add Krastorio 2 v1.1.12关键设计~/mods_repo/下直接是 Mod 文件夹如krastorio2_1.1.12/而非嵌套在子目录中。这样ln -s才能精准指向。6.2 建立符号链接让服务端“看到”最新 Mod# 进入 mods/ 目录 cd ~/mods # 删除原有内容首次为空 rm -rf * # 为每个 Mod 创建符号链接 ln -s ../mods_repo/krastorio2_1.1.12 krastorio2 ln -s ../mods_repo/Loader_v1.1.0 Loader # 验证链接 ls -la # 应显示krastorio2 - ../mods_repo/krastorio2_1.1.12优势更新 Mod 时只需在mods_repo/中拉取新版本、提交 Git然后重新运行ln -s命令或写成脚本。旧版本文件保留在mods_repo/中随时可回滚。6.3 自动化更新脚本一行命令完成全量更新创建/home/factorio/update-mods.sh#!/bin/bash # 切换到 mods_repo 并拉取最新 cd /home/factorio/mods_repo git pull origin main # 清空 mods/ 并重建链接 rm -rf /home/factorio/mods/* ln -s ../mods_repo/krastorio2_1.1.12 /home/factorio/mods/krastorio2 ln -s ../mods_repo/Loader_v1.1.0 /home/factorio/mods/Loader # 重启服务平滑重启玩家无感知 sudo systemctl restart factorio.service echo Mods updated and server restarted.赋予执行权限chmod x /home/factorio/update-mods.sh日常更新流程./update-mods.sh。整个过程 20 秒内完成玩家仅经历 1-2 秒的短暂连接中断。血泪教训某次我手动解压一个新版 Mod 到mods/忘记删除旧版同名文件夹导致 Factorio 加载时两个版本冲突报错Duplicate mod name bobinserters服务器无法启动。用 Git 符号链接后此类问题彻底消失。Mod 管理不是“能用就行”而是“可控、可溯、可逆”。7. 性能监控与调优读懂服务器的“心跳”而不是等它宕机Factorio 服务器不是黑盒。Linux 提供了丰富的工具链让我们实时感知其健康状态。以下是我每天必查的三项指标它们比任何“服务器在线”通知都更能预判崩溃7.1 实时 CPU 与内存占用htop是第一眼诊断sudo apt install htop sudo -u factorio htop关注CPU%单核超过 95% 持续 30 秒说明计算瓶颈。此时应检查是否有巨型蓝图正在渲染、流体网络是否形成无限循环、或 Mod 是否存在性能缺陷。MEM%内存使用率 85% 且SWAP使用量上升表明物理内存不足需增大MemoryLimit或优化地图。LOAD AVERAGE三个数字1/5/15 分钟。若第一个数字 CPU 核心数说明任务队列积压需介入。7.2 磁盘 I/O 压力iotop揭露隐藏瓶颈sudo apt install iotop sudo iotop -oFactorio 高频读写saves/目录。若iotop显示factorio_headles进程的IO常驻 90% 以上说明存档过大 500MB需启用autosave_only_on_server并减少autosave_slots磁盘为机械硬盘HDD强烈建议更换为 SSD同一磁盘上运行了 MySQL 等其他高 I/O 服务需分离存储。7.3 网络连接状态ss诊断连接池枯竭sudo ss -tn state established | grep :27015 | wc -l此命令统计当前与 Factorio 建立的 TCP 连接数初始握手用。正常值应 ≤players设置值如 16。若远超此数如 50说明玩家客户端异常断开未释放连接常见于手机热点不稳定需在server-settings.json中缩短afk_autokick_interval如设为1800秒云服务器安全组或 NAT 网关存在连接跟踪表溢出需联系服务商扩容。我的监控习惯每天早 9 点、晚 9 点各执行一次htopiotopss组合检查并将关键数值CPU%、MEM%、IO%记入简易文本日志。连续三天某项指标趋势上升立即启动优化——比如发现iotopIO% 从 40% 涨到 75%就着手清理旧存档、迁移 SSD。预防永远比抢救高效。8. 故障排查实战从“服务器崩了”到精准定位的完整链路再完善的部署也会遇到问题。以下是我在三年运维中总结的 Top 5 故障及其闭环排查链路每一步都有明确指令和预期输出拒绝“重启大法”。8.1 故障现象服务器进程消失但systemctl status显示 inactive排查链路sudo journalctl -u factorio.service -n 100 --no-pager→ 查看最后 100 行日志。若出现Segmentation fault或Aborted是程序崩溃。sudo dmesg -T | grep -i factorio\|oom→ 检查内核日志。若含Out of memory: Kill process证实被 OOM Killer 杀死。sudo systemctl show factorio.service | grep MemoryLimit→ 确认MemoryLimit设置。若为infinity立即设为4G并sudo systemctl daemon-reload sudo systemctl restart factorio。若无 OOM 记录检查磁盘空间df -h。/home分区满100%会导致 Factorio 写存档失败而退出。8.2 故障现象玩家能连接但游戏卡顿、机器人不动、电路无响应排查链路sudo -u factorio htop→ 观察 CPU%。若单核 100%执行sudo -u factorio strace -p $(pgrep factorio) -c30 秒查看strace输出中futex或epoll_wait占比。高占比说明线程阻塞非 CPU 瓶颈。sudo iotop -o -p $(pgrep factorio)→ 查看 Factorio 进程的 I/O。若IO持续 95%执行ls -laS /home/factorio/saves/找出最大存档文件。删除旧存档保留最近 3 个。sudo ss -tn state established | grep :27015 | wc -l→ 若连接数异常高30编辑server-settings.json将afk_autokick_interval改为1800重启服务。8.3 故障现象新玩家加入时报错 “Invalid server response”排查链路sudo ss -tuln | grep :27015→ 确认 Factorio 正在监听 UDP 端口。若无输出sudo systemctl start factorio。sudo ufw status | grep 27015→ 确认 ufw 规则存在。若无执行sudo ufw allow 27015/udp。curl -I http://your-server-ip:27015→ Factorio 不提供 HTTP 服务此命令应返回curl: (7) Failed to connect。若返回200 OK说明有其他服务如 Nginx占用了该端口需停止冲突服务。8.4 故障现象Mod 加载失败日志报 “Could not load mod xxx”排查链路ls -la /home/factorio/mods/→ 检查符号链接是否有效。若显示broken说明mods_repo/中对应文件夹不存在。cat /home/factorio/mods/xxx/info.json | python3 -m json.tool→ 验证 JSON 语法。若报错Expecting property name enclosed in double quotes说明 info.json 有语法错误如单引号、尾逗号。sudo -u factorio /home/factorio/bin/factorio_headless_x64 --check-mods --mod-directory /home/factorio/mods→ Factorio 官方校验命令。输出会明确指出哪个 Mod 版本不兼容或缺失依赖。8.5 故障现象服务器启动后立即退出日志无有效信息排查链路sudo strace -f -e traceexecve,openat,connect /home/factorio/bin/factorio_headless_x64 --start-server-load-latest 21 | head -n 50→ 追踪启动时的系统调用。若最后几行是openat(AT_FDCWD, /lib/x86_64-linux-gnu/libc.so.6, ...)后直接exit_group(1)说明 glibc 版本不匹配。ldd /home/factorio/bin/factorio_headless_x64 | grep not found→ 检查缺失的共享库。若输出libstdc.so.6 not found执行sudo apt install lib32stdc6。file /home/factorio/bin/factorio_headless_x64→ 确认文件类型。若输出ELF 32-bit LSB pie executable说明下载了 32 位版本需重下 x86_64 版。最后一句经验所有排查命令我都存为/home/factorio/troubleshoot.sh脚本一键执行。真正的效率不在于多快解决问题而在于让问题不再重复发生。