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

RedHat Linux下编写PHP x3270自动化脚本实现登录发命令并存屏到文本

问题修复方案与实现示例

核心问题原因

  • 你调用的是GUI版本的x3270,启动后会进入图形交互模式,无法通过标准输入输出完成自动化控制,应该使用同套件的脚本专用版本s3270,无需图形界面,完全基于命令流交互。
  • 代码存在语法错误:process = proc_open(...) 缺少变量前缀$,会触发语法报错。
  • 非阻塞流的读取逻辑有缺陷,没有超时机制,匹配不到指定文本就会进入死循环,ascii()命令的调用位置也不符合s3270的交互规则。
  • 缺少屏幕内容持久化逻辑,只要把ascii()返回的内容写入文件即可实现保存需求。

修正后完整代码

首先在RedHat环境执行yum install x3270安装完整套件,确认s3270命令可用后使用以下代码:

<?php
// 业务配置
$targetHost = '你的目标主机地址';
$targetPort = '目标端口';
$screenSavePath = './screen_output.txt'; // 屏幕内容保存路径

$descriptorspec = array(
    0 => array("pipe", "r"),  // 标准输入:给s3270发控制命令
    1 => array("pipe", "w"),  // 标准输出:读取s3270返回的结果
    2 => array("pipe", "w")   // 标准错误:排查交互异常
);

// 调用s3270而非x3270,可执行which s3270确认实际路径
$process = proc_open('/usr/bin/s3270', $descriptorspec, $pipes, null, null);
if (!is_resource($process)) {
    die("启动s3270失败");
}

// 设置流非阻塞模式
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);

/**
 * 等待匹配屏幕指定文本,带超时机制避免死循环
 * @param string $matchTxt 要匹配的文本
 * @param int $timeout 超时时间/秒
 * @return false|string 匹配成功返回屏幕内容,超时返回false
 */
function expecttxt(string $matchTxt, int $timeout = 10) {
    global $pipes;
    $startTime = time();
    $buffer = '';
    while (time() - $startTime < $timeout) {
        // 读取所有可用输出
        while ($line = fgets($pipes[1])) {
            $buffer .= $line;
            if (preg_match("/".preg_quote($matchTxt, '/')."/i", $buffer)) {
                return $buffer;
            }
        }
        // 打印错误日志便于排查
        while ($err = fgets($pipes[2])) {
            error_log("s3270交互错误:".$err);
        }
        usleep(500000); // 0.5秒轮询,降低CPU占用
    }
    return false;
}

/**
 * 保存屏幕内容到txt文件
 * @param string $content 屏幕内容
 * @param string $path 保存路径
 */
function saveScreen(string $content, string $path) {
    file_put_contents($path, "===== ".date("Y-m-d H:i:s")." 屏幕快照 =====\n".$content.PHP_EOL, FILE_APPEND);
}

// 业务流程实现
// 1. 连接目标设备
fwrite($pipes[0], "connect($targetHost:$targetPort)\n");
if (!expecttxt("connected")) {
    die("连接目标设备超时");
}

// 2. 读取初始屏幕、匹配CDN标识并保存
fwrite($pipes[0], "ascii()\n");
$screenContent = expecttxt("CDN");
if (!$screenContent) {
    die("等待CDN标识超时");
}
saveScreen($screenContent, $screenSavePath);

// 3. 输入会话名并回车
fwrite($pipes[0], "string(session-name)\n");
fwrite($pipes[0], "enter\n");

// 4. 读取会话状态页面并保存
fwrite($pipes[0], "ascii()\n");
$screenContent = expecttxt("SESSION STATUS");
if (!$screenContent) {
    die("等待会话状态页面超时");
}
saveScreen($screenContent, $screenSavePath);

// 5. 按下PF2键
fwrite($pipes[0], "PF(2)\n");

// 6. 读取下一页内容并保存
fwrite($pipes[0], "ascii()\n");
$screenContent = expecttxt("NEXT INFO");
if (!$screenContent) {
    die("等待下一页信息超时");
}
saveScreen($screenContent, $screenSavePath);

// 结束流程,释放资源
fwrite($pipes[0], "quit()\n");
proc_close($process);
?>

使用说明

  • 替换代码中主机地址、端口、会话名等占位内容为实际业务参数即可运行。
  • 每一步的屏幕快照会按执行时间追加到指定的txt文件中,便于后续回溯。
  • 所有交互步骤都设置了超时保护,可根据实际网络情况调整expecttxt的第二个参数修改超时时间。

内容的提问来源于stack exchange,提问作者Luciano Fattore

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:24:04