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

PHP脚本无法创建XML文件问题排查求助

问题排查:PHP脚本无法生成XML文件但PCAP上传正常

问题描述

我用PHP脚本实现两个功能:

  • 根据HTML表单输入在/usr/local/ezreplay/data/XML/目录创建并写入XML文件
  • 上传表单中的PCAP文件

目前PCAP上传功能正常,能看到成功提示,但XML文件始终未生成。已将目录权限改为apache用户所有甚至设置chmod 777,PHP和Apache日志也无报错信息。

附上PHP代码:

<?php
// Check if the 'expirydate' input is set
if (isset($_POST['expirydate'])) {

  // Convert the input string to a timestamp using 'strtotime'
  $timestamp = strtotime($_POST['expirydate']);

  // Format the timestamp as a 'mm/dd/yyyy' string using 'date'
  $expirydate = date('m/d/Y', $timestamp);
}

// Check if all required POST variables are set
if ( isset($_POST['destinationip']) && isset($_POST['destinationport']) && isset($expirydate) && isset($_POST['multiplier']) && isset($_POST['pcap']) ) {

    // Set the path for the XML file
    $path = '/usr/local/ezreplay/data/XML/' . trim($_POST['destinationip']) . ':' . trim($_POST['destinationport']) . ':' . $expirydate . ':' . trim($_POST['multiplier']) . ':' . trim($_POST['pcap']) . '.xml';

    // Initialize the contents of the XML file
    $contents = "";

    // Open the XML file in append mode
    if ( $fh = fopen($path,"a+") ) {

        // Add the opening 'config' tag to the XML file
        $contents .= '<config>';

        // If the 'destinationip' and 'destinationport' POST variables are not empty, add a 'destination' tag to the XML file
        if ( trim( $_POST['destinationip'] ) != "" && trim( $_POST['destinationport'] ) != "" ) {
            $contents .= "\n" . '<destination>' . $_POST['destinationip'] . ':' . $_POST['destinationport'] . '</destination>';
        }

        // If the 'multiplier' POST variable is not empty, add a 'multiplier' tag to the XML file
        if ( trim( $_POST['multiplier'] ) != "" ) {
            $contents .= "\n" . '<multiplier>' . $_POST['multiplier'] . '</multiplier>';
        }

        // If the 'pcap' POST variable is not empty, add a 'pcap' tag to the XML file
        if ( trim( $_POST['pcap'] ) != "" ) {
            $contents .= "\n" . '<pcap>/usr/local/ezreplay/data/PCAP/' . $_POST['pcap'] . '</pcap>';

            // Add default tags to XML config file to ensure the pcap does not fail and loops continuously until expiration date hits
            $contents .= "\n" . '<loop>0</loop>';
            $contents .= "\n" . '<nofail>true</nofail>';
        }

        // Add the closing 'config' tag to the XML file
        $contents .= "\n" . '</config>';

        // Write the contents to the file
        if ( fwrite( $fh, $contents ) ) {
            // Success
        } else {
            echo "The XML config could not be created";
        }

        // Close the file
        fclose($fh);
    }
}

// Set the target directory and file name
$target_dir = "/usr/local/ezreplay/data/PCAP/";
$basename = basename($_FILES["pcap"]["name"]);
$target_file = $target_dir . $basename;

// Check if the file has a pcap extension
$allowedExtensions = array('pcap');
$basenameWithoutExt = null;
foreach ($allowedExtensions as $allowedExtension) {
    if (preg_match('#\.' . $allowedExtension . '$#',$basename)) {
        $basenameWithoutExt = substr($basename,0,-1 - strlen($allowedExtension));
        break;
    }
}

// Accept only .pcap files
if (is_null($basenameWithoutExt)) {
    echo "Sorry, only .pcap files are allowed. Please try creating your Packet Replay again using a .pcap file.";
    exit;
}

// Check if the file already exists
if (file_exists($target_file)) {
    echo "The Packet Replay could not be started, the PCAP is already running.";
    exit;
}

// Try to upload the file
if (move_uploaded_file($_FILES["pcap"]["tmp_name"], $target_file)) {
    // Success
} else {
    echo "Sorry, there was an error uploading your file.";
    exit;
}

// Start the Packet Replay
$command = '/usr/local/ezreplay/bin/startreplay.sh ' . $path;
system($command);

echo "The Packet Replay has been started.";

?>

排查分析

1. 核心条件判断完全不触发

生成XML的代码块被包裹在一个多条件判断里,其中isset($_POST['pcap'])是致命错误:表单上传的文件信息会被PHP存放在$_FILES数组中,而非$_POST,所以这个判断始终为false,导致整个XML生成逻辑完全不执行。

另外$expirydate的初始化存在隐患:如果strtotime($_POST['expirydate'])转换失败(比如日期格式不符合要求),$timestamp会返回false,date()会生成1970年的默认日期,虽然isset($expirydate)为true,但会导致后续XML内容不符合预期。

2. 变量作用域与流程逻辑漏洞

XML生成逻辑中定义的$path变量,后续被用于执行startreplay.sh脚本,但如果XML生成的条件判断不成立,$path未被定义,此时执行system($command)会触发未定义变量错误,但因为没有错误捕获机制,日志也未记录该错误,导致问题被隐藏。

同时,XML生成失败的提示会被后续PCAP上传的流程覆盖——即使XML生成失败,PCAP上传代码仍会继续执行,最终输出成功提示,误导判断。

3. 错误处理缺失

  • fopen如果失败没有任何错误提示或日志记录
  • fwrite的成功分支无反馈,失败分支的提示会被后续流程覆盖
  • 未对$expirydate的有效性做校验

修复方案

1. 修正表单字段判断逻辑

将isset($_POST['pcap'])替换为isset($_FILES['pcap']),同时增加文件上传有效性检查:

// 替换原有的条件判断
if ( isset($_POST['destinationip']) && isset($_POST['destinationport']) && isset($expirydate) && isset($_POST['multiplier']) && isset($_FILES['pcap']) && $_FILES['pcap']['error'] == UPLOAD_ERR_OK ) {
    // XML生成逻辑
}

2. 完善$expirydate初始化逻辑

增加日期转换有效性检查,避免无效日期进入流程:

if (isset($_POST['expirydate'])) {
    $timestamp = strtotime($_POST['expirydate']);
    // 校验日期转换是否成功
    if ($timestamp !== false) {
        $expirydate = date('m/d/Y', $timestamp);
    } else {
        echo "Invalid expiration date format";
        exit;
    }
} else {
    echo "Expiration date is required";
    exit;
}

3. 调整代码执行顺序与错误终止逻辑

将PCAP上传逻辑移至XML生成逻辑之后,或者确保$path在所有分支都有定义;同时在XML生成失败时直接终止流程,避免后续错误执行:

// fwrite失败时终止流程
if (!fwrite( $fh, $contents )) {
    echo "The XML config could not be created";
    fclose($fh);
    exit;
}

4. 添加错误日志记录

在关键步骤添加错误日志,方便后续排查:

// fopen失败时记录日志
if (!($fh = fopen($path,"a+"))) {
    error_log("Failed to open XML file: " . $path);
    echo "The XML config could not be created";
    exit;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:10:26