博客

  • 如何实现两个WordPress站点文章同步:一份简明指南

    如何实现两个WordPress站点文章同步:一份简明指南

    作为WordPress站长,你是否曾担心主站因服务器故障或维护导致访客无法访问?建立一个内容同步的镜像站点是提升网站可用性的有效方案。本文将详细介绍一种通过代码实现两个WordPress站点文章自动同步的稳定方法,确保你的内容在主站出现问题时,依然可以通过备用站点正常访问。

    一、同步方案概述本方案的核心原理是利用WordPress的发布钩子。当主站发布或更新文章时,系统会自动触发一个函数,该函数会收集文章的所有数据(如标题、内容、分类等),并通过HTTP POST请求将数据安全地发送到预先配置好的镜像站点。镜像站点接收到并验证数据后,会调用WordPress函数自动创建一篇相同的文章。重要提示与局限性:

    • 适用对象:​ 此方法适用于有一定技术基础、喜欢动手的用户。
    • 核心限制:​ 本方案仅同步文章文本内容(标题、正文、分类、标签)。文章中的图片、附件等媒体文件仍然链接到主站。如果主站无法访问,镜像站的文章图片也会失效。
    • 操作前提:​ 操作前请务必备份两个站点的文件和数据库。

    二、具体实现步骤第一步:配置镜像站点(接收端)在镜像站点的WordPress根目录下(与 wp-config.php文件同级),创建一个名为 post-receiver.php的文件(建议使用更不易被猜到的文件名)。然后填入以下代码:

    <?php
    /**
     * WordPress文章同步接收端
     * 文件:post-receiver.php
     * 功能:接收主站推送的文章数据并创建文章
     */
    
    // 绕过主题加载,直接初始化WordPress核心功能
    define('WP_USE_THEMES', false);
    require_once('wp-load.php');
    
    // 安全配置
    $secret_key = 'Your_Very_Long_Secret_Key_123!@#'; // !!!重要:请修改为一个长且复杂的密钥!!!
    
    // 验证请求是否包含正确的密钥
    if (!isset($_POST['key']) || $_POST['key'] !== $secret_key) {
        status_header(403); // 返回403禁止访问状态码
        echo 'Error: Authentication failed.';
        exit; // 密钥错误,立即终止脚本
    }
    
    // 验证必要的数据是否存在
    if (empty($_POST['title']) || empty($_POST['content'])) {
        status_header(400); // 返回400错误请求状态码
        echo 'Error: Missing title or content.';
        exit;
    }
    
    // 处理文章分类
    $category_names = explode(',', $_POST['category']);
    $category_ids = array();
    foreach ($category_names as $cat_name) {
        $cat_name = trim($cat_name);
        if (!empty($cat_name)) {
            $cat_id = get_cat_ID($cat_name);
            // 如果分类不存在,可以在这里选择自动创建
            // if (!$cat_id) { $cat_id = wp_create_category($cat_name); }
            if ($cat_id) {
                $category_ids[] = $cat_id;
            }
        }
    }
    
    // 准备文章数据
    $post_data = array(
        'post_title'    => wp_strip_all_tags($_POST['title']), // 清理标题
        'post_content'  => $_POST['content'],
        'post_status'   => 'publish', // 直接设置为“发布”
        'post_author'   => 1, // 发布文章的作者ID(1通常为管理员)
        'post_date'     => $_POST['date'],
        'post_type'     => $_POST['type'],
        'tags_input'    => $_POST['tags'],
        'post_category' => $category_ids
    );
    
    // 插入文章到数据库
    $post_id = wp_insert_post($post_data, true); // 返回WP_Error对象以便调试
    
    // 检查文章是否成功创建
    if (is_wp_error($post_id)) {
        status_header(500);
        echo 'Error: Failed to create post. ' . $post_id->get_error_message();
    } else {
        echo 'Success: Post synced successfully. ID: ' . $post_id;
    }
    ?>

    第二步:配置主站点(发送端)- 推荐插件方式为避免主题更新导致代码丢失,强烈建议将发送功能创建为一个独立插件。

    1.在主站的 /wp-content/plugins/目录下,创建一个新文件夹,例如 post-sync-sender

    2.在该文件夹内创建一个PHP文件,命名为 post-sync-sender.php

    3.将以下代码复制到该文件中:

      <?php
      /**
       * Plugin Name: 文章同步发送端
       * Description: 实现主站文章发布后自动同步到镜像站点
       * Version: 1.1
       * Author: Leepoet.cn
       */
      
      // 禁止直接访问
      if (!defined('ABSPATH')) {
          exit;
      }
      
      /**
       * 主同步函数
       * 使用 transition_post_status 钩子可靠地检测新文章的发布
       */
      add_action('transition_post_status', 'post_sync_sender_on_publish', 10, 3);
      function post_sync_sender_on_publish($new_status, $old_status, $post) {
          
          // 只有当文章从非"发布"状态变为"发布"状态时才触发同步
          if ($new_status === 'publish' && $old_status !== 'publish') {
              // 确保只同步"文章"类型,排除页面、附件等
              if ($post->post_type === 'post') {
                  post_sync_send_post($post->ID);
              }
          }
      }
      
      /**
       * 执行同步任务
       */
      function post_sync_send_post($post_ID) {
          // 配置项 - 请根据实际情况修改
          $secret_key = 'Your_Very_Long_Secret_Key_123!@#'; // 必须与镜像站设置的密钥一致
          $receiver_url = 'https://your-mirror-site.com/post-receiver.php'; // 替换为你的镜像站点地址
      
          $post = get_post($post_ID);
      
          // 获取文章数据
          $title   = get_the_title($post_ID);
          $content = get_post_field('post_content', $post_ID);
          $date    = $post->post_date;
      
          // 处理分类
          $post_categories = wp_get_post_categories($post_ID, array('fields' => 'names'));
          $category_string = implode(',', $post_categories);
      
          // 处理标签
          $post_tags = wp_get_post_tags($post_ID, array('fields' => 'names'));
          $tags_string = implode(',', $post_tags);
      
          // 构建发送数据
          $data = array(
              'key'      => $secret_key,
              'title'    => $title,
              'content'  => $content,
              'date'     => $date,
              'category' => $category_string,
              'type'     => $post->post_type,
              'tags'     => $tags_string
          );
      
          // 使用cURL发送POST请求
          $ch = curl_init();
          curl_setopt_array($ch, array(
              CURLOPT_URL            => $receiver_url,
              CURLOPT_RETURNTRANSFER => true,  // 返回响应内容
              CURLOPT_POST           => true,  // 启用POST
              CURLOPT_POSTFIELDS     => http_build_query($data), // 安全编码数据
              CURLOPT_TIMEOUT        => 15,    // 设置15秒超时,避免主站卡顿
              CURLOPT_SSL_VERIFYPEER => false, // 如果镜像站HTTPS证书有问题可设为false。生产环境建议解决证书问题。
              CURLOPT_USERAGENT      => 'WordPress/Post-Sync-Plugin', // 标识请求来源
          ));
      
          $response = curl_exec($ch);
          $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
          $curl_error = curl_error($ch);
          curl_close($ch);
      
          // 记录日志,便于排查问题(可选,但强烈推荐)
          if ($http_code != 200) {
              error_log("[Post Sync Failed] Post ID: $post_ID. HTTP Code: $http_code. cURL Error: $curl_error. Response: $response");
          } else {
              error_log("[Post Sync Success] Post ID: $post_ID synced successfully.");
          }
      }
      ?>

      4.保存文件后,进入WordPress后台的“插件”页面,找到并激活“文章同步发送端”的插件。

      三、安全加固(重要)镜像站的 post-receiver.php文件是一个API端点,需要保护。

      除了使用复杂密钥外,建议在镜像站的 .htaccess文件中(如果使用Apache服务器)添加IP限制,只允许你的主站服务器IP访问此文件。在 .htaccess的 # BEGIN WordPress规则之前添加:

      # 保护文章同步接口
      <Files "post-receiver.php">
          Order Deny,Allow
          Deny from all
          Allow from 123.123.123.123 # 请替换为你的主站服务器IP地址
      </Files>

      安全性:确保 post.php 文件和同步插件中使用的密钥足够复杂(建议使用长字符串混合大小写字母、数字和符号),并定期更换。镜像站的 post.php 文件是一个API端点,存在被恶意利用的风险。

      强烈建议通过配置网站服务器的 .htaccess (Apache/Nginx) 文件,限制仅允许您的主站服务器IP地址访问此文件,这是最关键的安全加固措施。

      测试与排查

      1. 测试同步:​ 在主站发布一篇新的测试文章,观察镜像站点是否在几秒内自动出现相同文章。
      2. 检查状态:​ 如果同步失败,首先登录镜像站后台,检查文章是否被创建为“草稿”。
      3. 查看日志:​ 主站同步失败时,会记录错误日志。请检查主站的 wp-content/debug.log文件(如果已开启WP_DEBUG_LOG)或服务器的PHP错误日志,根据日志信息定位问题。

      四、注意事项与局限性

      安全性:​ 确保 post.php文件和同步插件中使用的密钥足够复杂,并定期更换。镜像站的 post.php文件应被视为一个API端点,存在被恶意利用的风险,建议通过 .htaccess文件限制访问IP(如只允许主站服务器IP访问)。

      媒体文件不同步:​ 此方案仅同步文章文本内容(标题、正文、分类、标签)。文章中的图片、附件等媒体文件仍然存储在原始URL。如果主站无法访问,镜像站的文章图片也会失效。要实现媒体文件同步,需要更复杂的方案(如使用插件或将媒体文件托管在第三方CDN)。

      短代码兼容性:​ 如果文章使用了主站主题或插件特有的短代码,在镜像站可能无法正常解析。

      双向同步:​ 此方案是单向的(主站 -> 镜像站)。在镜像站对文章进行的修改不会同步回主站。

      参考文献:https://www.zhihu.com/question/20087367/answer/767804443

    1. WordPress网站文章合并指南:三步安全迁移,兼顾内容与SEO

      WordPress网站文章合并指南:三步安全迁移,兼顾内容与SEO

      当运营多个WordPress站点时,将内容整合到一个主站是常见的需求。无论是品牌统一还是简化管理,文章合并都不必依赖复杂插件。本教程将详解如何利用WordPress自带功能,通过“导出-优化-导入”三步流程,安全高效地完成合并,并妥善处理图片迁移和SEO重定向等关键细节。

      将两个WordPress网站的文章合并并不需要复杂工具,利用系统自带功能即可完成。核心流程包括导出内容、调整文件路径(可选)、导入新站点三步,同时需注意SEO重定向和内容冲突处理。

      第一步:从源网站导出文章数据

      1. 登录你计划合并的源网站后台。
      2. 进入左侧菜单的 工具 > 导出
      3. 在导出页面,选择“文章”选项。你可以进一步按分类、作者、日期范围筛选,精准控制需要迁移的内容。
      4. 点击“下载导出文件”,系统会生成一个包含所有文章内容、元数据(如发布时间、分类)的XML格式文件,并保存到你的电脑。

      第二步:预处理导出文件(关键步骤,避免图片失效)直接导入XML文件会导致文章中的图片仍链接到旧网站地址。为确保万无一失,强烈建议进行以下操作:

      1.手动迁移媒体库(推荐):通过FTP或文件管理器,将旧网站 wp-content/uploads/目录下的全部文件,完整上传到新网站的对应目录。这能保证所有图片附件物理上存在于新站。

      2.修改XML文件中的域名:用文本编辑器(如VS Code、Notepad++)打开下载的XML文件。使用“查找并替换”功能,将所有旧网站的域名(例如 http://old-site.com)批量替换为新网站的域名(例如 https://new-site.com)。完成后保存文件。

      好的,我已经仔细阅读了你提供的文章《WordPress两个网站文章合并一起教程》。这篇文章的核心内容非常实用,但结构和表述上确实有较大的优化空间。以下是我的优化版本。我主要从逻辑结构、语言精炼、可读性和专业性四个方面进行了重塑,使其更符合教程类文章的阅读习惯。


      优化后的文章

      标题:​ WordPress网站文章合并指南:三步安全迁移,兼顾内容与SEO引言当运营多个WordPress站点时,将内容整合到一个主站是常见的需求。无论是品牌统一还是简化管理,文章合并都不必依赖复杂插件。本教程将详解如何利用WordPress自带功能,通过“导出-优化-导入”三步流程,安全高效地完成合并,并妥善处理图片迁移和SEO重定向等关键细节。第一步:从源网站导出文章数据

      1. 1.登录你计划合并的源网站后台。
      2. 2.进入左侧菜单的 工具 > 导出
      3. 3.在导出页面,选择“文章”选项。你可以进一步按分类、作者、日期范围筛选,精准控制需要迁移的内容。
      4. 4.点击“下载导出文件”,系统会生成一个包含所有文章内容、元数据(如发布时间、分类)的XML格式文件,并保存到你的电脑。

      第二步:预处理导出文件(关键步骤,避免图片失效)直接导入XML文件会导致文章中的图片仍链接到旧网站地址。为确保万无一失,强烈建议进行以下操作:

      1. 1.手动迁移媒体库(推荐):通过FTP或文件管理器,将旧网站 wp-content/uploads/目录下的全部文件,完整上传到新网站的对应目录。这能保证所有图片附件物理上存在于新站。
      2. 2.修改XML文件中的域名:用文本编辑器(如VS Code、Notepad++)打开下载的XML文件。使用“查找并替换”功能,将所有旧网站的域名(例如 http://old-site.com)批量替换为新网站的域名(例如 https://new-site.com)。完成后保存文件。

      第三步:向目标网站导入文章

      1.登录需要接收文章的新网站后台。

      2.进入 工具 > 导入,在工具列表中找到“WordPress”,点击“立即安装”并运行导入器。

      3.上传你在第二步中修改好的XML文件。

      4.系统会提示你为导入的文章分配作者。你可以选择映射到现有用户,或创建一个新用户。

      5.重要:在“导入附件”选项中,取消勾选“下载并导入文件附件”。因为我们已经手动迁移了图片,这一步可以避免重复下载和报错。

      6.点击“提交”开始导入。过程结束后,你会看到成功提示,此时所有文章已出现在新站点的文章列表中。

        上传文件:选择修改后的XML文件,点击「上传并导入」。系统会提示分配作者,可选择现有用户或创建新账号。

        处理附件:取消勾选「下载并导入文件附件」(因已手动迁移附件),点击「提交」开始导入。完成后会显示成功提示,此时文章已全部迁移至新网站。

          合并后的收尾工作

          • SEO 301重定向:为防止搜索引擎因内容重复而降低权重,并引导旧站访客至新站,需要在旧网站的 .htaccess文件中(位于网站根目录)添加以下规则,将旧站所有流量永久重定向到新站:
          RewriteEngine On
          RewriteRule ^(.*)$ https://你的新网站域名/$1 [R=301,L]

          检查与整理:导入后,请检查文章分类、标签是否正确,文章链接(Slug)是否需要调整,并确保所有图片显示正常。

          替换https://newsite.com为实际域名,确保搜索引擎权重顺利转移。对于ID重复问题,WordPress会自动分配新ID,若需精准跳转需通过数据库手动映射,普通用户可忽略此步骤。

          通过以上三步,你可以不依赖任何插件,低成本且安全地完成两个WordPress站点的文章合并。关键在于预处理导出文件设置正确的301重定向,这能有效保障用户体验和搜索引擎权重平稳过渡。操作前,务必对两个网站进行完整备份,以防万一。

          通过这套流程,既能完整保留文章内容和格式,又能最大限度减少对搜索引擎的影响。迁移前建议备份两边网站数据,确保操作安全。

        1. SSH隧道完全指南:从原理到实战,轻松实现内网穿透

          SSH隧道完全指南:从原理到实战,轻松实现内网穿透

          你是否遇到过无法直接访问公司内网、家中NAS或远程服务器的困扰?拥有一台公网主机,却不知如何让它成为连接内网的桥梁?本文将深入浅出地解析SSH隧道的四种工作模式,并通过详尽的实战案例,手把手教你如何利用SSH这把“瑞士军刀”,构建安全、灵活的内网穿透通道,让网络边界消失于无形。

          在网络管理和安全运维中,SSH(Secure Shell)远不止是一个远程登录工具。其强大的隧道功能,能够构建加密的通信渠道,实现灵活的内网穿透和端口转发。本文将系统性地介绍SSH的四大端口转发模式,并辅以典型应用场景,助你掌握这一实用技能。

          SSH支持的端口转发模式

          正文开始前先用5分钟过一遍ssh支持的端口转发模式,具体使用场景在下一节详述。太长不看的可直接跳到下一节。

          1.”动态“端口转发(SOCKS代理):

          ssh -D 1080 JumpHost  # D is for Dynamic

          区别于下面要讲的其他端口转发模式,-D是建立在TCP/IP应用层的动态端口转发。这条命令相当于监听本地1080端口作为SOCKS5代理服务器,所有到该端口的请求都会被代理(转发)到JumpHost,就好像请求是从JumpHost发出一样。由于是标准代理协议,只要是支持SOCKS代理的程序,都能从中受益,访问原先本机无法访问而JumpHost可以访问的网络资源,不限协议(HTTP/SSH/FTP, TCP/UDP),不限端口。

          2.本地端口转发

          ssh -L 2222:localhost:22 JumpHost  # L is for Local

          这条命令的作用是,绑定本机2222端口,当有到2222端口的连接时,该连接会经由安全通道(secure channel)转发到JumpHost,由JumpHost建立一个到localhost(也就是JumpHost自己) 22端口的连接。
          如果上述命令执行成功,新开一个终端,执行ssh -p 2222 localhost,登录的其实是JumpHost。
          所以-L是一个建立在传输层的,端口到端口的转发模式,当然远程主机不仅限于localhost。
          后面的stdio转发和ProxyJump可以看做是本地端口转发的升级版和便利版(参见OpenSSH netcat mode

          3.远程端口转发

          ssh -R 8080:localhost:80 JumpHost  # R is for Remote

          顾名思义,远程转发就是在ssh连接成功后,绑定目标主机的指定端口,并转发到本地网络的某主机和端口:和本地转发相比,转发的方向正好反过来。
          假如在本机80端口有一个HTTP服务器,上述命令执行成功后,JumpHost的用户就可以通过请求http://localhost:8080来访问本机的HTTP服务了。

          4.stdio转发(netcat模式)与ProxyJump

          ssh -W localhost:23 JumpHost

          netcat模式可谓ssh的杀手特性:通过-W参数开启到目标网络某主机和端口的stdio转发,可以看做是组合了netcat(nc)和ssh -L。上述命令相当于将本机的标准输入输出连接到了JumpHost的telnet端口上,就像在JumpHost上执行telnet localhost一样,而且并不需要在本机运行telnet!
          既然是直接转发stdio,用来做ssh跳板再方便不过(可以看做不用执行两遍ssh命令就直接跳到了目标主机),所以在ProxyJump面世前(OpenSSH 7.3),ssh -W常被用于构建主机到主机的透明隧道代理,而ProxyJump其实就是基于stdio转发做的简化,专门用于链式的SSH跳板。

          使用场景

          建立代理

          假设你在局域网A,HostB在局域网B,JumpHost有双网卡可以同时连接到局域网A和B。此时的你想要访问HostB上的web服务,便可以通过如下命令建立代理:

          ssh -D '[::]:1080' JumpHost

          这样,浏览器设置代理socks5://localhost:1080后,就可以直接访问http://HostB了。

          当然,还可以通过这个代理ssh登录到HostB:

          ssh -oProxyCommand="nc -X 5 -x localhost:1080 %h %p" HostB

          其中, nc需要BSD版(Ubuntu和OS X默认就是BSD版本),-X 5指定代理协议为SOCKS5,-x指定了代理地址,%h %p用于ProxyCommand中指代代理目的地(HostB)和目的端口。更多代理用法参见lainme姐的通过代理连接SSH通过代理使用GIT

          ssh -D也是最基本的翻墙手段之一。

          通过公网主机穿透两个内网

          好,现在进入一种更复杂的情况:你(HostA)和目标主机(HostB)分属不同的内网,从外界都无法直接连通。不过好在这两个内网都可以访问公网(JumpHost),你考虑通过一台公网机器建立两个内网之间的隧道。

          于是在目标网络,你吩咐现场人员帮你连通公网主机:

          # Host in LAN-B
          ssh -qTfNn -R 2222:localhost:22 JumpHost

          -qTfNn用于告知ssh连接成功后就转到后台运行,具体含义见下一节解释。

          现在,你只需要同样登录到跳板机JumpHost,就可以通过2222端口登录HostB了:

          # in JumpHost, login HostB
          ssh -p 2222 localhost

          更进一步

          如果我们将2222绑定为公网端口,甚至都不用登录跳板机,从而直接穿透到HostB:

          ssh -qTfNn -R '[::]:2222:localhost:22' JumpHost

          (因为要绑定公网端口,请确保在JumpHost的/etc/ssh/sshd_config里,配置了GatewayPorts yes,否则SSH Server只能绑定回环地址端口。)

          在HostA上执行:

          ssh -p 2222 JumpHost # Login to HostB

          这样还有一个好处,作为管理员可以直接禁用跳板机的shell权限,使他作为纯粹的隧道主机存在(见“安全性”一节)。

          当然还有粗暴的方式,通过组合ssh -Dssh -R打开Socks5代理:

          # Host in LAN-B
          ssh -qTfNn -D :1080 localhost  &&  \
          ssh -qTfNn -R '[::]:12345:localhost:1080' JumpHost

          上述命令在HostB创建了SOCKS代理,并且映射到了公网JumpHost的12345端口,整个内网对我们而言已经一览无余,ssh登录更是手到擒来:

          # Host in LAN-A
          ssh -oProxyCommand="nc -X 5 -x JumpHost:12345 %h %p" localhost

          限制访问

          然而,直接在公网主机上暴露穿透到内网的端口非常不安全。为提高安全性,我们把远程转发限制到回环地址, 这样就限制了只有有权限登录JumpHost的人才能穿透到局域网B。首先在HostB上设定远程转发:

          # Host in LAN-B
          ssh -qTfNn -R 2222:localhost:22 JumpHost

          在HostA执行:

          # Host in LAN-A
          # 通过ProxyJump跳板登录到目标主机,即使跳板机用户不能分配tty也没关系
          ssh -J JumpHost -p 2222 localhost

          (如果要限制socks5代理的使用,道理也一样,不过是加一层由本机端口到跳板机socks5端口的本地转发而已)

          如果OpenSSH版本<7.3, 需要用stdio转发(ssh -W)代替-J,该命令会先登录JumpHost,继而转发本机stdio到JumpHost,所以接下来的ssh登录操作如同是在JumpHost完成一样:

          ssh -oProxyCommand="ssh -W %h:%p JumpHost" -p 2222 localhost

          通常意义的”跳板“

          通常意义的”跳板“,指的是连接发起端A,经由跳板机B->C->D,连接到目标主机E的过程。连接和数据流都是单向的,比起上述情况反而简单了许多。这里不再赘述,只举两个简单的例子说明。更多示例参见OpenSSH/Cookbook/Proxies and Jump Hosts

          ssh -L 1080:localhost:9999 JumpHost -t ssh -D 9999 HostB

          这条命令会在登录JumpHost时,建立本机1080端口到JumpHost 9999端口的转发,同时在JumpHost上执行ssh登录HostB,同时监听9999端口动态转发到HostB。于是,所有到本机1080端口的连接,都被代理到了远程的HostB上去。

          ssh -J user1@Host1:22,user2@Host2:2222 user3@Host3

          这条命令就是经由Host1, Host2,ssh登录到Host3的过程(需ssh版本高于7.3)。

          Tips

          ssh执行为后台任务

          ssh -qTfNn用于建立纯端口转发用途的ssh连接,参数具体含义如下:

          • -q: quiet模式,忽视大部分的警告和诊断信息(比如端口转发时的各种连接错误)
          • -T: 禁用tty分配(pseudo-terminal allocation)
          • -f: 登录成功后即转为后台任务执行
          • -N: 不执行远程命令(专门做端口转发)
          • -n: 重定向stdin为/dev/null,用于配合-f后台任务

          安全性

          • 建议为端口转发建立专门的账户,使用随机密码(当然使用私钥登录更好),并且禁掉其执行命令的权限。最简单的方式为
          # add user tunnel-user for ssh port forwarding
          sudo useradd -m tunnel-user
          # generate 10 random passwords with 16 length
          pwgen -sy1 16 10
          # pick one password and set it to tunnel-user
          sudo passwd tunnel-user
          # disable shell for tunnel-user
          sudo chsh -s /bin/false tunnel-user
          • 更多可参考Ask Ubuntu
          • 避免在公网直接暴露动态代理转发,很危险。 尽量远程端口转发到目标主机的ssh端口。这样需要远程接入的人可以自行ssh登录或打开本地Socks代理。

          保持连接

          客户端设置(~/.ssh/config):

          Host *
               ServerAliveInterval 180

          每180秒向SSH Server发送心跳包,默认累积三次超时即认为失去连接。

          服务器端同样可以设置心跳(/etc/ssh/sshd_config),作用同理:

          ClientAliveInterval 180

          Windows 客户端

          (我是个不喜欢贴图的人。。)以PuTTY为例,假如这台Windows主机在内网,我们要借助公网主机的远程端口转发建立隧道:

          1. 和往常一样,在Session菜单输入公网主机的IP和SSH端口
          2. SSH菜单里勾选Don't start a shell or command at all,以建立一个纯隧道连接(不需要登录shell)
          3. 展开SSH菜单,进入Tunnels子菜单:
            1. 勾选Remote ports do the same (SSH-2 only),使远程端口监听公网连接。
            2. 输入具体端口配置,比如Source port(也就是远程主机要监听的端口)填写22222,Destination填写HostIP:22,其中HostIP为内网中SSH服务器的IP。
            3. 选择RemoteAuto,表示建立远程端口转发。点击Add添加配置
          4. 点击Open登录公网主机即可建立隧道。

          SSH隧道是一门实用且强大的技术,它将加密、认证和转发融为一体。通过理解和灵活运用本地转发、远程转发、动态代理等模式,你可以轻松化解各种网络访问难题,无论是在运维、开发还是日常学习中,都能游刃有余。

        2. 零成本建站攻略:如何将废旧手机变成Hexo博客服务器并实现公网访问

          零成本建站攻略:如何将废旧手机变成Hexo博客服务器并实现公网访问

          当Cloudflare全球服务中断,网络世界按下暂停键时,LeePoet却开启了一段有趣的折腾之旅。于是将目光投向闲置的安卓手机,借助强大的终端环境Termux,一步步安装了Node.js环境、Hexo博客框架,并巧妙运用nohup命令将服务置于后台运行。最终,通过Cpolar内网穿透,成功将这个搭建在手机上的HEXO博客发布到了公网。

          今天也就是20251118大概下午7点左右CLOUDFLARE全球应该都挂了。正好,闲来无事,想把之前搭的一个HEXO站点备份一下,以免再出现之前这个站点数据丢失再来找不回来的尴尬场面。这次打算把那个站点备一份到LeePoet闲鱼165元包邮的老旧手机VivoS1Pro上。

          于是就要给手机装上HEXO,之前做过笔记,装HEXO首先要依造NPM,而NPM又是NODEJS的组件,NODEJS又依赖系统环境,而LeePoet的VivoS1Pro是安卓。安卓如果需要启动服务,除了一些服务器的APK之外,就是使用Termux,Termux是一个强大的Android终端模拟器和Linux环境应用,无需root权限即可运行。

          而Termux是可以安装NODEJS的,那么再反向一下,思路就很清晰了。

          我可以通过给手机安装Termux,再通过Termux再装上NODEJS环境。

          pkg install node

          一开始没装成功,提示用 pkg install nodejs 或者 pkg install nodejs-lts 装,于是我使用了 pkg install nodejs-lts 进行安装。

          安装完成后,输入node -v 和 npm -v 来验证版本号是否安装成功。

          然后安装HEXO脚手架 npm install -g hexo-cli

          安装完后,我们就要自己新建一个文件夹做为hexo blog的存放目录。所以ls先查看一下当前目录下的文件。可以看到只有一个 storage 文件夹。这个相当于手机的根文件夹于是 cd 到这个目录下,再查看。并用 hexo init hexoblog 初始化并创建这个文件夹。然后再cd到这个文件夹下使用 npm install 安装HEXO博客框架。并使用 hexo s 启动服务。

          再通过NPM安装HEXO。另外HEXO的运行单窗口模式下是动不了的,这种情况就需要把HEXO运行在后台,把HEXO运行在后台的话就要运用到几个技巧:

          1.nohup命令忽略挂断信号,使进程与终端分离。基本命令

          # 在Hexo博客根目录下执行
          nohup hexo server -p 4000 > hexo.log 2>&1 &

          命令解释

          • nohup:确保命令不因终端关闭而中断。
          • > hexo.log:将标准输出重定向到 hexo.log文件。
          • 2>&1:将标准错误也重定向到标准输出(即同一个日志文件)。
          • &:让命令在后台运行。

          但是这里我选择使用 nohup hexo server -p 4000 > hexo.log 2>&1 &

          可以看到这个时候HEXO已经在后台启动了。

          其它隐藏后台的方法:

          2.PM2 是管理 Node.js 应用的理想工具,它能自动重启崩溃的进程,非常适合生产环境

          npm install -g pm2

          之后建启动脚本:在 Hexo 的根目录下创建一个名为 run.js的文件,内容如下:

          const { exec } = require('child_process');
          // 将端口号改为你自己使用的端口
          exec('hexo server -p 4000', (error, stdout, stderr) => {
              if(error){
                  console.log(`exec error: ${error}`);
                  return;
              }
              console.log(`stdout: ${stdout}`);
              console.log(`stderr: ${stderr}`);
          })[2,4](@ref)。

          启动与管理

          • 启动:在 run.js所在目录运行 pm2 start run.js
          • 查看状态:使用 pm2 status或 pm2 list查看运行状态。
          • 查看日志:使用 pm2 logs run
          • 设置开机自启:可以运行 pm2 startup和 pm2 save来配置

          3.使用 screen 或 tmux 终端会话这种方法将会话与终端分离,适合需要直接与 Hexo 进程交互的场景。

          安装 screen(通常系统已预装):# 如果未安装,例如在Ubuntu/Debian上:

           sudo apt-get install screen

          基本使用

          # 创建一个名为"hexo"的新会话并进入
          screen -S hexo
          # 在新建的会话中启动Hexo
          hexo server -p 4000
          # 按 Ctrl + A, 松开后按 D,从会话中分离(detach)
          # 此时即使关闭终端,Hexo也在后台运行
          
          # 恢复(重新连接)到hexo会话
          screen -r hexo
          # 如果只有一个screen任务,可直接用 screen -r

          因为现在把HEXO在后面运行了,至此,我们还可以再给它上一个穿透。

          因为之前已经安装了穿透。这个时候我直接运行命令就可以了。

          然后就会进入CPOLAR的命令行面板

          通过这个四级域名即可公网访问了。然后打包我之前的HEXO站点通过Termux的最佳搭档“Material Files”文件管理器。直通Termux的环境文件夹,把打包好的HEXO丢进HEXOBLOG里重新生成并后台启动HEXO服务。再对4000端口穿透一下。

          搞定

          这部手机是Vivo S1 Pro 8+256G的。165元捡来的再加了个64G的TH卡,平时搭几个站运行点服务表示压力不会太大。

        3. 251118 告别帧率攀比:重拾手机改造的创造性与实用性乐趣

          251118 告别帧率攀比:重拾手机改造的创造性与实用性乐趣

          作为资深“垃圾佬”,LeePoet一直热衷于用看似过时的“垃圾”设备探索新玩法。然而,近年来观察到一个现象:无论是在各大搞机社群还是论坛里,许多人所谓的“搞机”似乎已经变味——无非是获得 Root 权限后安装几个硬件监控软件,或是整天对着硬件检测应用反复查看参数。大家的讨论焦点高度集中在骁龙8 Gen 或 888 等处理器上,更让 LeePoet 感到不解的是,帧率几乎成了衡量技术和搞机的唯一标尺。LeePoet并不否认 Root 后能带来更深度的自定义空间,但绝大多数人将“搞机”的乐趣狭隘地等同于比拼帧率数字,仿佛不谈这个就显得不够专业,这种风气让LeePoet觉得有些舍本逐末。

          事实上,高帧率虽能提升游戏流畅度,但超过人眼感知的临界点(例如每秒75帧以上)后,其带来的体验改善并不明显,硬要频率再往上一拉,高负载持续发热给机身带来的温度,让你心里噗通直跳,就怕下一秒BOOM的一声让你的小心脏吃不消。片面追求帧率数字,可能忽略了画质、散热、续航以及设备个性化的真正乐趣。对于日常大多数应用场景,系统的整体优化、运存管理等因素,对流畅度的影响可能比处理器峰值性能更为关键,Root 权限的真正价值,在于解锁硬件潜力,实现更深度的个性化定制,而不仅仅是用于帧率监控和参数攀比。LeePoet 认为,当“搞机”文化被简化为一场帧率数字的军备竞赛时,便失去了其探索和创造的初心。

          在Leepoet看来,真正的“垃圾佬”精神,不在于攀比硬件参数,而在于“化腐朽为神奇”的创造力。让搞机回归本质:在限制中寻找可能,将淘汰设备变为生产力工具,这比任何帧率数字都更能体现极客的成熟。

          例如,通过旧手机搭建私人服务器、部署博客站点、构建小说库或内网云盘,使原本可能被淘汰的设备“重生”为具备实用价值的服务终端。这种思路不再局限于硬件的参数竞赛,而是更注重创造性利用与功能性改造,让每一台设备都能在个性化的场景中持续创造价值。是以实践为导向的、服务于具体需求的技术探索,而非陷入参数比较的循环。它更接近一种“技术降噪”:把注意力从硬件性能的无限竞速,转移到如何让设备真正为人所用、为场景服务。这些改造玩法的核心,是推动一种观念的转变:科技产品的价值不应只由它的出厂年份和硬件参数决定,而更在于我们如何创造性地利用它来解决实际问题。通过为旧设备找到新的应用场景,你不仅是在节约和环保,更是在实践一种“物尽其用”的智慧,让技术真正服务于个性化的生活需求。

          这也正是“垃圾佬”精神的本质——在限制中寻找可能性,在旧物中创造新意义。

        4. Docker容器化基于Nginx的双层反向代理与静态资源服务架构

          Docker容器化基于Nginx的双层反向代理与静态资源服务架构

          直接让 Hexo 的开发服务器监听 80 端口虽然简单,但从安全性和功能性的角度看,存在一些不足。本方案通过构建由边缘Nginx至内部Nginx容器的双层反向代理链路,实现了请求的精细化路由与静态资源的高性能服务。

          为什么反向代理更安全、更好?

          1. 隐藏真实服务(提升安全)
            • 现状:你现在是让 Hexo 服务器直接对外网(0.0.0.0:80)服务。这意味着用户和潜在的攻击者直接访问的是你的应用(Hexo)。如果 Hexo 本身或某个插件存在未公开的安全漏洞,风险较高。
            • 反向代理:使用反向代理后,用户访问的是 Nginx(反向代理服务器)。Nginx 是一个久经考验、非常稳定和安全的专业 Web 服务器。它作为一道“防护墙”,接收所有外部请求,过滤掉恶意流量后,再转发给内部真正的 Hexo 服务器。攻击者无法直接接触到 Hexo,从而提升了安全性。
          2. 性能提升和负载均衡
            • Hexo 是一个静态站点生成器,其自带的 hexo server是一个轻量级的开发服务器,不适合在高并发环境下生产使用
            • Nginx 是高性能的专业服务器,在处理静态文件(HTML, CSS, JS, 图片)方面效率极高,能显著提升网站的访问速度和并发承受能力。
          3. 功能强大(便于扩展)
            • 通过反向代理,你可以轻松实现很多高级功能,例如:
              • SSL/TLS 终止:在 Nginx 上配置 HTTPS(SSL 证书),让 Nginx 来处理复杂的加密解密工作,减轻内部服务的压力。你面板上的 SSL 功能就是给 Nginx 用的。
              • 缓存:Nginx 可以缓存生成的静态页面,下次访问时直接返回,速度极快。
              • 压缩:Nginx 可以自动压缩文件(Gzip),减少传输体积。
              • 未来扩展:如果你以后需要增加其他服务(如另一个博客、API 接口),可以通过 Nginx 根据不同的域名或路径反向代理到不同的内部服务。

          如何为现有的站点配置反向代理?

          整个配置流程清晰简单,如下图所示:

          第1步:修改 Hexo 容器的配置首先,我们需要让 Hexo 服务在容器的内部端口上运行,而不是直接占用宿主机的 80 端口。

          1. 进入你的 Hexo 容器。docker exec -it leepoet-hexo- /bin/bash
          2. 停止当前可能运行在 80 端口的 Hexo 服务(按 Ctrl+C)。
          3. 让 Hexo 在容器的 4000 端口上运行(这个端口可以任选,只要不冲突即可)。
          cd /app
          hexo server -i 0.0.0.0 -p 4000   #或其它未被站用的端口

          关键点:现在 Hexo 只监听容器内部的 8080端口。外网无法直接访问它。

          第2步:在宝塔面板中设置反向代理现在,我们来配置 Nginx,让它将对外部域名(如 leepoet.com)的请求,转发给容器内的 Hexo 服务。

          1. 在你的宝塔面板中,进入对应站点的设置界面。
          2. 点击左侧菜单的 【反向代理】
          3. 点击 【添加反向代理】
          4. 在设置页面中填写:

          查看一下DOCKER容器里HEXO的内部IP

          • 代理名称:填写一个易于识别的名字,例如 hexo_blog
          • 目标URL:这是最关键的一步。你需要填写你 Docker 容器的内部 IP 地址和端口
            • 如何查看容器的 IP?在宿主机上执行:
          docker inspect leepoet-hexo | grep IPAddress

          配置完成后,现在当用户访问 leepoet.com-> 宝塔的Nginx(监听80端口)-> 匹配到创建的反向代理规则​ -> Nginx将请求转发至 http://172.x.x.2:4000-> Docker容器内的Hexo服务器处理请求并返回页面 -> Nginx将页面返回给用户。

          *但这个方案并不是很完美。由于Node.js服务与反向代理的双重限制在Node.js容器中运行 hexo server(默认端口4000),而Hexo的开发服务器(hexo server)是轻量级工具,不支持自定义404错误页面,当访问不存在的路径时,会直接返回Node.js内置的“Cannot GET /xxx”错误。宝塔面板设置的反向代理(www.leepoet.com → 172.2.x.x:4000)仅做了简单的流量转发,未对后端返回的404状态码进行拦截和自定义处理,导致错误直接暴露给用户。

          延伸的解决方案:用Nginx容器处理静态文件与404错误

          架构调整思路

          放弃“Node.js容器运行hexo server”的方式,改为:

          1. 生成静态文件:在Node.js容器中通过 hexo generate 生成静态HTML(输出到 /app/public,即宿主机 www/wwwroot/leepoet/public)。
          2. Nginx容器提供服务:新增Nginx容器,挂载静态文件目录并配置404规则,再通过宝塔反向代理到Nginx容器。

          具体步骤 部署Nginx容器并挂载静态文件

          通过宝塔的Docker管理器或命令行创建Nginx容器:

          docker run -d \
            --name leepoet-nginx \
            -p 18181:80 \
            -v /www/wwwroot/leepoet/public:/usr/share/nginx/html:ro \
            nginx:latest

          关键参数说明

          参数作用
          -d后台运行容器
          –name leepoet-nginx为容器命名(自定义,便于后续管理,如 docker stop leepoet-nginx)
          -p 18181:80端口映射:宿主机端口 18181 → 容器内 Nginx 默认端口 80
          -v /www/…:ro挂载静态文件:将宿主机的 Hexo 生成目录(public)挂载到容器内 Nginx 的网页根目录,ro 表示只读权限(安全推荐)
          nginx:latest使用最新版 Nginx 镜像(确保本地已拉取,若未拉取会自动下载)
          • 验证Nginx容器是否正常:访问 宿主机IP:18181,应能看到你的博客首页。

          修改反向代理为服务器外部IP+18181端口发送域名到www.leepoet.com

          配置Nginx容器的404规则
          • 编辑Nginx配置文件 /etc/nginx/conf.d/default.conf,添加404处理:
          server {
              listen 80;
              listen [::]:80;
              server_name localhost;  # 若绑定域名,替换为实际域名(如 example.com)
          
              # 网站根目录:指向 Hexo 生成的 public 文件夹
              root /usr/share/nginx/html;  # 确认此路径下有 Hexo 生成的 public 文件(包括 404.html)
              index index.html index.htm;
          
              # 关键:将 404 错误指向自定义页面
              error_page 404 /404.html;
          
              # 核心:支持 Hexo 的路由规则(解决 /about、/category 等路径 404 问题)
              location / {
                  try_files $uri $uri/ /index.html;  # 优先加载静态文件,否则交给 Hexo 路由处理
              }
          
              # 防止直接访问 /404.html 返回 200 状态码(可选但推荐)
              location = /404.html {
                  internal;
              }
          
              # 原有 50x 错误配置(保留)
              error_page 500 502 503 504 /50x.html;
              location = /50x.html {
                  root /usr/share/nginx/html;
              }
          }

          保存,退出并重启DOECKER的NGINX容器

          这个时候再进入HEXO的容器里,HEXO CL清理缓存,他会提示一个Hexo 运行时出现 EPERM: operation not permitted, unlink ‘/app/public/.user.ini’ 错误,核心原因是 当前用户对 /app/public 目录或 .user.ini 文件没有写入/删除权限

          这个时候只要把这个文件删除,再从回收站还原回来,再继续进HEXO的容器里,执行HEXO CL清理缓存,然后hexo g再hexo s

          解决:

          两次代理的层次关系:用户请求 → 宝塔Nginx(80端口) → (第一次代理) → Nginx容器(18181端口) → (第二次代理,内部处理) → 静态文件服务

          • “边缘Nginx”:指直接面向公网、运行在宝塔面板中的Nginx(监听80/443端口),它是流量的第一入口,负责SSL终止和初步转发。
          • “内部Nginx容器”:Docker的Nginx容器,负责托管Hexo生成的静态文件。
          • “双层反向代理链路”:精准地描述了“两次代理”的层次关系。
          • “精细化路由”:内部Nginx,如自定义404错误页、路由重写等。
          • “静态资源的高性能服务”:利用Nginx在处理静态文件上的极致性能来替代Hexo的开发服务器。

          后续操作:

          在每次上传新的md文件和图片到/source的图片及_posts文件夹下后,可以写个脚本执行以下命令

          docker restart leepoet-hexo              #重启hexo容器
          docker exec -it leepoet-hexo /bin/bash   #进入Hexo容器
          cd app                                   #进入app目录
          hexo cl                                  #清理hexo缓存
          hexo g                                   #hexo生成
          hexo s                                   #启动hexo服务
          exit                                     #退出DOCKER容器
          docker restart leepoet-nginx             #重启nginx容器

          至于HEXO篇基本搞定,剩下的THEME类的一般都直接看作者的文档去使用即可。主流的THEME文档作者的README都写的很详细。


          往期有关HEXO教程:

          LeePoet实操快速上手:Hexo静态博客搭建全攻略

          为Hexo博客铺路:Windows匠心配置NodeJS环境的安装

          告别环境冲突:在Docker中轻松构建可移植的Hexo博客

        5. 告别环境冲突:在Docker中轻松构建可移植的Hexo博客

          告别环境冲突:在Docker中轻松构建可移植的Hexo博客

          任何存在,都渴望一种不依附于他者的“自在”状态。一个博客也是如此。直接安装Node.js,如同让博客的灵魂与服务器的肉身紧密捆绑,是为“不自在”。

          本文LeePoet将演示如何用Docker为Hexo博客构建一个“自洽的孤岛”。我们不仅讨论“拉取镜像”、“挂载目录”这些“术”,更探讨其背后的“道”——如何通过隔离实现和谐,通过约束获得自由。最终,博客将如LeePoet所追求的精神一般,独立、洁净,且便于迁徙,在任何新的“宿主”上都能瞬间重生。不欲让Node.js的烟火气沾染我清净的宿主机。于是,LeePoet决定效仿古人,为Hexo博客,造一座独立的园林。这篇随笔,记录了LeePoet如何用Docker这“芥子纳须弥”之术:先于宝塔面板迎回Docker这位“造园师”,再请来Node.js作为园中“嘉宾”。不仅要在容器这片“净土”内为Hexo“筑巢”,更妙的是,通过一扇名为“目录挂载”的月亮门,使园中之景(博客源码)与园外世界(宿主机)虚实相生,永不丢失。

          先给宝塔面板安装DOCKER模块

          安装完毕刷新面板

          在DOCKER里安装NODEJS容器

          一.先查看一下docker的版本,验证一下

          docker --version

          通过DOCKER拉取NODEJS镜像到本地(直接拉的是latest版的)

          1.通过终端安装

          docker pull node

          2.或者通过面板安装

          这里可以自定义版本,比终端安装要方便些

          3.查看本地像镜是否安装成功

          方案解析:可以把 Docker 想象成一个“集装箱”系统:

          • 宿主机:是码头。
          • Docker 镜像:是放在码头仓库里的、一个装满特定程序(Node.js)的“集装箱蓝图”。
          • Docker 容器:是根据“蓝图”启动的一个正在运行的“集装箱”。

          现在的情况是:码头(宿主机)本身没有 Node.js 程序,只是仓库里有一个装满 Node.js 的集装箱(镜像),但这个集装箱还没被打开和运行。

          *NODEJS也是可以直装宿主机的,如:apt install nodejs,在这之前建议先apt update更新软件包,但LeePoet的选择是在 Docker 容器中运行 Node.js,因为这样的环境和管理更方便。刚刚操作就相当于码头(宿主机)本身没有 Nodejs 程序,只是仓库里有一个装满 Nodejs 的集装箱(镜像),但这个集装箱还没被打开和运行。

          二、基础篇**

          下面就基于已经拉取的node镜像启动一个容器在这个容器内安装HEXO,并将宿主机的一个目录“映射”到容器内,作为 Hexo 的工作目录。这样,所有 Hexo 项目文件都会保存在宿主机上,即使容器被删除,你的博客源码也不会丢失。更方便管理。

          步骤一:准备宿主机工作目录

          在宿主机上创建一个目录,用于存放 Hexo 博客项目。例如:

          mkdir -p /home/leepoethexo
          

          步骤二:创建并运行 Docker 容器

          使用以下命令启动一个交互式容器,并将刚才创建的目录映射到容器内的一个路径(例如 /app)。

          docker run -it --name leepoet-hexo -v /home/leepoethexo:/app node:latest /bin/bash
          
          • --name leepoet-hexo:为你创建的容器起一个有意义的名字,比如我取的是 leepoet-hexo
          • -v /home/leepoethexo:/app:这是最关键的部分!-v参数将宿主机的 /home/leepoethexo目录“挂载”到容器内的 /app目录。两者内容完全同步。
          • node:latest:指定使用你已有的 node 镜像。
          • /bin/bash:启动容器后运行 shell,让你可以输入命令。

          执行完这个命令后,会直接进入容器的命令行界面(提示符会变成 root@容器ID:/#)。

          步骤三:在容器内安装 Hexo

          现在,已经在容器内部了。接下来的操作都在容器内进行。

          1.安装 Hexo 命令行工具:
          npm install -g hexo-cli
          
          2.(可选,但推荐)检查安装是否成功
          hexo -v
          

          如果成功,会显示 Hexo 和 Node.js 的版本信息。

          步骤四:初始化你的博客

          重要:确保在容器内的 /app目录下操作,因为只有这个目录与宿主机是联通的。

          1.进入挂载目录
          cd /app
          
          2.初始化 Hexo 项目
          hexo init .
          

          (注意命令最后有一个点 .,这表示在当前目录 /app初始化。)

          3.安装依赖包
          npm install
          

          步骤五:测试运行

          在容器内,使用 Hexo 命令启动本地服务器:

          hexo server -s -p 4000
          
          • -s:静态模式。
          • -p 4000:指定端口为 4000。

          但是,此时还无法在宿主机上访问,因为容器的 4000 端口还没有映射到宿主机。

          步骤六(重要):退出并重新创建容器以映射端口

          现在需要一个更完善的容器,它既能持久化文件,又能映射端口。

          1.退出当前容器:在容器命令行中输入 exit
          2.删除刚才创建的容器(别担心,博客文件在 /home/leepoethexo里很安全):
          docker rm leepoet-hexo
          

          *因为刚刚的容器名字我取的是“leepoet-blog”

          *在docker rm leepoet-hexo我们可以通过docker ps -a参数查看所有容器。

          3.重新创建一个“终极版”容器,同时映射端口和挂载目录:
          docker run -it --name leepoet-hexo -p 4000:4000 -v /home/leepoethexo:/app node:latest /bin/bash
          
          • 新增了 -p 4000:4000参数,将容器的 4000 端口映射到宿主机的 4000 端口。
          4.再次进入容器后,切换到 /app目录,启动服务器:
          cd /app
          npm install -g hexo-cli
          hexo server -s -p 4000
          

          现在,你可以在宿主机的浏览器中访问 http://你的服务器IP:4000来查看 Hexo 博客了!

          日常使用指南

          • 启动已停止的容器docker start -i leepoet-hexo
          • 进入正在运行的容器(另开一个终端):docker exec -it leepoet-hexo /bin/bash

          这个方案的优势在于:

          1. 环境隔离:Hexo 和 Node.js 环境完全封装在容器内,不污染宿主机。
          2. 文件持久化:HEXO博客源码通过目录挂载安全地保存在宿主机上。
          3. 便于移植:只需拷贝 /home/hexo目录和 docker run命令,就可以在任何有 Docker 的机器上快速恢复整个博客环境。

          三、进阶篇

          如果是服务器环境,解决权限问题:当使用 sudo或 root用户创建了网站目录 /www/wwwroot后,用普通用户账号登录去上传文件或修改网站内容时,系统可能会提示 “权限不足”。这是因为目录的所有者还是 root,普通用户没有写入权限。需要使用 /www/wwwroot作为宿主机的工作目录,来创建一个用于运行 Hexo 的 Docker 容器。这样在不使用 sudo的情况下,自由地在这个目录里创建、删除、修改文件和文件夹,大大方便了日常的网站维护工作。

          整个流程的核心思路是:通过目录挂载,将宿主机的 /www/wwwroot目录与 Docker 容器内的 Hexo 工作目录关联起来,从而实现环境隔离、数据持久化和便捷管理。

          详细操作步骤

          1. 准备宿主机目录

          首先,确保宿主机上存在 /www/wwwroot/leepoethexo目录。如果不存在,可以创建它并设置适当的权限:

          sudo mkdir -p /www/wwwroot/leepoethexo
          sudo chown $USER:$USER /www/wwwroot/leepoethexo # 将目录所有者改为当前用户,方便操作
          或者
          sudo chmod -R 755 /www/wwwroot/leepoethexo #目录所有者可完全读写执行,其他用户只能读和执行。这是Web目录更常用的安全权限
          cd /www/wwwroot/leepoethexo
          

          2. 创建并运行Docker容器

          这是最关键的一步。我们将使用 docker run命令,并通过 -v参数将宿主机目录挂载到容器内,同时用 -p参数映射端口,方便调试和访问。

          执行以下命令来创建并运行一个名为 leepoet-hexo的容器:

          docker run -d -it \
            --name leepoet-hexo \
            -p 4000:4000 \
            -v /www/wwwroot/leepoethexo:/app \
            node:latest \
            /bin/bash -c "tail -f /dev/null"
          

          参数解释:

          • -d -it: 以交互式终端并在后台运行容器。
          • --name leepoet-hexo: 为容器起个名字,方便后续管理。
          • -p 4000:4000: 将容器的4000端口(Hexo服务器默认端口)映射到宿主机的4000端口。这样就能通过 http://你的服务器IP:4000访问博客了。
          • -v /www/wwwroot/leepoethexo:/app: 这就是目录挂载。它将宿主机的 /www/wwwroot/leepoethexo目录关联到容器内的 /app目录。你在容器内 /app下的所有操作,都会实时同步到宿主机的 /www/wwwroot/leepoethexo下。
          • node:latest: 使用已有的 Node.js 镜像。
          • tail -f /dev/null: 一个让容器保持运行的小技巧。

          3. 在容器内安装和初始化Hexo

          现在,容器已经在后台运行了。我们需要进入容器内部完成Hexo的安装。

          a. 进入容器

          docker exec -it leepoet-hexo /bin/bash
          

          执行后,你的命令行提示符会变成类似 root@容器ID:/#的样子,表示你已经进入了容器内部。

          b. 全局安装Hexo命令行工具

          npm install -g hexo-cli
          

          c. 初始化Hexo项目

          cd /app  # 这是挂载点,务必在此目录下操作!
          hexo init .  # 注意最后有个点,表示在当前目录初始化
          npm install  # 安装Hexo所需的依赖包
          

          初始化完成后,你会在宿主机的 /www/wwwroot/leepoethexo目录下看到Hexo的项目文件。

          d. 生成静态文件并启动本地服务器(在容器内执行):

          hexo generate
          hexo server -s -p 4000 &
          

          现在,你应该可以在宿主机的浏览器中访问 http://localhost:4000看到默认的Hexo博客页面了。

          日常使用指南

          当环境搭建好后,你通常会进行以下操作:

          操作场景命令说明
          启动已停止的容器docker start leepoet-hexo容器停止后,用它重新启动。
          进入容器docker exec -it leepoet-hexo /bin/bash进入容器内部执行命令(如写作、安装插件)。
          停止容器docker stop leepoet-hexo正常停止容器。
          查看容器日志docker logs leepoet-hexo排查问题时查看输出信息。
          在宿主机上编辑用你的IDE直接编辑 /www/wwwroot/leepoethexo下的文件所有更改会实时同步到容器内。
          • exec:表示在容器内执行命令。
          • -it:这是两个选项的组合。-i(--interactive) 保持标准输入流开放,允许你输入命令;-t(--tty) 分配一个伪终端,让你获得一个格式良好的交互式 Shell 体验。
          • leepoet-hexo:是你的容器名称。如果你当时创建时用了其他名字,这里需要替换掉。 /bin/bash:指定在容器内运行的 Shell 程序(这里指 Bash)。
          • 重要优点:使用 exec方式进入容器,当你输入 exit退出时,只会结束当前的 Shell 会话,而不会导致你的 Hexo 容器停止运行。这对于需要长期运行的服务(比如你的博客服务器)至关重要。

          常用Hexo命令(在容器内执行)

          hexo new "我的新文章"   # 创建一篇新文章
          hexo clean             # 清理缓存
          hexo generate          # 生成静态文件
          hexo deploy            # 部署到服务器
          hexo server -s -p 4000 # 启动本地服务器进行预览
          hexo generate --debug  # 启用调试模式
          hexo g --debug   # 或简写
          hexo g --verbose  # 查看每个文件的处理情况
          hexo g --debug --verbose   # 同时启用调试和详细模式
           

          方案优势与注意事项

          这个方案的优势在于:

          数据持久化:你的所有Hexo博客源文件都安全地保存在宿主机的 /www/wwwroot/leepoethexo目录下。即使你删除了Docker容器,你的博客源码也不会丢失。

          环境隔离:Hexo的运行环境被封装在容器内,不会污染宿主机系统。

          便捷开发:你可以在宿主机上用熟悉的编辑器修改 /www/wwwroot/leepoethexo下的文件,更改会立刻在容器中生效,无需反复进入容器。

          需要注意的事项:

          权限问题:如果遇到容器内进程没有权限写入挂载目录的情况,可能需要检查宿主机目录( /www/wwwroot/leepoethexo)的权限设置

          端口占用:确保宿主的4000端口没有被其他程序占用。

          备份:虽然源码已在宿主机上,但定期备份整个 /www/wwwroot/leepoethexo目录是一个好习惯。


          往期有关HEXO教程:

          LeePoet实操快速上手:Hexo静态博客搭建全攻略

          为Hexo博客铺路:Windows匠心配置NodeJS环境的安装

        6. LeePoet针对2H2G服务器性能优化LNMP+Redis配置详解

          LeePoet针对2H2G服务器性能优化LNMP+Redis配置详解

          前几天因为把数据库给搞崩溃了,气恼之下直接重装了服务器。由于年纪大了,平时搞的东西也多,导致很多时候做完的事,一些数据参数以及作用都要临时再查询并设置,为了方便以后更换服务器不再花费大量时间优化配置,所以LeePoet做了一个记笔,也算是备份。以下是LeePoet一直以来LeePoet BLOG都是用的2H2G的配置。自己是怎么优化服务器的。

          作为一名“资深二手垃圾收藏家废物站长”,LeePoet深知2核2G(2H2G)配置的服务器是许多个人站长的首选。它成本低廉,但资源有限,尤其在面对突发流量或不当配置时,数据库崩溃、网站卡顿是家常便饭。2GB内存是主要限制。所有优化都必须围绕“节约内存、防止溢出”展开。盲目追求高并发参数(如MySQL的max_connections)是导致服务器崩溃最常见的原因。

          LeePoet在多次重装服务器后,总结出的一套针对 宝塔面板 + LNMP(Linux, Nginx, MySQL, PHP)环境 + Redis​ 的深度优化配置。目标明确:在保证稳定性的前提下,最大化榨取2H2G服务器的每一分性能。

          一、服务器的NGINX优化

          在保证服务器稳定性的前提下,最大化利用您有限的硬件资源(2核CPU,2GB内存),以支持更高的并发连接和更大的文件上传。

          核心配置参数分析与建议

          可以直接参照此表在您的管理面板中进行修改。

          配置参数默认值2H2G服务器推荐值说明
          worker_processesautoauto或 2Nginx工作进程数。auto会自动设置为CPU核数,对于2核服务器,设为2auto都是最佳选择。
          worker_connections5120020480【重要调整】​ 每个工作进程的最大连接数。图片中的51200对2G内存来说过高,容易导致内存耗尽。建议保守设置为20480,理论最大并发为 worker_processes * worker_connections = 2 * 20480 = 40960,这已经非常充足。
          keepalive_timeout6030 - 60长连接超时时间。60秒是合理的,可以减少连接重建开销。如果您的站点并发很高,可以适当调低至30秒以快速释放连接。
          client_max_body_size50 MB根据需求调整(如200M)【您最可能需要的调整】​ 允许客户端上传的最大文件大小。如果您需要上传大于50MB的文件(如高清图片、视频、软件包),就在这里修改。例如设为200M注意:修改后必须点击“保存”并重载Nginx配置才能生效。
          gzip开启开启开启Gzip压缩可以有效减少文本类资源(HTML,CSS,JS)的传输大小,提升加载速度。
          gzip_min_length1 KB1 KB小于1KB的文件压缩可能得不偿失,保持默认即可。
          gzip_comp_level53 - 5压缩级别(1-9),级别越高压缩率越好但CPU消耗越大。建议在3-5之间取得平衡,5是很好的选择。
          server_names_hash_bucket_size512512如果您的服务器配置了大量域名,出现哈希桶大小错误时才需要调整这个值。通常默认或512足够。
          client_header_buffer_size32 KB32 KB用于读取客户端请求头的缓冲区大小。对于绝大多数情况够用,保持默认。
          client_body_buffer_size512 KB512 KB用于读取客户端请求主体(如POST数据)的缓冲区大小。通常够用,保持默认。如果经常有超大POST请求,可考虑增大。

          针对2H2G服务器的综合配置策略

          1. 核心思路:平衡内存与并发
            • 内存是您的瓶颈:2GB内存需要精打细算。过高的worker_connections会预分配资源,可能导致服务器在真正的高并发下因内存不足而崩溃。因此,我们将worker_connections从51200下调到更安全的20480
            • CPU足够应对:2个CPU核心可以很好地处理Nginx的两个工作进程。
          2. 重点调整步骤:
            • 第一步(关键):将 client_max_body_size修改为您需要的值(例如 200M)。
            • 第二步(推荐):将 worker_connections修改为 20480,以提升服务器稳定性。
            • 第三步:检查其他参数,确认与推荐值一致。
            • 最后:滚动到页面底部,点击绿色的 “保存”​ 按钮,并重启Nginx服务或重载配置以使更改生效。

          二、服务器的MYSQL优化

          对于2G内存的服务器来说(如最大连接数500)过于激进,存在耗尽内存导致数据库崩溃的高风险。我们的优化目标是:在有限的内存下,优先保证数据库的稳定性和响应速度,而不是追求不切实际的高并发连接数

          核心优化思路

          1. 内存是最大瓶颈:2GB内存中,操作系统和其他服务(如Nginx、PHP)需要占用约300-500MB。留给MySQL的安全内存上限应在 1.2GB ~ 1.5GB​ 左右。
          2. 连接数是内存杀手:许多缓冲区(如sort_buffer_size)是“按连接”分配的。即使一个空闲连接,也会占用这些内存。500个连接会瞬间吃光内存。
          3. 抓住重点innodb_buffer_pool_size是MySQL性能的“心脏”,它用于缓存数据和索引,应分配最多内存。

          2H2G服务器MySQL配置推荐

          配置的详细优化建议,可以直接在管理面板中修改。

          配置参数默认值2H2G服务器推荐值修改说明
          最大使用内存~1348 MB约 1200 – 1400 MB这是计算结果,无需直接设置。它由下面各个参数值累加而来。我们的目标就是将其控制在安全线内。
          max_connections500100【最关键调整】​ 大幅降低最大连接数。100个连接对中小型网站已足够。这能有效防止内存过载。实际并发连接数可能只有10-30个。
          innodb_buffer_pool_size128 MB768 M​ 或 1024 M【性能核心】​ 这是缓存数据和索引的地方,越大查询越快。建议分配总可用内存的50-70%。从128MB提升到768MB或1G,性能将有质的飞跃。
          key_buffer_size32 MB16 M仅用于MyISAM引擎的索引缓存。如果您的表都是InnoDB引擎(现代MySQL的默认引擎),这个值可以设小,比如16M。
          tmp_table_size32 MB16 M临时表的最大大小。如果复杂查询多,可以保持32M,否则可以适当降低以节省内存。
          innodb_log_buffer_size16 MB8 M– 16 M用于缓冲重做日志(Redo Log)数据。16MB对一般业务足够,如果大事务不多,可以设为8MB。
          table_open_cache128512– 1024表示可以同时打开的表的数量。适当增大(如512)可以减少表开关销,对内存影响不大。
          thread_cache_size1616– 32缓存线程数量,避免频繁创建销毁线程。16是一个合理的值,可以保持。

          【重点】按连接分配的缓冲区优化

          这些参数是“内存杀手”,必须谨慎设置。它们乘以可能的并发连接数就是总消耗。

          配置参数默认值2H2G服务器推荐值修改说明
          sort_buffer_size768 KB256 KB每个连接排序时使用的缓冲区。不要超过256KB。
          read_buffer_size768 KB128 KB– 256 KB每个连接顺序扫描表时使用的缓冲区。降低到256KB或更低。
          read_rnd_buffer_size256 KB128 KB每个连接用于随机读的缓冲区。128KB足够。
          join_buffer_size256 KB128 KB每个连接用于表关联的缓冲区。128KB足够。如果查询优化得当,很少需要大的join buffer。
          thread_stack256 KB256 KB每个线程的堆栈大小。保持默认即可,不要动。
          binlog_cache_size32 KB32 KB每个连接用于二进制日志的缓存。保持默认即可。

          修改后内存估算(理想情况)

          估算一下推荐配置下的内存使用峰值:

          • 全局缓冲区:
            • innodb_buffer_pool_size: 768 MB
            • key_buffer_size: 16 MB
            • tmp_table_size& 其他: ~50 MB
            • 小计: ~834 MB
          • 每连接缓冲区​ (按最大100连接,但实际可能只有20个活跃连接计算):
            • (256K256K128K128K) * 20个连接 ≈ (768KB/连接) * 20 = 15 MB
          • 操作系统/其他开销: ~200 MB
          • 总计峰值: 834 MB + 15 MB + 200 MB ≈ 1050 MB

          这个估算值在您2GB内存的安全范围内,系统运行会非常稳定。

          操作步骤

          1. 备份:如果数据库中有重要数据,修改配置前最好先备份。
          2. 修改:在您的管理面板中,按照上表的“推荐值”逐一修改。
          3. 保存并重启:滚动到页面底部,点击绿色的 “保存”​ 按钮,然后点击 “重启数据库”​ 使配置生效。
          4. 监控:重启后,通过数据库管理工具或SHOW GLOBAL STATUS LIKE 'Threads_connected';命令监控实际的最大连接数,通常远低于max_connections

          对于2H2G服务器,MySQL配置的精髓就是“保守”。通过大幅降低 max_connections并优化每个连接的缓冲区大小,将节省下来的内存集中分配给 innodb_buffer_pool_size,这样才能在有限资源下获得最佳性能。


          三、Redis配置与优化

          对于2G内存的服务器来说(如maxclients 10000风险极高,我们的目标是:在有限的内存下,确保Redis稳定运行,防止内存耗尽导致服务崩溃,并保障安全

          核心优化思路

          1. 内存是生命线:Redis所有数据存储在内存中。必须设置内存上限,否则Redis会吃光所有内存,导致系统崩溃。
          2. 连接数不是重点:与MySQL不同,Redis是单线程模型,处理连接非常高效。但每个连接仍会占用少量内存,无需设置得过高。
          3. 安全第一:默认只绑定内网(127.0.0.1)并设置强密码,是防止服务器被入侵的关键。

          下表是针对默认值的配置的详细优化建议。

          配置参数默认值2H2G服务器推荐值修改说明
          bind127.0.0.1127.0.0.1【安全关键】​ 保持默认。这意味着Redis只允许本机(即服务器上的PHP、Web应用)连接。绝对不要改为 0.0.0.0(允许任何IP连接),否则极易被黑客入侵。
          port63796379​ 或 自定义端口保持默认即可。如果为了隐蔽性,可以改为其他端口(如 6479),但这并非主要安全手段。
          timeout0300客户端空闲超时时间(秒)。0表示不断开。建议设为 300(5分钟),自动断开闲置连接,释放资源。
          maxclients100001000【重要调整】​ 最大客户端连接数。10000对2G服务器过高,可能占用几百MB内存。设置为 1000对于绝大多数应用绰绰有余,能有效控制内存使用。
          databases1616数据库数量。16是合理的默认值,无需修改。
          requirepass【必须设置一个强密码】【安全关键】​ 这是保护Redis的第二道防线。请务必设置一个包含大小写字母、数字和特殊字符的复杂密码(例如 MyRedisPass123!)。应用程序连接Redis时也需要使用此密码。
          maxmemory01024 MB​ 或 1536 MB【最核心的调整】​ 0表示无限制,这是极其危险的!必须设置为一个上限。建议为系统预留500MB-1GB内存,因此Redis最大内存可设为 1024M(1GB)。如果您的应用主要是Redis,可以设为 1536M(1.5GB)

          【关键】maxmemory-policy配置(至关重要!)

          当内存使用达到 maxmemory限制时,Redis的行为由 maxmemory-policy决定。您需要在配置文件中找到并设置它。对于通用场景,推荐:

          • allkeys-lru(推荐)​ 从所有键中淘汰最近最少使用的键。这是最常用的策略,能保证热点数据常驻内存。
          • volatile-lru:仅从设置了过期时间的键中淘汰最近最少使用的键。

          需要在配置文件(通常位于 /etc/redis/redis.conf)中手动添加或修改这一行:

          maxmemory-policy allkeys-lru

          针对2H2G服务器的完整配置方案

          1. 第一步(安全与稳定核心)
            • 将 maxmemory​ 设置为 1024M
            • 在 requirepass​ 中设置一个强密码
          2. 第二步(资源优化)
            • 将 maxclients​ 从 10000修改为 1000
            • 将 timeout​ 从 0修改为 300
          3. 第三步(高级策略,需手动修改配置文件)
            • 使用SSH登录服务器,用文本编辑器(如 nano或 vim)打开Redis配置文件(路径可能为 /etc/redis/redis.conf)。
            • 找到并修改(或添加)一行:maxmemory-policy allkeys-lru
            • 保存文件并退出编辑器。
          4. 最后
            • 在宝塔面板的Redis设置页面,点击绿色的 “保存”​ 按钮。
            • 重要:根据页面提示,重启Redis服务​ 以使所有配置生效。

          注意事项

          • 重启影响:重启Redis会清空所有当前存储在内存中的数据(如果未开启持久化)。请在业务低峰期操作。
          • 持久化:如果您需要数据持久化,请确保配置了RDB快照或AOF日志。宝塔面板通常默认已配置,但建议您检查“性能调整”或配置文件中的 save和 appendonly相关设置。
          • 监控:配置完成后,通过宝塔面板的“监控”功能或Redis自带的 INFO命令,观察内存使用情况是否稳定。

          对于2H2G服务器,Redis配置的核心就三点:

          1)用 maxmemory设限保命;

          2)用 bind和 requirepass筑牢安全防线;

          3)用 maxclients等参数优化资源。

          按照以上方案配置,您的Redis服务将能在一个安全、稳定的环境下运行。

          后续

          因为在设置完redis密码后,WP会报错,是因为我们WP也装了redis插件如:

          所以在修改完redis后再打开站点会出现一个报错

          解决方法

          我们直接找到站点的wp-config.php文件,编辑WordPress根目录下的 wp-config.php文件再添加一段redis配置:

          // 在wp-config.php中添加或修改以下配置
          define('WP_REDIS_HOST', '127.0.0.1');
          define('WP_REDIS_PORT', 6379);
          define('WP_REDIS_PASSWORD', 'your_redis_password_here'); // 这里是redis的密码
          define('WP_REDIS_TIMEOUT', 1);
          define('WP_REDIS_READ_TIMEOUT', 1);

          四、配置PHP

          在内存紧张的情况下,优先保证服务器稳定性,按需分配资源。

          【最佳推荐方案:切换到“按需模式”(ondemand)】

          这是最节省内存的方案,非常适合访问量不大或波动明显的站点。

          配置参数默认值(动态)2H2G推荐值(按需)说明
          运行模式 (pm)dynamic(动态)ondemand(按需)【关键修改】​ 此模式下,PHP进程在无请求时会自动结束,仅在需要时创建,能极大节省内存。
          max_children2015即使切换到按需模式,也需要设置一个上限防止爆内存。15是2G内存下相对安全的数值。
          start_servers5(此模式无效)按需模式无需设置起始进程数。
          min_spare_servers5(此模式无效)按需模式不保持空闲进程。
          max_spare_servers10(此模式无效)按需模式不保持空闲进程。
          pm.process_idle_timeout60s(或默认值)进程空闲多少秒后关闭。保持默认或设为60秒即可。

          此方案优点:在网站无人访问时,PHP进程数为0,内存占用极低。当有访问时,系统会快速创建进程处理请求,处理完毕后一段时间会自动回收。

          1. 强烈建议您采用【最佳推荐方案】
          2. 在这个“性能调整”界面,将 “运行模式”​ 从 “动态”​ 改为 “按需”
          3. 将下方的 “max_children”​ 从20修改为 15
          4. 点击绿色的 “保存”​ 按钮。
          5. 最重要的一步:需要到宝塔的“软件商店”或“服务”页面,找到PHP-8.2,点击“重启”。不重启配置不会生效!

          2H2G服务器,PHP-FPM进程管理是内存优化的重中之重。将模式从“动态”改为“按需”,并设置一个合理的max_children(如15),可以确保服务器在承受访问压力时不会因PHP进程过多而内存耗尽崩溃。这是提升服务器稳定性的最有效手段。

          以下是PHP的 FPM主配置文件已经是最优配置

          配置分析与评价

          配置行默认值分析与评价
          pmondemand【核心优化,非常正确!】​ 这是最省内存的模式。进程只有在有请求时才会创建,请求处理完后会自动结束。完美契合2G内存服务器。
          pm.max_children15【设置合理】​ 这是PHP进程数的上限。15对于您的服务器内存来说是安全且可承受的,防止进程过多导致内存耗尽。
          pm.start_servers5(此模式下无效)​ 在ondemand模式下,系统启动时不会预先创建5个进程,所以这个值没有影响,可以忽略。
          pm.min_spare_servers5(此模式下无效)​ 在ondemand模式下,系统不保持任何空闲进程,所以这个值没有影响,可以忽略。
          pm.max_spare_servers10(此模式下无效)​ 同上,在ondemand模式下无效。
          listen.backlog8192监听队列长度,默认值,足够大,没问题。
          request_terminate_timeout100【设置合理】​ 单个请求最大执行时间100秒,比php.ini里的max_execution_time更长,确保FPM能强制结束超时进程,避免进程阻塞。
          listen.mode0600Socket文件权限,仅允许所有者读写,安全。

          将PHP-FPM设置成了对小型服务器最友好的 “按需模式 (ondemand)”,并设置了安全的进程上限 15。这能确保:

          1. 低内存占用:在网站访问低谷期,PHP进程数为0,几乎不占用额外内存。
          2. 高稳定性:进程数有硬性上限,不会因为突发流量而拖垮整个服务器。
          3. 按需响应:当有访问请求时,系统会立刻创建新的进程来处理,响应速度不受影响。

          确认修改后,点击界面下方的绿色 “保存”​ 按钮,然后到宝塔的“服务”页面,重启PHP-8.2服务,使新的配置生效。

          安装PHP的OPcache 扩展

          安装并启用OPcache是提升PHP性能性价比最高的操作,没有之一。

          检查并优化OPcache配置

          仅仅安装还不够,我们需要确保它的配置对于您的2G内存服务器是优化的。请您按照以下步骤操作:

          1. 点击左侧菜单的【配置修改】,打开PHP的主配置文件(php.ini)。
          2. 在文件中找到 [opcache]部分。如果找不到,可以直接在文件末尾添加。
          3. 请对照下表,检查或修改您的OPcache配置,使其达到最佳状态:
          配置项推荐值(用于2H2G服务器)说明
          opcache.enable1确保OPcache是开启状态。
          opcache.memory_consumption128【核心参数】​ 为OPcache分配的内存量(MB)。默认值可能很小(如64)。建议设置为128,这能为大量PHP脚本提供缓存空间,显著提升性能,同时不会对您2G的总内存造成压力。
          opcache.interned_strings_buffer8存储 interned strings 的内存大小(MB)。PHP会重复使用相同的字符串,这个配置能节省内存。从默认值提升到 8效果很好。
          opcache.max_accelerated_files10000OPcache哈希表中可存储的脚本文件数量上限。建议设为10000,以确保所有项目文件都能被缓存。
          opcache.revalidate_freq60检查脚本是否更新的时间间隔(秒)。设为 60意味着OPcache会每60秒检查一次源文件是否有变化。在生产环境,为了最高性能,甚至可以设为 0,但这样需要手动重启PHP来更新更改。
          opcache.save_comments1保留代码注释。某些框架(如Laravel)依赖注释,请保持为1。
          opcache.enable_cli0是否为命令行接口(CLI)启用OPcache。通常不需要,设为 0以避免潜在问题。

          优化的配置示例(复制粘贴到 php.ini中):

          opcache.enable = 1
          opcache.memory_consumption=128
          opcache.interned_strings_buffer=8
          opcache.max_accelerated_files=10000
          opcache.revalidate_freq=60
          opcache.fast_shutdown=1
          opcache.enable_cli=0

          配置中的 opcache.jit_buffer_size和 opcache.jit是PHP 8.0+的即时编译功能,属于高级优化。如果OPcache工作正常,可以保留它们。但如果重启PHP后网站出现任何问题,可以暂时将这两行开头加上分号;注释掉,先确保基础OPcache能正常运行。

          修改完成后,点击保存最重要的一步:回到【服务】页面,重启PHP(点击对应的重启按钮)。不重启,配置更改不会生效。


          设置计划任务,每日凌晨重启服务

          “宝塔任务管理器”主要用于实时监控和管理进程,而设置定时任务需要用到宝塔面板自带的“计划任务”功能。操作步骤如下:

          1. 在宝塔面板左侧导航栏中,找到并点击 “计划任务”
          2. 点击页面右上角的 “添加计划任务”​ 按钮。
          3. 在弹出的窗口中,按以下说明进行配置:
            • 任务类型:选择 “Shell脚本”
            • 任务名称:填写一个便于识别的名称,例如 “每日凌晨重启PHP和MySQL”
            • 执行周期:选择 “每天”,并在时间设置中选择一个凌晨的、访问量最少的时间点,例如 凌晨 3:00
            • 脚本内容:这是最关键的部分,请将以下命令复制粘贴进去:
          # 重启PHP-FPM服务(请根据您的PHP版本修改,例如php-fpm-82)
          /etc/init.d/php-fpm restart
          # 重启MySQL服务
          /etc/init.d/mysqld restart

          1. 在任务列表中,找到您刚刚创建的任务,点击右侧的 “执行”​ 按钮。
          2. 注意:请根据您服务器上安装的PHP版本,将 php-fpm替换为正确的服务名。通常格式为 php-fpm-版本号,例如 php-fpm-82(对应PHP 8.2)。您可以在宝塔的“软件商店”中查看已安装的PHP版本,或者在“服务”页面查看PHP服务的全名。
          3. 确认信息无误后,点击 “添加任务”

          成功设置了在每天凌晨自动重启PHP和MySQL服务的计划任务。这有助于释放被长时间占用的内存,清理可能存在的内存泄漏,从而保持服务器的稳定性和性能。对于您这台2H2G的服务器来说,这是一个非常有效的维护手段。


          额外说明:为什么没有装Memcached?

          1.服务器内存只有2GB,非常宝贵。同时运行Redis和Memcached两个内存型服务,意味着需要为两者分别分配内存(比如Redis 1GB,Memcached 128MB)。这会造成内存资源的浪费和碎片化。将分配给Memcached的这部分内存也划给Redis,让Redis拥有更大的缓存空间,性能会更好。

          “把好钢用在刀刃上”:集中所有内存资源给一个更强大的缓存服务(Redis),比分散给两个服务更高效。

          2.Redis的功能是Memcached的超集

          •Redis支持数据持久化,可以定期将内存数据写入磁盘,防止服务器重启后所有缓存丢失。而Memcached不支持持久化,重启后缓存就全没了。

          Memcached只能做简单的键值对缓存,如图中的配置,它就是一个纯内存缓存。

          Redis不仅可以做键值对缓存,还支持更丰富的数据结构(如列表、集合、哈希表、有序集合),这使得它能处理更复杂的场景(如排行榜、消息队列、会话存储等)。

          2H2G服务器,保留Redis,停用Memcached是一个更优、更专业的选择。​ 这能让有限的硬件资源发挥出最大的效能,同时获得更强大的功能。


          优化进阶:解决同一服务器上两个WordPress网站共用Redis导致数据混乱的问题

        7. 使用Ventoy制作Windows To Go:一个U盘搞定所有系统,随身携带你的PC

          使用Ventoy制作Windows To Go:一个U盘搞定所有系统,随身携带你的PC

          (清了清嗓子,拍了拍桌子)哎,各位朋友,我是李哥!今天咱们不聊虚的,就说说怎么把Windows系统塞进U盘里,让你走到哪儿都像带着“移动网吧”——这玩意儿叫Windows To Go,绝对是打工人、学生党的救命神器!

          为啥要搞这玩意儿?​想象一下:公司电脑卡成PPT、学校机房软件不全、出差不敢用酒店公共电脑……这时候你掏出U盘,插上任何电脑,直接启动自己熟悉的Windows系统——软件、文件、浏览器记录全在兜里,隐私安全还拉满!李哥当年就是靠这招,在网吧边吃泡面边改完了毕业论文(别问,问就是热血青春)

          准备家伙事儿!(硬件门槛)

          1. U盘别抠门:至少64GB起步,读写速度要快(推荐USB 3.0以上),否则装系统慢到你想砸电脑。李哥用过某顿的普通U盘,结果安装6小时,开机转圈半小时……(血泪教训!)
          2. 系统镜像:去微软官网下个正经的Windows 10/11企业版或教育版ISO文件(其他版本可能不支持)。
          3. 工具软件:推荐WTG辅助工具ventoy,小白也能一键操作,比老辈分的“命令行敲代码”省心一百倍

           


          • 一、怎么在u盘上跑完整的windows呢?
            我们都知道,操作系统一定要操作……哦不对,常见的操作系统一定要在硬盘上跑。无论是固态硬盘也好,还是机械硬盘也罢,我们概念中的系统一定是装在电脑里的那个固定不动的硬盘上的。一般windows的默认安装位置就是机内的存储介质,并不能像linux那样直接在livecd里就能直接装在u盘上。
            其实windows to go的历史很久了,可以追溯到2011年:2011 年 4 月,Windows to go就已包含在泄漏的 Windows 8 Build 7850 版本中。同年 9 月,微软在 Build 大会上正式公布了此功能,并分发了预装该系统的 32GB 启动 U 盘。它起初适配 Windows 8 企业版,后续拓展支持 Windows 8.1 及 Windows 10 的企业版、教育版,Windows 10 1607 版本及之后的专业版也纳入适配范围。
            但是,到了 2019 年 的 Windows 10 1903 版本发布时,微软宣布停止对其开发,2020 年 Windows 10 2004 版本中该功能被正式移除,缘由是它不支持功能更新,且所需的特定类型 USB 设备也逐渐不再被 OEM 厂商支持。
            不过这个功能确实非常方便,也吸引很多大佬来研究、发展Windows to go。其中最具有代表性的就是萝卜头IT论坛的WTG辅助工具,以及edgeless工具。今天我们暂时不用这两个工具,教大家直接手动在ventoy上部署windows to go!
            今天我们就来制作一个既能用ventoy,还能启动完整windows的u盘。了解了我们今天的任务,我们现在就可以开始教学了!
            哦对了,在看完文章后,如果手痒难耐想要实践一把,不要忘记领取文末的关键词哦!

          • 二、制作wintogo镜像并导入u盘
            首先,我们先需要下载想要安装的windows版本镜像。这里我推荐各位使用企业版windows的ltsc2019版本,ltsc企业版的镜像包相对于家庭版、专业版的镜像而言会精简一些,而且这些被精简掉的功能——比如xbox中控、microsoft商店等——基本不会影响正常的使用。假如你在ltsc上运行某些软件,碰到了诸如“xxx.dll”缺失的问题,一般直接百度就可以了,一般都很容易找到答案。
            如果你和我一样是个懒人,那么直接用现成的iso镜像包就可以了。如果你是个有极客精神的弗雷尔卓德人,把电脑当哥们,就喜欢折腾它,那么你可以使用一些经过民间优化的wim、esd格式的优化版本镜像,甚至你可以把自己正在用的操作系统封装成一份wim做成wintogo——虽然我并不推荐这么做,很有可能出现驱动冲突的情况。
            这里我们就先来点简单的,直接用现成的LTSC2019来进行演示。
            不想开网页下镜像也不要紧,罗某人为各位整理了一些常用的windows版本镜像包,在文末就能看到关键词了哦!
            好,现在我们打开电脑,右键此电脑——显示更多选项——管理,点击磁盘管理。
            来到这个页面没有?我们点开右侧的更多操作,选择创建VHD,将硬盘格式改为VHDX,类型设为“动态扩展”,然后随便把它放到哪里,大小随便设,别太小就行。这里我就设个100g就行了。
            然后你的窗口底部就会出现一个新的磁盘了!右键那个新建的磁盘x,选择初始化,初始化成GPT分区表,点击确定。
            接下来再右键磁盘x右侧的黑色条条,点击“新建简单卷”,这里我建议新手直接全部按照默认参数创建分区,无脑点下一步直到分区创建完成即可。
            这样就能看到那个黑色的框框变成蓝色的框框了!
            好,创建虚拟磁盘这一步我们就完成了。下一步我们要用到一个新工具,是俄罗斯人做的一个windows系统安装工具,叫做winntsetup。使用它,我们就可以非常方便地安装windows了。同样,这个工具会一并放在文末的关键词里。
            一看这个网页风格就非常程序员,一点多余的装饰都没有:
            打开程序后,我们首先点击第一行“选择windows安装源”,选择我们下载好的镜像,第二行选择一个EFI System(ESP)分区类型的分区即可;第三行就是我们的系统安装位置,选择虚拟磁盘即可。
            接下来我们点击安装,将引导代码切换为“不更新引导代码”,点击确定,坐着等就行了。
            好,在安装完成后,会跳出一个弹窗,询问你要不要重启,这时候我们重启,进行一下系统的初始化。
            这个应该不用我教吧?
            在激活系统后,我们可以进行下一步了:导入ventoy。

          • 三、配置ventoy,启动wintogo
            安装ventoy的流程就不再赘述了,各位可以乘坐文章开头的传送门前往学习。首先,我们在ventoy的根目录下创建一个名为“ventoy”的文件夹,然后在官网下载ventoy用以启动vhd的插件:ventoy_vhdboot.img。找不到也不要紧,文末有的。
            如果各位在官网下的话,会得到一个压缩包,里面有2个版本的插件文件,一般我们选win10based的那个版本即可。
            解压完后,我们直接把解压得到的ventoy_vhdboot.img放到我们刚刚创建的ventoy文件夹里——注意,一定是文件夹里面,而不是外面。
            然后呢?快点想想我们刚刚做了什么?对了!创建了个vhdx虚拟磁盘嘛!此时我们把这个vhdx文件复制粘贴到ventoy盘里面——不是文件夹里面!然后……重启电脑,启动ventoy!
            在ventoy里面找到我们的vhdx文件,启动它!不出意外的话……会不出意外地,成功了!
          • 四、enjoy!记得装驱动哦。
            对了,不要学我用一半拔u盘,容易蓝屏,我是为了拍封面才拔的。哦对了,拔下来一会再把u盘插上,系统就会继续正常工作哦。

           

        8. 为Hexo博客铺路:Windows匠心配置NodeJS环境的安装

          为Hexo博客铺路:Windows匠心配置NodeJS环境的安装

          想要栽种Hexo这朵静态博客的繁花,必先悉心培育Node.js这方土壤。本篇手记详述了从获取种苗(下载)、择地而植(安装),到修渠引水(环境变量配置)的全过程。三分诗意留给想象,七分严谨付诸实践,愿你的博客花开满枝。

          一、进入官网地址下载安装包

          安装最近包兼容性方面要好些,这里我选择的是[Windows系统]、64位

          Tips:如果想下载指定版本,点击【以往的版本】,即可选择自己想要的版本下载

          二、安装程序

          (1)下载完成后,双击安装包,开始[安装Node.js]

          (2)直接点【Next】按钮,此处可根据个人需求修改安装路径,修改完毕后继续点击【Next】按钮

          (3)可根据自身需求进行,此处我选择默认安装,继续点击【Next】按钮

          (4)不选中,直接点击【Next】按钮

          Tip:这是Node.js官方安装程序的推荐选项(默认已勾选),自动安装编译原生模块所需的完整工具链(Python、Visual Studio构建工具),避免后续开发中遇到”node-gyp”编译错误的问题。特别适合需要安装带有C++扩展的npm包(如bcrypt、sqlite3等)。因为我的系统已经您的系统已经安装了完整的Visual Studio和Python开发环境,所以没选这个。

          (5)点击【Install】按钮进行安装

          (6)安装完毕,点击【Finish】按钮

          (7)测试安装是否成功,按下【win+R】键,输入cmd,打开cmd窗口

          node -v     // 显示node.js版本
          npm -v     // 显示npm版本

          成功显示版本说明安装成功

          三、环境配置

          (1)找到安装的目录,在安装目录下新建两个文件夹【node_global】和【node_cache】

          (2)创建完毕后,使用管理员身份打开cmd命令窗口(打开方法见下方Tips),输入

          ①npm config set prefix “你的路径\node_global” (复制你刚刚创建的“node_global”文件夹路径)

          npm config set prefix "E:\Program Files\nodejs\node_global"  

          ②npm config set cache “你的路径\node_cache” (复制你刚刚创建的“node_cache”文件夹路径)

          npm config set cache "E:\Program Files\nodejs\node_cache"

          Tips: 使用管理员身份运行cmd的方法 :点击左下角【开始】菜单,在搜索区域输入“命令提示符”,然后点击【以管理员身份运行】

          或单击鼠标右键选择【以管理员身份运行】

          (3)配置环境变量

          ①【此电脑】-单击右键-【属性】-【高级系统设置】-【环境变量】

          ② 在【系统变量】中点击【新建】

          变量名:NODE_PATH

          变量值:E:\Program Files\nodejs\nodejs\node_global\node_modules

          然后你就会发现【node_global】里多出了一个【node_modules】文件夹,Tips: 如果输入变量值之后没有自动创建【】文件夹,就在【node_global】下手动创建一个【node_modules】文件夹,再复制你创建的【node_modules】文件夹的路径地址到变量值

          ③编辑【用户变量】中的【Path】

          ④将默认的 C 盘下【 AppData\Roaming\npm 】修改成 【node_global】的路径,点击确定

          ⑤在【系统变量】中选择【Path】点击【编辑】添加【%NODE_PATH%】,随后一直点击【确定】

          接下来是安装HEXOLeePoet实操快速上手:Hexo静态博客搭建全攻略