通过命令行处理PHP禁用函数

kkcode
kkcode
2026-05-01阅读 303

从一行命令说起:
curl -Ss https://www.workerman.net/webman/fix-disable-functions | php

该指令的作用是从指定URL获取一个PHP脚本,并将其通过管道传递给PHP解释器执行。

  1. curl -Ss https://www.workerman.net/webman/fix-disable-functions部分:

    • curl是一个用于传输数据的命令行工具。
    • -S选项使curl在静默模式下显示错误信息。
    • -s选项使curl静默模式,不显示进度或错误信息(除非使用-S)。它从指定的URL(https://www.workerman.net/webman/fix-disable-functions)获取数据,这里获取的是一个PHP脚本内容。
  2. | php部分:

    • 管道符|curl获取的数据(即PHP脚本内容)传递给php命令,php命令会执行接收到的PHP脚本。

    这个PHP脚本的功能主要是检查和修改PHP配置中的disable_functions设置,它会检查一些必要的函数是否在disable_functions列表中,如果在则尝试从列表中移除,然后更新php.ini文件(如果找到),最后输出移除的函数和操作成功的信息。

执行这个指令后,会根据服务器上php.ini文件中的disable_functions设置情况进行相应操作。如果disable_functions中包含脚本中列出的函数,并且脚本有权限修改php.ini文件,那么这些函数将被从disable_functions列表中移除,同时在控制台输出移除的函数名和操作成功的提示信息;如果disable_functions中不包含这些函数或者找不到php.ini文件等情况,也会有相应的输出提示。

脚本逻辑

该链接中的内容是一个PHP脚本,其主要功能是处理PHP配置中的disable_functions设置,具体如下:

  1. 获取disable_functions设置:
    • 首先通过ini_get("disable_functions")获取当前PHP配置中disable_functions的值,并存储在$disable_functions_str变量中。如果该值为空,则直接输出ok并退出脚本,这意味着当前没有禁用任何函数,不需要进行后续处理。
  2. 定义所需函数列表:
    • 定义了一个名为$functions_required的数组,其中包含了一系列函数名,如stream_socket_serverpcntl_signal_dispatch等。这些函数是脚本认为在当前环境中可能需要启用的函数。
  3. 检查所需函数是否被禁用:
    • 通过循环遍历$functions_required数组中的每个函数,使用strpos函数检查该函数是否在$disable_functions_str中(即是否被禁用)。如果找到任何一个所需函数被禁用,就将$has_disbaled_functions设置为true并跳出循环。如果所有所需函数都未被禁用,同样输出ok并退出脚本。
  4. 处理禁用函数列表:
    • 如果存在被禁用的所需函数,将$disable_functions_str以逗号分隔为数组,存储在$disable_functions变量中。然后再次循环遍历$disable_functions数组,对于每个函数,去除首尾空格后,检查其是否以$functions_required中的函数名开头。如果是,则将该函数添加到$disable_functions_removed数组中,并从$disable_functions数组中删除该元素。这样就筛选出了需要从disable_functions设置中移除的函数。
  5. 更新php.ini文件:
    • 通过php_ini_loaded_file()获取当前加载的php.ini文件路径,如果获取失败或者文件不存在,则输出错误信息并退出脚本。接着读取php.ini文件内容到$php_ini_content变量,如果读取失败则输出相应错误信息并退出。然后将处理后的禁用函数列表重新组合为字符串$new_disable_functions_str,并使用preg_replace函数在$php_ini_content中替换原来的disable_functions设置行。最后将更新后的内容写回php.ini文件。
  6. 输出结果:
    • 循环遍历$disable_functions_removed数组,根据操作系统目录分隔符是否为/,以不同的格式输出被启用的函数名(左对齐并填充到30个字符宽度,绿色显示[enabled])。最后输出success表示操作成功。

总体而言,这个脚本的目的是确保某些特定的函数不被disable_functions设置禁用,如果发现这些函数在禁用列表中,就尝试从php.ini文件中移除对它们的禁用设置。

脚本内容

<?php
// 获取PHP配置中disable_functions的值
$disable_functions_str = ini_get("disable_functions");
// 如果disable_functions为空,直接输出ok并退出脚本
if (!$disable_functions_str) {
    exit("ok\n");
}

// 定义一系列可能需要启用的函数名数组
$functions_required = [
    "stream_socket_server",
    "stream_socket_accept",
    "stream_socket_client",
    "pcntl_signal_dispatch",
    "pcntl_signal",
    "pcntl_alarm",
    "pcntl_fork",
    "pcntl_wait",
    "posix_getuid",
    "posix_getpwuid",
    "posix_kill",
    "posix_setsid",
    "posix_getpid",
    "posix_getpwnam",
    "posix_getgrnam",
    "posix_getgid",
    "posix_setgid",
    "posix_initgroups",
    "posix_setuid",
    "posix_isatty",
    "proc_open",
    "proc_get_status",
    "proc_close",
    "shell_exec",
    "exec",
    "putenv",
    "getenv",
];

// 标记是否存在被禁用的所需函数,初始化为false
$has_disbaled_functions = false;
// 遍历所需函数数组
foreach ($functions_required as $func) {
    // 检查当前函数是否在disable_functions中被禁用
    if (strpos($disable_functions_str, $func)!== false) {
        // 如果找到被禁用的函数,设置标记为true并跳出循环
        $has_disbaled_functions = true;
        break;
    }
}
// 如果没有找到被禁用的所需函数,输出ok并退出脚本
if (!$has_disbaled_functions) {
    exit("ok\n");
}

// 将disable_functions字符串以逗号分隔为数组
$disable_functions = explode(",", $disable_functions_str);
// 用于存储需要从disable_functions中移除的函数
$disable_functions_removed = [];
// 遍历disable_functions数组
foreach ($disable_functions as $index => $func) {
    // 去除函数名的首尾空格
    $func = trim($func);
    // 再次遍历所需函数名数组
    foreach ($functions_required as $func_prefix) {
        // 检查当前函数是否以所需函数名开头(即是否是需要移除的函数)
        if (strpos($func, $func_prefix) === 0) {
            // 如果是,将其添加到移除数组中,并从原数组中删除
            $disable_functions_removed[$func] = $func;
            unset($disable_functions[$index]);
        }
    }
}

// 获取当前加载的php.ini文件路径
$php_ini_file = php_ini_loaded_file();
// 如果获取失败或文件不存在,输出错误信息并退出脚本
if (!$php_ini_file ||!is_file($php_ini_file)) {
    exit("$php_ini_file not found\n");
}
// 读取php.ini文件内容
$php_ini_content = file_get_contents($php_ini_file);
// 如果读取失败,输出错误信息并退出脚本
if (!$php_ini_content) {
    exit("$php_ini_file content empty\n");
}

// 将处理后的disable_functions数组重新组合为字符串
$new_disable_functions_str = implode(",", $disable_functions);
// 使用正则表达式替换php.ini文件内容中的disable_functions设置行
$php_ini_content = preg_replace("/\ndisable_functions *?=[^\n]+/", "\ndisable_functions = $new_disable_functions_str", $php_ini_content);
// 将更新后的内容写回php.ini文件
file_put_contents($php_ini_file, $php_ini_content);

// 遍历需要移除的函数数组,输出被启用的函数名(根据操作系统格式)
foreach ($disable_functions_removed as $func) {
    echo DIRECTORY_SEPARATOR === "/"? str_pad($func, 30). " \033[32;40m [enabled] \033[0m\r\n" : str_pad($func, 30). " [enabled]\r\n";
}
// 输出操作成功的提示
echo "\r\nsuccess\r\n";
评论数量:0