PHP ssh2执行远程npm start无输出,需显示JS程序运行输出
解决PHP ssh2扩展执行
npm start无法实时显示JS程序输出的问题 我之前也踩过类似的坑——用ssh2_exec执行像npm start这种长期运行、持续输出日志的命令时,要么拿不到输出,要么输出迟迟不显示。问题主要出在这几个地方:
ssh2_exec默认是一次性执行命令的模式,不会持续捕获实时输出,而且很多程序的输出会被缓冲,直到进程结束才会返回内容- 你只读取了
SSH2_STREAM_STDIO,但npm start的运行日志经常会输出到标准错误流(STDERR),没捕获到的话自然看不到 - 没有模拟终端环境,部分命令在非终端模式下的输出行为会异常
下面是调整后的代码,能实时输出JS程序的运行日志:
<?php $domain = 'your-server-ip'; $user = 'root'; $pass = 'your-password'; // 禁用内容编码,避免输出被压缩导致显示异常 header('Content-Encoding: none;'); // 取消超时限制,适配npm start这类长期运行的进程 set_time_limit(0); // 关闭输出缓冲,确保内容实时推送到浏览器 ob_implicit_flush(true); ob_end_flush(); // 建立SSH连接 $connection = ssh2_connect($domain, 22); if (!$connection) { die('无法连接到远程服务器'); } // 密码认证 if (!ssh2_auth_password($connection, $user, $pass)) { die('认证失败'); } // 关键:用ssh2_shell模拟终端环境,支持持续输出的命令 // 指定xterm终端类型,避免命令输出格式异常 $shell = ssh2_shell($connection, 'xterm'); if (!$shell) { die('无法创建shell会话'); } // 先切换到目标目录,再执行npm start fwrite($shell, "cd token && npm start\n"); fflush($shell); // 循环读取输出,实时推送到浏览器 while (!feof($shell)) { // 读取一行输出 $output = fgets($shell); // 转义HTML特殊字符,避免乱码或页面格式错乱 echo htmlspecialchars($output) . '<br>'; // 强制刷新输出缓冲区,确保内容立刻显示 flush(); // 避免循环过于频繁占用资源,休眠100毫秒 usleep(100000); } // 关闭资源 fclose($shell); ssh2_disconnect($connection); ?>
关键调整说明:
- 替换
ssh2_exec为ssh2_shell:shell会话会模拟真实终端,完美支持持续输出的命令,而exec更适合一次性执行的短命令 - 处理输出缓冲:通过
ob_implicit_flush和flush确保每读取到一点内容就立刻输出到浏览器,不会攒到缓冲区满才推送 - 合并输出流:shell会话会把标准输出和错误流合并返回,不用单独处理两个流,避免漏掉日志
- 添加休眠机制:
usleep(100000)是100毫秒的休眠,防止循环太频繁占用过多服务器资源,同时不影响实时性
额外注意点:
- 确认远程服务器上的
token目录存在,且npm命令能被当前用户正常调用(root用户一般没问题,普通用户可能需要配置环境变量) - 可以先手动登录远程服务器执行
cd token && npm start,确认确实有日志输出到终端 - 浏览器端要关闭缓存,部分浏览器会缓冲长连接的输出,导致看不到实时内容
内容的提问来源于stack exchange,提问作者Hery Winarto
相关产品推荐
相关产品推荐

