<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>懒洋洋</title><link>https://lanlan.work/</link><description>Recent content on 懒洋洋</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sat, 03 Oct 2026 14:00:00 +0800</lastBuildDate><atom:link href="https://lanlan.work/index.xml" rel="self" type="application/rss+xml"/><item><title>POSCMS 在 IIS + PHP 5.6 下 php-cgi 进程持续暴涨的排查与处理</title><link>https://lanlan.work/posts/technology/poscms-cgi/</link><pubDate>Sat, 03 Oct 2026 14:00:00 +0800</pubDate><guid>https://lanlan.work/posts/technology/poscms-cgi/</guid><description>&lt;h2 id="现象与结论"&gt;现象与结论&#10;&lt;/h2&gt;&lt;p&gt;Windows 服务器（IIS + FastCGI + PHP 5.6）上的一个多年未升级的 POSCMS 站点，IIS 站点一启动 php-cgi.exe 进程就不断增多，伴随偶发数据库连接失败。&lt;/p&gt;&#10;&lt;p&gt;PHP 5.6 本身不会 fork，多个 php-cgi.exe 是 FastCGI 为并发请求分配进程槽位的正常机制。真正的问题是：&lt;strong&gt;每个请求都可能被拖住最长 60 秒释放不掉，而站点被扫描机器人 7×24 轰炸，请求不断堆积，IIS 只能不停拉新进程接客&lt;/strong&gt;。把请求拖死的元凶是 PHP 文件 Session 的垃圾回收（GC）。&lt;/p&gt;&#10;&lt;h2 id="排查过程"&gt;排查过程&#10;&lt;/h2&gt;&lt;p&gt;先搜 &lt;code&gt;pcntl_fork&lt;/code&gt;/&lt;code&gt;exec&lt;/code&gt;/&lt;code&gt;fsockopen&lt;/code&gt; 等调用，确认程序没有主动起进程，也排除了 POSCMS 自带的任务队列（&lt;code&gt;SYS_CRON_QUEUE&lt;/code&gt; 为关闭）和附件同步的自我 HTTP 调用（未启用），顺手扫了一遍无 webshell。&lt;/p&gt;&#10;&lt;p&gt;决定性证据来自 &lt;code&gt;cache/errorlog/&lt;/code&gt; 的运行日志：从两年前持续到排查当天，几乎每天都是同一种致命错误，最重的日子一天 200+ 条：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;ERROR --&amp;gt; Maximum execution time of 60 seconds exceeded&#10;C:\wwwroot\&amp;lt;站点目录&amp;gt;\diy\system\libraries\Session\drivers\Session_files_driver.php 380&#10;----&amp;gt; http://&amp;lt;域名&amp;gt;/index.php/xin/2023-11-05 14:37:57/ben/amp/a/xxxxxxx.ppt&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;报错行号 375/380/387 全落在 &lt;code&gt;Session_files_driver.php&lt;/code&gt; 的 &lt;code&gt;gc()&lt;/code&gt; 里——遍历整个 session 目录逐文件 &lt;code&gt;filemtime&lt;/code&gt;+&lt;code&gt;unlink&lt;/code&gt; 的循环。&lt;strong&gt;请求卡在&amp;quot;清扫 session 目录&amp;quot;上整整 60 秒，被入口文件的 &lt;code&gt;set_time_limit(60)&lt;/code&gt; 强杀&lt;/strong&gt;。一天 200 次即 200 分钟被记录在案的卡死，且凌晨也在持续（机器人不睡觉）。&lt;/p&gt;&#10;&lt;p&gt;session 目录为什么这么大，三个条件叠加：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;POSCMS 基础控制器对&lt;strong&gt;每个请求&lt;/strong&gt;无条件 &lt;code&gt;$this-&amp;gt;load-&amp;gt;library('session')&lt;/code&gt;；&lt;/li&gt;&#10;&lt;li&gt;文件驱动写入 &lt;code&gt;cache/session/&lt;/code&gt;；&lt;/li&gt;&#10;&lt;li&gt;机器人不带 cookie，CI3 对新访客必定写一个 session 文件（文件名 = cookie 名 + 会话 ID），只能等 GC 删。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;目录膨胀到数万文件后，PHP 默认约 1% 的请求触发 GC 全目录扫描，Windows/NTFS 上逐文件操作极慢（再叠杀软更甚）。这里有个 Windows 特有的坑：&lt;strong&gt;&lt;code&gt;max_execution_time&lt;/code&gt; 在 Windows 下算墙钟时间（含 IO 等待）&lt;/strong&gt;，所以这种 IO 型卡死在 Linux 上往往不触发超时，在 Windows 上必然 60 秒被杀。&lt;/p&gt;&#10;&lt;p&gt;请求侧还有一个细节：日志里被卡死的全是 &lt;code&gt;/index.php/xxx.ppt&lt;/code&gt; 这类扫描 URL，而 POSCMS 的伪静态解析把 &lt;code&gt;index.php&lt;/code&gt; 开头的 URI 一律置空——&lt;strong&gt;这类请求全部被当首页处理&lt;/strong&gt;，每个垃圾 URL 都完整跑一遍 CMS + MySQL + session，程序没有廉价的 404 出口。&lt;/p&gt;&#10;&lt;p&gt;连锁反应随之而来：并发 php-cgi 滚起来后 MySQL 连接被拒（日志成串的&amp;quot;由于目标计算机积极拒绝&amp;quot;），其他请求又在等连接超时，进程进一步堆住。&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;机器人 7×24 轰炸（无 cookie）&#10; → 每请求完整跑 CMS + 生成一个 session 文件&#10; → 目录膨胀到数万文件&#10; → 1% 请求触发 GC 全目录扫描，60 秒被强杀&#10; → 每个 GC 请求钉住一个 php-cgi 一分钟，新请求还在涌入&#10; → IIS 不停拉新进程，进程数暴涨，MySQL 被拖垮&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="修复方案"&gt;修复方案&#10;&lt;/h2&gt;&lt;h3 id="方案一治本改三处代码无-session-cookie-的请求不启动-session"&gt;方案一（治本，改三处代码）：无 session cookie 的请求不启动 session&#10;&lt;/h3&gt;&lt;p&gt;机器人永远不携带 session cookie，真人在第一次 POST/登录/验证码后就会带上。改前需把代码里所有 session 使用点过一遍，本例只需动三处。下表行号为本站代码的&lt;strong&gt;原始行号&lt;/strong&gt;，套到其他 POSCMS 站时若版本有偏移，按&amp;quot;定位方法&amp;quot;列搜索即可：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;#&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;文件&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;位置&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;定位方法&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;①&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;diy/poscms/core/Common.php&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;第 126 行&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;搜索 &lt;code&gt;library('session')&lt;/code&gt;（全文件唯一一处）&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;②&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;diy/poscms/model/Attachment.php&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;第 18 行（&lt;code&gt;__construct()&lt;/code&gt; 内）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;搜索 &lt;code&gt;userdata('siteid')&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;③&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;diy/poscms/model/Member.php&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;第 1113 行之后（&lt;code&gt;member_uid()&lt;/code&gt; 内）&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;搜索 &lt;code&gt;function member_uid&lt;/code&gt;，找到 &lt;code&gt;if (!$uid) { return NULL; }&lt;/code&gt; 的闭合 &lt;code&gt;}&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;&lt;strong&gt;① Common.php 第 126 行&lt;/strong&gt;（基础控制器构造函数内，&lt;code&gt;define('SYS_ADMIN_PAGESIZE', ...)&lt;/code&gt; 下方）：把 &lt;code&gt;$this-&amp;gt;load-&amp;gt;library('session');&lt;/code&gt; 这一行替换为：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IS_POST&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;IS_ADMIN&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;IS_MEMBER&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_COOKIE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;config_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sess_cookie_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;captcha&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;// 验证码图片&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;m&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;aslogin&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;// 后台免登录握手&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;auth_code&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// 移动端api授权&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;session&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意 &lt;code&gt;IS_MEMBER&lt;/code&gt; 在 Init/Rewrite 阶段&lt;strong&gt;恒有定义&lt;/strong&gt;（非会员为 &lt;code&gt;FALSE&lt;/code&gt;），判断要用常量值而非 &lt;code&gt;defined('IS_MEMBER')&lt;/code&gt;（后者恒真）。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;② Attachment.php 第 18 行&lt;/strong&gt;（附件模型构造函数，全站唯一无条件下读 session 的点，而附件模型每个内容页都会实例化）：把&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;siteid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;userdata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;siteid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;替换为（紧随其后的 &lt;code&gt;SITE_ID&lt;/code&gt; 兜底行保持不变）：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;siteid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;is_loaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;session&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;userdata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;siteid&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;③ Member.php 第 1113 行之后&lt;/strong&gt;（&lt;code&gt;member_uid()&lt;/code&gt; 方法内）：处理&amp;quot;记住登录&amp;quot;用户 session 过期（2 小时）后回访的边界情况。在该方法里 &lt;code&gt;if (!$uid) { return NULL; }&lt;/code&gt; 的闭合 &lt;code&gt;}&lt;/code&gt; 与 &lt;code&gt;if (!$this-&amp;gt;session-&amp;gt;userdata('uid'))&lt;/code&gt; 之间插入一行：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-php" data-lang="php"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;is_loaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;session&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;session&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其余调用点天然安全：无 cookie 机器人走不到 session 读取就提前返回；评论防灌水等都是 POST；OAuth 回调在会员域被 &lt;code&gt;IS_MEMBER&lt;/code&gt; 覆盖。上线后用无痕窗口回归：前台页面不再新增 &lt;code&gt;sess&lt;/code&gt; 文件，登录/验证码/评论/后台正常。&lt;/p&gt;&#10;&lt;h3 id="方案二治流量iis-层把机器人挡在-php-之前"&gt;方案二（治流量）：IIS 层把机器人挡在 PHP 之前&#10;&lt;/h3&gt;&lt;p&gt;利用&amp;quot;&lt;code&gt;/index.php/*&lt;/code&gt; 被当首页处理、对站点毫无价值&amp;quot;这一事实，URL Rewrite 整段 404（正常链接是 &lt;code&gt;/index.php?c=xx&lt;/code&gt; 格式，不受影响），加在站点 &lt;code&gt;web.config&lt;/code&gt; 的 &lt;code&gt;&amp;lt;rewrite&amp;gt;&lt;/code&gt; 节点内：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;rule&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;blockPathInfoJunk&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;stopProcessing=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;match&lt;/span&gt; &lt;span class="na"&gt;url=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;^index\.php/.+&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;ignoreCase=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;CustomResponse&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;statusCode=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;404&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;statusReason=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Not Found&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/rule&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再开 IIS 自带的动态 IP 限制，把高频扫描源直接封掉。先执行两条前置命令（装角色服务 + 解锁站点级配置，不解锁的话 web.config 会报 500.19）：&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;Install-WindowsFeature Web-IP-Security&#10;%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/security/dynamicIpSecurity&#10;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然后在同一个 &lt;code&gt;web.config&lt;/code&gt; 的 &lt;code&gt;&amp;lt;system.webServer&amp;gt;&lt;/code&gt; 内、与 &lt;code&gt;&amp;lt;rewrite&amp;gt;&lt;/code&gt; 并列加上：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;security&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;&amp;lt;!-- 单IP并发超过10个请求、或1秒内超过30个请求即拒绝 --&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;dynamicIpSecurity&lt;/span&gt; &lt;span class="na"&gt;denyByConcurrentRequests=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;10&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;denyByRequestRate=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;30&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;requestRateInInterval=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1000&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;denyAction=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Forbidden&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;enableProxyMode=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;false&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/dynamicIpSecurity&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/security&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;套了 CDN/反代的站必须把 &lt;code&gt;enableProxyMode&lt;/code&gt; 改为 &lt;code&gt;true&lt;/code&gt; 并放宽阈值&lt;/strong&gt;，否则所有访客都记在代理 IP 一个头上，会把代理整个封掉。&lt;/p&gt;&#10;&lt;p&gt;宝塔 Windows 面板用户：面板只是壳，底层仍是 IIS，最终都落到站点根目录 &lt;code&gt;web.config&lt;/code&gt;——URL 重写用&amp;quot;网站 → 设置 → URL重写&amp;quot;或文件管理直接编辑（先备份）；动态 IP 限制按上面命令操作；session 定时清理用面板的 计划任务跑 &lt;code&gt;forfiles&lt;/code&gt; 删一天前的旧文件（注意 CI3 文件前缀是 cookie 名如 &lt;code&gt;poscms_ci_session*&lt;/code&gt;，不是 &lt;code&gt;sess_*&lt;/code&gt;）。&lt;/p&gt;&#10;&lt;h3 id="配套参数phpini"&gt;配套参数（php.ini）&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;session.gc_probability = 0&lt;/code&gt; 禁用请求时 GC（靠计划任务清理），这是消灭 60 秒卡死最见效的一条。另外建议入口文件里 &lt;code&gt;memory_limit&lt;/code&gt; 从 1024M 降到 256M、&lt;code&gt;set_time_limit&lt;/code&gt; 从 60 降到 30。&lt;/p&gt;&#10;&lt;h2 id="验证清单"&gt;验证清单&#10;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;/index.php/anything&lt;/code&gt; 返回 404；站点日志出现 403.501/403.502（IP 限制生效）；php-cgi.exe 数量回落；&lt;code&gt;cache/session/&lt;/code&gt; 不再增长；错误日志里 Session 超时基本消失；前台/登录/后台回归正常。&lt;/p&gt;&#10;&lt;h2 id="复盘要点"&gt;复盘要点&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;多 php-cgi 进程 ≠ 程序在起进程&lt;/strong&gt;。进程数暴涨几乎总是&amp;quot;请求变慢 + 流量不退&amp;quot;，要找的是什么把请求拖住了；&lt;/li&gt;&#10;&lt;li&gt;&amp;ldquo;每请求无条件 session + 文件驱动&amp;quot;在 Windows 上有放大效应：墙钟超时 + NTFS 小文件遍历慢 + 杀软，GC 慢到荒谬且每次钉死一个 FastCGI 进程一分钟；&lt;/li&gt;&#10;&lt;li&gt;排查这类问题，错误日志里致命错误的&lt;strong&gt;文件名 + 行号&lt;/strong&gt;比通读代码快得多；&lt;/li&gt;&#10;&lt;li&gt;无 cookie 访客跳过 session 是普适模式：机器人在入口就被识别，真人首次需要 session 时才创建；&lt;/li&gt;&#10;&lt;li&gt;挡扫描流量优先在 Web 服务器层静态拒绝，让恶意请求的成本从&amp;quot;完整跑一遍 PHP + MySQL&amp;quot;降到一次内核态 404。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>服务器数据盘扩容：growpart + resize2fs 热操作</title><link>https://lanlan.work/posts/technology/server-disk-expand/</link><pubDate>Tue, 25 Aug 2026 20:00:00 +0800</pubDate><guid>https://lanlan.work/posts/technology/server-disk-expand/</guid><description>&lt;h2 id="任务"&gt;任务&#10;&lt;/h2&gt;&lt;p&gt;老张的服务器（宝塔面板，Aliyun ECS）数据盘从 20G 扩到 100G，让面板识别新容量。&lt;/p&gt;&#10;&lt;h2 id="现状操作前"&gt;现状（操作前）&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;系统盘 /dev/vda1：ext4 100G（已满，不动）&lt;/li&gt;&#10;&lt;li&gt;数据盘 /dev/vdb1：ext4 20G，挂在 /www，已用 17G（92%）&lt;/li&gt;&#10;&lt;li&gt;vdb 整盘已扩到 100G，但分区表 vdb1 还是 20G，文件系统也只认 20G&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="操作步骤实际成功路径"&gt;操作步骤（实际成功路径）&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;growpart /dev/vdb 1&lt;/code&gt; → 扩分区表&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;resize2fs /dev/vdb1&lt;/code&gt; → 扩文件系统&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;df -hT /www&lt;/code&gt; → 验证&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="跳过项"&gt;跳过项&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;没有走 &lt;code&gt;echo 1 &amp;gt; /sys/class/scsi_disk/.../rescan&lt;/code&gt; 重扫——因为 &lt;code&gt;lsblk&lt;/code&gt; 已经看到 vdb 是 100G，内核已认到新容量，分区表没跟上而已。&lt;/li&gt;&#10;&lt;li&gt;virtio 通道的 ECS 走 &lt;code&gt;/sys/block/vdb/device/rescan&lt;/code&gt;，不是 scsi_disk 路径。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="注意事项"&gt;注意事项&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;宝塔面板&lt;strong&gt;不用动&lt;/strong&gt;，磁盘监控和文件管理自动刷新。&lt;/li&gt;&#10;&lt;li&gt;growpart + resize2fs 都是热操作，不用卸载 /www，ext4 在线扩安全。&lt;/li&gt;&#10;&lt;li&gt;操作前在阿里云控制台做一次快照更稳。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>窗台的试卷——写给儿子的一首歌</title><link>https://lanlan.work/posts/daily/a-song-for-my-son/</link><pubDate>Fri, 24 Jul 2026 12:00:00 +0800</pubDate><guid>https://lanlan.work/posts/daily/a-song-for-my-son/</guid><description>&lt;p&gt;七月里和儿子起了一场冲突，情绪落定之后，写了这首《窗台的试卷》。&lt;/p&gt;&#10;&lt;h2 id="发行版歌词"&gt;发行版歌词&#10;&lt;/h2&gt;&lt;p&gt;阳台堆满了试卷&lt;br&gt;&#10;奈何我见他不见&lt;br&gt;&#10;滴答滴答&lt;br&gt;&#10;盛夏被切成了碎片&lt;/p&gt;&#10;&lt;p&gt;任务计划都在线&lt;br&gt;&#10;他一心要把平板见&lt;br&gt;&#10;我好心把他来劝&lt;br&gt;&#10;忧伤 不满 立刻现&lt;/p&gt;&#10;&lt;p&gt;他哭着 嚎嚎嚎&lt;br&gt;&#10;我怒火 烧烧烧&lt;br&gt;&#10;他跟我 哇哇叫&lt;br&gt;&#10;我气的 脑仁跳&lt;/p&gt;&#10;&lt;p&gt;情绪决堤&lt;br&gt;&#10;收不了&lt;br&gt;&#10;收不了&lt;/p&gt;&#10;&lt;p&gt;椅子掀翻试卷抛&lt;br&gt;&#10;散落一地各自逃&lt;br&gt;&#10;房门一关两不相见才是最好&lt;br&gt;&#10;这个夏天我的心儿碎了碎了&lt;/p&gt;&#10;&lt;p&gt;躺在沙发思绪飘&lt;br&gt;&#10;担心未来他不好&lt;br&gt;&#10;可我事业未寻到&lt;br&gt;&#10;正值中年最难熬&lt;/p&gt;&#10;&lt;p&gt;罢了罢了&lt;br&gt;&#10;认了认了&lt;/p&gt;&#10;&lt;p&gt;该来的躲不掉&lt;br&gt;&#10;该好的希望他更好&lt;/p&gt;&#10;&lt;h2 id="灵感描述"&gt;灵感描述&#10;&lt;/h2&gt;&lt;p&gt;以钢琴作为核心主伴奏乐器，表达出一位父亲和儿子之间的激烈情绪冲突和父亲的咆哮行为，到黯然离开房间，到惆怅的思绪和自己和解。&lt;/p&gt;&#10;&lt;h2 id="ai-写歌提示词"&gt;AI 写歌提示词&#10;&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;以厚重带颗粒感的原声钢琴作为核心主伴奏乐器，开篇用急促密集的低音区重键敲击，搭配短促尖锐的高音跳音，烘托父子之间激烈的情绪冲突，穿插粗粝的低音和弦重击模拟充满张力的咆哮感；随后节奏逐步放缓，琴键触键力度变轻，低音区旋律带着断续的颤音，对应转身离开房间的落寞；后续转为舒缓平缓的分解和弦流动，高音区铺展柔和长音，传递怅然思绪，最终以轻柔的低音单音收尾，完成与自我和解的松弛氛围。整体BPM为70-90，动态范围跨度大，从强冲击感逐步过渡到温和松弛，混响轻微带室内空间感。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="发行平台"&gt;发行平台&#10;&lt;/h2&gt;&lt;p&gt;汽水音乐&lt;/p&gt;&#10;</description></item><item><title>稀里糊涂入行，兜兜转转回归——一个老程序员的自白</title><link>https://lanlan.work/posts/essays/my-it-journey/</link><pubDate>Sat, 18 Jul 2026 12:00:00 +0800</pubDate><guid>https://lanlan.work/posts/essays/my-it-journey/</guid><description>&lt;p&gt;新网站上线，想了很多可能性，最后决定这第一篇不成文的文章，先写写自己吧。&lt;/p&gt;&#10;&lt;h2 id="一稀里糊涂地入行"&gt;一、稀里糊涂地入行&#10;&lt;/h2&gt;&lt;p&gt;高中毕业那会儿，考得不咋地。爹妈问我怎么打算？地道的农村人，既不聪明又没见过什么世面，哪知道往哪走。只是记得那会儿家里电视上，新东方烹饪、美容美发的广告铺天盖地。于是，他们从电视广告里给我提供了一些选项：汽修、电脑、美发、烹饪。他们比较倾向汽修，那会儿私家车越来越多，觉得前景不是问题。但我毫不犹豫地选择了电脑——单纯觉得会打电脑的人比较厉害，而且以后工作环境应该会比较干净（主观认为我是个重度的强迫症和洁癖患者）。就这样走进了合肥电脑学院的大门，一学就是2年。于是，我的大专学历和电脑技能（学的皮毛）就到手了。也算是一只脚踏入了软件行业。&lt;/p&gt;&#10;&lt;h2 id="二财富自由的东方"&gt;二、财富自由的东方&#10;&lt;/h2&gt;&lt;p&gt;毕业要去实习，学校也给了几个城市坐标：上海、杭州、合肥（留在本地），还有其他几个城市，时间太久了记不清了。跟着朋友们就一起去了杭州。这里为什么说&amp;quot;财富自由的东方&amp;quot;呢？是因为也有点相信玄学，说我往这个方向容易发财。我秉着“要信早信”的理念，先做个知行合一再说。&lt;/p&gt;&#10;&lt;h2 id="三千里相会的贵人"&gt;三、千里相会的贵人&#10;&lt;/h2&gt;&lt;p&gt;在骄阳似火的夏天到了杭州。学校安排的实习单位，现场让做一张电子商务的海报，虽然也学了点，但让一个开发的人做设计的活，那 PS 根本玩不转。后来还去应聘电脑维修学员，老板生意做得看起来不错，给我开出 800 元/月的薪资。一个不要我，一个我不要。眼看没希望了，接到一个应聘公司 HR 叫我过去面试。我提前 1 小时坐公交车晃到他们公司，公司 400 平，一切看起来都非常新。大概聊了 10 分钟左右吧，就让我第二天去上班——可我连老板或是部门负责人都没见到。但不重要了，当天晚上奖励自己一顿，也算是为找了半个月的工作画上个句号。后来老板也确实对我挺好的，是我第一个贵人。&lt;/p&gt;&#10;&lt;h2 id="四铺满荆棘的软路"&gt;四、铺满荆棘的软路&#10;&lt;/h2&gt;&lt;p&gt;在公司安顿下来之后，技术部实际上就我一个人。后来陆续来了新的成员，硬是把三脚猫功夫的我推上部门负责人宝座。可原本内向型的我，面对自身技术烂、带不好团队、应付不了客户等场面，一度非常崩溃。也就这样深一脚浅一脚地走在软件开发的路上。后来和一些朋友聊天才发现，大多数人都没从事所学的专业。我们常说专业要对口，但好像只有我还坚守在这个专业上，不知道是对是错，但我当时好像没有什么更好的选择。在这条软件路上，我遇到第二位贵人。&lt;/p&gt;&#10;&lt;h2 id="五双城生活之创业"&gt;五、双城生活之创业&#10;&lt;/h2&gt;&lt;p&gt;在入行 7 年之后，跟着我人生中第二位贵人，开启了创业之路，也同时开启了为期 6 年的双城生活。我们从 5 人团队做到 30 多人团队，再做到 10 人团队。从企业应用定制做到三维数据可视化，再做到政府数字化系统软件建设。这 6 年里跌宕起伏，行业发展、时代变迁、客户群体变化等等，也算是见了大风大浪了。创业真的是九死一生，也深刻地感受到：这个世界唯一不变的就是一切都在不停地变化。身处这个变化中，你只能让自己以更快的速度去适应。&lt;/p&gt;&#10;&lt;h2 id="六深思熟虑的回归"&gt;六、深思熟虑的回归&#10;&lt;/h2&gt;&lt;p&gt;随着年龄增长，职业瓶颈也渐渐凸显。另外，长期不着家，家庭成员角色的缺失，让我陷入一种极度没有归属感的环境里。家顾不上，孩子管不了，爱人不能陪，收入缩水且每周往返让我疲惫不堪。在纠结 2 个月后，我还是选择了辞职回归家庭。也想过回来不知道做什么，也可能很长时间没有收入，但现实是——到那一步的时候，我觉得我不能在犹豫中浪费时间，我该回去了。&lt;/p&gt;&#10;&lt;h2 id="写在最后"&gt;写在最后&#10;&lt;/h2&gt;&lt;p&gt;如今，我回来已经一年了。虽然有时候会觉得，处于当前这样的经济时期，应该慎重考虑辞职一事。但人生之路的选择，谁又能保证每一次都是对的。这一年里，对自己这些年的表现也深刻地做了反省和总结。有可圈可点的，也有蠢到让人想哭的。不过，都翻篇了。&lt;/p&gt;&#10;&lt;p&gt;现在在昆山，陪陪家人，做做饭，看看书，学习 AI 技能。偶尔做一些老客户的项目，最近也在做一些自己的小软件。收入不多，但胜在内心平静。&lt;/p&gt;&#10;&lt;p&gt;如果你也在昆山，需要网站建设、小程序开发，软件定制服务或者就是想聊聊软件定制那些事，可以找我。&lt;/p&gt;&#10;&lt;p&gt;15 年的经验不敢说多厉害，但至少知道哪里容易踩坑。&lt;/p&gt;&#10;&lt;p&gt;这次，也希望我自己的网站和应用能落地生根，让那条曾经铺满荆棘的“软件之路”变得软软的，以“懒洋洋”的姿态，欣赏这世界。&lt;/p&gt;&#10;</description></item></channel></rss>