Logo

site iconJustYY | 小赖子

小赖子的英国生活和资讯,以及投资和个人生活。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

JustYY | 小赖子 RSS 预览

WordPress安全加固: 禁止在 wp-content/uploads 目录中执行PHP

2026-08-13 22:02:20

WordPress的上传目录必须允许写入媒体文件,却没有执行PHP代码的必要。本文介绍如何通过Apache全局配置禁止在`wp-content/uploads`中访问和执行PHP类文件,并使用`.htaccess`作为第二层保护,同时分析两种方式的优缺点、`Options -ExecCGI`的作用及配置验证方法。这项加固不能代替漏洞修复和及时更新,但可以切断恶意文件上传后被执行为Web Shell的常见攻击路径。
我目前维护着8个WordPress博客,从服务器配置、系统升级到日常备份和安全防护,基本上都是自己动手完成。这几年也遇到过几次规模不大的安全事件,好在发现和处理得比较及时,目前并没有造成太严重的损失。 每一次事故后的排查、复盘和总结,都是一次很好的学习和提升机会,也让我逐渐意识到:服务器安全没有真正意义上的“一劳永逸”,更不能因为系统已经稳定运行多年就放松警惕。及时更新WordPress及插件、妥善管理密钥、收紧文件权限、检查日志和备份,以及禁止在上传目录中执行PHP,这些看似琐碎的措施,往往能够在关键时刻阻断攻击链。安全本质上是一项需要长期坚持、不断完善的工作。

WordPress安全加固: 禁止在 wp-content/uploads 目录中执行PHP

正常情况下,WordPress需要向wp-content/uploads目录写入图片、视频等媒体文件。这种设计虽然方便,却也形成了一个非常重要的安全边界:这个目录必须允许Web应用写入,但保存在其中的文件绝对没有执行PHP代码的必要。 如果某个存在漏洞的插件、主题或自定义上传接口允许攻击者把PHP文件写入上传目录,攻击者接下来就可能尝试通过浏览器直接访问这个文件。一旦Apache把它交给PHP解释器执行,一个普通的文件上传漏洞就可能升级为远程代码执行,甚至变成一个以Web服务器用户权限运行的Web Shell。 禁止在uploads目录中执行PHP并不能修复最初的漏洞,但它可以切断这条常见的攻击链。这是一项成本低、影响小的纵深防御措施,应该和及时更新WordPress、限制文件权限、检查日志、验证备份等措施一起使用。WordPress官方的安全加固指南同样强调,安全依赖多层防护,而不是某一个单独的设置。

方法一:使用Apache全局配置

我的服务器在/var/www目录下运行着多个WordPress网站,因此我创建了下面这个Apache配置文件:
/etc/apache2/conf-available/wordpress-uploads-no-php.conf
配置内容如下:
<DirectoryMatch "^/var/www/(?:[^/]+/)*wp-content/uploads(?:/|$)">
    <FilesMatch "(?i)\.(?:php[0-9]*|phtml|phar)$">
        Require all denied
    </FilesMatch>
</DirectoryMatch>
外层的DirectoryMatch把规则限定在/var/www下面的WordPress上传目录中。它也会覆盖uploads下面常见的年份和月份子目录。 内层的FilesMatch会以不区分大小写的方式检查文件名,并拒绝通过HTTP直接访问以下扩展名的文件:
  • .php
  • .php5.php7.php8以及其他带数字后缀的PHP扩展名
  • .phtml
  • .phar
真正起到拒绝访问作用的是Require all denied:任何匹配的文件都不能通过Apache直接访问。Apache官方文档也介绍了如何使用DirectoryMatchFilesMatchRequire all denied对文件系统中的内容进行访问控制。 启用并检查配置:
a2enconf wordpress-uploads-no-php
apache2ctl configtest
systemctl reload apache2
不要跳过configtest。Apache应该输出:
Syntax OK

是否还需要加入Options -ExecCGI

可以把它作为额外的防护措施:
<DirectoryMatch "^/var/www/(?:[^/]+/)*wp-content/uploads(?:/|$)">
    Options -ExecCGI

    <FilesMatch "(?i)\.(?:php[0-9]*|phtml|phar)$">
        Require all denied
    </FilesMatch>
</DirectoryMatch>
Options -ExecCGI禁止Apache通过CGI机制执行该目录里的程序。但它本身并不能禁用PHP-FPM、mod_php或其他所有可能的处理器。因此,这是一项附加加固措施,不能代替FilesMatch中的拒绝访问规则。 Apache的CGI文档说明,ExecCGI正是用于允许目录执行CGI程序的选项

方法二:使用.htaccess作为第二层保险

我还在每个网站的wp-content/uploads/.htaccess中加入了下面的内容:
<FilesMatch "(?i)\.(?:php[0-9]*|phtml|phar)(?:\.|$)">
    Require all denied
</FilesMatch>
这里不需要再写DirectoryMatch,因为.htaccess中的规则会自动应用于它所在的目录以及下面的所有子目录。 Apache会在处理请求时读取.htaccess文件,而服务器的AllowOverride设置决定了其中允许使用哪些指令。Apache的配置文件文档对此有更详细的说明。 这个表达式比前面的规则更加严格,还会拒绝下面这类可疑的双扩展名:
shell.php.jpg
backdoor.phtml.png
payload.phar.gif
在PHP处理器配置正确的情况下,.php.jpg本来不应该被当作PHP执行。但上传目录没有合理的理由保存带有可执行扩展名的文件,因此直接拒绝这类文件更加稳妥。它的代价是,即使这个文件实际上是一张图片,只要文件名包含这些可疑扩展名,同样会被拒绝访问。 如果添加这个.htaccess后网站返回500 Internal Server Error,可以检查Apache错误日志:
tail -n 50 /var/log/apache2/error.log
出现500通常意味着当前目录对应的AllowOverrideAllowOverrideList设置不允许使用这项指令。 不要仅仅为了让这个安全规则生效,就把服务器改成AllowOverride All。如果自己拥有服务器管理权限,应该优先使用Apache全局配置。

Apache全局配置和.htaccess的优缺点

方式 优点 缺点
Apache全局配置 一条规则可以保护所有网站;由root用户控制;不依赖AllowOverride;被入侵的WordPress进程通常无法修改;配置更集中,性能也更好 需要服务器管理权限;修改后必须检查配置并重新加载Apache;路径表达式必须和服务器上的实际目录结构匹配
上传目录中的.htaccess 可以按网站部署;适合共享主机;不需要重新加载Apache就能生效;可以作为全局规则之外的第二层保险 只有允许覆盖配置时才会生效;每个网站都要单独维护;Apache需要在请求过程中检查相关文件;如果应用拥有目录写权限,攻击者可能删除或篡改它
Apache指出,启用覆盖配置后,它可能沿着请求对应的文件系统路径逐级查找.htaccess文件。因此,在自己能够控制服务器的情况下,使用全局配置在性能上也更加合理。 所以,我把服务器级别的规则作为真正的安全边界,而把.htaccess当作第二层保险。

不要假设配置有效,一定要实际测试

可以在其中一个网站的上传目录中临时创建一个测试文件:
printf '%s\n' '<?php echo "SHOULD-NOT-EXECUTE";' \
  > /var/www/example.com/wp-content/uploads/security-test.php
然后访问它:
curl -i https://example.com/wp-content/uploads/security-test.php
预期返回结果是:
403 Forbidden
最重要的是,响应中绝对不能出现SHOULD-NOT-EXECUTE。 同时还应该检查同一目录中已有的JPEG或PNG图片是否仍然能够正常访问:
curl -I https://example.com/wp-content/uploads/path/to/existing-image.jpg
测试完成后立即删除临时文件:
rm /var/www/example.com/wp-content/uploads/security-test.php
以后如果修改了Apache、PHP-FPM或虚拟主机的重要配置,也应该重新执行这项测试。没有经过验证的安全设置只是一种假设,还不能算是真正有效的安全控制。

这项防护不能解决什么问题?

这项措施的目的非常明确,也有清晰的能力边界。它不能:
  • 修复WordPress、主题或插件中的漏洞;
  • 阻止存在漏洞的应用把恶意文件写入服务器;
  • 阻止已经通过其他PHP文件运行的恶意代码;
  • 阻止插件通过PHP的includerequire在服务器内部加载恶意文件;
  • 代替恶意软件扫描、日志检查、备份和合理的文件系统权限。
它能做的是,禁止通过Web直接访问上传目录中带有危险扩展名的文件。对于最基本的上传型Web Shell,这可能已经足以阻止其运行;但如果网站曾经遭到入侵,仅凭这个设置绝不能证明服务器已经安全或已经清理干净。

最终建议

如果自己管理Apache服务器,应该把全局配置作为主要防护措施。如果上传目录确实没有运行CGI程序的合法需求,还可以加入Options -ExecCGI作为额外的纵深防御。 只有在服务器原本就允许使用覆盖配置的情况下,才建议保留.htaccess作为附加保护。不要为了支持这份.htaccess而放宽服务器的整体安全配置。 最重要的是,仍然要及时更新WordPress核心、主题和插件。禁止在uploads目录执行PHP可以降低某一条攻击路径造成的影响,却不能修复最初允许攻击者上传文件的漏洞。 [show_file file=""] [show_posts keyword="wordpress"] 英文:Hardening Wordpress: Disable PHP Execution in wp-content/uploads/

他们看到的是景点, 我看到的是童年

2026-08-12 23:45:27

2024年4月,我带着媳妇孩子短暂回到厦门,也重返自己生活到高考前的故乡鼓浪屿。小时候宽阔悠长的街道,如今显得狭窄拥挤;熟悉的海边音乐、龙头路小吃,以及攒零花钱买海蛎煎的记忆,却依然清晰。多年后带着在英国长大的孩子故地重游,我才发现:变小的或许不是鼓浪屿,而是童年的世界;真正回不去的,也不是故乡,而是那个尚未离开故乡的自己。 《多年以后,我带着老婆孩子回到鼓浪屿》 《鼓浪屿还是那座岛,我却不再是当年的少年》 《回到鼓浪屿,寻找那个没有离开故乡的自己》 《他们看到的是景点,我看到的是童年》 《鼓浪屿:故乡依旧,童年已远》 《小时候很宽的路,长大后怎么变窄了》 《从一份海蛎煎,到带着妻儿重回故乡》 《再回鼓浪屿:街道变窄了,时间也变快了》 《记忆里的鼓浪屿,再也回不去了》 《长大后再回鼓浪屿,才读懂什么叫故乡》
[caption id="attachment_72251" align="alignnone" width="550"]01 01[/caption]

不是鼓浪屿的街道变小了,而是我们长大了

前几天翻到两年前在鼓浪屿拍的照片,我随手发了一句:小时候觉得鼓浪屿的街道又宽又大,长大后再回来,却觉得有些狭窄和拥挤。也许不是街道变小了,而是我们长大了。 朋友看到后问我:“赖博士回国了?” 我说:“上次。” 这个“上次”,已经是2024年4月。那一次,我带着媳妇和孩子短暂回国,去了北京、厦门和福州。整个行程很赶,在厦门也只待了三四天,但无论时间多紧,鼓浪屿总是要回去看一看的。 因为那里不只是一处旅游景点,也是我真正意义上的故乡——高考以前,我人生中绝大多数的时光都生活在这片土地上。

小时候很宽的路,如今怎么变窄了

小时候,我总觉得鼓浪屿的路很宽、很长,仿佛怎么走也走不完。一个孩子的世界本来就很小,所以家门口的一条街、一段斜坡和一个转角,都可以大得像整个世界。 长大以后,每次再回去,我却总有一种奇怪的感觉:自己好像变得很大,而街道变得很小。 小时候觉得遥远的地方,如今走不了多久就到了;记忆里宽敞的道路,现在看起来窄窄的,两边挤满了游客、店铺和各式各样的招牌。 鼓浪屿似乎还是那个鼓浪屿,却又早已不是我小时候的鼓浪屿了。 这些年,岛上的旅游商业化越来越浓。尤其是龙头路一带,各种小吃店、伴手礼店和网红店一家挨着一家,有些地方甚至显得拥挤而脏乱。过去那些带着生活气息的小店,许多已经不见了;即使卖的还是相似的小吃,吃进嘴里,也很难再找到小时候的味道。 当然,也可能并不全是食物变了。人的记忆本来就会给童年加上一层滤镜。真正回不去的,也许不是当年的味道,而是当年那个只需要攥着一点零花钱,就能获得巨大满足的自己。 [caption id="attachment_72252" align="alignnone" width="550"]02 02[/caption]

整座岛曾经有自己的背景音乐

我一直记得,小时候沿着海边的马路走,每隔二三十米,路旁便藏着一个小喇叭。 那些喇叭里会播放钢琴曲和熟悉的旋律,有《鼓浪屿之波》,也有后来韦唯演唱的《鼓浪屿》。海风、浪声和音乐混在一起,构成了我对故乡最深的声音记忆。 那时候没有耳机,也没有手机里的播放列表,但整座岛仿佛有自己的背景音乐。走到哪里,旋律就跟到哪里。 多年以后,在别的地方偶然听到这些歌,我还是会在一瞬间想起鼓浪屿的海、弯弯曲曲的街道,以及那个在岛上慢慢长大的自己。

那份攒起来买海蛎煎的零花钱

小时候,我很喜欢吃鼓浪屿街边的海蛎煎。 有一次,我拿着平时一点点攒下来的零花钱去买,小摊老板看我把钱掏出来,还笑着打趣我: “这么小就知道存钱,是要留着以后娶老婆啊?” 那时候的我,大概只觉得好笑,根本不会想到“娶老婆”是多么遥远的事情。我只关心手里的钱够不够买一份海蛎煎,也只想着赶紧趁热吃掉。 几十年后,我真的带着老婆和孩子回到了这里。 当年那个攥着零花钱买海蛎煎的小男孩,如今已经有了自己的家庭。只是当我再站在同样的街道上时,小时候熟悉的摊贩早已不知去了哪里,当年的味道也只能到记忆里寻找。 [caption id="attachment_72253" align="alignnone" width="550"]03 03[/caption]

他们看到的是景点,我看到的是从前

孩子们属于Z世代,又是在英国土生土长。对他们来说,鼓浪屿可能只是一座游客很多、街道很窄、需要走很多路的小岛。 他们很难理解,为什么爸爸会对一条普通的街道、一首老歌,甚至一份小吃有那么多感触。 这也很正常。 他们看到的是眼前的鼓浪屿,而我看到的,是一层又一层叠在现实之上的从前。 我看到自己小时候走过的路、听过的音乐、吃过的小吃;看到那些已经消失的人和事;也看到一个孩子从这里出发,后来去了很远的地方生活,许多年后又带着自己的家人回来。 孩子们未必能够真正理解我的乡愁,就像小时候的我,也不会理解父辈为什么总爱回忆他们的过去。 但也许有一天,当他们长大,离开自己熟悉的地方,再带着下一代回去时,也会突然明白这种感觉。 故乡从来不只是地图上的一个地点,它更像是我们童年的比例尺。 小时候,街道很宽,日子很长,零花钱很少,一份海蛎煎就足以让人开心很久;长大以后,街道变窄了,时间变快了,身边也多了媳妇和孩子。 不是鼓浪屿的街道变小了,而是我们长大了。 而我们真正怀念的,也不只是从前的鼓浪屿,更是那个还没有离开鼓浪屿的自己。 [caption id="attachment_72668" align="alignnone" width="2048"]两年前的兄弟俩,现在已经长大了很多。 两年前的兄弟俩,现在已经长大了很多。[/caption] [caption id="attachment_72672" align="alignnone" width="1366"]要离开家了,老妈和媳妇在吩咐事情。 要离开家了,老妈和媳妇在吩咐事情。[/caption] [caption id="attachment_72671" align="alignnone" width="2048"]媳妇在鼓浪屿留影 媳妇在鼓浪屿留影[/caption] [caption id="attachment_72670" align="alignnone" width="2048"]两娃第一次回厦门,老大一岁的时候在2013年的时候有回,当时老二还在媳妇肚子里。老大在福州的时候学会走路的,老二的第一次真是记不住了。 两娃第一次回厦门,老大一岁的时候在2013年的时候有回,当时老二还在媳妇肚子里。老大在福州的时候学会走路的,老二的第一次真是记不住了。[/caption] [caption id="attachment_72669" align="alignnone" width="1365"]兄弟俩第一次回厦门 兄弟俩第一次回厦门[/caption] [caption id="attachment_72675" align="alignnone" width="2048"]小时候每天走的路,每天上下学都要走这个陡坡。 小时候每天走的路,每天上下学都要走这个陡坡。[/caption] [caption id="attachment_72676" align="alignnone" width="1477"]鼓浪屿晚上只有市中心那块比较有人气,其它地方都有点黑。 鼓浪屿晚上只有市中心那块比较有人气,其它地方都有点黑。[/caption] [caption id="attachment_72677" align="alignnone" width="1477"]夜景上的厦门 夜景上的厦门[/caption] [caption id="attachment_72678" align="alignnone" width="1477"]厦门/鼓浪屿小吃:海蛎煎 厦门/鼓浪屿小吃:海蛎煎[/caption] [caption id="attachment_72679" align="alignnone" width="1477"]小时候:妈妈总说,如果不好好学习就得去拉板车。我现在只是换了个赛道搬砖,不同行业的牛马。 小时候:妈妈总说,如果不好好学习就得去拉板车。我现在只是换了个赛道搬砖,不同行业的牛马。[/caption] [caption id="attachment_72680" align="alignnone" width="1477"]两娃/酒店 两娃/酒店[/caption] [caption id="attachment_72681" align="alignnone" width="1270"]老妈每次都会做好吃的等我们回去。 老妈每次都会做好吃的等我们回去。[/caption] [caption id="attachment_72682" align="alignnone" width="1477"]最爱沙茶面,但是味道可能和小时候的不太一样了。 最爱沙茶面,但是味道可能和小时候的不太一样了。[/caption] [caption id="attachment_72683" align="alignnone" width="714"]家里太小,只能和媳妇孩子到酒店 家里太小,只能和媳妇孩子到酒店[/caption] [caption id="attachment_72684" align="alignnone" width="1280"]鼓浪屿最有名的除了日光岩就是这个郑成功雕像了,面向大海/金门 鼓浪屿最有名的除了日光岩就是这个郑成功雕像了,面向大海/金门[/caption] [show_file file="/var/www/wp-post-common/justyy.com/2024-china.php"] [show_posts keyword="厦门"]

弟弟的生日礼物: 一套”小码农”装备

2026-08-11 22:55:59

弟弟今年的生日礼物是一套颇具“码农气质”的装备:无线鼠标、无线机械键盘和iPad支架。他喜欢Minecraft和科技产品,也跟着我每天刷力扣,不知不觉已经坚持了500多天。孩子喜欢玩是天性,希望他能在玩中发现兴趣,在兴趣中学习和成长,将来慢慢把对科技的好奇变成真正的创造力。
[caption id="attachment_72251" align="alignnone" width="550"]01 01[/caption] [video width="1280" height="720" mp4="https://justyy.com/wp-content/uploads/2026/08/Ryan-try-new-keyboard.mp4"][/video] 今年年初弟弟过生日,我问他想要什么礼物。他没有要玩具,而是自己挑了一只无线鼠标、一把无线机械键盘,还有一个iPad支架。 看到这份礼物清单,我的第一反应是:这不就是一套标准的“码农装备”吗? 现在的小孩懂得越来越多,选东西也越来越有自己的想法。特别是那把机械键盘,手感和做工感觉比我自己用的还好。相比之下,我的鼠标只是Amazon Basics最便宜的那款,突然感觉自己的装备还不如孩子了(笑)。 生日蛋糕当然也是他喜欢的Minecraft主题。弟弟很爱玩Minecraft(我的世界),听说在游戏里玩得还挺厉害。Minecraft本身也是一个很有创造力的游戏,可以搭建筑、做机关、设计各种复杂的东西。有一次他给我展示了他在游戏里搭建一个二进制的计数器,只是我平时并不怎么玩,也对这个游戏不怎么感兴趣,只知道是微软收购来的。 弟弟从去年开始跟着我刷力扣。现在,我每天都会带着他做一道题,不知不觉已经坚持了500多天。一天做一点,看起来并不起眼,但能连续坚持这么久,本身就是一种积累。很多能力并不是靠某一天突然努力获得的,而是在日复一日的练习中慢慢形成的。 [caption id="attachment_72252" align="alignnone" width="550"]02 02[/caption] 他说,长大以后也想像我一样当软件工程师。 不过从目前来看,他的大部分精力还是花在玩游戏和看YouTube视频上。看的内容也大多和游戏、手机、平板电脑以及各种电子产品有关。孩子喜欢玩很正常,我小时候如果有这些东西,大概也会玩得停不下来。 我并不认为玩游戏和看视频就一定是在浪费时间。兴趣往往就是从“玩”开始的。玩Minecraft可以接触创造、设计和简单的逻辑;关注手机、平板和电脑,也说明他对科技产品有自己的好奇心。但“喜欢使用科技产品”和“能够创造科技产品”之间,仍然隔着很长的一段路。 一套机械键盘不会自动把人变成程序员,刷力扣也不是学习编程的全部。真正重要的是,他能不能慢慢学会主动探索、独立思考,并把脑子里的想法做成真正的东西。 孩子将来是否真的会成为软件工程师,其实并不重要。他现在的兴趣以后也可能发生变化。我更希望的是,他能在玩中发现兴趣,在兴趣中学习,再把学习到的东西变成自己的能力。 至于我能做的,就是继续陪他每天刷一道题,在他愿意探索的时候给他一点帮助。也许多年以后再回头看,这把机械键盘、这只鼠标和这个iPad支架,就是他通往技术世界的第一套装备。 [caption id="attachment_72253" align="alignnone" width="550"]03 03[/caption] [caption id="attachment_72648" align="alignnone" width="1920"]每天带娃刷力扣。 每天带娃刷力扣。[/caption] [caption id="attachment_72647" align="alignnone" width="2048"]这键盘还会发光/和Keychron一样。 这键盘还会发光/和Keychron一样。[/caption] [caption id="attachment_72646" align="alignnone" width="2048"]弟弟的办公桌 弟弟的办公桌[/caption] [caption id="attachment_72645" align="alignnone" width="2048"]弟弟是那种有多少钱就花多少钱的人。 弟弟是那种有多少钱就花多少钱的人。[/caption] [caption id="attachment_72644" align="alignnone" width="2048"]弟弟拿到生日礼物很开心,哥哥生日一般没啥想要的,就给他50英镑现金。 弟弟拿到生日礼物很开心,哥哥生日一般没啥想要的,就给他50英镑现金。[/caption] [caption id="attachment_72643" align="alignnone" width="2048"]机械键盘支持三种模式:无线WIFI/Type C/蓝牙/内置电池 机械键盘支持三种模式:无线WIFI/Type C/蓝牙/内置电池[/caption] [caption id="attachment_72642" align="alignnone" width="2048"]IPAD是轻工作站/没有主机/方便便捷 IPAD是轻工作站/没有主机/方便便捷[/caption] [caption id="attachment_72641" align="alignnone" width="2048"]用IPAD+机械键盘刷题 用IPAD+机械键盘刷题[/caption] [caption id="attachment_72640" align="alignnone" width="1152"]刷题是不是更厉害了 刷题是不是更厉害了[/caption] [caption id="attachment_72639" align="alignnone" width="2048"]弟弟在测试新的机械键盘 弟弟在测试新的机械键盘[/caption] [caption id="attachment_72638" align="alignnone" width="539"]在亚马逊下单买的码农设备。 在亚马逊下单买的码农设备。[/caption] [caption id="attachment_72637" align="alignnone" width="2048"]弟弟的办公桌 弟弟的办公桌[/caption] [caption id="attachment_72636" align="alignnone" width="1152"]没有浪费,基本上都吃了。以往吃不完也会分给同事/朋友。 没有浪费,基本上都吃了。以往吃不完也会分给同事/朋友。[/caption] [caption id="attachment_72635" align="alignnone" width="2048"]蛋糕还行,不会很腻 蛋糕还行,不会很腻[/caption] [caption id="attachment_72634" align="alignnone" width="2048"]这个蛋糕做工不错。 这个蛋糕做工不错。[/caption] [caption id="attachment_72633" align="alignnone" width="1152"]仪式感还是要有的,一年一个重要的日子。 仪式感还是要有的,一年一个重要的日子。[/caption] [caption id="attachment_72632" align="alignnone" width="1152"]开始点蜡烛了 开始点蜡烛了[/caption] [caption id="attachment_72631" align="alignnone" width="1152"]弟弟这两年沉迷于我的世界/Minecraft 弟弟这两年沉迷于我的世界/Minecraft[/caption] [caption id="attachment_72630" align="alignnone" width="1881"]蛋糕上的玩具不能吃的 蛋糕上的玩具不能吃的[/caption] [caption id="attachment_72629" align="alignnone" width="2048"]他最爱的哥哥写的生日卡片 他最爱的哥哥写的生日卡片[/caption] [caption id="attachment_72628" align="alignnone" width="2048"]这个蛋糕+上面的小玩具花了55英镑 这个蛋糕+上面的小玩具花了55英镑[/caption] [caption id="attachment_72627" align="alignnone" width="2048"]弟弟打开哥哥写的生日贺卡 弟弟打开哥哥写的生日贺卡[/caption] [caption id="attachment_72626" align="alignnone" width="2048"]弟弟在玩minecraft 弟弟在玩minecraft[/caption] [caption id="attachment_72625" align="alignnone" width="1152"]车库改成的书房/我的办公地方在楼上卧室改的 车库改成的书房/我的办公地方在楼上卧室改的[/caption] [caption id="attachment_72624" align="alignnone" width="2048"]他现在主要的设备就是 iPAD 他现在主要的设备就是 iPAD[/caption] [caption id="attachment_72623" align="alignnone" width="2048"]弟弟在玩游戏 弟弟在玩游戏[/caption] [caption id="attachment_72622" align="alignnone" width="2048"]弟弟的办公桌 很乱 弟弟的办公桌 很乱[/caption] [caption id="attachment_72649" align="alignnone" width="627"]朋友圈记录娃的成长 朋友圈记录娃的成长[/caption] [show_file file="/var/www/wp-post-common/justyy.com/leetcode.php"] [show_file file="/var/www/wp-post-common/justyy.com/birthday.php"] [show_posts keyword="刷题"] [show_posts keyword="生日"]

8年的力扣不打算续费了: 古法编程最好的时代过去了

2026-08-10 04:15:25

连续续费力扣八年后,今年决定暂时不续了。从2018年准备亚马逊面试,到后来几乎每天刷题,力扣已经成为生活的一部分。AI正在改变程序员写代码的方式,但算法、基本功和长期坚持依然重要。不续费不是因为它没用了,也不是付不起,只是对现在的我来说,边际收益已经没有以前那么高。写篇文章记录这八年的陪伴,以及我对AI时代软件工程师的一些思考。💻

连续续费力扣会员八年后,我决定今年暂不续费。从2018年准备亚马逊面试,到2019年开始坚持每天刷题,力扣早已成为我技术成长的一部分。如今AI已经改变软件工程师的工作方式,工程师的重点正从手工编写代码,转向设计方案、提供上下文、审核AI产出并识别系统风险。力扣和算法能力依然重要,技术面试短期内也不会放弃这种高效的筛选方式;只是对现在的我而言,每年159美元会员费带来的边际收益已经明显下降。不是付不起,而是这笔钱可以花在家庭更需要的地方。当然,如果黑五打折,说不定我又会回来。

连续续费八年后,我决定不再续费力扣会员了

上周,我做了一个不算艰难、但多少有点舍不得的决定:今年不再续费力扣会员了。 力扣会员这些年的价格一直是每年159美元,也可以按月购买,每月35美元。对正在突击准备面试的人来说,按月付费其实很合适,集中刷上一两个月,找到工作以后就可以停掉。而我从2018年第一次购买会员开始,一续就是八年。 [caption id="attachment_72597" align="alignnone" width="1360"]续了8年的力扣 不打算再续了。一个月省两杯咖啡钱。 续了8年的力扣 不打算再续了。一个月省两杯咖啡钱。[/caption]

从一场亚马逊面试开始

[caption id="attachment_72251" align="alignnone" width="550"]01 01[/caption] 2018年我准备找工作,在去亚马逊面试前的那个周末,才临时决定购买力扣会员。那个周末大概刷了二三十道题,自以为准备得还不错。 后来才发现,当时对面试的理解还是太简单了。我以为只要算法题做得足够多就可以,真正参加面试后才知道,对于有经验的工程师来说,系统设计往往比单纯写出一道算法题更加重要。算法题只能证明一部分编码和思维能力,系统设计考察的则是架构、取舍、扩展性、可靠性以及工程经验。 不过,力扣会员还是一直续了下来。 最开始的两年,也就是2018年和2019年,我是通过PayPal付款的。当时网站上似乎还没有这个付款选项,我专门发邮件联系力扣,由客服人工帮我处理。后来才改成直接在网站上按年续费。 从账单记录来看,八年间每年都是159美元。单看一年不算多,但八年累计下来也有1272美元。力扣也陪着我走过了八年的日日夜夜。

从2019年开始,我几乎一天都没有停过

我从2019年3月2日开始,基本上每天都会刷力扣。 所谓“每天刷”,并不是一时兴起坚持几个星期,而是逐渐变成了生活的一部分。每天打开力扣、看题、写代码、提交,已经和吃饭、刷手机一样自然。工作忙的时候少做一点,有空的时候多做几道,但这个习惯一直保留了下来。 去年,我在国际版力扣上漏签了两天。 其中一天是媳妇生日,另一天下落在11月21日,至于当天为什么忘记了,我现在已经完全想不起来了。也就是说,从2019年3月2日到现在,国际版力扣一共只漏了这两天。 不过严格来说,我其实一天都没有真正落下,因为我同时也在刷力扣中国,那两天在中文版上仍然完成了打卡。只是国际版的连续记录断了,看起来多少还是有点可惜。 刷了这么多年以后,做题早已不完全是为了找工作,更像是一种习惯,甚至是每天给大脑做的一点热身运动。

力扣会员到底值不值?

客观地说,力扣会员还是有价值的。 它最大的好处,是可以解锁一些质量较高、比较有代表性的会员题目,其中也包括不少公司的面试题。对于正在准备技术面试的人来说,这部分内容确实有用。 会员提交代码时通常也能得到更快的判题体验。据说会员提交会进入优先队列。平时感觉可能不明显,但在服务器繁忙或者参加周赛时,速度上的差别还是能够感受到。 每年159美元,用来投资自己的职业能力并不算贵。如果它能帮助一个人通过面试、拿到更好的工作,那么这点费用几乎可以忽略不计。 我今年不续费,并不是因为它完全没有价值,而是因为它对我的边际收益已经明显下降了。

2026年,工程师写代码的方式已经变了

[caption id="attachment_72252" align="alignnone" width="550"]02 02[/caption] 尤其到了2026年,软件工程师的工作方式已经发生了很大变化。 现在已经不太需要从头到尾手工编写所有代码了。有人开玩笑把纯手写代码称为“古法编程”,虽然有些夸张,却也反映了现实:今天的AI已经能够完成相当大比例的代码实现,而且速度远远超过人类工程师。 我现在工作中最常见的操作,就是打开VS Code,选择GPT-5.6 Sol,把思考模式设为MAX,再打开“Allow All”,让AI自行读取代码、修改文件、运行测试和检查结果。 接下来,我就在那里等它干活。 [caption id="attachment_72596" align="alignnone" width="2048"]现在AI太强大了,Harness Engineering是最好的AI编程时代 现在AI太强大了,Harness Engineering是最好的AI编程时代[/caption] 有时只要几分钟,有时需要几十分钟。等AI完成以后,我再回来检查它的设计、实现和测试结果。现在的我越来越像测试经理、产品经理加甲方:负责提出需求、补充上下文、判断方案、验收产出,以及在AI跑偏时把它拉回来。 前些年曾经有一名美国工程师偷偷把自己的工作外包给中国工程师,最后被公司发现并解雇。现在我们某种程度上也在“外包”工作,只不过外包对象变成了AI,而且这是公开、合规,甚至受到公司鼓励的工作方式。 当然,这并不意味着工程师已经没有用了。 恰恰相反,AI生成代码的速度太快,一次就可能提交一大坨改动,人类已经很难再像过去那样逐行审查每一行代码。工程师必须把注意力放到更重要的地方:整体设计是否合理,模块边界是否清晰,异常路径是否处理正确,安全性和可维护性是否达标,以及这次修改会不会给系统埋下长期隐患。 AI很擅长把测试“弄绿”,但测试变绿并不等于设计正确。 例如,AI特别喜欢到处添加`try-catch`,有时甚至直接捕获通用异常。这样确实可能绕过当前错误,让测试暂时通过,却可能掩盖真正的问题。AI能够解决眼前的局部任务,但通常缺少对整个系统历史、业务目标和长期演进方向的理解。 这些缺口不能只靠一句更漂亮的Prompt解决。工程师需要通过上下文工程、RAG、设计文档、测试策略和明确的架构约束,把真正重要的知识提供给AI;最后还要依靠自己的判断,对AI的方案负责。教娃编程 vLog: Harness Engineering – 指挥 AI 干活 因此,未来工程师最值钱的能力,可能不再是“能不能快速手写出几百行代码”,而是能不能提出正确的问题、提供完整的上下文、识别AI的错误,并在大量自动生成的代码中抓住真正关键的风险

AI时代,力扣还重要吗?

[caption id="attachment_72253" align="alignnone" width="550"]03 03[/caption] 我认为力扣依然重要,至少短期内不会从技术面试中消失。不过刷题进大厂的时代可能已经过去了,至少只刷题是不够的。 很多公司仍然会考算法题,因为这是成本较低、标准相对统一、执行效率较高的一种筛选方式。面试官不需要了解候选人过去所有项目的复杂背景,只需要给出一道题,在有限时间内观察对方如何分析、沟通、编码和验证。 这种方式当然不完美。 它可能错过一些工程能力很强、但不擅长在45分钟压力下写算法题的人,也可能让一些大量背题、实际工程能力一般的人通过面试。因此,力扣题既可能产生“假阴性”,也不能彻底消灭“假阳性”。 但对于公司而言,招进一个不合格候选人的成本,通常远高于错过一个优秀候选人的成本。算法题虽然有缺陷,却便宜、可控、容易标准化,所以仍然会被广泛使用。 从另一个略显残酷的角度看,刷力扣也带有一点“服从性测试”的意味:候选人是否愿意投入时间熟悉规则,能否在压力下保持思考,并在45分钟内写出一两道正确、可运行的代码。 所以,我不认为AI出现以后,算法和数据结构就不需要学习了。相反,当AI替你写代码时,如果自己没有基本功,甚至无法判断AI写得对不对。只是对于我个人来说,继续付费解锁更多题目,已经不像八年前那么必要了。

不是付不起,而是可以花在更需要的地方

159美元并不是付不起。 只是最近两年孩子上私校,家里的钱包多少有点紧。该花的钱还是要花,但能够节省的地方也应该节省。与其为了维持一个已经用了八年的会员身份继续付款,不如把钱留给目前更需要的地方。 这并不是和力扣告别。我依然会继续刷题,免费题库对我来说已经足够丰富。过去八年积累下来的算法思维和刷题习惯,也不会随着会员到期而消失。 感谢力扣陪我度过这八年。从准备亚马逊面试,到后来换工作,再到如今带着孩子一起刷题,它早已不只是一个面试网站,而是我这些年技术成长的一部分。 [caption id="attachment_72595" align="alignnone" width="494"]力扣不再续费 力扣不再续费[/caption] 当然,话也不能说得太绝。 说不定到了年底黑色星期五,力扣又推出优惠,一年便宜30美元,我算了一下觉得挺划算,然后又默默把会员续上了。 [caption id="attachment_72598" align="alignnone" width="2048"]和媳妇约会喝咖啡刷个题 和媳妇约会喝咖啡刷个题[/caption] [caption id="attachment_72599" align="alignnone" width="2048"]随身带着IPAD,每周末到COSTA喝咖啡刷题 随身带着IPAD,每周末到COSTA喝咖啡刷题[/caption] [caption id="attachment_66760" align="alignnone" width="1536"]这次力扣奖励的衣服是新版的,感觉比之前的质量要好。 这次力扣奖励的衣服是新版的,感觉比之前的质量要好。[/caption] 这8年得到了力扣的T-shirt和卫衣大概有十几件了。 [caption id="attachment_72480" align="alignnone" width="864"]当天还穿了个力扣,应景一下刷个题 当天还穿了个力扣,应景一下刷个题[/caption] 7年前(2019年)在GE工作的时候的一个周六开始的刷题之旅。 [caption id="attachment_66886" align="alignnone" width="1887"]2019年在美国通用电气工作的时候中午吃完饭在湖边着着IPAD刷题 2019年在美国通用电气工作的时候中午吃完饭在湖边着着IPAD刷题[/caption] [caption id="attachment_6474" align="alignnone" width="1600"]刷题过了 Accepted 刷题过了 Accepted[/caption] 照片里,一个是陪我过日子的人,一个是陪我刷了八年的力扣。逛街喝咖啡的间隙,顺手完成了当天的打卡,连续刷题也来到第2718天(从2019年3月2日至今)。每天进步一点点,当时看不出什么,几年以后再回头看,这大概就是坚持和复利的意义。😊 微博 | X | FB [caption id="attachment_72603" align="alignnone" width="1152"]还好约会的时候刷题媳妇不管的。 还好约会的时候刷题媳妇不管的。[/caption]

复利效应(Compound Effect)

每天进步一点点,长期坚持所积累的成长将是巨大的。现在我每天带着孩子一起刷力扣也是如此:一两天,甚至几个月,可能都看不出明显变化,但只要坚持几年,这个习惯一定会让我们受益。活到老,学到老;保持耐心、坚持积累,享受延迟满足带来的回报。 [caption id="attachment_69529" align="alignnone" width="640"]每天10来分钟 带娃刷力扣,每天进步一点点。 每天10来分钟 带娃刷力扣,每天进步一点点。[/caption] 年前在Linkedin上分享刷题火了 (1万6000次喜欢/600多条评论) [caption id="attachment_72608" align="alignnone" width="809"]几年前在Linkedin上分享刷题火了 几年前在Linkedin上分享刷题火了[/caption] [caption id="attachment_66880" align="alignnone" width="713"]从2013年到2024的力扣刷题之路。 从2013年到2024的力扣刷题之路。[/caption] [caption id="attachment_72607" align="alignnone" width="842"]2024年到2026年打卡力扣刷题 2024年到2026年打卡力扣刷题[/caption] [show_file file="/var/www/wp-post-common/justyy.com/leetcode.php"] [show_posts keyword="力扣"]

蜘蛛侠4上映第二天: 在剑桥Everyman看《Brand New Day》

2026-08-09 03:20:38

上周六,我们在《Spider-Man: Brand New Day》(蜘蛛侠4)上映的第二天,来到剑桥Grand Arcade里的Everyman电影院观看。当天市中心交通拥堵,好在电影开始前播放了近半小时广告,让我顺利赶上。三个人的电影票花了50.70英镑,差不多已经可以买一张四人家庭票。由于没有看全前几部电影,部分剧情没有完全理解,媳妇还临时用ChatGPT补充背景。虽然电影长达两个多小时,但也算是一次轻松的周末家庭活动。
上周六,《Spider-Man: Brand New Day》(蜘蛛侠4)在Everyman上映的第二天,我们去了剑桥市中心Grand Arcade购物商场里的Everyman电影院观看。
Spider-Man: Brand New Day 12A · 2 hr. 25 min. Everyman Cambridge in Screen 3 Saturday, 1 August 2026 01/08/2026 13:00:00 A10 · A8 · A9 Adult x 1 £ 20.00 Adult & Child x 1 £ 28.20 Booking Fee £ 2.50 Sub-total £ 45.61 Tax (incl. in ticket price) £ 5.09 Order total: £ 50.70
老大当天上午11点到下午1点在图书馆做义工,结束后便直接去电影院和我们会合。电影票上写着下午1点开始,不过英国电影院通常不会准时播放正片,前面总要先放一大段广告和预告片。这一场也差不多放了30分钟,倒是给迟到的观众留出了充足的缓冲时间。 当天剑桥市中心的草地上正好有活动,路上非常拥堵。我先把媳妇放在Grand Arcade门口,然后再开车去找停车位。停好车后走回电影院,已经是下午1点25分了。幸好广告还没有结束,刚坐下来不久,电影才正式开始。 老二原本也可以一起去,不过他对这部电影没有兴趣,宁愿留在家里。我们三个人的电影票一共花了50.70英镑。再多加两三英镑,其实就可以买一张包含两个大人和两个孩子的Family Ticket。可惜老二不来,这张家庭票也就失去了意义。 Everyman和普通的连锁电影院有些不同,主打的是比较精致的观影体验,影厅里主要是柔软的沙发座椅,还可以把食物和饮料送到座位上。剑桥这家店位于Grand Arcade一楼,2024年才开业。环境和座椅确实比较舒服,不过票价也明显比一般电影院贵一些。[Everyman Cambridge官网] 《Spider-Man: Brand New Day》片长约2小时25分钟,是Tom Holland主演的第四部蜘蛛侠个人电影,也是《Spider-Man: No Way Home》的续集。上一部结尾,所有人都忘记了Peter Parker,而这一部的故事正是从这个设定继续展开。[Sony Pictures官方介绍] 由于我并没有完整看过前面的几部蜘蛛侠电影,所以有些人物关系和剧情背景没有完全弄明白。漫威电影之间的联系越来越多,如果中间漏掉几部,再接着看新片,确实很容易有一种“大家好像都认识,只有我不知道发生了什么”的感觉。 媳妇有些地方也没看懂,于是一边看,一边用ChatGPT查询前面的剧情和人物背景。以前看电影遇到不明白的地方,只能回家以后再慢慢搜索;现在倒是可以在电影院里直接让AI补课了。只是电影中的角色和支线实在太多,即使临时补了一些背景,也不一定能够完全跟上。 正片两个多小时,再加上前面的广告,整场下来接近三个小时。虽然剧情没有完全看懂,但这次看电影本身也算是一场周末家庭活动:老大做完义工后过来会合,老二选择留在家里,我们三个人在拥堵的剑桥市中心赶上了电影,也算是有惊无险。 [caption id="attachment_72696" align="alignnone" width="1600"]Spider-Man: Brand New Day 蜘蛛侠电影
Spider-Man: Brand New Day 蜘蛛侠电影
[/caption] 最后补充一句与剧情无关的观后感: [bctt tweet="PS:女主Zendaya真的很漂亮。"] [caption id="attachment_72588" align="alignnone" width="1538"]电影结束后,老大和媳妇在讨论剧情。 电影结束后,老大和媳妇在讨论剧情。[/caption] [caption id="attachment_72587" align="alignnone" width="2048"]前一天晚上才订的票,只剩下最前排的三四个连续的座了 前一天晚上才订的票,只剩下最前排的三四个连续的座了[/caption] [caption id="attachment_72586" align="alignnone" width="1577"]蜘蛛侠4电影海报 蜘蛛侠4电影海报[/caption] [show_file file="/var/www/wp-post-common/justyy.com/movie.php"] [show_posts keyword="电影"]

《Spider-Man: Brand New Day》剧情简介

几年过去,Peter独自住在纽约,把几乎全部精力都投入到打击犯罪中。他只能远远关注已经开始新生活的MJ和Ned,却始终不敢告诉他们过去发生的一切。长期的孤独和压抑也令他的身体发生变化:感官和力量进一步增强,甚至能够直接从手腕射出蛛丝,但情绪也变得越来越暴躁,逐渐失去控制。Sony官方剧情简介 与此同时,纽约接连发生一系列离奇案件,一个能够侵入并控制他人意识的神秘敌人开始出现。对方不仅知道Peter的真实身份,还利用他对MJ的感情设下陷阱,并试图渗透负责监管超能力者的损害控制局。为了弄清自己的身体变化并阻止这场危机,Peter向Bruce Banner求助,途中又与行事更加冷酷的惩罚者Frank Castle产生交集。Deep Focus Review剧情介绍 这一次的故事没有再把重点放在多元宇宙,而是回到Peter个人的孤独、愤怒与责任之中。他必须面对的并不只是一个看不见的敌人,还有那个被痛苦逐渐改变的自己。即使MJ和Ned已经不再记得他,他仍然选择保护他们——世界遗忘了Peter Parker,但Peter从未忘记自己所爱的人。