.NET RedirectStandardOutput在Linux环境下失效求助
Linux下.NET捕获SA-MP服务器进程输出失败问题
问题描述
- Windows 10环境中,以下代码可正常获取目标进程输出,但Debian/Ubuntu x64虚拟机的Linux环境下完全失效,程序其余逻辑均正常
- 目标进程是SA-MP官网下载的0.3.7-R2版本Linux x86服务器程序,已确认进程能正常启动
- 异常细节:
- 设置
RedirectStandardOutput=false时,控制台能直接看到进程输出 - 设置
RedirectStandardOutput=true并尝试读取StandardOutput时,代码出现冻结 - 已尝试异步(如代码示例中的
BeginOutputReadLine)、同步等多种读取方式,均无法捕获输出
- 设置
代码示例
var p = new Process(); var psi = new ProcessStartInfo() { FileName = filePath, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false, }; p.StartInfo = psi; p.EnableRaisingEvents = true; p.OutputDataReceived += (sender, a) => Console.WriteLine(a.Data); p.ErrorDataReceived += (sender, a) => Console.WriteLine(a.Data); p.Start(); p.BeginOutputReadLine(); p.BeginErrorReadLine(); p.WaitForExit();
原因分析与解决方法
核心原因:Linux进程的输出缓冲策略差异
Linux下的进程默认可能使用全缓冲而非行缓冲——当输出内容未填满缓冲区时,不会主动刷新输出流,导致.NET无法捕获到内容;而Windows环境下进程通常采用行缓冲,输出一行就会触发刷新。
具体解决方法
用
stdbuf强制行缓冲启动进程
通过stdbuf工具修改目标进程的缓冲策略,强制标准输出和错误输出使用行缓冲:var psi = new ProcessStartInfo() { FileName = "stdbuf", Arguments = "-oL -eL " + filePath, // filePath替换为SA-MP服务器程序的实际路径 RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false, };其中
-oL表示设置标准输出为行缓冲,-eL表示设置标准错误为行缓冲。同步读取时避免死锁
如果使用同步读取方式,必须同时启动线程分别读取标准输出和标准错误,避免因某一缓冲区填满导致进程挂起:p.Start(); // 启动线程读取标准输出 Task.Run(() => { while (!p.StandardOutput.EndOfStream) Console.WriteLine(p.StandardOutput.ReadLine()); }); // 启动线程读取标准错误 Task.Run(() => { while (!p.StandardError.EndOfStream) Console.WriteLine(p.StandardError.ReadLine()); }); p.WaitForExit();检查32位运行库依赖
目标进程是x86程序,Linux x64系统需要安装对应的32位运行库才能正常运行并输出内容,比如Ubuntu下执行:sudo apt install lib32gcc-s1 lib32stdc++6
内容的提问来源于stack exchange,提问作者Vi_
相关产品推荐
相关产品推荐

