分类目录归档:挨踢

Ollama + Dify 双 L20 显卡操作手册

这是一份非常详细的操作手册,旨在指导您在搭载两块 NVIDIA L20 显卡的本地服务器上,从零开始安装最新的显卡驱动,并配置 Ollama 以充分利用双显卡资源,最后与 Dify 对接。

NVIDIA L20 是一款功能强大的数据中心级显卡,单卡拥有 48GB VRAM。两块 L20 意味着您拥有 96GB 的总显存,这足以在本地流畅运行像 Llama 3 70B 这样顶尖的开源大模型。


本地部署 Ollama + Dify 双 L20 显卡操作手册

本手册分为六个主要步骤:

  1. 系统准备与环境检查
  2. 安装最新的 NVIDIA 显卡驱动
  3. 安装 Ollama
  4. 配置 Ollama 使用双显卡
  5. 运行模型并验证双卡工作状态
  6. 与 Dify 集成

第一步:系统准备与环境检查

在开始之前,请确保您的服务器满足以下条件:

  • 操作系统:一个现代的 Linux 发行版,强烈推荐 Ubuntu 22.04 LTS(本教程以此为例)。
  • 拥有 sudo 或 root 权限。
  • 服务器已连接到互联网。

1.1 更新系统

首先,更新您的系统软件包列表和已安装的包:

sudo apt update && sudo apt upgrade -y

1.2 确认显卡被系统识别

在安装驱动之前,先确认操作系统已经从硬件层面识别到了两块 L20 显卡。

lspci | grep -i nvidia

您应该能看到类似下面两行输出,确认有两台 NVIDIA Corporation 的设备:

01:00.0 3D controller: NVIDIA Corporation AD102GL [L20]
02:00.0 3D controller: NVIDIA Corporation AD102GL [L20]

如果看不到,请检查显卡是否已正确安装在 PCIe 插槽上并接通了电源。


第二步:安装最新的 NVIDIA 显卡驱动

我们将使用 NVIDIA 官方推荐的 CUDA Toolkit 仓库进行安装,这是最稳定、最可靠的方法。它会自动处理依赖关系并安装匹配的驱动程序。

2.1 清理旧的驱动(可选但推荐)

如果系统上曾安装过其他版本的 NVIDIA 驱动,最好先彻底卸载,避免冲突。

sudo apt-get purge nvidia* -y
sudo apt autoremove -y

2.2 添加 NVIDIA CUDA 仓库

访问 NVIDIA CUDA Toolkit 官网下载页面:https://developer.nvidia.com/cuda-downloads

按照页面指引选择您的系统配置,例如:

  • Linux -> x86_64 -> Ubuntu -> 22.04 -> deb (local) 或 deb (network)

推荐使用 deb (network),因为它会保持更新。官网会生成一系列命令,请依次执行。以下是截至目前的示例命令:

# 下载仓库 pinning 文件
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-ubuntu2204.pin
sudo mv cuda-ubuntu2204.pin /etc/apt/preferences.d/cuda-repository-pin-600

# 下载并安装仓库 GPG 密钥
wget https://developer.download.nvidia.com/compute/cuda/12.4.1/local_installers/cuda-repo-ubuntu2204-12-4-local_12.4.1-550.54.15-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2204-12-4-local_12.4.1-550.54.15-1_amd64.deb
sudo cp /var/cuda-repo-ubuntu2204-12-4-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt-get update

注意:请务必从官网获取最新的命令,以上仅为示例。

2.3 安装 CUDA 驱动

现在,直接安装 CUDA 驱动包。这个包会自动安装最新、最稳定的驱动版本。

sudo apt-get install cuda-drivers -y

2.4 重启服务器

驱动安装完成后,必须重启服务器以加载新的内核模块。

sudo reboot

2.5 验证驱动安装

服务器重启后,打开终端,执行 NVIDIA 的系统管理命令:

nvidia-smi

如果安装成功,您将看到一个表格,清晰地列出了两块 NVIDIA L20 显卡的信息,包括驱动版本、CUDA 版本以及显存使用情况(初始应为 0 MiB)。

(这是一个示例图,您看到的应该是两块 L20)

看到这个界面,恭喜您,最关键的一步已经完成!


第三步:安装 Ollama

Ollama 官方提供了一键安装脚本,非常方便。

curl -fsSL https://ollama.com/install.sh | sh

安装脚本会自动下载 Ollama、创建 ollama 用户和组,并设置 systemd 服务。

安装完成后,Ollama 服务会自动启动。您可以检查其状态:

systemctl status ollama

您应该看到 active (running) 的状态。


第四步:配置 Ollama 使用双显卡

这是实现双卡协同工作的核心步骤。Ollama 通过 CUDA_VISIBLE_DEVICES 这个环境变量来决定使用哪些 GPU。我们需要修改 Ollama 的 systemd 服务文件,使其在启动时加载这个环境变量。

4.1 创建服务覆盖配置

使用 systemd 的 edit 命令来创建一个覆盖文件,这是修改服务配置的最佳实践,可以避免在 Ollama 升级时覆盖您的设置。

sudo systemctl edit ollama.service

这会打开一个空的文本编辑器。

4.2 添加环境变量

在打开的编辑器中,粘贴以下内容:

[Service]
Environment="CUDA_VISIBLE_DEVICES=0,1"
  • [Service]:告诉 systemd 我们要修改服务相关的配置。
  • Environment="CUDA_VISIBLE_DEVICES=0,1":这是关键。它告诉 Ollama(以及其他 CUDA 程序)只能看到并使用索引为 0 和 1 的 GPU。根据 nvidia-smi 的显示,这两块卡正是您的两块 L20。

保存文件并退出编辑器(在 nano 编辑器中,按 Ctrl+X,然后按 Y,最后按 Enter)。

4.3 重启 Ollama 服务

为了让新的配置生效,需要重新加载 systemd守护进程并重启 Ollama 服务。

sudo systemctl daemon-reload
sudo systemctl restart ollama

现在,Ollama 已经被配置为可以同时看到并使用您的两块 L20 显卡了。


第五步:运行模型并验证双卡工作状态

当请求运行一个足够大的模型时,Ollama 会自动将模型的不同层(layers)分配到不同的 GPU 上。

5.1 选择一个大模型

为了测试双卡负载,我们需要一个足够大的模型,使其无法完全放入单张 L20(48GB VRAM)。llama3:70b 的 Q4 量化版本大约需要 40GB+ 的显存,是完美的测试对象。

5.2 下载并运行模型

在终端中执行:

ollama run llama3:70b

首次运行时,Ollama 会下载模型文件(约 40GB),请耐心等待。下载完成后,模型会开始加载。

5.3 实时监控 GPU 使用情况

在模型加载和运行时,打开另一个终端窗口,执行以下命令来实时监控 GPU 状态:

watch -n 1 nvidia-smi

watch -n 1 会每秒刷新一次 nvidia-smi 的输出。

您应该能观察到以下现象,这证明双卡配置成功:

  1. 显存占用 (Memory-Usage):两块 L20 显卡的显存都被占用了。例如,您可能会看到 GPU 0 使用了 24GB,GPU 1 使用了 16GB。这表明模型层被成功地分割并加载到了两张卡上。
  2. GPU 利用率 (GPU-Util):当您与模型进行对话(推理)时,两块显卡的 GPU-Util 都会出现波动,说明它们都在参与计算。

(这是一个示例图,展示了两块 GPU 都有显存占用的情况)

看到两块卡的 Memory-Usage 都有显著增加,就意味着您已成功让 Ollama 同时使用两块 L20!


第六步:与 Dify 集成

Dify 通过 API 与 Ollama 通信。默认情况下,Ollama 只监听本地回环地址 127.0.0.1。如果您的 Dify 是通过 Docker 或在另一台机器上运行,需要让 Ollama 监听所有网络接口。

6.1 (可选) 配置 Ollama 监听公网 IP

如果 Dify 和 Ollama 不在同一台机器或同一个网络命名空间(如 Docker),请执行此步。

再次编辑 Ollama 服务文件:

sudo systemctl edit ollama.service

在 [Service] 部分,追加一个新的环境变量 OLLAMA_HOST。文件内容将变为:

[Service]
Environment="CUDA_VISIBLE_DEVICES=0,1"
Environment="OLLAMA_HOST=0.0.0.0"

保存并退出。然后再次重启 Ollama 服务:

sudo systemctl daemon-reload
sudo systemctl restart ollama

安全提示:将服务暴露在 0.0.0.0 意味着局域网内的任何设备都可以访问它。请确保您的服务器有防火墙保护,只允许受信任的 IP(例如 Dify 服务器的 IP)访问 11434 端口。

6.2 在 Dify 中配置 Ollama

  1. 登录您的 Dify 平台。
  2. 进入 设置 -> 模型供应商。
  3. 在列表中找到并选择 Ollama。
  4. 模型名称:填写您想在 Dify 中使用的模型名称,例如 llama3:70b。
  5. 基础 URL:填写您的 Ollama 服务器地址。
  • 如果 Dify 和 Ollama 在同一台服务器上,且没有使用 Docker,可以直接填写:http://localhost:11434
  • 如果 Dify 在另一台机器上,或使用了 Docker,请填写 Ollama 服务器的局域网 IP 地址,例如:http://192.168.1.100:11434
  1. 点击 保存。

现在,您可以在 Dify 中创建应用,并在提示词编排中选择您刚刚添加的 llama3:70b 模型了。当您在 Dify 中与模型交互时,可以再次通过 watch -n 1 nvidia-smi 观察到两块 L20 显卡都在协同工作。


故障排查 (Troubleshooting)

  • nvidia-smi: command not found
  • 原因:驱动安装失败或环境变量 PATH 不正确。
  • 解决:重新执行第二步,确保没有报错。检查 reboot 是否已执行。
  • Ollama 只使用一块 GPU
  • 原因:CUDA_VISIBLE_DEVICES 环境变量未生效。
  • 解决:检查 /etc/systemd/system/ollama.service.d/override.conf 文件内容是否正确。确保执行了 sudo systemctl daemon-reload 和 sudo systemctl restart ollama。
  • Dify 无法连接到 Ollama
  • 原因:网络问题或 Ollama 监听地址错误。
  • 解决:
  1. 在 Dify 服务器上 ping <Ollama服务器IP> 确认网络是通的。
  2. 在 Dify 服务器上 curl http://<Ollama服务器IP>:11434,如果看到 “Ollama is running”,说明 Ollama API 可达。
  3. 如果连接不通,检查防火墙设置,并确认已按 6.1 节配置 OLLAMA_HOST=0.0.0.0 并重启了服务。

pbootcms kernel解密

[rihide]解密分两步 – 仅供阅读源码使用

  • 1.修改ParserController.php 加密消除机制;
  • 2. 解密覆盖kernel文件

1.修改ParserController.php 加密消除机制;

/apps/home/controller/ParserController.php 第255行

注释掉,里面有检测如果解密了就直接退出,去掉就好了:

// if (strpos(file_get_contents(CORE_PATH . base64_decode('L2Jhc2ljL0tlcm5lbC5waHA=')), base64_decode('S2VybmVs')))
//     exit();

2. 解密覆盖kernel文件 解密kernel.php 文件内容如下:

<?php
namespace core\basic;

class Kernel
{
    private static $_url_bindArray;
    public static function run()
    {
        self::_check_auth_sn();
        self::_check_cache();

        $_path_info = self::_get_path_info();
        $_path_info = self::_check_url_bind($_path_info);
        $_path_info = self::_check_route($_path_info);
        $_ctrl = self::_get_ctrl($_path_info);
        $_ctrl_name = self::_get_ctrl_name($_ctrl);
        self::_init_boot();

        self::exec($_ctrl_name);
    }
    private static function _get_path_info()
    {
        if (isset($_SERVER['PATH_INFO']) && !mb_check_encoding($_SERVER['PATH_INFO'], 'UTF-8')) {
            $_SERVER['PATH_INFO'] = mb_convert_encoding($_SERVER['PATH_INFO'], 'utf-8', 'GBK');
        }
        if (isset($_SERVER['REQUEST_URI']) && !mb_check_encoding($_SERVER['REQUEST_URI'], 'UTF-8')) {
            $_SERVER['REQUEST_URI'] = mb_convert_encoding($_SERVER['REQUEST_URI'], 'utf-8', 'GBK');
        }
        if (isset($_SERVER['ORIG_PATH_INFO']) && !mb_check_encoding($_SERVER['ORIG_PATH_INFO'], 'UTF-8')) {
            $_SERVER['ORIG_PATH_INFO'] = mb_convert_encoding($_SERVER['ORIG_PATH_INFO'], 'utf-8', 'GBK');
        }
        $_path_info = '';
        if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO']) {
            $_path_info = $_SERVER['PATH_INFO'];
        } elseif (isset($_SERVER["REDIRECT_URL"]) && $_SERVER["REDIRECT_URL"]) {
            $_path_info = str_replace('/' . basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['REDIRECT_URL']);
            $_path_info = str_replace(SITE_DIR, '', $_path_info);
            $_SERVER['PATH_INFO'] = $_path_info;
        }
        if (!$_path_info) {
            if (isset($_GET['p']) && $_GET['p']) {
                $_path_info = $_GET['p'];
            } elseif (isset($_GET['s']) && $_GET['s']) {
                $_path_info = $_GET['s'];
            }
        }
        if ($_path_info) {
            $pljjaui50a16ce4bc582c9d154bfde2f385deb7 = '{^\/?([\x{4e00}-\x{9fa5}\w\-\/\.' . Config::get('url_allow_char') . ']+?)?$}u';
            if (preg_match($pljjaui50a16ce4bc582c9d154bfde2f385deb7, $_path_info)) {
                $_path_info = preg_replace($pljjaui50a16ce4bc582c9d154bfde2f385deb7, '$1', $_path_info);
            } else {
                $vyae93130f40d6900ea3b3380dd21598fb1 = true;
            }
        }
        if (isset($vyae93130f40d6900ea3b3380dd21598fb1) && $vyae93130f40d6900ea3b3380dd21598fb1) {
            http_response_code(404);
            $vaoaiv872c6075636c3185446c60afe7927f6d = ROOT_PATH . '/defend.html';
            if (file_exists($vaoaiv872c6075636c3185446c60afe7927f6d)) {
                require $vaoaiv872c6075636c3185446c60afe7927f6d;
                exit();
            } else {
                error('您访问路径含有非法字符,防注入系统提醒您请勿尝试非法操作!');
            }
        }
        define('P', $_path_info);
        return $_path_info;
    }
    private static function _check_url_bind($_path_info)
    {
        $_url_bind = '';
        if (!!$_app_domain_bind = Config::get('app_domain_bind')) {
            $host = get_http_host();
            if (isset($_app_domain_bind[$host])) {
                $_url_bind = $_app_domain_bind[$host];
            }
        }
        if (defined('URL_BIND')) {
            if ($_url_bind && URL_BIND != $_url_bind) {
                error('系统配置的模块域名绑定与入口文件绑定冲突,请核对!');
            } else {
                $_url_bind = URL_BIND;
            }
        }
        return $_url_bind ? trim_slash($_url_bind) . '/' . $_path_info : $_path_info;
    }
    private static function _check_route($_path_info)
    {
        if (!!$_url_route = Config::get('url_route')) {
            if (!$_path_info && isset($_url_route['/'])) {
                return $_url_route['/'];
            }
            foreach ($_url_route as $_uri => $_ctrl) {
                $_uri = trim_slash($_uri);
                $_regx = "{" . $_uri . "}i";
                if (preg_match($_regx, $_path_info)) {
                    $_ctrl = trim_slash($_ctrl);
                    $_path_info = preg_replace($_regx, $_ctrl, $_path_info);
                    break;
                }
            }
        }
        return $_path_info;
    }
    private static function _get_ctrl($_path_info)
    {
        $_public_app = Config::get('public_app', true);
        if ($_path_info) {
            $_path_info = trim_slash($_path_info);
            $_url_bind_array = explode('/', $_path_info);
            self::$_url_bindArray = $_url_bind_array;
            $_url_bind_count = count($_url_bind_array);
            if ($_url_bind_count >= 3) {
                $_ctrl['m'] = $_url_bind_array[0];
                $_ctrl['c'] = $_url_bind_array[1];
                $_ctrl['f'] = $_url_bind_array[2];
            } elseif ($_url_bind_count == 2) {
                $_ctrl['m'] = $_url_bind_array[0];
                $_ctrl['c'] = $_url_bind_array[1];
            } elseif ($_url_bind_count == 1) {
                $_ctrl['m'] = $_url_bind_array[0];
            }
        }
        if (!isset($_ctrl['m'])) {
            $_ctrl['m'] = $_public_app[0];
        }
        if (!isset($_ctrl['c'])) {
            $_ctrl['c'] = 'Index';
        }
        if (!isset($_ctrl['f'])) {
            $_ctrl['f'] = 'index';
        }
        if (!in_array(strtolower($_ctrl['m']), $_public_app)) {
            error('您访问的模块' . $_ctrl['m'] . '未开放,请核对后重试!');
        }
        return $_ctrl;
    }
    private static function _get_ctrl_name($_ctrl)
    {
        define('M', strtolower($_ctrl['m']));
        define('APP_MODEL_PATH', APP_PATH . '/' . M . '/model');
        define('APP_CONTROLLER_PATH', APP_PATH . '/' . M . '/controller');
        if (($_tpl_dir = Config::get('tpl_dir')) && array_key_exists(M, $_tpl_dir)) {
            if (strpos($_tpl_dir[M], ROOT_PATH) === false) {
                define('APP_VIEW_PATH', ROOT_PATH . $_tpl_dir[M]);
            } else {
                define('APP_VIEW_PATH', $_tpl_dir[M]);
            }
        } else {
            define('APP_VIEW_PATH', APP_PATH . '/' . M . '/view');
        }
        if (strpos($_ctrl['c'], '.') > 0) {
            $_ctrl_name = str_replace('.', '/', $_ctrl['c']);
            $controller = ucfirst(basename($_ctrl_name));
            $_ctrl_name = dirname($_ctrl_name) . '/' . $controller;
        } else {
            $controller = ucfirst($_ctrl['c']);
            $_ctrl_name = $controller;
        }
        $_ctrl_file = APP_CONTROLLER_PATH . '/' . $_ctrl_name . 'Controller.php';
        $wltl_yiijuizzau8157f84e7d7d1c7b2105515e8681b822 = array('List', 'Content', 'About');
        $lvxrwj998a9adf1e19f1078357d314822985c3 = 0;
        if (M == 'home' && (!file_exists($_ctrl_file) || in_array($controller, $wltl_yiijuizzau8157f84e7d7d1c7b2105515e8681b822))) {
            $controller = 'Index';
            $_ctrl_name = 'Index';
            define('F', $_ctrl['c']);
            $lvxrwj998a9adf1e19f1078357d314822985c3 = -1;
        } elseif (M == 'home' && in_array($controller, Config::get('second_rvar'))) {
            define('F', 'index');
            define('RVAR', $_ctrl['f']);
        } else {
            define('F', $_ctrl['f']);
        }
        define('C', $controller);
        if (isset($_SERVER["REQUEST_URI"])) {
            define('URL', $_SERVER["REQUEST_URI"]);
        } else {
            define('URL', $_SERVER["ORIG_PATH_INFO"] . '?' . $_SERVER["QUERY_STRING"]);
        }
        $_url_bind_count = count(self::$_url_bindArray);
        for ($i = 3 + $lvxrwj998a9adf1e19f1078357d314822985c3; $i < $_url_bind_count; $i = $i + 2) {
            if (isset(self::$_url_bindArray[$i + 1])) {
                $_GET[self::$_url_bindArray[$i]] = self::$_url_bindArray[$i + 1];
            } else {
                $_GET[self::$_url_bindArray[$i]] = null;
            }
        }
        return $_ctrl_name;
    }
    private static function _init_boot()
    {
        Config::get('debug') ? Check::checkAppFile() : '';
        if (M == 'api') {
            if (!!$_request_sid = request('sid')) {
                session_id($_request_sid);
                session_start();
            }
            header("Access-Control-Allow-Origin: *");
        } else {
            Check::checkBs();
            Check::checkOs();
        }
        if (file_exists(APP_PATH . '/common/function.php')) {
            require APP_PATH . '/common/function.php';
        }
        $_cfg_file = APP_PATH . '/' . M . '/config/config.php';
        if (file_exists($_cfg_file)) {
            Config::assign($_cfg_file);
        }
        $_func_file = APP_PATH . '/' . M . '/function/function.php';
        if (file_exists($_func_file)) {
            require $_func_file;
        }
        if (file_exists(APP_PATH . '/common/' . ucfirst(M) . 'Controller.php')) {
            $_ctrl_class = '\\app\\common\\' . ucfirst(M) . 'Controller';
            $_ctrl_obj = new $_ctrl_class();
        }
    }
    private static function exec($controllerPath)
    {
        $_ctrl_file = $controllerPath . 'Controller.php';
        $_ctrl_file = APP_CONTROLLER_PATH . '/' . $_ctrl_file;
        $_ctrl_class = '\\app\\' . M . '\\controller\\' . str_replace('/', '\\', $controllerPath) . 'Controller';
        $_user_func = F;

        if (!file_exists($_ctrl_file)) {
            http_response_code(404);
            $_404 = ROOT_PATH . '/404.html';
            if (file_exists($_404)) {
                require $_404;
                exit();
            } else {
                error('对不起,您访问的页面类文件不存在,请核对后再试!');
            }
        }
        if (!class_exists($_ctrl_class)) {
            error('类文件中不存在访问的类名!' . $_ctrl_class);
        }
        $controller = new $_ctrl_class();

        if (method_exists($_ctrl_class, $_user_func)) {
            if (strtolower($_ctrl_class) != strtolower($_user_func)) {
                $resp = $controller->$_user_func();
            } else {
                $resp = $controller;
            }
        } else {
            if (method_exists($_ctrl_class, '_empty')) {
                $resp = $controller->_empty();

            } else {
                error('不存在您调用的类或方法' . $_user_func . ',可能正在开发中,请耐心等待!');
            }
        }
        if ($resp !== null) {
            print_r($resp);
            exit();
        }
    }
    private static function _check_cache()
    {
        if (!Config::get('tpl_html_cache') || URL_BIND == 'api' || get('nocache', 'int') == 1) {
            return;
        }
        $zb_ylyna328f80565fce50d4d921a0a9f362f0a0 = RUN_PATH . '/config/' . md5('area') . '.php';
        if (!file_exists($zb_ylyna328f80565fce50d4d921a0a9f362f0a0)) {
            return;
        } else {
            Config::assign($zb_ylyna328f80565fce50d4d921a0a9f362f0a0);
        }
        $_cfg_lgs = Config::get('lgs');
        if (count($_cfg_lgs) > 1) {
            $_host = get_http_host();
            foreach ($_cfg_lgs as $_ctrl) {
                if ($_ctrl['domain'] == $_host) {
                    cookie('lg', $_ctrl['acode']);
                }
            }
        }
        if (!isset($_COOKIE['lg'])) {
            $vaolrzj7ca22c6bc98d271b4c0c1d53799e8e8c = current(Config::get('lgs'));
            cookie('lg', $vaolrzj7ca22c6bc98d271b4c0c1d53799e8e8c['acode']);
        }
        $yiioyb_ylyna8256502dd6eb15e11781dfc48a4464e3 = RUN_PATH . '/config/' . md5('config') . '.php';
        if (!Config::assign($yiioyb_ylyna8256502dd6eb15e11781dfc48a4464e3)) {
            return;
        }
        if (Config::get('open_wap') && (is_mobile() || Config::get('wap_domain') == get_http_host())) {
            $wap_flag = 'wap';
        } else {
            $wap_flag = '';
        }
        $ylyna_oyza5cab4a25d6e10b15c6dfe4b60cfa365b = RUN_PATH . '/cache/' . md5(get_http_url() . $_SERVER["REQUEST_URI"] . cookie('lg') . $wap_flag) . '.html';
        if (file_exists($ylyna_oyza5cab4a25d6e10b15c6dfe4b60cfa365b) && time() - filemtime($ylyna_oyza5cab4a25d6e10b15c6dfe4b60cfa365b) < Config::get('tpl_html_cache_time')) {
            ob_start();
            include $ylyna_oyza5cab4a25d6e10b15c6dfe4b60cfa365b;
            $_cache_html = ob_get_contents();
            ob_end_clean();
            if (Config::get('gzip') && !headers_sent() && extension_loaded("zlib") && strstr($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip")) {
                $_cache_html = gzencode($_cache_html, 6);
                header("Content-Encoding: gzip");
                header("Vary: Accept-Encoding");
                header("Content-Length: " . strlen($_cache_html));
            }
            echo $_cache_html;
            exit();
        }
    }
    private static function _check_auth_sn()
    {
        $_server_addr = isset($_SERVER['LOCAL_ADDR']) ? $_SERVER['LOCAL_ADDR'] : $_SERVER['SERVER_ADDR'];
        if ($_server_addr == '::1') {
            $_server_addr = '127.0.0.1';
        }
        $_license = 0;
        if (!!$_cfg_sn = Config::get('sn', true)) {
            $_cfg_sn_user = Config::get('sn_user');
            $_uri_user = strtoupper(substr(md5(substr(sha1($_cfg_sn_user), 0, 20)), 10, 10));
            $_license = $_license ?: (in_array($_uri_user, $_cfg_sn) ? 3 : 0);
            $_uri_host = strtoupper(substr(md5(substr(sha1($_server_addr), 0, 15)), 10, 10));
            $_license = $_license ?: (in_array($_uri_host, $_cfg_sn) ? 2 : 0);
            $_host = $_SERVER['HTTP_HOST'];
            $_uri_domain = strtoupper(substr(md5(substr(sha1($_host), 0, 10)), 10, 10));
            $_license = $_license ?: (in_array($_uri_domain, $_cfg_sn) ? 1 : 0);
        }
        define('LICENSE', $_license);
        if (!LICENSE && (filter_var(get_http_host(), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) || get_http_host() == 'localhost')) {
            return;
        }
        if (!$_license && (defined('URL_BIND') && URL_BIND != 'admin')) {
            $_sn_file = ROOT_PATH . '/sn.html';
            if (file_exists($_sn_file)) {
                require $_sn_file;
                exit();
            } else {
                error('未匹配到本域名(' . $_host . ')有效授权码,请到PbootCMS官网免费获取,并登录系统后台填写到"全局配置>>配置参数"中。');
            }
        }
    }
}

[/rihide]

Sublime Text 替代npp

由于npp作者的严重错误的立场,决定用Sublime代替,下载链接https://www.sublimetext.com/download_thanks?target=win-x64

安装完成后几个操作

A.汉化

1、点击菜单栏Tools—>Install Package Control 跳出弹框点击 确定按钮

2、点击菜单栏 Preferences – Package Control

3、弹框中输入 install package,选中 Package Control: Install Package 然后等待弹窗(可能需要耐心等待一段时间)

4、等出现如下弹窗后, 在弹窗的搜索框中输入 ChineseLocalizations , 点击出现的选项

5、等待一段时间,如果出现了如下画面则汉化步骤全部完成

6、后续若需要更改,可点击菜单栏 帮助-–>Language 选择进行更改。

B:显示中文内容乱码

1.Ctrl+Shift+P 然后输入Install Package Control等待
2.然后Ctrl+Shift+P 输入Install Package 等待出现的命令框中输入ConvertToUTF8
3.回车!关掉再次打开文档就能正常显示啦

C:其他

软件可以无限期免费试用,只是会有弹框提醒,如果不想弹框可以如下操作:

Ctrl + F 搜到到

1
8079 0500 0f94 c2
BASIC

更改为

1
c641 0501 b200 90

请支持正版