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

无法从外部versionen.php提取$software_version变量的问题排查

问题

将文件versionen.php存于所有已定义域名账户的"dataplace"文件夹中,尝试使用下方脚本读取并输出外部多个域名下该文件中的$software_version变量。该变量在本地可正常显示,脚本也能正确加载目标URL(已通过if ($content === false)的else分支验证),但测试输出中域名显示正常,$version却始终显示"Software-Empty",无法获取变量内容。

原脚本代码:

error_reporting(E_ALL);
ini_set('display_errors', '1');

// FTP-Zugangsdaten für alle URLs (1 bis x) | FTP access data for all URLs (1 to x)
$ftpCredentialsList = array(
    1 => array("hostname" => "url-1.tld", "username" => "xxxxxxxx", "password" => "yyyyyyyy"),
    2 => array("hostname" => "url-2.tld", "username" => "xxxxxxxx", "password" => "yyyyyyyy"),
    3 => array("hostname" => "url-3.tld", "username" => "xxxxxxxx", "password" => "yyyyyyyy"),
    4 => array("hostname" => "url-4.tld", "username" => "xxxxxxxx", "password" => "yyyyyyyy"),
    5 => array("hostname" => "url-5.tld", "username" => "xxxxxxxx", "password" => "yyyyyyyy"),
);

########## Software-Release ##########

// Funktion, um die Software-Version einer URL abzurufen | Function to retrieve the software version of a URL
function getSoftwareVersion($url) {
    // cURL-Verbindung erstellen | Create cURL connection
    $curl = curl_init($url);

    // Optionen für cURL festlegen | Setting options for cURL
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // Folge Umleitungen | Follow redirects

    // Inhalt der Datei abrufen | Retrieve file contents
    $content = curl_exec($curl);

    if ($content === false) {
        die("Fehler beim Abrufen der Software-Version für $url: " . curl_error($curl)."| Error retrieving software version for $url: " . curl_error($curl));
    } else {
        // echo 'Abruf der Software-Version für '.$url.' war erfolgreich. | Retrieving the software version for '.$url.' was successful.<br>';
    }

    // Die Variable $software_version aus dem Inhalt extrahieren | Extract the variable $software_version from the content
    preg_match('/\$software_version\s*=\s*(.*?);/i', $content, $matches);
    $softwareVersion = isset($matches[1]) ? $matches[1] : null;

// Debugging-Ausgabe | Debugging output
echo "Regex-Matches: ";
var_dump($matches);
echo "<br>";

echo "Software-Version: ";
var_dump($softwareVersion);
echo "<br>";
// Ende Debugging

    curl_close($curl);

    return $softwareVersion;
}

// Ergebnisse speichern | Save results
$softwareVersions = array();

foreach ($ftpCredentialsList as $index => $ftpCredentials) {
    $url = "https://{$ftpCredentials['hostname']}/dataplace/versionen.php";
    $softwareVersion = getSoftwareVersion($url);

    // Überprüfen, ob die Software-Version gültig ist, bevor Farbe zugewiesen wird
    // Check if the software version is valid before assigning color
    $colorClass = 'software_empty'; // Standardfarbe, wenn die Software-Version leer ist | Default color if the software-version is empty
    if ($softwareVersion !== null) {
        $colorClass = (stripos($softwareVersion, 'software_red') !== false ? 'software_red' : 'software_green');
    }

    // Ergebnisse in Array speichern | Save results in array
    $softwareVersions[$ftpCredentials['hostname']] = (empty($softwareVersion) ? "Software-Empty" : htmlspecialchars($softwareVersion));

    // Farbinformationen zusätzlich speichern | Store additional color information
    $softwareVersions['color'][$ftpCredentials['hostname']] = $colorClass;
}

// Testausgabe | Test issue
foreach ($softwareVersions as $hostname => $version) {
    if (!is_array($version)) { // Überprüfen, ob $version kein Array ist | Check if $version is not an array
        echo "<b>Hostname: <span style=\"color: #00F;\">$hostname</span> > Software-Version: <span style=\"color: #00F;\">$version</span><br>";
    }
}
解决方案

核心问题:HTTP请求获取的是PHP执行结果而非源代码

当你通过curl访问https://xxx/dataplace/versionen.php时,服务器会执行该PHP文件,返回的是文件的输出内容,而非PHP源码。如果versionen.php中仅定义了$software_version变量但没有输出语句,返回的内容为空,正则自然匹配不到变量定义。

解决方法二选一:

方法1:修改目标服务器的versionen.php,让它直接输出变量值

在versionen.php的末尾添加输出语句:

echo $software_version;

然后修改getSoftwareVersion函数,无需正则匹配,直接返回请求到的内容:

function getSoftwareVersion($url) {
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    $content = curl_exec($curl);

    if ($content === false) {
        die("Fehler beim Abrufen der Software-Version für $url: " . curl_error($curl)."| Error retrieving software version for $url: " . curl_error($curl));
    }

    curl_close($curl);
    // 直接返回获取到的输出内容(即$software_version的值)
    return trim($content);
}

方法2:改用FTP读取PHP文件源代码

利用你已有的FTP凭证,直接连接服务器读取versionen.php的源码,再进行正则匹配。修改getSoftwareVersion函数为接收FTP凭证:

function getSoftwareVersion($ftpCredentials) {
    $hostname = $ftpCredentials['hostname'];
    $username = $ftpCredentials['username'];
    $password = $ftpCredentials['password'];
    $filePath = '/dataplace/versionen.php'; // 注意路径需符合服务器实际结构

    // 建立FTP连接
    $ftpConn = ftp_connect($hostname);
    if (!$ftpConn) {
        die("无法连接到FTP服务器 $hostname");
    }

    // 登录FTP
    $loginStatus = ftp_login($ftpConn, $username, $password);
    if (!$loginStatus) {
        die("FTP登录失败 $hostname");
    }

    // 切换到被动模式(大多数服务器需要)
    ftp_pasv($ftpConn, true);

    // 获取文件内容
    ob_start();
    $success = ftp_fget($ftpConn, STDOUT, $filePath, FTP_ASCII);
    $content = ob_get_clean();

    if (!$success) {
        die("无法读取文件 $filePath 从 $hostname");
    }

    ftp_close($ftpConn);

    // 优化正则,匹配带引号/不带引号的变量值
    preg_match('/\$software_version\s*=\s*["\']?(.*?)["\']?;/i', $content, $matches);
    $softwareVersion = isset($matches[1]) ? trim($matches[1]) : null;

    return $softwareVersion;
}

同时修改调用处的代码:

// 原代码中的foreach循环内修改:
// $url = "https://{$ftpCredentials['hostname']}/dataplace/versionen.php";
// $softwareVersion = getSoftwareVersion($url);
$softwareVersion = getSoftwareVersion($ftpCredentials);

其他优化点

  1. 正则表达式鲁棒性优化:如果使用方法2,原正则无法匹配带单/双引号的变量值,优化后的正则/\$software_version\s*=\s*["\']?(.*?)["\']?;/i可以兼容多种定义格式。
  2. 数组结构优化:原代码中$softwareVersions同时存储版本和颜色子数组,结构混乱,建议调整为每个主机对应一个子数组:
// 替换原结果存储部分
$softwareVersions[$ftpCredentials['hostname']] = [
    'version' => empty($softwareVersion) ? "Software-Empty" : htmlspecialchars($softwareVersion),
    'color' => $colorClass
];

// 修改测试输出循环
foreach ($softwareVersions as $hostname => $info) {
    echo "<b>Hostname: <span style=\"color: #00F;\">$hostname</span> > Software-Version: <span class=\"{$info['color']}\">{$info['version']}</span><br>";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 19:47:06