Unity无头服务器程序如何将日志输出至stdout而非Player Log
我之前在搭建Unity无头服务器时也碰到过一模一样的问题——明明重置了Console输出流,结果所有内容还是跑到Player Log里,根本看不到stdout输出。折腾了一阵后,找到了几个靠谱的解决办法,分享给你:
方案1:使用Unity命令行参数(最省心,推荐)
Unity本身提供了命令行参数可以直接把日志导向stdout,完全不需要改代码。启动服务器时加上 -logfile - 参数(注意后面的短横线),它会告诉Unity把所有日志(包括Console.WriteLine和Debug.Log的内容)直接输出到标准输出。
比如你的启动命令可以改成这样:
# Linux/macOS ./YourServerBuild.x86_64 -batchmode -nographics -logfile - # Windows YourServerBuild.exe -batchmode -nographics -logfile -
这个参数会彻底绕过Player Log,直接把所有日志内容打到stdout里,非常适合无头服务器的场景。
方案2:直接写入原生标准输出路径
Unity的Console.OpenStandardOutput()可能会被内部机制拦截,导致重置无效。我们可以直接针对不同平台的原生stdout路径来创建写入流,绕开Unity的封装:
using System.IO; using UnityEngine; public class StdoutRedirector : MonoBehaviour { void Awake() { // 根据平台选择对应的stdout路径 string stdoutPath = Application.platform switch { RuntimePlatform.WindowsPlayer => "CONOUT$", RuntimePlatform.LinuxPlayer or RuntimePlatform.OSXPlayer => "/dev/stdout", _ => null }; if (!string.IsNullOrEmpty(stdoutPath)) { var stdoutStream = File.OpenWrite(stdoutPath); var standardOutput = new StreamWriter(stdoutStream) { AutoFlush = true }; // 同时重定向标准输出和错误输出 Console.SetOut(standardOutput); Console.SetError(standardOutput); // 测试输出 Console.WriteLine("Server started (this is Console output to stdout)."); } } }
把这个脚本挂在服务器启动的GameObject上,启动后就能直接把Console.WriteLine的内容输出到stdout了。
方案3:通过Unity日志回调转发
如果需要更精细的控制(比如只转发特定类型的日志),可以注册Unity的日志回调,把Debug.Log的内容手动写入stdout:
using System.IO; using UnityEngine; public class LogForwarder : MonoBehaviour { void Start() { // 注册日志接收回调 Application.logMessageReceived += OnLogMessageReceived; Debug.Log("Server started (this is redirected to stdout via callback)."); } void OnLogMessageReceived(string condition, string stackTrace, LogType type) { // 过滤掉不需要的日志(可选) if (type == LogType.Log || type == LogType.Warning || type == LogType.Error) { string logMessage = $"[{type}] {condition}\n{stackTrace}"; using (var writer = new StreamWriter(File.OpenWrite("/dev/stdout"))) { writer.WriteLine(logMessage); writer.Flush(); } } } void OnDestroy() { // 记得注销回调,避免内存泄漏 Application.logMessageReceived -= OnLogMessageReceived; } }
这个方案适合需要对日志做额外处理(比如格式化、过滤)的场景,但会把所有Unity日志都转发过去,需要自己加过滤逻辑。
内容的提问来源于stack exchange,提问作者Joe Strout
相关产品推荐
相关产品推荐

