普通视图
美化你的RSS订阅地址
腾讯云原生开发自动化部署Hexo
CNB 简介
前阵子偶然在雨月空间站了解到腾讯出了一个云原生构建项目 CNB,一开始以为只是另一个国产的 gitee,但是深入体验后才发现它比半死不活的 gitee 高明得很多,非常接近 github。借用评论区的简要概括:云原生开发是 github codespace,云原生构建是 github actions,制品库是 github registry。
CNB 还是很大方地提供了免费额度,详情见云原生构建定价,实际云开发使用体验也非常不错。自从我换电信宽带后,基本无法直接向 github 推代码,既然如此,那我是不是也可以将我的博客自动化迁移到 CNB 上呢?
CNB 自动化部署hexo流程
必要步骤
1.注册一个 CNB 的账号,目前只支持使用微信登陆;
2.创建一个组织,实测非常见字符可以直接创建,但是短字符或常用字符需要域名验证。因为支持 .cool 域名验证,所以我创建了组织“hin”;
3.创建仓库,和 github 一样,你可以创建公开和私有仓库,此外,github 中的私钥等环境变量在 CNB 中得通过创建秘钥仓库来实现;
4.在这里创建访问令牌,以便拉取和推送代码,场景和权限范围还是非常细致的。特别提醒:记得保存生成的令牌!
创建 hexo 仓库
如果你要推送 hexo 博客到腾讯云 cos,那么你可以使用 hexo-cos-demo 这个模板;如果你要推送到自己的服务器,则可以使用 hexo-rsync-remote这个模板。这两个模板都自带云原生开发环境,可以一键上手。
起初考虑到我的 hexo 以及主题版本都太低,至少有两年没更新了,所以我选择了创建空白仓库,复制原 github 仓库文件和代码,参考案例编写环境。
强烈建议:创建私密仓库,以免配置文件中的一些密钥泄露!!!
仓库根目录创建.ide/Dockerfile
文件,参考内容如下:
# 帮助文档地址: https://docs.cnb.cool/zh/vscode/quick-start.html |
推送 hexo 到仓库
拉取和推送项目的操作和使用 github 一样,不再赘述。在第一次拉取私密仓库或者推送时,需要登陆,在登陆框填写此前创建的令牌即可。
我复制了此前 hexo 文件夹下的 source
、themes
等文件夹,以及 _config.yml
、package.json
等文件,然后 git push
到仓库。
点击右上角的橙色“云原生开发”,很快就会创建好环境,可以选择使用 WebIDE,也可以使用 VSCode 等 IDE 打开。为了方便,我就直接选择了网页版的 IDE。
打开网页版的 IDE 就可以在网页上使用 vscode 进行代码编写、拉取和推送等操作了。IDE 自带了腾讯的代码助手,但是我没使用过它。
和 github codespace 一样,你可以直接在网页版 IDE 中使用 hexo s
这样的命令来在线运行和调试。
此外,建议你使用子模块的方式引入 hexo 主题,以便于后续主题的更新和修改。和在 github 一样,在当前仓库创建 .gitmodules
文件即可,内容参考:
[submodule "themes/butterfly"] |
创建密钥仓库
在网页 IDE 中测试没有问题后,即可开始下一步了。
新建仓库,类型选择密钥仓库,参考文档在仓库里创建一个env.yml
文件,内容参考如下:
# 密钥仓库 env.yml |
详细的参数说明参考官方的 rsync 文档。此外,一定要记得粘贴私钥内容有两个要点:
1.在 yml 中,多行内容要用|
来表明;
2.由于 yml 对格式非常敏感,所以私钥的每一行都需要缩进两个空格而不是 Tab。
一开始我没注意到第二点,导致尝试推送静态文件到服务器时登陆失败,虽然构建日志中也提供满血版 deepseek 帮忙分析日志,但这也为我明明格式正确却无法连接到服务器埋下了另一个伏笔。
创建自动化工作流
在 hexo 仓库(不是密钥仓库)中创建一个名为 .cnb.yml
的文件,它的作用和 .github/workflows/main.yml
是一样的,写法上稍有不同,参考代码如下:
main: |
到此我们要做的事已经基本完成。当这个文件创建之后,云原生构建便会自动开始。起初,我的每一次构建都在上传到服务器这一步失败了,原因是服务器拒绝了连接。后来查看服务器日志才发现,因为之前失败次数达到设定的值,IP 已经被 fail2ban 给拉黑了。
写在最后
其实这个过程我尝试并失败过很多次,比如 hexo s
的时候发现有标签报错呀,我一直很纳闷,明明主题里有这个标签。后来偶然发现,我的主题是以子模块的方式引入的,在 CNB 仓库里没有声明子模块,导致浪费了很多时间。
其实自从腾讯云的 webify 基本没什么存在感之后,我对 CNB 的期待也不会太高,不知道哪一天这个项目也会被腾讯给淡忘。但是就目前来说,拉取和推送代码快速,云端 IDE 方便,配置给得也很大方,后面试试用来编译 openwrt 的固件都是值得一试的,我们切用且珍惜吧。
Hexo上传服务器建议使用rsync来替代git上传,repo文件夹越来越大解决方法
网站被恶意镜像了该怎么办
Hexo-AlgoliaSearch插件报错“Error has occurred during indexing posts”
给hexo添加本地搜索
之前用多个google搜索,baidu搜索也用过,实际上体验并不如何好。
主要是更新慢,百度收录还不全。
所以我还尝试了 swiftype ,这个搜索引擎是收费的。
搜索效率高,收录提交虽然也不慢,但是它收费呀。
这时候我看到有个本地搜索的选项:
1 | self_search: false ## Use a jQuery-based local search engine, true/false. |
稍微了解下发现它是基于xml文件索引的,大概原理是将往期文章要素存在xml,然后js搜索对应的数据。
通过npm进行安装,这是源项目地址 https://github.com/wzpan/hexo-generator-search
。
1 | $ npm install hexo-generator-search --save |
工作原理
运行 hexo g
之后,实际会生成下面的xml文件在根路径下。节选部分结构,发现这确实只是一个内容匹配。
1 | <entry> |
加载与搜索速度都比站站外的工具快,好用,推荐。
效果如下:
演示站点: https://vrast.cn
谈谈独立博客友链
事件起因
昨天,一条交换友链的评论里,对方博主有了一连串的回复,所以我很想就“友链”说点什么,不管是自证还是狡辩,总归是要说点什么才舒服。毕竟独立博客从某种程度上来说,就是博主自娱自乐的地方。
为了便于各位看官直观了解事情的前因后果,我尽量以时间线的方式展现我们在评论中的交流。如果你觉得可能不够客观,可以点击这里直达该评论。
评论时间线
2024年7月1日
对方评论并留下了友链信息:有幸通过中文博客列表导航项目访问到贵站,希望有机会和您互换友链~
2024年7月11日
对方评论:看到您已经超过一周没有回复我了,我这边就先下链了,希望您可以回复一下
2024年7月11日
我回复:抱歉,友链页写了的“不熟可能会不添加”
2024年7月15日
对方连续回复五条:①哈哈,不过不熟怎么发现贵站呢?②鄙人一直都是认为,绝大部分网站间的互动都应起源于一次友链,如果不是有友链,很多站肯定是永远不会有互动的③更何况您所谓不熟不会加,但您并没有给我们希望和您相识的人一个机会,不是吗?④如果不是我再次回访,您都不打算回复我的评论了吗?⑤各位同为开往项目的一员,也是中文博客导航项目的一员,鄙人来申请您的友链也是十分客气的语气,但您的冷处理方式令我无法苟同,更无法理解
2024年7月16日
我回复:首先,我无法苟同你的观点。互联网大部分的网站互动并非从友链起源。我和一部分博主有相对比较密切的互动,但我们直到现在甚至还不是对方友链的一员。其次,我不止一次拜访过贵站,我自认为针对你的内容,我可能没有什么想要发表的评论,也认为未来可能不会有更多的互动。不如你也看看,你在我站留下的评论除了在友链页面,还有哪篇博文下面有吗?难道所谓的互动就是十几年前qq空间的互踩?最后,虽然我们可能同为比如开往计划的成员,但并不代表我就要因此做点什么。大家都是中国人呢。每一个我都要花费时间和精力去相处吗?请不要道德绑架我。
2024年7月16日
对方连续回复三条:①既然您也知道不可能所有人都能与他人的文章产生互动,您又为什么要强制他人要先在您这里眼熟呢?②与此同时请允许我纠正您的偏见,我自始至终没有想过道德绑架,但贵站确实对我的申请进行了冷处理,这点您又作何解释呢?如果是大家的留言您都没有回复,我自然不会来怪您,毕竟有些站点的确已经不在做下去了,但很显然我是七月一日申请的贵站友链,但直到您给五天前的他人申请回复都没有给我一个正常回复,这又是我应得的了吗?③我昨晚给贵站评论的态度完全来自我遭受的不公平对待,如果您曾主动回复我说您觉得没有眼缘、您觉得和我还不熟悉等等各种理由我都会欣然接受,并争取和您多互动再添加。但很显然,您宁可给别人回复也不回复我,我想在此以前我并没有任何行为招惹或冒犯到您吧?
2024年7月16日
我回复:我没有强制谁一定要跟我互动甚至眼熟,但是如果要友链那本该如此。友链不是挂个链接就完事,在链之前是“友”。还有你说我没有给你正常的回复,可事实上我已经回过了。如果你觉得我的做法让你认为没有被尊重或者自尊心破碎,那我可以给你道歉。
2024年7月16日
对方回复:首先,我接受您的道歉,但请您不要本末倒置,五天前他人的友链都是在发出后您主动回复的不添加,明明是同样的结果,为什么我就要被您“晾着”,偏偏要在我再发—条消息才肯回复我呢。另外,我已经申请您的QQ好友,我希望咱们都可以平静下来好好聊一聊,也就当了解彼此了,还望您同意一下
对方后来确实加了我的 QQ,附言:兹认为占用贵站珍贵的评论资源吵架想必是毫无意义的
关于此事
看过我前面更新的朋友应该知道,7月1号到7月7号的七天,我都处于非常忙碌和疲惫的状态中。在忙碌结束后,7月8号我更新了一篇日志。
对方提交友链评论信息的日期是7月1号,此后的一段时间我几乎无暇顾及博客互动。也有一些我通过 rss 订阅的博主有更新,但是没有及时去进行互动。此后的时间里虽然闲暇了下来,但是此前的评论我可能忽略掉了,没有及时回复。或者用时不时不回我消息的碎月的话来说,已经意念回复过了。
毕竟网络和博客都不是生活的全部啊,我无法做到面面俱到。
关于友链
在我写博客之初,也积极主动和许多有意思的博主申请交换友链。当然,我几乎能满足这些友好的博主并不苛刻的要求,比如有独立域名啦,有实质内容啦等等。
在去年还是前年,我停止了友链交换,并关闭了友链页面的评论框。但是期间也有个别博主在我其它文章页里提交友链信息,我可能没有回应,也可能回应过了。
在今年初,我决定重新开放交换,因为在这一两年我又认识了许多有趣的博主。同时也计划清理掉一部分无法访问的、没什么交集的和长期不更新的博客。
在重新开放交换后,我主动、单方面添加过几位博主的友链信息,比如 Jeffer.z 和网友小宋等;也有我们日常都有互动、比较熟悉却没有添加友链的博主,比如 obaby 等,其中 obaby 的域名太多但是每一个都很好记,所以我认为用不着多此一举。
有几位博主的博客可能没有提供友链信息,所以我手动去找需要填充的内容。这样做很大程度上是受了当初的友链博主(现在他的博客无法访问了)“李子白了”的影响。我认为在我博客的友链,应当是服务于我的,使我可以随时更便捷地访问其他博主的博客;而不是主要服务于其他的访客或者搜索引擎。
当然,有好多博主都整了个“朋友圈”,即通过 rss 订阅的方式,在自己博客展现其他博主更新的博文。我认为这才是更有效的独立博客互动方式,无论是对博主还是其他访客,文章外链肯定比单纯的网站外链更有价值。但是因为我技术菜又有拖延症,所以一直没实施这个计划。
在我的友链页面有一个小小的说明:
私以为,友链之所以叫“友链”,通常是因为先友后链,它的作用是记录并方便博主个人访问。
为此,我单方面添加了几位博主的链接,请博主见到后不要见怪。
\交换友链看眼缘和感觉,不熟可能不会添加!**
当初写这个说明,一方面是表明我的态度,另一方面也希望有些第一次来就直接提交友链信息的博主能够谨慎,因为一开始我总是认为对方提交了我却不添加很尴尬,这也导致了我的博客曾经出现过个别我确实不想添加的友链。但这样的说明似乎并没有什么卵用,因为还是不止一次有我从未见过的 id 在我的友链页提交友链信息。
如果都不熟,或者对方的内容确非我所爱,那贴一个外链的意义在哪呢?所以我想,友链要先“友”这一点没什么不妥。
写在最后
我没有通过上面那位博主的 QQ 好友请求,我在博客留 QQ 仅仅是因为公安网备的时候,叔叔要求我添加能联系到我的投诉和举报方式。
在我看来,加 QQ 可比第一次来就直接提交友链更没边界感。
当然,以上并非为批评谁。打心底里说,这位博主非常有教养,从始至终的语气和态度都很恰当,没有恶意的攻击和诋毁。我写这篇博文也并非是像小学生一样“挂网”,因为评论信息本就是公开可见的。
如果我经常和哪位博主互动,那说明我对你写的东西感兴趣。提不起兴趣的博客,其实真没有勉强自己互动的理由。
博客带给我什么?——博客重建7周年
自2016年12月29日博客重建以来,至今已走过7个年头。有句话叫“七年之痒”,博客重建7年后,写博客的热情因极度繁忙的工作而有所减退——本来想在2023年12月29日将这篇文章发出来,无奈闲暇时间太少,断断续续写到现在。然而,即便如此,我依然没有放弃长文写作。宁愿不写,我也不愿意将博客完全变成微博。如果没有这个信念,我也不会在2016年底选择重建博客。既然重建,那就把这个信念坚持到底。
博客带给我精神层面的提升
接受曾经的自己
博客重建伊始,我想督促自己戒掉智能手机成瘾,记录相应的心路历程。最终,博客建立的比较成功,但戒掉智能手机成瘾却失败了。
2018年,我开始记录自己的成长经历,名为《人生前三十年》。这个连载在2020年暂时停更,原因是这种记录方式并没有凸显我和家庭成员的性格成因,以及带给我的无穷伤害。我需要换一种方式去记录这一切,但由于工作的忙碌而无暇顾及。
我为何要去写《人生前三十年》呢?起因在2017年,我陷入有点严重的抑郁状态。当时的我,不知道问题的起源,受制于物质条件,我无法去进行昂贵的专业心理咨询。天无绝人之路,因缘和合之下,经过有相似经历之人的点拨,后购买心理问卷调查,我终于得以了解到,自己抑郁,以及一系列性格和行为缺陷及障碍的根源,完全来自于原生家庭。经过总结和思考,我决定以《人生前三十年》的名字将这一切记录下来。虽然文章没有写出自己想要的样子,但写作的过程极大缓解了我的痛苦,减轻了抑郁的折磨。
2019年6月,我去了当时赫赫有名的建立在安徽宣城的净土宗寺院“弘愿寺”。三天后,我离开寺院,此时我基本走出抑郁,能够正常工作和生活。从此以后,自己的性格有极大改善,虽然目前仍有缺陷——比如自己依然喜好争执——但已经和过去的自己完全不同,几乎已经彻底脱胎换骨。重建后的博客,记录了这整个历程。
这便是博客重建带给我的巨大帮助之一。精神层面的提升,对我非常重要,彻底改变了我的人生走向。如果没有通过在博客上写作,进而发生这些改变,也许我已被埋在黄土之下。
陪伴自己成长
在博客的“关于”页面,我列出了自己使用独立博客的历史。里面提到,2013年9月16日博客因主机垮掉而倒闭之时,有个唯一的数据库备份。博文数据现在完整地放在wordpress.com上,但我从来没有去回顾。直到前两个月,我在进行测试时(下文会提到我在测试什么),将数据又恢复了一次,保存在了测试站上。工作之余稀少的休息时间,我间歇性的将以前的文章通读了一遍。
以前的文章,与现在的对比非常明显。不仅透露出曾经的幼稚,还凸显出来因原生家庭环境影响而出现的性格问题,及进而导致的语言表达问题。另外,观察世界、思考问题及写作方面的思维,已在接受学校教育之后被固化,这大大限制了我从多角度、多方面去观察世界和自身,这种情况在文章里同样表现的非常明显。
所幸的是,我终于在2018年以后认识到了这些问题。在摆脱原生家庭影响方面,我做的还算是成功;摆脱思维固化方面,仍在努力挣扎。我知道,在背后那只“手”的操纵下,想做到摆脱思维固化是非常难的。但既然已经意识到这个问题了,我必须去解决掉它。
在这里,我把其中一个事情单独拎出来说说。以后我也许单独撰文回顾这件事,因此本文中我只用寥寥数语讲述一下,希望您不要把焦点全部放在这件事上。2010年时,我喜欢过一个女生,暧昧了两个月以后,她拒绝了我。大半年以后我才走出来,因为她,我写了五篇文章。现在回头看看,当初的情执,反映的问题恰恰是原生家庭环境塑造了我缺乏关爱、没有安全感、缺乏调节情绪的能力和控制欲强的性格。这个女生在2021年结婚生子,她的老公不是我,而我也从这恶劣的性格中解脱了出来。
这些成长的过程,被我用博客记录了下来。博客的存在,陪伴了我的成长。
只是2016年之前的数据,我永远都不会再公开出来。存储这些文章的wordpress.com站点,被我设置成了私密。
反抗思想的“被迫”退化
在《警惕背后的那只手——读和菜头〈重开博客〉有感》这篇文章中,我提到,背后的那只“手”在操纵着我们能够从纸质材料和互联网中获取的一切信息类型和内容,更是操纵我们只能获取他们编撰或是杜撰的一切知识、思想和情绪。在他们的操纵下,绝大多数人会愈发心浮气躁,进而丧失逻辑思维和思考能力。即便是热爱写作的人,除了会发生前文提到的观察世界、思考问题和写作方面的思维被禁锢的问题之外,还存在这些能力的退化,首先表现出的便是阅读和写作长文能力的丧失。
大秦从未消亡,法家的理论体系对治理我们的人来说从未“过时”。对治理我们的人来说,我们出现这些恶性变化对他们和他们的后人绝对利好;对我们来说,这导致我们失去了最基本的学习能力,进而会丧失重要的生活能力,沦为一个丢失灵魂的行尸走肉。
有一些被操纵的人,意识不到这些不说,反而仗着手里的话语权去替那只“手”辩护,再试图让意志不坚定或没有主观意志的人堕入更深层的思想地狱。
如果换在过去,受原生家庭影响,我是个讨好型人格,没有任何主见,别人说什么我都相信,我能想象到自己早已踏上通往奴役之路的样子。通过不断的思考、观察和写作,如今虽然也在这条路上,但行走缓慢,希望永远不会走到终点。
博客带给我技术上的进步
折腾,还是折腾
我曾多次在博客上说“多思考,少折腾”,但只要有闲暇时间,我便收不住这颗折腾的心。
这些年,注册过数不清的BSP,折腾过独立搭建Typecho、Zblog PHP、MovableType、Flatpress(文本数据库)、Ghost、PivotX(已停止开发)、Farbox 2.0,以及已经记不住名字的程序。前些日子,我利用一个随时可能跑路的个人主机商的月付版高配VPS折腾了消耗运行内存很严重的Halo程序。有的程序折腾的掉头发,有的则能做到熟练使用。
我已熟练掌握如何利用Netlify、Vercel和CloudFlare Pages在线编译Jekyll、Hexo和Hugo,而不是本地生成html再上传。
我在自己的VPS上用过Ubuntu、Debian、Centos和AlmaLinux操作系统,在VPS上用过纯命令行操作的LAMP和2023年发生挂马事件的LNMP,也用过宝塔、1Panel、AMH、WDCP、WebAdmin等服务器控制面板。
现在,我将目标放在使用Litespeed环境、Mariadb数据库的CyberPanel面板。我的两台VPS分别在跑OpenLitespeed和已开通Starter Plan(免费)的Litespeed Enterprise。
我曾发布过3个Typecho主题,分别是Diary、Write和Simple,修改并发布了Typecho的目录树插件。
我曾魔改几个WordPress主题,包括现在自己在用、啊呜喵在用的,以及几个在测试站上欣赏的。
我还曾无偿帮助过几位博友建立、维护自己的博客。
在折腾的过程中,虽然远达不到精通的程度,但还是了解了不少东西,促使我能够基本独立进行博客的建立和维护,还能帮助博友解决一些常见的基础问题。在技术层面之外,与人心有关的种种,我也深刻领悟了——我在求助技术问题时,曾被少部分博主嘲讽,特别是折腾Bitcron期间;当思想本可以碰撞出火花时,极个别博主却不想真心讨论问题,只想让你接受,只想教育你,只想证明你是错的,在找不到理由时,便直接进行人身攻击。可又能怎么样?始终没能阻止我技术和思想的成长。
折腾是我的爱好,但我不会将它变成职业。有位WordPress免费主题开发者的前车之鉴便是如此。
博客运营的备用选择
经过折腾,我可以做到不拘泥于某个特定的服务,某个特定的技术去维护博客。假如,提供服务的主机商倒闭了,或服务质量大幅度下降,可以立刻迁移;某个著名的服务器控制面板加入了后门(懂得都懂),可以立刻使用其他的面板;博客程序能做到无缝切换,不损失任何数据……
为了博客能顺利的维护下去,我准备了备选方案。
前面提到,我为了测试而恢复了旧的博客数据。我测试的,正是上文提到的Litespeed Enterprise。我花费0元购买了Litespeed Enterprise的Starter Plan,复刻了与目前所用虚拟主机完全一致的服务质量和使用体验。如果目前的虚拟主机不再使用,我可以在自己的VPS上独立托管这个博客。
对于使用Litespeed Enterprise的虚拟主机,或者专业的WordPress Hosting,也有备选,虽然花销会比目前使用的虚拟主机高,但依然低于使用VPS的费用。
等待天明
影视节目制作人季业曾说过这样一段话:
如果天总也不亮,那就摸黑过生活;如果发出声音是危险的,那就保持沉默;如果自觉无力发光,那就别去照亮别人。但是——但是:不要习惯了黑暗就为黑暗辩护;不要为自己的苟且而得意洋洋;不要嘲讽那些比自己更勇敢、更有热量的人们。可以卑微如尘土,不可扭曲如蛆虫。
摸黑生存并不可怕,可怕的是为黑暗辩护;同样可怕的是,身处黑暗却不自知,以至于双目失明。
我想起这样两类人:
第一类人,代表之一便是斯维拉娜·亚历塞维奇在《二手时代》中记录的,那些在罪恶的时代结束之后反而仓皇失措的人。
第二类人,代表之一则是东晋、姚秦时期著名高僧鸠摩罗什。从公元382年开始,他经历了人生至暗的20余年,但他依然没有放弃信仰和信念,厚积薄发,最终成为一代高僧,译经三十五部,广为流传到今天。
我正在向鸠摩罗什及以他为代表的第二类人学习。在至暗时刻,我一直试图点燃烛光,哪怕再微弱,也要照亮内心。如果能唤醒他人,那便是功德无量。我相信,天亮之前是最黑暗的时刻,熬过这一刻便是黎明的曙光。我会耐心守护心中的烛火,拼尽全力等待天明。
魔改笔记七:分类条及外链卡片
Friend-Circle-Lite:轻量友链朋友圈
Github Action实现友链状态检测
安全跳转页面·插件版
魔改笔记六:twikoo及导航栏美化
安全跳转页面·重制版
twikoo仿段落评论,实现快速评论功能
魔改笔记五:从头开始,手搓一个关于页面
魔改笔记四:友链页重构及友链朋友圈适配
折腾瑞芯微RV1126嵌入式开发板
2020年前后,当华为海思被美国制裁时,国内安防芯片缺口很大(安防领域,当时海思IPC SoC大约占有70%市场,DVR/NVR SoC大约占有90%市场)。之后群雄逐鹿,瑞芯微也适时推出了两款面向IPC的SoC芯片,RV1126(4K800万IPC)及RV1109(500万IPC)。RV1126采用四核32位ARM Cortex A7架构,有2T算力的NPU,适合用来做视频编解码,跑与视频相关的算法模型。
手边有一块闲置很久的基于RV1126的嵌入式开发板,1G内存,自带8G eMMC硬盘。闲暇之余,想用来安装宝塔面板,搭建nginx等环境,然后跑web应用。厂家提供的固件是基于 buildroot的,如此,需要从源代码开始,编译和配置自己需要各种软件和库。对此我一窍不通,难度太大,只能作罢。
最近发现厂家更新了固件,提供了基于Ubuntu的底层固件,之前的想法又冒出来了,试了试,居然成功了,这里做些回顾记录。
刷机
刷机方法与刷安卓手机类似。电脑首先安装usb驱动,瑞芯微有提供驱动安装助手–DriverAssitant_v5.0(下载)。驱动安装好后,开发板通过USB与电脑连接,识别到设备。
瑞芯微的刷机工具–RKDevTool(下载),刷机过程中可能出现的问题与安卓刷机基本一样,包括不限于USB线,设备连接,识别,驱动等方面。
RV1126开发板厂商提供的基于Ubuntu的固件–RV1126-Ubuntu-20.04-firmware_20240227(下载)。
环境搭建配置
刷完机,插上网线,因为设备默认DHCP,搜索查询到设备的IP,然后SSH登录。
1panel面板
因为时常操作云服务器,此时第一想法是安装宝塔面板。却被提示在线安装的宝塔,不支持这个arm 32位设备。让去试试宝塔5.9。简单搜索了下,不知道去哪弄宝塔5.9的安装包,官方的离线安装服务里可能有旧版的,但要收费。(写此博文时,又在网络搜索一番,发现有好心人搜集整理了旧版本的宝塔,此处)
转念想到何不试试其他的面板程序,比如1panel。1panel面板官网写着支持armv7l服务器架构。试了下,果然安装成功。有宝塔的经验在先,1panel面板的安装,使用上手很快。终端SSH及文件管理,很直观,与宝塔的使用基本一致。
frp
为了方便SSH远程登录,及面板的远程管理以及后续web站点能外网访问,首先用上frp。用一台阿里云香港服务器(2C2G30M)做frp的服务端,配置好。虽然第一次使用frp,因工作原因,对p2p,nat穿透,端口映射,DDNS知识了解很多,所以对frp理解,上手,使用起来很容易。
frp的设计理念可能是要保持服务端配置的精简,统一(在客户端做各种区分),比如保持服务端唯一的对外http端口,https端口,ssh端口等。如果有多个对外服务(比如web应用),只需要在frp客户端做配置即可,通过绑定不同域名来区分不同web应用(而非常规的采用不同端口区分不同web应用),如此思路很清晰,就是有点费域名。:-)
持续将近半个月的frp使用下来,很稳定,速度也很好。当然,这可靠性多半要归我这台2C2G30M的阿里云香港服务器。看网上的讨论,这个系列的阿里云香港服务器很抢手,性价比很高。我比较看重的,回国内延时非常低,在广州ping值延时只有8-9ms,比广州服务器ping值还低。(对于我用来科学上网,非常完美)。
说个题外话,我曾持续(从一个月到一年时间不等)测试各种云的香港服务器(比如狗云,马云,鸡云,草云。当然还有大厂的,腾讯云,华为云,天翼云等),回大陆线路,表现最好最稳定,性价比最高的还是阿里云。
应用
解决了服务器远程管理,外网访问问题。剩下的就是搭建网站了。使用宝塔时,习惯一键安装NMP等环境。1panel也有类似功能,不过其提供的默认web环境是OpenResty,安装时却出了点状况,始终安装失败。
1panel的理念是一切皆docker。安装的所有应用均是基于docker的。安装OpenResty失败,起初以为是docker镜像源,网络问题。不过,这个很快排除了。
前段时间网络上讨论很多,docker hub及国内的众多加速服务在国内完全无法用,当然解决办法也很多。我比较喜欢的办法,对于个人用户,可以将常用的镜像通过GitHub action同步到阿里云容器镜像服务 ACR,然后选择公开或者私有,需要时从ACR拉取容器镜像。(见 docker_image_pusher)
这种方法,我使用多次,国内服务器上拉取容器镜像,速度很快,也稳定可靠。当然,更常规的做法是使用docker hub镜像加速,比如1panel提供的临时加速地址:https://docker.1panel.live 。目前大环境下,国内的docker hub镜像站几乎都关了。我上面提到的docker image pusher方法对于个人用户是非常实用的。
排除网络问题,查看日志,发现安装OpenResty失败的原因是因为1panel商店里上架的这个版本不支持我使用的armv7l处理器。此时恍然大悟,然后又有点忧心。相较于x86,armv7l算比较小众,很多docker应用可能没有适配。如果通过1panel自带的商店安装,估计很多安装不了。如此,对于这个开发版使用1panel面板作用不大了。当然1G内存,外加4核心处理器,本身有点鸡肋和尴尬。也只能用来跑些简单的web应用。
找到问题以后,手动安装了nginx/1.18.0,PHP 7.4.3-4ubuntu2.23 (cli),这样能来跑静态及PHP站点了。
目前这个开发板上运行的web应用有:
- 1panel面板
- frp
- Pi Dashboard
- twikoo(实验)
- uptime-kuma
- blog(节点之一)
之前在网友小宋的博客看见介绍的用来监控树莓派状态的应用Pi Dashboard,UI比较好看,起初试了在云服务器上跑,但是x86的服务器获取不到CPU温度。如今这个是arm的开发版,安排上。
通过docker安装的twikoo,uptime-kuma可以成功运行。
作为我这个hexo博客节点之一(目前我这个博客节点有:阿里云广州,华为云北京,京东云北京,海外netlify以及此开发板的香港服务器frp反代)。通过Github action构建,然后分发到不同节点服务器上,方法参见我之前的博文:博客网站更新总结-2023–Github-action及通过GitHub Action将博客网站等静态文件同步到云服务器。
考虑停电,断网,设备重启等意外情况,给相关程序加上开机启动,进程守护。同时因为只有1G内存,加上定时任务,定时清理内存,缓存。此时1panel面板的价值作用体现了。
前面提到frp是通过不同域名区分不同网站的,最后各web网站的访问地址是域名+端口,比如one.jiangyu.org:8090,two.jiangyu.org:8090。给这些源站套上CDN,就能不带端口,直接用绑定的CDN域名访问对应的web站点。只是这样一来,就更费域名了。:-)
还有一个问题。绑定CDN以后,我习惯强制https,如此需要给CDN上传SSL证书。如今SSL证书有效期已缩短到90天(我曾在6个月前的博文 SSL证书,部署及相关知识中总结过与SSL证书相关的知识,彼时证书有效期还多是1年,半年不到普遍都是90天了),如果自己的VPS部署站点,开启https,申请SSL证书,然后绑定,不断更新,这都能自动化完成。可是在CDN应用里,需要自己上传SSL证书,如果过期,需要重新再上传新的证书。如果使用的是大厂CDN,这个问题比较好解决,厂家开放了各种api,基于此很多大神帮忙造好了轮子,SSL证书申请,上传到CDN,部署,更新都能通过脚本自动化完成。可是对于小厂CDN,一般没开放api或者没有现成的造好的轮子,需要自己频繁手动更新SSL证书,是个大问题。
最近看到有某CDN小厂提供了名为证书无忧的服务,能很好解决上述问题。在CDN配置里,第一次先上传自己的SSL证书,在证书到期前,会自动更新有效期为 90 天的免费证书。目前公测期间这个功能免费,以后可能每次成功更新证书收费1-2元。这是个很好的功能,不知道会不会有其他CDN厂家跟进。
其他
这个开发板尺寸100 x 60mm,比树莓派略大,买来一个树莓派的亚格力外壳(外壳整体尺寸与这个开发板相当),重新钻孔,保护起来。买外壳时,看见店家有与外壳配套的散热风扇,也买了一个。测试了一段时间,对比发现,这个5V 0.2A的小风扇能给CPU降温5-6℃。不过因为RV1126这颗SoC面向的是安防,消费类IPC领域,低功耗,温度控制这块做得比较好。即使不加散热风扇,在室温30℃时,一般负载下运行时的最高温度也只在50℃上下,离会降频的85℃还很远。
这个开发板有个40pin 的 gpio接口,厂家文档说兼容树莓派的接口,除此没有更多资料。本来想着如同树莓派一样,接几个诸如温度,湿度这样的传感器,调试一下,资料欠缺,需要补的课很多,只能暂时作罢。
hello YU say!
一直将博客当成知识输出的平台(如何做好笔记),所写博文均是(相对)深思熟虑的结果。但日常,时常会有只言片语的想法,瞬间的感受想要表达,发布,用长博文不太合适。
在WordPress时代,有关注一款主题blix,blixed(WordPress领域的大佬,我爱水煮鱼还一直在使用这款主题)。这款主题有个功能,叫Mini Entries。主题内置了一个叫BX post type的字段,专门用来发布短博文,即不写标题,博文可能就短短的一句话,一张图,会自动更新在页面(类似微博,Twitter这样的效果)。当时(2009年前后)的WordPress似乎自定义字段功能还不怎么完善。
今天看WordPress,通过自定义字段,发布短博文很方便了。见旅行漫记的随笔板块有使用这样的短博文样式效果。
说这一段,是因为一直想在hexo这样的静态博客框架里实现上面提到的短博文的效果。后来看见了五木老师的哔哔点啥 2.0 By Memos,能将memos内置到静态博客里。大体上就是我想要的短博文效果。Memos高度复刻flomo(浮墨笔记),主打能随时随地将自己的想法记录保存下来。
flomo可以通过多种终端、方式无压力输入记录自己的想法,将flomo与静态博客相结合其实就能满足我的需求,但是如果使用flomo api需要开通会员,于我这完全没必要。我仅仅只是把想法记录下来,后续的回顾,整理之类都不会再依靠flomo(见我曾经总结的,上面提到的如何做好笔记一文)。
Memos没有api方面的限制,但Memos有个我认为最致命的问题,不方便手机端输入。使用Memos,flomo这样的工具的最大目的应该是方便手机端能随时随地记录自己片刻的所思,所想,所见。对于Memos,虽然有网友适配的第三方手机客户端,但UI界面太丑,简陋,而flomo则有非常方便的手机端输入方式,客户端,微信等。以上是我迟迟没怎么使用Memos,宁愿暂时使用flomo的重要原因。
如此一直默默关注着Memos,前不久发现,Memos开始支持Telegram Bot,通过Telegram 手机端随时随地发布自己的想法,然后会自动保存到Memos,完美解决了Memos手机端功能缺失,不完美的问题。
马上上手,安装Memos,然后绑定Telegram机器人。同时参考上述五木老师的教程,将Memos内置到博客,以后通过Telegram发布的所思所想,会自动显示在此博客–说说(YU say)。如此比较完美的实现了在静态博客随时随地发布短博文的功能。
喜悦之情溢于言表,写文以记之!
- 白宦成
- Hexo 构建过程中报错 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed – JavaScript heap out of memory 如何处理?
Hexo 构建过程中报错 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed – JavaScript heap out of memory 如何处理?
最近在处理 Linux 中国的静态站点,在技术选项上,为了方便修改,选择了 Hexo 来建设。
数据从 Discuz 转换到 Markdown 已经处理好了,但在构建过程中遇到了一些问题,会报如下错误
linux [main]
hexo g
INFO Validating config
INFO Start processing
INFO Files loaded in 2.37 min
<--- Last few GCs --->
[4685:0x118008000] 188193 ms: Scavenge (reduce) 3974.1 (4131.6) -> 3974.1 (4131.6) MB, 1.96 / 0.00 ms (average mu = 0.143, current mu = 0.117) allocation failure;
[4685:0x118008000] 188198 ms: Scavenge (reduce) 3977.5 (4135.0) -> 3977.5 (4135.0) MB, 1.88 / 0.00 ms (average mu = 0.143, current mu = 0.117) allocation failure;
[4685:0x118008000] 188202 ms: Scavenge (reduce) 3981.0 (4138.5) -> 3981.0 (4138.5) MB, 1.79 / 0.00 ms (average mu = 0.143, current mu = 0.117) allocation failure;
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0x104762660 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
2: 0x1048dcc84 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
3: 0x1048dcc34 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
4: 0x104a82410 v8::internal::Heap::CallGCPrologueCallbacks(v8::GCType, v8::GCCallbackFlags, v8::internal::GCTracer::Scope::ScopeId) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
5: 0x104a84e98 v8::internal::Heap::ComputeMutatorUtilization(char const*, double, double) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
6: 0x104a84b80 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
7: 0x104a83f08 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
8: 0x104a829a4 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)::$_6::operator()() const [/opt/homebrew/Cellar/node/21.5.0/bin/node]
9: 0x104a8277c void heap::base::Stack::SetMarkerAndCallbackImpl<v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags)::$_6>(heap::base::Stack*, void*, void const*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
10: 0x104680028 PushAllRegistersAndIterateStack [/opt/homebrew/Cellar/node/21.5.0/bin/node]
11: 0x104a8122c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
12: 0x104a7977c v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
13: 0x104a79f20 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
14: 0x104a61988 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
15: 0x104a58874 v8::internal::MaybeHandle<v8::internal::SeqTwoByteString> v8::internal::FactoryBase<v8::internal::Factory>::NewRawStringWithMap<v8::internal::SeqTwoByteString>(int, v8::internal::Tagged<v8::internal::Map>, v8::internal::AllocationType) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
16: 0x104d74a6c v8::internal::Runtime_StringBuilderConcat(int, unsigned long*, v8::internal::Isolate*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
17: 0x104573954 Builtins_CEntry_Return1_ArgvOnStack_NoBuiltinExit [/opt/homebrew/Cellar/node/21.5.0/bin/node]
18: 0x1045e94c4 Builtins_RegExpReplace [/opt/homebrew/Cellar/node/21.5.0/bin/node]
19: 0x1045625ac Builtins_StringPrototypeReplace [/opt/homebrew/Cellar/node/21.5.0/bin/node]
20: 0x1044e8b84 Builtins_InterpreterEntryTrampoline [/opt/homebrew/Cellar/node/21.5.0/bin/node]
21: 0x1289db514
22: 0x1289dbae4
23: 0x128def07c
24: 0x1289db514
25: 0x128d2de58
26: 0x1289db514
27: 0x1289d9e20
28: 0x1288da1d8
29: 0x128de4df4
30: 0x1288ce2bc
31: 0x1288c99d8
32: 0x1288de57c
33: 0x1288de6d8
34: 0x1288d0654
35: 0x1044e68ac Builtins_JSEntryTrampoline [/opt/homebrew/Cellar/node/21.5.0/bin/node]
36: 0x1044e6594 Builtins_JSEntry [/opt/homebrew/Cellar/node/21.5.0/bin/node]
37: 0x1049fca88 v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
38: 0x1049fc480 v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
39: 0x1048f093c v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
40: 0x104681110 node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
41: 0x104681508 node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
42: 0x1047001fc node::Environment::CheckImmediate(uv_check_s*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
43: 0x107d57ec8 uv__run_check [/opt/homebrew/Cellar/libuv/1.47.0/lib/libuv.1.dylib]
44: 0x107d52cc4 uv_run [/opt/homebrew/Cellar/libuv/1.47.0/lib/libuv.1.dylib]
45: 0x1046819dc node::SpinEventLoopInternal(node::Environment*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
46: 0x1047a9ad4 node::NodeMainInstance::Run(node::ExitCode*, node::Environment*) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
47: 0x1047a983c node::NodeMainInstance::Run() [/opt/homebrew/Cellar/node/21.5.0/bin/node]
48: 0x104722e80 node::Start(int, char**) [/opt/homebrew/Cellar/node/21.5.0/bin/node]
49: 0x187fb10e0 start [/usr/lib/dyld]
[1] 4685 abort hexo g
这个报错中,最有价值的便是 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed – JavaScript heap out of memory。
这个报错的意思是目前 JavaScript 使用的内存已经超出了可用范围,导致程序挂掉,而如果想要解决这个问题,只需要分配更多的内存给 Hexo 即可。
只需要在构建的命令前加入NODE_OPTIONS=--max-old-space-size=24576
,就可以分配更多的内存给 Node.js 。这里的 24576 是 24GB 内存的含义,你可以根据你的需要来选择。
PS. Linux 中国的数据太多,以至于我用 Hexo 分配了 24GB 都不行。。我决定换 Hugo 了。。希望 Hugo 可以。。。