从一行命令说起:
curl -Ss https://www.workerman.net/webman/fix-disable-functions | php
该指令的作用是从指定URL获取一个PHP脚本,并将其通过管道传递给PHP解释器执行。
-
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脚本内容。
-
| 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设置,具体如下:
- 获取
disable_functions设置:- 首先通过
ini_get("disable_functions")获取当前PHP配置中disable_functions的值,并存储在$disable_functions_str变量中。如果该值为空,则直接输出ok并退出脚本,这意味着当前没有禁用任何函数,不需要进行后续处理。
- 首先通过
- 定义所需函数列表:
- 定义了一个名为
$functions_required的数组,其中包含了一系列函数名,如stream_socket_server、pcntl_signal_dispatch等。这些函数是脚本认为在当前环境中可能需要启用的函数。
- 定义了一个名为
- 检查所需函数是否被禁用:
- 通过循环遍历
$functions_required数组中的每个函数,使用strpos函数检查该函数是否在$disable_functions_str中(即是否被禁用)。如果找到任何一个所需函数被禁用,就将$has_disbaled_functions设置为true并跳出循环。如果所有所需函数都未被禁用,同样输出ok并退出脚本。
- 通过循环遍历
- 处理禁用函数列表:
- 如果存在被禁用的所需函数,将
$disable_functions_str以逗号分隔为数组,存储在$disable_functions变量中。然后再次循环遍历$disable_functions数组,对于每个函数,去除首尾空格后,检查其是否以$functions_required中的函数名开头。如果是,则将该函数添加到$disable_functions_removed数组中,并从$disable_functions数组中删除该元素。这样就筛选出了需要从disable_functions设置中移除的函数。
- 如果存在被禁用的所需函数,将
- 更新
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文件。
- 通过
- 输出结果:
- 循环遍历
$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";
