You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:27:23