如何用Rust通过Bash向Minecraft Java服务器发送指令并后台运行
解决Rust启动Minecraft服务器并按需发送/stop指令的问题
你当前代码用output()方法会阻塞主线程直到服务器进程结束,且无法与服务器的标准输入交互,因此没法发送/stop指令。要实现后台运行服务器并按需停止,需要做以下调整:
核心修改点
- 用
spawn()替代output():spawn()会启动后台进程并立即返回子进程句柄,不会阻塞主线程。 - 配置子进程标准输入为管道:通过
Stdio::piped()创建管道,让Rust程序能向服务器进程写入指令。 - 监听终端输入:主线程循环读取用户输入,当输入
/stop时,将指令发送给服务器并等待其退出。
完整代码示例
use std::io::{self, Write}; use std::process::{Command, Stdio}; fn main() { // 替换为你的实际配置 let server_name = "your_server_folder"; let java_version = "your_jdk_version"; let minecraft_version = "minecraft_server.jar"; let command = format!( "cd ./servers/{server_name}/ && ../../jdk/{java_version}/bin/java -Xmx2048M -Xms2048M -jar ../../profiles/{minecraft_version} nogui" ); println!("执行命令: {}", command); // 启动服务器进程,配置输入输出 let mut child = Command::new("/bin/sh") .args(["-c", &command]) .stdin(Stdio::piped()) // 创建输入管道,用于发送指令 .stdout(Stdio::inherit()) // 继承父进程标准输出,直接显示服务器日志 .stderr(Stdio::inherit()) // 继承父进程标准错误,显示错误信息 .spawn() .expect("启动服务器进程失败"); // 获取服务器进程的输入句柄 let mut server_stdin = child.stdin.take().expect("无法获取服务器输入流"); println!("服务器已启动,输入/stop可停止服务器"); // 循环监听用户输入 loop { let mut input = String::new(); io::stdin() .read_line(&mut input) .expect("读取终端输入失败"); let input = input.trim(); // 去除输入中的换行符和空格 if input == "/stop" { // 向服务器发送/stop指令,必须添加换行符模拟回车确认 writeln!(server_stdin, "/stop").expect("发送指令失败"); // 等待服务器进程退出 let exit_status = child.wait().expect("等待服务器退出失败"); println!("服务器已停止,退出状态码: {}", exit_status); break; } else { println!("未知指令,请输入/stop停止服务器"); } } }
关键细节说明
Stdio::inherit():让服务器的日志直接输出到当前终端,方便查看运行状态。writeln!:发送指令时必须包含换行符,因为Minecraft服务器需要接收到换行符才会执行输入的指令。- 错误处理:用
expect()捕获可能的错误并给出明确提示,作为Rust新手,这种方式能快速定位问题。
内容的提问来源于stack exchange,提问作者JE597
相关产品推荐
相关产品推荐

