PHP通过SSH2启动Minecraft服务器异常问题求助
问题描述
我用PHP的ssh2扩展编写了远程连接服务器启动Minecraft服务器的代码。执行后PHP提示服务器已在线,但实际在终端执行screen -r显示无可用会话,Minecraft服务器也并未启动。需要修改代码,让Minecraft服务器能正常启动,且可通过终端会话执行服务器命令。
原代码
<?php $serverAddress = 'ip'; // Replace with the IP address of your remote server $sshUsername = 'root'; // Replace with your SSH username $sshPassword = 'pass'; // Replace with your SSH password $minecraftDir = 'path'; // Connect to the remote server via SSH $connection = ssh2_connect($serverAddress, 22); if (!$connection) { die("SSH connection failed."); } // Authenticate with the SSH credentials if (!ssh2_auth_password($connection, $sshUsername, $sshPassword)) { die("SSH authentication failed."); } // Open a shell $shell = ssh2_shell($connection, 'xterm'); if (!$shell) { die("Failed to open shell."); } // Check if the Minecraft server is online fwrite($shell, "pgrep -a java | grep serwer.jar "); sleep(1); $output = stream_get_contents($shell); if (strpos($output, "serwer.jar") !== false) { echo "Minecraft server is online." . PHP_EOL; } else { echo "Minecraft server is offline. Starting it..." . PHP_EOL; // Start the Minecraft server fwrite($shell, "cd $minecraftDir && screen java -Xmx1G -Xms1G -jar serwer.jar nogui"); sleep(5); // Wait for the server to start // Check again if the server is online fwrite($shell, "pgrep -a java | grep serwer.jar "); sleep(1); $output = stream_get_contents($shell); if (strpos($output, "serwer.jar") !== false) { echo "Minecraft server has been started." . PHP_EOL; } else { echo "Failed to start Minecraft server." . PHP_EOL; } } // Close the SSH connection and shell fclose($shell); fclose($connection); ?>
终端执行结果
root@ip13:~# screen -r There is no screen to be resumed. root@ip13:~#
问题原因与修复方案
核心问题
- screen命令使用错误:直接用
screen java...在非交互式shell环境下无法创建可恢复的后台会话,必须指定参数让screen在后台独立运行。 - 命令未触发执行:启动服务器的命令末尾没有添加换行符
\n,导致shell没有执行这条命令。 - 进程检测误判:原检测逻辑依赖shell输出内容,容易因为缓存或残留字符误判服务器状态。
修改后的代码
<?php $serverAddress = 'ip'; // 替换为远程服务器IP $sshUsername = 'root'; // 替换为SSH用户名 $sshPassword = 'pass'; // 替换为SSH密码 $minecraftDir = 'path'; // 替换为Minecraft服务器所在目录 $screenSessionName = 'mcserver'; // 自定义screen会话名称,方便后续连接 // 建立SSH连接 $connection = ssh2_connect($serverAddress, 22); if (!$connection) { die("SSH连接失败。"); } // 身份验证 if (!ssh2_auth_password($connection, $sshUsername, $sshPassword)) { die("SSH身份验证失败。"); } // 打开交互式shell,指定终端参数确保环境正常 $shell = ssh2_shell($connection, 'xterm', null, 80, 24, SSH2_TERM_UNIT_CHARS); if (!$shell) { die("无法打开shell会话。"); } // 等待shell初始化,清空初始输出避免干扰后续检测 sleep(1); stream_get_contents($shell); // 检测Minecraft服务器运行状态 fwrite($shell, "pgrep -f 'serwer.jar' > /dev/null && echo 'RUNNING' || echo 'STOPPED'\n"); sleep(1); $status = trim(stream_get_contents($shell)); if ($status === 'RUNNING') { echo "Minecraft服务器已在线。" . PHP_EOL; } else { echo "Minecraft服务器已离线,正在启动..." . PHP_EOL; // 切换到服务器目录,用screen后台启动服务器并指定会话名 $startCommand = "cd {$minecraftDir} && screen -dmS {$screenSessionName} java -Xmx1G -Xms1G -jar serwer.jar nogui\n"; fwrite($shell, $startCommand); sleep(8); // 延长等待时间确保服务器完成启动 // 再次检测运行状态 fwrite($shell, "pgrep -f 'serwer.jar' > /dev/null && echo 'RUNNING' || echo 'STOPPED'\n"); sleep(1); $status = trim(stream_get_contents($shell)); if ($status === 'RUNNING') { echo "Minecraft服务器启动成功。" . PHP_EOL; echo "可通过终端执行 `screen -r {$screenSessionName}` 连接到服务器会话,执行服务器命令。" . PHP_EOL; } else { echo "Minecraft服务器启动失败。" . PHP_EOL; } } // 关闭shell和SSH连接 fclose($shell); fclose($connection); ?>
关键修改说明
- screen启动参数优化:使用
screen -dmS <会话名>,-d让会话在后台运行,-m强制创建新会话,-S指定名称,确保SSH连接关闭后服务器仍能持续运行,且后续可通过会话名恢复。 - 命令添加换行符:所有通过
fwrite发送的命令末尾添加\n,确保shell立即执行该命令。 - 状态检测优化:用
pgrep -f匹配完整命令行避免误判,将检测结果简化为明确的RUNNING/STOPPED,减少输出干扰导致的误判。 - shell初始化处理:等待shell初始化后清空输出,避免初始提示信息影响状态检测结果。
内容的提问来源于stack exchange,提问作者Sawio2001
相关产品推荐
相关产品推荐

