2026-08-13 22:02:20
WordPress的上传目录必须允许写入媒体文件,却没有执行PHP代码的必要。本文介绍如何通过Apache全局配置禁止在`wp-content/uploads`中访问和执行PHP类文件,并使用`.htaccess`作为第二层保护,同时分析两种方式的优缺点、`Options -ExecCGI`的作用及配置验证方法。这项加固不能代替漏洞修复和及时更新,但可以切断恶意文件上传后被执行为Web Shell的常见攻击路径。我目前维护着8个WordPress博客,从服务器配置、系统升级到日常备份和安全防护,基本上都是自己动手完成。这几年也遇到过几次规模不大的安全事件,好在发现和处理得比较及时,目前并没有造成太严重的损失。 每一次事故后的排查、复盘和总结,都是一次很好的学习和提升机会,也让我逐渐意识到:服务器安全没有真正意义上的“一劳永逸”,更不能因为系统已经稳定运行多年就放松警惕。及时更新WordPress及插件、妥善管理密钥、收紧文件权限、检查日志和备份,以及禁止在上传目录中执行PHP,这些看似琐碎的措施,往往能够在关键时刻阻断攻击链。安全本质上是一项需要长期坚持、不断完善的工作。
wp-content/uploads目录写入图片、视频等媒体文件。这种设计虽然方便,却也形成了一个非常重要的安全边界:这个目录必须允许Web应用写入,但保存在其中的文件绝对没有执行PHP代码的必要。
如果某个存在漏洞的插件、主题或自定义上传接口允许攻击者把PHP文件写入上传目录,攻击者接下来就可能尝试通过浏览器直接访问这个文件。一旦Apache把它交给PHP解释器执行,一个普通的文件上传漏洞就可能升级为远程代码执行,甚至变成一个以Web服务器用户权限运行的Web Shell。
禁止在uploads目录中执行PHP并不能修复最初的漏洞,但它可以切断这条常见的攻击链。这是一项成本低、影响小的纵深防御措施,应该和及时更新WordPress、限制文件权限、检查日志、验证备份等措施一起使用。WordPress官方的安全加固指南同样强调,安全依赖多层防护,而不是某一个单独的设置。
/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.pharRequire all denied:任何匹配的文件都不能通过Apache直接访问。Apache官方文档也介绍了如何使用DirectoryMatch、FilesMatch和Require 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通常意味着当前目录对应的AllowOverride或AllowOverrideList设置不允许使用这项指令。
不要仅仅为了让这个安全规则生效,就把服务器改成AllowOverride All。如果自己拥有服务器管理权限,应该优先使用Apache全局配置。
.htaccess的优缺点| 方式 | 优点 | 缺点 |
|---|---|---|
| Apache全局配置 | 一条规则可以保护所有网站;由root用户控制;不依赖AllowOverride;被入侵的WordPress进程通常无法修改;配置更集中,性能也更好 |
需要服务器管理权限;修改后必须检查配置并重新加载Apache;路径表达式必须和服务器上的实际目录结构匹配 |
上传目录中的.htaccess
|
可以按网站部署;适合共享主机;不需要重新加载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或虚拟主机的重要配置,也应该重新执行这项测试。没有经过验证的安全设置只是一种假设,还不能算是真正有效的安全控制。
include或require在服务器内部加载恶意文件;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[/caption]
02[/caption]
03[/caption]
两年前的兄弟俩,现在已经长大了很多。[/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年的时候有回,当时老二还在媳妇肚子里。老大在福州的时候学会走路的,老二的第一次真是记不住了。[/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[/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[/caption]
他说,长大以后也想像我一样当软件工程师。
不过从目前来看,他的大部分精力还是花在玩游戏和看YouTube视频上。看的内容也大多和游戏、手机、平板电脑以及各种电子产品有关。孩子喜欢玩很正常,我小时候如果有这些东西,大概也会玩得停不下来。
我并不认为玩游戏和看视频就一定是在浪费时间。兴趣往往就是从“玩”开始的。玩Minecraft可以接触创造、设计和简单的逻辑;关注手机、平板和电脑,也说明他对科技产品有自己的好奇心。但“喜欢使用科技产品”和“能够创造科技产品”之间,仍然隔着很长的一段路。
一套机械键盘不会自动把人变成程序员,刷力扣也不是学习编程的全部。真正重要的是,他能不能慢慢学会主动探索、独立思考,并把脑子里的想法做成真正的东西。
孩子将来是否真的会成为软件工程师,其实并不重要。他现在的兴趣以后也可能发生变化。我更希望的是,他能在玩中发现兴趣,在兴趣中学习,再把学习到的东西变成自己的能力。
至于我能做的,就是继续陪他每天刷一道题,在他愿意探索的时候给他一点帮助。也许多年以后再回头看,这把机械键盘、这只鼠标和这个iPad支架,就是他通往技术世界的第一套装备。
[caption id="attachment_72253" align="alignnone" width="550"]
03[/caption]
[caption id="attachment_72648" align="alignnone" width="1920"]
每天带娃刷力扣。[/caption]
[caption id="attachment_72647" align="alignnone" width="2048"]
这键盘还会发光/和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英镑现金。[/caption]
[caption id="attachment_72643" align="alignnone" width="2048"]
机械键盘支持三种模式:无线WIFI/Type C/蓝牙/内置电池[/caption]
[caption id="attachment_72642" align="alignnone" width="2048"]
IPAD是轻工作站/没有主机/方便便捷[/caption]
[caption id="attachment_72641" align="alignnone" width="2048"]
用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[/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英镑[/caption]
[caption id="attachment_72627" align="alignnone" width="2048"]
弟弟打开哥哥写的生日贺卡[/caption]
[caption id="attachment_72626" align="alignnone" width="2048"]
弟弟在玩minecraft[/caption]
[caption id="attachment_72625" align="alignnone" width="1152"]
车库改成的书房/我的办公地方在楼上卧室改的[/caption]
[caption id="attachment_72624" align="alignnone" width="2048"]
他现在主要的设备就是 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="生日"]
2026-08-10 04:15:25
连续续费力扣八年后,今年决定暂时不续了。从2018年准备亚马逊面试,到后来几乎每天刷题,力扣已经成为生活的一部分。AI正在改变程序员写代码的方式,但算法、基本功和长期坚持依然重要。不续费不是因为它没用了,也不是付不起,只是对现在的我来说,边际收益已经没有以前那么高。写篇文章记录这八年的陪伴,以及我对AI时代软件工程师的一些思考。💻
连续续费力扣会员八年后,我决定今年暂不续费。从2018年准备亚马逊面试,到2019年开始坚持每天刷题,力扣早已成为我技术成长的一部分。如今AI已经改变软件工程师的工作方式,工程师的重点正从手工编写代码,转向设计方案、提供上下文、审核AI产出并识别系统风险。力扣和算法能力依然重要,技术面试短期内也不会放弃这种高效的筛选方式;只是对现在的我而言,每年159美元会员费带来的边际收益已经明显下降。不是付不起,而是这笔钱可以花在家庭更需要的地方。当然,如果黑五打折,说不定我又会回来。
续了8年的力扣 不打算再续了。一个月省两杯咖啡钱。[/caption]
01[/caption]
2018年我准备找工作,在去亚马逊面试前的那个周末,才临时决定购买力扣会员。那个周末大概刷了二三十道题,自以为准备得还不错。
后来才发现,当时对面试的理解还是太简单了。我以为只要算法题做得足够多就可以,真正参加面试后才知道,对于有经验的工程师来说,系统设计往往比单纯写出一道算法题更加重要。算法题只能证明一部分编码和思维能力,系统设计考察的则是架构、取舍、扩展性、可靠性以及工程经验。
不过,力扣会员还是一直续了下来。
最开始的两年,也就是2018年和2019年,我是通过PayPal付款的。当时网站上似乎还没有这个付款选项,我专门发邮件联系力扣,由客服人工帮我处理。后来才改成直接在网站上按年续费。
从账单记录来看,八年间每年都是159美元。单看一年不算多,但八年累计下来也有1272美元。力扣也陪着我走过了八年的日日夜夜。
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编程时代[/caption]
有时只要几分钟,有时需要几十分钟。等AI完成以后,我再回来检查它的设计、实现和测试结果。现在的我越来越像测试经理、产品经理加甲方:负责提出需求、补充上下文、判断方案、验收产出,以及在AI跑偏时把它拉回来。
前些年曾经有一名美国工程师偷偷把自己的工作外包给中国工程师,最后被公司发现并解雇。现在我们某种程度上也在“外包”工作,只不过外包对象变成了AI,而且这是公开、合规,甚至受到公司鼓励的工作方式。
当然,这并不意味着工程师已经没有用了。
恰恰相反,AI生成代码的速度太快,一次就可能提交一大坨改动,人类已经很难再像过去那样逐行审查每一行代码。工程师必须把注意力放到更重要的地方:整体设计是否合理,模块边界是否清晰,异常路径是否处理正确,安全性和可维护性是否达标,以及这次修改会不会给系统埋下长期隐患。
AI很擅长把测试“弄绿”,但测试变绿并不等于设计正确。
例如,AI特别喜欢到处添加`try-catch`,有时甚至直接捕获通用异常。这样确实可能绕过当前错误,让测试暂时通过,却可能掩盖真正的问题。AI能够解决眼前的局部任务,但通常缺少对整个系统历史、业务目标和长期演进方向的理解。
这些缺口不能只靠一句更漂亮的Prompt解决。工程师需要通过上下文工程、RAG、设计文档、测试策略和明确的架构约束,把真正重要的知识提供给AI;最后还要依靠自己的判断,对AI的方案负责。教娃编程 vLog: Harness Engineering – 指挥 AI 干活
因此,未来工程师最值钱的能力,可能不再是“能不能快速手写出几百行代码”,而是能不能提出正确的问题、提供完整的上下文、识别AI的错误,并在大量自动生成的代码中抓住真正关键的风险。
03[/caption]
我认为力扣依然重要,至少短期内不会从技术面试中消失。不过刷题进大厂的时代可能已经过去了,至少只刷题是不够的。
很多公司仍然会考算法题,因为这是成本较低、标准相对统一、执行效率较高的一种筛选方式。面试官不需要了解候选人过去所有项目的复杂背景,只需要给出一道题,在有限时间内观察对方如何分析、沟通、编码和验证。
这种方式当然不完美。
它可能错过一些工程能力很强、但不擅长在45分钟压力下写算法题的人,也可能让一些大量背题、实际工程能力一般的人通过面试。因此,力扣题既可能产生“假阴性”,也不能彻底消灭“假阳性”。
但对于公司而言,招进一个不合格候选人的成本,通常远高于错过一个优秀候选人的成本。算法题虽然有缺陷,却便宜、可控、容易标准化,所以仍然会被广泛使用。
从另一个略显残酷的角度看,刷力扣也带有一点“服从性测试”的意味:候选人是否愿意投入时间熟悉规则,能否在压力下保持思考,并在45分钟内写出一两道正确、可运行的代码。
所以,我不认为AI出现以后,算法和数据结构就不需要学习了。相反,当AI替你写代码时,如果自己没有基本功,甚至无法判断AI写得对不对。只是对于我个人来说,继续付费解锁更多题目,已经不像八年前那么必要了。
力扣不再续费[/caption]
当然,话也不能说得太绝。
说不定到了年底黑色星期五,力扣又推出优惠,一年便宜30美元,我算了一下觉得挺划算,然后又默默把会员续上了。
[caption id="attachment_72598" align="alignnone" width="2048"]
和媳妇约会喝咖啡刷个题[/caption]
[caption id="attachment_72599" align="alignnone" width="2048"]
随身带着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刷题[/caption]
[caption id="attachment_6474" align="alignnone" width="1600"]
刷题过了 Accepted[/caption]
照片里,一个是陪我过日子的人,一个是陪我刷了八年的力扣。逛街喝咖啡的间隙,顺手完成了当天的打卡,连续刷题也来到第2718天(从2019年3月2日至今)。每天进步一点点,当时看不出什么,几年以后再回头看,这大概就是坚持和复利的意义。😊
微博 | X | FB
[caption id="attachment_72603" align="alignnone" width="1152"]
还好约会的时候刷题媳妇不管的。[/caption]
每天10来分钟 带娃刷力扣,每天进步一点点。[/caption]
年前在Linkedin上分享刷题火了 (1万6000次喜欢/600多条评论)
[caption id="attachment_72608" align="alignnone" width="809"]
几年前在Linkedin上分享刷题火了[/caption]
[caption id="attachment_66880" align="alignnone" width="713"]
从2013年到2024的力扣刷题之路。[/caption]
[caption id="attachment_72607" align="alignnone" width="842"]
2024年到2026年打卡力扣刷题[/caption]
[show_file file="/var/www/wp-post-common/justyy.com/leetcode.php"]
[show_posts keyword="力扣"]
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 蜘蛛侠电影
电影结束后,老大和媳妇在讨论剧情。[/caption]
[caption id="attachment_72587" align="alignnone" width="2048"]
前一天晚上才订的票,只剩下最前排的三四个连续的座了[/caption]
[caption id="attachment_72586" align="alignnone" width="1577"]
蜘蛛侠4电影海报[/caption]
[show_file file="/var/www/wp-post-common/justyy.com/movie.php"]
[show_posts keyword="电影"]
2026-08-09 01:26:22
我把一台闲置多年的 Beelink SEi8 迷你电脑安装上 Ubuntu,放在鞋柜里作为家庭服务器,用来运行 STEEM 节点、Node.js 程序、数据库、反向代理及 Cloudflare Tunnel。文章还解释了双重 NAT 导致 NUC-8 可以主动访问树莓派、树莓派却无法反向发起连接的原因,并分享了旧电脑再利用、家庭宽带和服务器散热方面的经验。
现在家庭网络的拓扑图[/caption]
flowchart TB
Internet(("Internet"))
subgraph PL["Plusnet LAN — upstream subnet"]
Hub["Plusnet Hub 2<br/>Router and NAT"]
Pi4["Raspberry Pi 4B<br/>Connected directly to Hub 2"]
Hub <-->|Direct connection| Pi4
end
subgraph DL["Deco LAN — downstream subnet"]
Deco1["Deco 1 — Primary<br/>Router, NAT and firewall"]
Deco2["Deco 2 — Mesh node<br/>Upstairs office — bedroom"]
Deco3["Deco 3 — Mesh node<br/>Study room — former garage"]
NUC["NUC-8 / Beelink SEi8<br/>Ubuntu home server"]
Pi1["Raspberry Pi Model B Rev 2<br/>~475 MB RAM"]
Deco1 <-->|Ethernet| NUC
Deco1 -.-|Wireless mesh| Deco2
Deco1 -.-|Wireless mesh| Deco3
Deco3 <-->|Ethernet| Pi1
end
Internet <--> Hub
Hub <-->|Ethernet to Deco WAN| Deco1
Plusnet 路由器是最上游的主路由器。两台树莓派——一台只有约 475MB 内存的老款 Raspberry Pi Model B Rev 2是和NUC-8一样分别连到了两个DECO路游器,一台 4GB 内存的 Raspberry Pi 4B—直接连接在 Plusnet 路由器上(有线/RJ45网线)。
Deco 则连接到 Plusnet 路由器,并继续以“路由器模式”工作,而不是桥接或 AP 模式。NUC-8 通过网线连接到 Deco。因此,Plusnet 和 Deco 分别建立了两个不同的局域网子网。例如,树莓派可能位于 192.168.1.x 网段,而 NUC-8 则位于 Deco 管理的 192.168.68.x 网段。
这就形成了家庭网络中常见的“双重 NAT”。
当 NUC-8 主动访问树莓派时,数据从 Deco 的内网侧发往上游。Deco 会通过 NAT 把连接转换成自己的上游地址,并在连接跟踪表里记录这次请求。树莓派返回的数据因此能够被 Deco 正确地转发回 NUC-8,所以这个方向可以正常通信。
从树莓派4b PING下游的NUC-8和树莓派Model B行不通。
From 192.168.1.XXX icmp_seq=460 Destination Host Unreachable但当树莓派主动访问 NUC-8 时,情况就不同了。树莓派所在的 Plusnet 网络通常不知道 192.168.68.x 网段应该通过哪台设备到达;即使请求发到了 Deco 的上游接口,Deco 的防火墙也会把它视为从 WAN 侧发起的、没有对应连接记录的入站请求,默认不会转发给内部的 NUC-8。 所以,这并不是数据真正意义上的“只能单向流动”,而是只有 NUC-8 一侧能够主动发起连接。NUC-8 发起连接以后,树莓派的响应仍然可以原路返回;树莓派却不能无条件地主动建立一条通往 NUC-8 的新连接。 如果想让三台机器彼此直接访问,最简单的办法是把 Deco 切换成 AP 模式,或者把两台树莓派也接入 Deco,让所有设备处在同一个子网里。另一种更专业但也更麻烦的做法,是在 Plusnet 路由器上添加一条指向 Deco 的静态路由,并相应调整 Deco 的 NAT 和防火墙规则;但不少家用路由器并不完整支持这种配置。若只需要访问 NUC-8 上的个别服务,也可以在 Deco 上设置端口转发,不过管理起来不如统一子网清晰。
第一次安装还是加个显示器方便一些。[/caption]
[caption id="attachment_72569" align="alignnone" width="1189"]
STEEM区块链见证人就跑在这台服务器上[/caption]
[caption id="attachment_72568" align="alignnone" width="733"]
利用起来,跑上pm2用于管理nodejs程序:监控STEEM区块链然后入数据库。[/caption]
[caption id="attachment_72567" align="alignnone" width="877"]
这台服务器neofetch显示的信息。[/caption]
[caption id="attachment_72566" align="alignnone" width="1160"]
内存和处理器放在WINDOWS上可能勉强用,但是在LINUX上会很流畅。[/caption]
USB存储需要提前下好Ubuntu的镜象,然后从USB启动。
[caption id="attachment_72565" align="alignnone" width="2048"]
接上键盘鼠标和显示器,然后需要在另一台电脑上下载好镜像,刷到USB上启动安装。[/caption]
[caption id="attachment_72564" align="alignnone" width="1536"]
这个NUC-8小机器有个风扇,还是有点噪音。[/caption]
[caption id="attachment_72563" align="alignnone" width="1536"]
体积不大,盒子已经被我拆掉了,因为散热更好一些。[/caption]
[caption id="attachment_72562" align="alignnone" width="1536"]
从抽屉里找出来的,还能用。[/caption]
[caption id="attachment_72561" align="alignnone" width="864"]
小小的鞋柜里塞下两台服务器:树莓派4b和这个NUC-8[/caption]
[caption id="attachment_72560" align="alignnone" width="953"]
五年前买的小电脑 现在还在发挥余热[/caption]
[show_file file="/var/www/wp-post-common/justyy.com/home-topology.php"]
[show_posts keyword="家庭 网络 拓扑"]
英文:Turning a Dusty Mini PC into a Home Server: My NUC 8's Second Life
[caption id="attachment_72582" align="alignnone" width="1086"]
NUC-8配置[/caption]
[caption id="attachment_72583" align="alignnone" width="1074"]
树莓派 4b 配置[/caption]
[caption id="attachment_72584" align="alignnone" width="1089"]
树莓派b rev2配置[/caption]