临时邮箱:开发者的隐私工具实践笔记

上周,我正在为一个新的开源项目收集各类API文档和开发工具时,遇到了一个令人烦恼的问题:几乎每个开发资源网站都要求我注册并验证邮箱。在此之后,我的邮箱已经开始收到营销邮件以及各种营销通知。 那一刻,我意识到自己需要一个临时邮箱。 困境与解决方案 作为一名开发者,我经常需要注册各种服务:测试新的API、下载SDK文档、注册测试账号验证自己应用的注册流程…每次都使用真实邮箱,意味着你的收件箱将永远被各种营销邮件和通知填满。 朋友曾开玩笑说:”你的主邮箱已经不是工作工具,而是各大平台的营销战场了。” 这句话虽然夸张,但却戳中了痛点。 就在我为了测试一个新开发的注册流程需要创建20个测试账号时,临时邮箱成了我的救星。 临时邮箱 临时邮箱(也称一次性邮箱或匿名邮箱)是我现在开发工作中不可或缺的工具。它无需注册,打开网站就能即时获得一个可用邮箱地址,用完即丢,简单高效。 我第一次使用临时邮箱时惊讶于它的简洁性 —— 没有复杂的界面,没有强制注册,只有一个随机生成的邮箱地址和一个接收邮件的界面。作为崇尚简洁设计的开发者,这正合我意。 我的实际应用场景 在日常开发工作中,我发现临时邮箱在以下场景特别有用: 批量测试注册流程:当我需要验证应用的注册逻辑时,创建10个不同测试账号变得异常轻松。再也不用担心”邮箱已被注册”的提示了! API服务对比测试:上个月,我需要对比三家不同的支付API服务。每家都需要注册开发者账号,使用临时邮箱让我能快速注册并获取测试凭证,而不必担心后续的营销邮件轰炸。 下载开发资源:很多SDK、教程和开发工具都藏在”免费下载”的邮件验证后面。使用临时邮箱,我能快速获取资源而不必担心隐私泄露。 临时团队协作:有次与外部开发者短期合作,我们使用临时邮箱注册了一个共享的项目管理平台,项目结束后自然”过期”,不留痕迹。 使用心得与建议 经过几个月的实践,我总结了一些使用临时邮箱的经验: 优点体验: 开发效率提升:测试各种服务时再也不用担心邮箱问题,专注于代码和功能。 隐私得到保护:我的主邮箱垃圾邮件明显减少,重要邮件不再被淹没。 使用无负担:不需要记住额外的账号密码,打开网站即用。 需要注意的限制: GitHub、AWS等重要开发平台会识别并拒绝临时邮箱域名,这很合理,毕竟这些平台需要可靠的身份验证。 有些临时邮箱服务稳定性不佳,我曾在等待一个重要的API密钥邮件时遇到服务中断。 一些推荐 目前我在使用这些临时邮箱服务,是我认为比较稳定和易用的: Temp Mail TempMail 365 写在最后 作为注重效率和隐私的开发者,临时邮箱已经成为我工具箱中的常用工具。它不仅保护了我的主邮箱和个人信息,也简化了测试流程,让我能更专注于代码本身。 当然,它不适合注册重要的开发账号或长期项目协作平台。对于GitHub、AWS、Azure等核心开发平台,我依然使用专业的开发者邮箱。临时邮箱是辅助工具,而非替代品。 如果你也经常需要测试注册流程或频繁注册各类开发资源网站,不妨试试临时邮箱,它可能会为你节省大量时间,并让你的主邮箱恢复清爽。

2025/6/21
articleCard.readMore

为 QuMagie 备份的照片添加 Exif 信息

前言 一直想入手一台成品的 NAS。在此之前, 我一直用的是一台蜗牛星际的黑群晖 配了 4块各种型号的 500G 二手硬盘, 两两组 RAID1, 连续运行快4年了, 也遇到了停电几次,别说, 矿机就是耐造, 依旧稳得一批。 正好遇到双十一, 看到威联通的 TS-564 这款机型, 配上 4T * 3 只要 3.7k, 还是希捷酷狼。于是便入手了, 还顺带整了台 APC 的 UPS。对了, 顺带还入了快 1T 的希捷酷鱼 SSD 作为系统盘, 来避免 HDD 的频繁读写。 总计 4.5k 吧 别问我为什么不买 464C, 因为这个四盘位的外观已经烂大街了, 个人感觉有亿点丑了。 u1s1, 威联通的系统是真的比不上 群晖的 DSM (众所周知 群晖是买系统送 NAS), 动不动就 加载中… 和老年机一样。 后期再使用一段时间,应该还会再出一个具体的评测。 QuMagie QuMagie 是 QNAP 出品的一个类似AI相册的平台, 和群晖的 photos 差不多, 也支持自动分类, 人脸识别等功能。 但是这个 QuMagie 的时间线是真的不大行, 在手机客户端备份照片时, 部分截图等因为没有 exif 信息, 会全部使用备份时间作为拍摄时间, 导致时间线混乱。 添加 Exif 信息 在网上找了一圈, 也没有找到一个较为完美的解决方案, 于是花了点时间, 写了一个脚本, 用于为 QuMagie 备份的照片添加 Exif 信息。 可以在 Github 中找到, 原理就是读取文件名中的时间信息, 然后写入到 exif 的 DateTime 和 DateTimeOriginal 中。 使用方法 在控制台中启用 SSH 使用 SSH 连接到 NAS, 用户名和密码同你的管理账号密码 从 Release 下载最新的 quexif, 对于 qnap 的 intel 机型, 通常为 quexif-linux-amd64 通过 File Station 或 SFTP / SMB 等方式将 quexif 上传到 NAS 在 ssh 中, 运行 chmod +x quexif 使其可执行 运行 ./quexif -p /path/to/your/photo/folder 即可 提示 目前只支持 jpg (jpeg) / png 格式的照片, 其他格式的照片会被忽略。

2024/11/5
articleCard.readMore

Riverpod - flutter 状态管理的应用

前言 Riverpod 是 Flutter 下知名度较高的状态管理依赖,同样出自 Provider 的开发者 rrousselGit 之手。 其实仔细去看 Riverpod 似乎只是 Provider 的拼写打乱了顺序,其提供了更简洁的API 设计,实现了依赖注入。 如果去看过 rrousselGit 的主页,你可以发现,他也是著名的 Flutter_hooks 的作者,RiverPod 也理所当然的拥有 hook 相关的血统 > HookConsumerWidget, 我们可以在享受 hooks 的同时,直接使用Widget.ref(provider).watch 来监听变更并自动刷新页面。 为什么 Flutter 需要状态管理 Flutter 作为优秀的跨端框架,其使用的声明式UI有诸多优势,但嵌套的组件给数据传递带来了极大的挑战。 如果将数据在 组件类的构造函数中携带,并在数层中进行传递,随着代码量的提升,将会极大的增加代码的复杂和易理解程度。 因此状态管理组件出现了,其提供了一个清晰的模型来管理数据流,确保数据在正确的时机以正确的方式流动。这有助于避免数据不一致和难以追踪的 bug。通过集中的状态管理,我们可以更加容易的理解和增删需要传递的数据。 举个例子 我们可以使用最常见的 Flutter demo 来看, 在初始化完成项目之后,我们便可以看到这个例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.headlineMedium, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } 因为 需要渲染的页面和按钮在 同一个组件 MyHomePage 下 因此我们可以很简单的在按钮点击的同时 setState 来使Flutter 感知数据的变化 并重新渲染页面。 组件分离 但是 多数情况下, 我们需要渲染的页面,和改变数据的按钮 并不在一个组件中,例如,如果我们将这个按钮单独封装在一个类中。这种情况下,我们应该如何在点击按钮的时候增加数据呢? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( '${_counter._count}', style: Theme.of(context).textTheme.headlineMedium, ), ], ), ), floatingActionButton: const Button(), ); } } class Button extends StatelessWidget { const Button({super.key}); @override Widget build(BuildContext context) { return FloatingActionButton( onPressed: _counter.increment, tooltip: 'Increment', child: const Icon(Icons.add), ); } } 使用 ChangeNotify ChangeNotify 是 Flutter 下用于监听数据变更的组件,在这个场景下,我们可以使用其监听 counter 的变化, 并重新渲染页面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 class Counter extends ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } Counter _counter = Counter(); ...... class _MyHomePageState extends State<MyHomePage> { @override void dispose() { _counter.dispose(); super.dispose(); } @override void initState() { super.initState(); _counter.addListener(() { setState(() {}); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( '${_counter._count}', style: Theme.of(context).textTheme.headlineMedium, ), ], ), ), floatingActionButton: const Button(), ); } } ...... 使用 RiverPod 再简单场景下,ChangeNotify 和 ValueNotify 已经能够胜任, 但对于复杂场景,还是有一定的局限性。 先添加如下依赖 (这里使用 Flutter_hooks 举例) 1 2 3 4 5 6 7 8 dependencies: flutter_hooks: ^0.20.5 hooks_riverpod: ^2.5.1 riverpod_annotation: ^2.3.5 dev_dependencies: build_runner: ^2.4.11 riverpod_generator: ^2.4.0 别忘记在最外围增加一个 ProvideScope 1 2 3 void main() { runApp(const ProviderScope(child: MyApp())); } 接着新增一个 counter_provider.dart 文件 1 2 3 4 5 6 7 8 9 10 11 import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'counter_provider.g.dart'; @Riverpod(keepAlive: true) class Counter extends _$Counter { @override int build() => 0; void increment() { state++; } } 运行 代码生成 1 $ dart run build_runner build 他将会生成一个 counter_provider.g.dart 文件 1 2 3 4 // 接着我们可以使用 `ref.watch` 来监听数据的变化 ref.watch(counterProvider); // 使用 ref.read().increment() 增加1 ref.read(counterProvider.notifier).increment; 完整的例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import 'package:daka/counter_provider.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; void main() { runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(), ); } } class MyHomePage extends HookConsumerWidget { const MyHomePage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( ref.watch(counterProvider).toString(), style: Theme.of(context).textTheme.headlineMedium, ), ], ), ), floatingActionButton: const Button(), ); } } class Button extends HookConsumerWidget { const Button({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final counter = ref.read(counterProvider.notifier); return FloatingActionButton( onPressed: counter.increment, tooltip: 'Increment', child: const Icon(Icons.add), ); } }

2024/7/19
articleCard.readMore

夜景随拍

带上新买的 mini 4k 和 单反,随便拍了拍一些夜景。 TIPS: 所有图片均为原创,未经允许禁止转载

2024/6/16
articleCard.readMore

大疆 Mini 4K 初体验

大疆 最近发布了一个 特别便宜的 mini 系列无人机, 新品+618 直接给单电的价格干到了 1499, 于是 果断下单, 在附近尝试了一下。 可惜旁边是个机场,只能限高 120, 不过从第三视角看还是很不错的,虽然宣称是 4k, 但放在电脑上有点勉勉强强,不过对于这个价格来说,已经很不错了。 先简单的看一下拍摄效果吧 (图片非原图)

2024/6/7
articleCard.readMore

5月12日 随笔

现在是 凌晨的3点50分 未眠。 不懂何时,开始慢慢的害怕记录,在写作时经常提笔又忘,似乎是为了追求绝对的完美,害怕一些小小的错误,会对别人带来误导,于是又将写下的文字,匆匆删去。 人们似乎总喜欢沉溺在过去,想起这18年的夏天,原来已经过去了那么久,又开始怀念21年的夏天。疫情时代也过去了那么久。 常常听着几首歌发呆,思考,以后究竟会做些什么,哪方面的工作呢。自己又是多渴望像别人一样,背上行李,去野外露营,过上房车生活。但转念又想 有些脱离现实。 小时候总觉得,时间过的,真的很慢。等长大了才发现… 不知何时变成了那些所谓的大人模样。开始思考怎么赚钱,怎么养活自己,怎么处理人情世故。 很喜欢网易云音乐 苏子星河的一个歌单,名字是「荒诞的梦」末日余欢与最后的狂奔, 那些我们曾做过荒诞的梦,着迷于假象。 他们曾说2012年是 世界末日,你说,或许在那一刻我们已悄然消失。摘下戴着许久的眼镜,是时候回归现实生活了。

2024/5/12
articleCard.readMore

你好 2024

前言 和, 往年一样,又到了年度总结的时候了。似乎好像已经很久没有更新过博客了。 今年陆陆续续 写过一些东西,也放弃过很多东西。 其实我还是很喜欢大一上学期的住宿生活,六个人的寝室,住着五个人。随说因为疫情,我们总是过着两点一线的生活,穿梭在教学楼与宿舍之间。 还记得那时候,接触到了森林这款游戏,还想念着五个人追着野人跑的日子。也许我是个特别讨厌 名利的人,我不喜欢得到太多的关注,大学是一个小社会,其中也充斥着太多的利益关系。 其实很多人就像是那森林中的野人,喜欢着对自己有利的东西,不断的追逐着,却忘记了自己的初心。通俗的讲,谁对他好,他就把他捧上天。在我遇到的人中,总感觉充斥着太多的虚伪,等级的划分。 人心是最难以琢磨的,请记住,没有永远的朋友,只有永远的利益。 有些东西,我不想讲的太细,我不太喜欢这样的环境,也许我喜欢简单些的生活,不用去想太多,不用去计较太多。 一些奖项 字节跳动 2023 青训营 优秀营员 年初,我参加了字节跳动的 青训营,有幸学习了字节关于 Go 语言相关的知识,也和队友一起完成了一个简易的抖音。第一次接触 微服务,感受到了微服务的魅力,也学习到了很多东西。 我使用了 Go-Zero 这款框架,但是对于日志收集,链路追踪,监控等等,我还没有详细的使用,对于数据库分库分表只有一些简单的了解,还没有实际的使用过。 优秀寝室 其实能获得这个奖项,还挺意外的 :> 看看我们的寝室: 去看了 Quinn 的演唱会! 一直很喜欢 Quinn 的歌曲,他的歌曲真的很有感染力。 节选自 Quinn 的专辑《理想》- 《樂色》 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 爱你的在自我感动幻想中遨游 恨你的想诋毁不管理由多荒谬 你望着苍穹,心不自觉惶恐 你的生命也许从来不在你掌控 而那匿名的恐吓,你提防的红色 把你击落下马之后居然哭泣得痛彻 然后安慰你,却也没忘邀功颂德 先把一切重设,还想和你同乐 第一份兼职 我的第一份兼职 是 <瑞幸咖啡> 一开始是 16/h,在考取咖啡师资质后,涨到了 21/h 第一天去 就是贴贴杯子,按按糖浆什么的,但是站着那么久,真的会脚疼。 要背很多很多配方,别说了,头会爆炸 … 瑞幸真的很严格,每小时都需要洗手,碰到鼻子,脸,还得去洗。真的,很讨厌瑞纳冰!每次做完要洗好久!(少点少点这个) 终于拿到了 拾光的软著 ps: 审核真的很慢, 等了我块 6个月 准备参加 集成电路应用与设计大赛 这是我第一次参加这样的比赛,也是第一次接触到了 FPGA, Verilog, 华大九天等等。 现在我的脑子里都是 LM324, CD4511, 运放, ADC .. 爆炸 我主要负责的是 使用 lk8810s 测试机 测试芯片的 IOH,VOH, 开短路 等等数据。 还有华大九天的 模拟电路设计。 今年(2024) 3月份的比赛,其实还是挺紧张的。 2024 2024年,希望自己能有所改变,能有所进步。不在局限于过去的那个小空间,不在局限于过去的那个自己。

2024/1/27
articleCard.readMore

HHKB 使用体验

应该是去年双11吧,入手了第一款属于自己的 HHKB, 我选择的是 HHKB Professional HYBRID Type-S (无刻) 很早就听说 HHKB 了,不过因为价格等因素,一直都没有入手,双11应该是便宜了一点吧,还是狠狠心入手了。经过几个月的使用,也来谈谈我的使用体验吧。 作为一款 Happy Hacking Kyeborad, 我个人感觉吧,手感还挺好,噪音大小也在可接受范围内。在此之前对于长轴键盘也只使用过 Keychron 的 K3 (矮茶轴) 对比起来,HHKB 键程稍微长一点,同时的话键盘的高度也要高许多,还是建议搭配掌托使用的。 噪音方面,由于怕被舍友撵出去,还是选择了 Type-S (静音版),综合下来,还可以接受吧。比我原来的矮茶轴可小多了。 连接方面,HYBRID 版本支持双模,即 蓝牙和有线。蓝牙支持三设备切换,可以通过 Fn + Control + 1/2/3 快捷切换连接设备,实际体验下来,设备切换在 1s 内,这点做的还是比其他厂商要好很多。虽然其还使用 蓝牙4.2,但是并没有出现过断连(原来的 Keychron 日常断连) HHKB 的按键与普通键盘有着较大的区别,它将 Control 移动到了 Shift 上方,将 Tab 与 CapsLock 合并,使用 Fn + Tab 触发大写锁定, 它取消了普通的 方向键,取而代之的是通过 Fn组合来进行操作。对于新入手HHKB的用户还是建议先去购入 有刻的版本,不然真的会需要很长时间来适应。 缺点方面,贵,然后就是对于无刻的版本,数字总是按错。电池仓的设计,也总感觉不太协调。

2023/3/11
articleCard.readMore

历经59天, 终于拿到软著

目前的话, 大部分的国内安卓应用商店如果需要上架软件,都需要提供软著。App Store 的话是不需要的,但是需要每年99美元的 “苹果税”。 所以需要上架自己开发的软件就需要去申请软著,这个价格的话是免费的,大概需要3个月左右。如果着急的话也可以去找一些代理,不过需要一定的费用。还是比较建议大家去申请下软著的,如果遇到别人恶意使用或模仿软件的时候,软著是一个很好的保护手段。 我是直接自己去 中国版权保护中心 自行申请的,第一次由于未成年,给驳回了,给出的理由是要求成年人代理申请,后来也就没有去管了。 然后在2022年12月7日,完善了下使用文档再次进行了申请. 申请时需要提供 申请表(官网可下载),身份证复印件,程序源代码(60页)以及软件详细的使用说明。 这里的程序源代码时需要打印下来,( ps: 建议自己打印,外面打印不仅贵,而且还有可能泄漏源代码) 接着需要将这些资料寄送至北京的版权保护中心。 从邮寄到审查大概经过了 20天,也就是 12月27日。最终在 2023年2月2日 审核通过了,状态变为待发放,此时软著证书已经可以下载电子稿了。 申请下来比想象中的要容易些,就是比较浪费时间,不过好在准备的比较充分,没有遇到像别人需要补正的情况。 目前(2月28日)状态依旧处于待发放状态,不知道什么时候才能拿到纸质的软著证书呢。(等拿到了再更新下) 最后配上一张软著证书图片: 拾光

2023/2/25
articleCard.readMore

渺软公益CDN - 又一个静态资源加速站

渺软公益 CDN - 又一个前端静态资源加速站。 目前支持 jsdeivr, unpkg, cdnjs 的加速 项目官网 https://cdn.onmicrosoft.cn 渺软公益CDN 项目介绍 记得以前有篇文章介绍了 Jsdelivr 加速 Github Repo, 来实现静态资源加速,不过目前,因为一些原因,使用体验也下降了很多。 在前端开发者日常开发中,总会去使用很多现成的框架或前端UI,如 我用的比较多的: React.Js,AntDesign 等。 如果将这些静态资源都存放在自己服务器上,不论对用户还是开发者来说,都会带来较差的体验. 但目前来说,国内的 Jsdelivr 和 Unpkg 的体验并不好。 在这些情况下 渺软公益CDN 便诞生了. 它使用 DogeCloud 对这些站点进行反向代理,同时也拥有完善的 Abuse 措施. 用户可在官网对违规资源进行举报,审核通过后将会对其封禁。 限制 本项目的开发初衷是为了方便开发者使用公共静态资源如js,css等文件,不支持托管私人静态图片, 私人字体文件等大流量文件(公共字体,知名前端UI库除外)。 目前限制的话是 24G / Day,还是比较充足的. 我们也在官网为其开发了一个简易图表来展示实时的使用情况,具体可在官网查看。

2023/1/11
articleCard.readMore

你好 2023

前言 时间过得很快,转眼 2022 年就离我们远去了。 2022 年,发生了挺多事。很多细节也就不一一叙述了。 这一年,搬家了,新的家小了些,但比原来“精致“了些。 这一年,步入大学了,低于预期,但也不错。 这一年 … 日常 今年的生活其实挺没意思的。 就很像网上说的那样,今年似乎就是 1~11月常态化的核酸与时不时的隔离 以及 12月的阳了。 上半年在家,几乎接近中午才起床,吃点东西,下午呆在家中或是到门口的星巴克一坐一下午。 年初了解到了 光·遇,“光是遇到,就很美好”,画风很唯美的一款游戏。从中也结识到一些朋友,似乎玩这个游戏的有很多年纪很小的朋友。也有一个人给我留下了很深的印象。但是他也很久没上线了,不知道还能不能遇到他。 我们每天都可能遇到不同的人,其中很多都是过客,很少有人会与你的人生产生交集。我算是个比较念旧的人,经常回忆过去。似乎过去,还有着太多的遗憾。 每天都在重复,重复,重复 … 直到六月份,高考结束,当然,这与我没有太大关系。原先的一些朋友放假了,他们大多考的不错。也去参加了他们的升学宴。 我们学校开学很晚,别的学校似乎9月初就开学了。唯独我们一直延迟到10月9号。为了早点体验大学生活,我参加了学校的志愿者,提前一天到校。等到第二天跑到当地的车站去迎接新生。可能是疫情原因吧,我们这届连开学典礼都没有举办。 草草上了近一个月的课,才开始军训,这期间还因为疫情原因在宿舍上了一段时间的网课。军训不算太累,但也有些许遗憾。我是在数字方队,原先排练几天的汇演,却在汇报当天因下雨而取消了。 12月初,也去自愿参加了无偿献血,算是挺有意义的一件事吧。 风景 平常也挺喜欢摄影,周末有空也会经常去海边,公园转转。照片似乎是留下记忆的最好的方式。每当没事做时,都会翻一翻过去的照片,想一想曾经发生的事。 7月份去了趟安吉,不同于我们这儿,安吉似乎是山中的城市。感觉住在这儿,生活节奏也慢下许多。去了那儿的浙北大峡谷,也体验了将军关漂流。 反思 时间过的很快,2022年也是我成年的一年。小时候总感觉时间很慢总幻想着长大后的日子,长大了却总想回到过去,小时候是多么的无忧无虑。 今年空闲时间很多,却没有多读上几本书,多做些有意义的事情。天天呆在家/宿舍,也没多出去运动运动,也是该多锻炼锻炼了。 希望2023年的自己,能多些进步,多些成长。

2023/1/3
articleCard.readMore

记一次 RAID 硬盘离线

事故 使用 Dedipath 的服务器应该已经超过三年了吧。价格便宜,客服服务也挺不错的。但是,这次的事情,让我对其服务的可靠性及服务态度产生了怀疑。 事情应该是发生在今年的12月1日,收到Uptime-Kuma发来的邮件, 说我的 OpenID 的后端似乎离线了。 检查了一下,发现其所在的服务器 文件系统变成了 Readonly Filesystem . 无奈,只能发工单联系其客服,客服给出的回复是: We are currently trying to run maintenance on the host server for this node. We will contact you once we have an update. Sorry for the delay. and thank you for your patience. 简单来说,就是我们正在对宿主机所在的节点进行回复。但其并没有任何的预先通知,再次询问过后,客服给出了如下的回复: VPS’ on Node Los Angeles OpenVZ Node DC04R11SRV36 We discovered a disk in this node which fell out of the RAID-10 array, but was marked as in good health. As such, we re-added the disk to the array, but for unknown reasons, we immediately begun to see file system errors. As such, we are requesting that all customers on this node login to SSH (we have tested SSH on various VMs and it does respond) and create a backup of any important data. Once complete, please open a technical support ticket and request that we re-create your VPS on a new node. Our sincere apologies for the troubles caused. We are not sure why the behaviour that occured has occured, but an examination into our processes will be undertaken to try and prevent such issues from re-occuring. 简单来说,就是因为 RAID-10 阵列的一块硬盘离线, 但其 SMART 数据显示状态正常。将其重新加入到阵列中,但是出现了文件系统错误。 什么是 RAID 可能有的人不懂什么是 RAID, 这里简单的介绍一下. RAID, 即磁盘阵列。通常由多块硬盘组成,通过硬件或者软件的方式,将多块硬盘组合成一个逻辑的磁盘,以提高数据的可靠性和可用性。 此处使用的 RAID-10 至少需要4快硬盘。可以理解为 RAID10 是: 2快硬盘组成 RAID1,再由2组 RAID-1 组成 RAID-0。 通常来说, 这似乎能够允许最少两块硬盘的损坏,不会影响数据的可靠性和可用性。 给出的解决方案 Dedipath 给出的解决方案是: 给我在一个新的 node 上重新开一台 VPS。 在我询问对于我原先的数据如何迁移,以及这期间造成的损失时,客服表示,他们没有 SLA 赔偿协议。 It is your responsibility to maintain frequent backups of your data. We are not liable for any data loss. 挺离谱的,但还好对于数据库有定期备份,所以并没有造成太大的损失。 反思 不论使用的是一些不知名的服务商,还是一些大厂如腾讯云,阿里云。对于服务器,还是建议对其进行定期备份。 DB-Backuper 对于数据库的备份,花了点时间,通过 Golang 实现了一个简单的数据库定时备份工具: DB-Backuper 目前仅支持 Mysql, 以及自动备份至腾讯云的对象存储。

2022/12/26
articleCard.readMore

大一 碎语

好像已经挺久没有写文章了,上次似乎还在8月份。 大一上半学期很短。10月8日开学去车站做志愿者,隔离三天。10月12日到自己宿舍,上床下桌,独立卫浴,还算不错。虽说不算什么好学校,但命运已定,也没有什么其他办法,唯有接受。 我选择的是现代移动通信技术(通信工程),主要是移动方面的学习。大一上半学期,主要专业课也就是,移动通信概览,讲的也挺模糊,然后就是电路基础,挺有趣也挺复杂的。 作为一个从来没有住宿经历的人来说,大学住宿生活其实还算不错。晚上和舍友玩到12点多,早上7:50的课,7:30起来匆匆忙忙赶过去。星期一星期三晚上上到8:30的高数,嗯… 还算不错。比走读生要多些乐趣,多些时间。 周六周日也会去去图书馆,补补上课摸鱼不太理解的内容。图书馆人人挺多,用书占位置的也挺多。三层的图书馆,很多书籍仍然是10年代甚至90年代的,可能文学方面的书籍仍然存在价值,但一些技术方面,天天都在迭代,大多数书籍已没有意义。 在这之间,也有过部分项目,仍然是对不蒜子的略微修改,以及新写了某学校的自动打卡。主要技术栈仍然是 Golang,php 到挺久没写了。Golang 算是一个不错的语言,写起来很优雅,很方便,跨平台,支持交叉编译,平常在Macbook上写的软件,编译后可以直接在 Linux 上运行。作为一个编译性语言,源码安全性方面也有一定保障。前端的话,依旧是 NextJs + Typescript, Typescript 作为 Javascript的超集,很不错。React 的渐进式开发和 Flutter 有些类似,我个人认为吧,React 是优于 Vue 的。不太喜欢 Vue.js. ”放假“很匆忙,因为疫情原因,本来计划是月底放假,突然通知能离校的尽快离校。于是用了半天的时间稍做收拾,第二天便匆匆离校了。两个月的时间,体验了下大学生活,嗯… 很匆忙,和想象中的大学生活有些出入,但还算不错。 疫情相关,也似乎有了些改变,不做太多评价。青春几年,疫情占了三年。很烦,但没太多办法。希望明年会有些好转吧。希望明年的自己,能有个新的开始。未来是不可预测的,少些期待,多些脚踏实地,订些可行的近期目标,以及一些可行的长期目标。一步一步走下去。 未来可期,前程似锦。

2022/12/13
articleCard.readMore

试用 Google CA 的 SSL 证书

其实对于大多数个人用户来说, 申请 SSL 应该都是不可避免的, 且大多数都会去选择一些免费的证书. 比如 Let’s Encrypt, TrustAsia, DigiCert 等. Let’s 的好处应该就是可以免费申请通配符证书, 这点比较方便, 但证书有效期只有3个月. TrustAsia 可以提供最长1年的证书. (一般来说 证书有效期不能超过398天) Google 在 今年的 3月30日 也推出了类似 Lets 的免费证书申请, 有效期最长也为3个月, 目前仍然处于内测状态. 不过既然是免费 那为何不试一试. 优劣势 支持通配符以及多域名. 支持为 IP 申请证书. 支持设置 1~90 天的有效期. 但是目前其不支持 IDN 域名 (常见的 包含中文的域名不行) 申请内测 创建 Project 首先需要申请一个 Google Cloud Platform 账户, 创建一个自己的项目并记录下其 project ID 填写申请表单 https://docs.google.com/forms/d/1Euhflb5CXpuLik8czElhyAloTZJZobar4086dmlPqXA Google Cloud Project ID 处填写上文记下的 Project ID 即可. 接着可能需要等待两到三天, 通过后 会收到一封 主题为 ‘Welcome to Google Cloud Certificate Manager, Public CA’的 邮件. 准备申请 启用 API 在通过内测申请后, 我们需要启用 ‘Public Certificate Authority API’. 进入 API服务 中选择你申请内测时的 Project ID, 点击启用. https://console.cloud.google.com/apis/library/publicca.googleapis.com?project=project-id (注意替换上文的 Project ID) 获取密钥 接着点击 右上角的 ‘激活 Cloud Shell’ 来快速申请相关密钥: 介入 1 gcloud beta publicca external-account-keys create 期待返回 1 2 3 Created an external account key [b64MacKey: KEYHASH keyId: KEYID] 签发证书 安装 acme.sh 在签发证书之前, 您的设备需要有 acme.sh 的环境, 可以通过 1 curl https://get.acme.sh | sh -s 快速安装. 签发 注册 1 2 3 4 5 acme.sh --register-account \ --server https://dv.acme-v02.api.pki.goog/directory \ --server google -m user@example.com \ # 邮箱 --eab-kid {KEYID} \ # 上文得到的 keyId --eab-hmac-key {KEYHASH} # 上文得到的 b64MacKey 开始申请 1 2 3 acme.sh --server google --issue -d *.example.com \ # 域名 --keylength ec-256 --force \ --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please 提交过后需要你去 解析相关的 TXT 记录用来验证身份, 解析好了后, 通过 --renew 来完成证书申请 1 2 acme.sh --server google --renew -d *.example.com \ # 域名 --dns --ecc --yes-I-know-dns-manual-mode-enough-go-ahead-please 为了让 Nginx 使用该证书, 可以通过 acme 安装证书并自动续期 1 2 3 4 acme.sh --installcert -d *.example.com --ecc \ --key-file /usr/local/nginx/conf/ssl/example.com.key \ --fullchain-file /usr/local/nginx/conf/ssl/example.com.crt \ --reloadcmd "service nginx force-reload" 安装后还需要修改 网站相关配置文件 来启用ssl访问.

2022/8/5
articleCard.readMore

Waline 邮件异步推送

前言 目前我使用的评论是 Waline,总体来说 体验还算可以。但是在使用过程中也遇到过一些问题,比如加上邮件推送后, 评论的速度会变的很慢。 研究过后发现 Waline 貌似是在评论时 直接进行发送邮件的,同步进行发信便会导致评论耗时较长,很影响用户体验,有时评论需要耗时几秒甚至超时。 Waline 应该是使用的 ThinkJs,理论上可以通过异步函数来进行异步发信,不清楚为什么要同步发信。由于我对于 ThinkJs 并没有太深入了解,直接修改源码也可能造成部署麻烦,于是我尝试寻找另外的方式来实现异步发信,在研究过后, 发现 Waline 可以设置一个 Webhook 地址,在评论时会自动向该地址发送一个 POST 请求。 其 POST 内容大致为: 评论文章时: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "type": "new_comment", "data": { "comment": { "link": "https://blog.example.com", "mail": "email@example.com", "nick": "xcsoft", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.115 Safari/537.36", "url": "/", "comment": "test", "ip": "127.0.0.1", "insertedAt": "2022-07-09T13:46:52.085Z", "status": "approved", "objectId": 1, "rawComment": "test" } } } 回复别人评论时: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 { "type": "new_comment", "data": { "comment": { "link": "https://blog.example.com", "mail": "email@example.com", "nick": "xcsoft", "pid": 1, "rid": 1, "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.115 Safari/537.36", "url": "/", "comment": "[@xcsoft](#1): reply", "ip": "127.0.0.1", "insertedAt": "2022-07-09T13:47:53.526Z", "user_id": 1, "status": "approved", "objectId": 2, "rawComment": "reply" }, "reply": { "user_id": null, "comment": "test", "insertedAt": "2022-07-09 21:46:52", "ip": "127.0.0.1", "link": "https://blog.example.com", "mail": "email@example.com", "nick": "xcsoft", "rid": null, "pid": null, "sticky": null, "status": "approved", "like": null, "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.115 Safari/537.36", "url": "/", "createdAt": "datetime('now', 'localtime')", "updatedAt": "datetime('now', 'localtime')", "objectId": 1 } } } 实现 了解了 Webhook 内容后, 便打算使用 golang-gin 开发服务端, 得益于 Golang 的协程 异步发信还是很方便的。 我这里直接通过 gin 提供的 ShouldBindJSON来解析 Waline 发送的 json, 其结构体类似 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 type CommentStruct struct { Type string `json:"type"` Data struct { Comment struct { Nick string `json:"nick"` Mail string `json:"mail"` Url string `json:"url"` Comment string `json:"comment"` RawComment string `json:"rawComment"` Ip string `json:"ip"` InsertedAt string `json:"insertedAt"` Status string `json:"status"` } `json:"comment"` Reply struct { Nick string `json:"nick"` Mail string `json:"mail"` Comment string `json:"comment"` InsertedAt string `json:"insertedAt"` Status string `json:"status"` } `json:"reply"` } `json:"data"` } 其中 Type 始终为 new_comment, Data.Comment 为评论信息, Data.Reply 为被回复信息(可能为空) 邮件采用的是 gomail 库, 由于大多数服务商默认是有发送频率限制的, 于是我通过 Redis 实现了一个消息队列, 用来控制发信频率。 发信效果 模版及图片 来源于网络 开源 源码以 Apache 2.0 协议开源于 soxft/waline-async-mail 基本部署方式可以在 wiki 找到

2022/7/11
articleCard.readMore

Magic Trackpad 使用体验

自从去年换了 Macbook Pro m1, 就感觉回不到 Windows 了. 不得不说 m1 的续航是真的可以, 带出去的时候从来不需要带上电源适配器. vscode + 浏览器 一个下午下来基本上还有 60% 以上的电. 但是它的扩展性的确有些难难堪, 只有两个 typec, 拓展坞我选择的是 Dockcase 的七合一 感觉还不错. 之前一直用的都是笔记本的自带键盘和罗技的 K380, 基本都是薄膜键盘, 其实体验还算可以, 一直没有机会尝试机械键盘. 趁着 618 入手了 Keychron 的 K7 矮茶轴. 用了几天还算不错. 在 Macbook 上使用鼠标其实并不方便, 即使再使用 Mos 等平滑鼠标的软件后, 使用起来也很别扭. 很久之前够买过 Magic Mouse, 但是它的设计的确令人发狂, 用起来很不习惯, 最终还是将它卖掉了. Macbook 的触控板体验 一直都是业内较为优秀的。可以说用了触控板后, 就再也不喜欢鼠标了 游戏除外. 于是我忍痛下单了 2021 新款 Magic Trackpad. 很喜欢这种包装风格, 很简约. 总体来说, 体验很不错, Macbook 的触控板 有很多手势操作, 我习惯将三指设置为拖动窗口, 四指切换窗口, 四指上滑打开多窗口 等等. 新款的 Trackpad 面板变得更加圆润了, 背面采用了磨砂处理, 手感不错. 和 Macbook 的触控板一样, 妙控板 也支持两级按压, 点击采用的是震动反馈. 不同于windows的触控板, Magic Trackpad 支持全面板按压, 而 Windows 的大多都只能两个角落进行单击按压操作. 还送了一根 c to lighting 的编织线 不太环保, 充一次电 理论可以使用 一个月. 唯一的缺点可能就是 仍然使用 蓝牙3.0. 虽然使用下来 没有遇到什么问题. 总体来说 对于这块妙控板的体验还是较为满意的.

2022/6/20
articleCard.readMore

Centos 编译安装 php81

出于 开发环境配置及学习的需求, 需要直接在 Centos 7 上编译安装 php-81. 最近在使用 webman 重构 拾光 的后端, 虽然 这次迭代可能存在一定的破坏性, 但得益于 Webman 的现有生态 以及 复用了多数的 Composer 库. 将会为 以后的版本迭代及功能扩展 带来一定的便利. 我们可以直接在 官网 找到源码, 这里选择 php-8.1.7.tar.gz, 通过 wget 等工具 下载至服务器. 相关依赖 编译之前, 需要安装一些依赖. 1 $ yum install libxml2-devel openssl-devel sqlite-devel libcurl-devel libicu-devel gcc-c++ oniguruma oniguruma-devel libxslt-devel libpng-devel libjpeg-devel freetype-devel libsodium libsodium-devel epel-release -y 接着通过tar -xzvf php-8.1.7.tar.gz 解压下载后的文件. 进入文件夹 开始编译 我们可以使用 cconfigure 来检验当前的系统环境, 看是否满足安装软件所必需的条件: 1 $ ./configure --prefix=/root/php/81 --with-config-file-path=/root/php/81/etc --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --enable-soap --with-gettext --disable-fileinfo --enable-opcache --with-sodium=/usr/local/libsodium 如果此处 出现错误, 可以尝试根据提示 安装相关依赖 这里 我们已经选择安装了一些 常用的php扩展, 您也可以在 ext 目录下 找到更多信息. 在校验完成后 我们会看到 类似 Thank you for using PHP. 的相关信息 接着 使用 make && make install 将其 编译安装至 /root/php/81 目录下, 安装完成后, 我们需要将 当前目录下的 php.ini-development 或 php.ini-production 文件 复制到 /root/php/81/etc/ 目录下, 并重命名为 php.ini 接着添加 PATH="/root/php/81/bin:$PATH" 至 ~/.bashrc 中 来将 php 添加至环境变量中, 重新打开终端 或使用 source ~/.bashrc 使环境变量生效 验证安装 1 2 3 4 5 6 $ php -v PHP 8.1.7 (cli) (built: Jun 16 2022 14:52:05) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.7, Copyright (c) Zend Technologies 其他 对于 Centos 8 后, 使用 dnf 替代了 yum, 需要启用 PowerTool 来安装部分 开发依赖 1 2 $ sudo yum install dnf-plugins-core $ sudo dnf config-manager --set-enabled powertools

2022/6/16
articleCard.readMore

Redis 统计实时在线人数

zset Redis 中的 sorted set (有序集合) 也称为 zset. 它提供了两个参数, 一个为 score, 一个为 member. 其中, score 为排序的分数, 它可以是双精度或者整数. 其结构类似 1 2 3 | (score) member1 key => | (score) member2 | (score) member3 如何实现 我们可以简单的通过 zadd 方法向一个有序集合内添加成员. 为了方便演示, 在这里使用 Interval 的方式, 定时请求指定接口. 将 score 设置为请求时的 unix时间戳 zset 提供了一个 zcount 方法, 可以让我们快速获取指定 socre 范围内的成员数量. 我们假设用户5秒钟内无操作, 即掉线. 这样便可以通过 zcount 获取实时在线人数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 func main() { // 使用 gin 提供 web 服务 r := gin.Default() r.GET("/", func(c *gin.Context) { _redis := redisutil.R.Get() // redis pool defer redis.Close() // 用户标识 userId := c.ClientIp() _, _ = _redis.Do("ZADD", "online_user", time.Now().Unix(), userId) // 获取在线人数 count, _ := redis.Int(_redis.Do("ZCOUNT", "online_user", time.Now().Unix()-5, "+inf")) c.JSON(200, gin.H{ "count": count, }) }) r.Run() } 当然, 为了防止 数据一直增加, 对于 5秒前的数据, 应该定时将其移出. 我们可以通过 zremrangebyscore 方法, 来移除 指定范围内的数据. 1 2 3 4 5 6 7 8 9 10 11 func AutoRemover() { _redis := redisutil.R.Get() // redis pool defer redis.Close() c := Cron.New() c.AddFunc("@every 5s", func() { _, _ = _redis.Do("ZREMRANGEBYSCORE", "online_user", "-inf", time.Now().Unix()-5) }) c.Start() } zset 的其他方法 除了上述提到的方法, zset 还提供了很多其他的方法, 如: zcard key 直接获取 指定 key 内的成员数量 zscore key member 获取指定成员的分数 zincrby key incr member 增加指定成员的分数 zrange key start end [WITHSCORES] 获取指定范围内的成员 并按照分数从小到大排序 zrevrange key start end [WITHSCORES] 与上一个相反 etc. 其他 可以在 Github 找到 示例. 这里同时实现了, 所有用户及自己的 在线时间显示. 当然, 也可以通过 WebSocket 来实现类似的功能, 这样会更加准确, 但是可能会带来一定的性能损失. 参考 Redis zset 的一些操作命令

2022/6/6
articleCard.readMore

Centos 7 升级 Glibc-2.28

最近在捣鼓 Hexo 相关的评论系统, 一开始使用的是 Waline. 前端部署在 Vercel, 数据库使用的是官方推荐的Leancloud. 整体相应速度真的挺慢. 在尝试修改 Vercel 的serverless function所属位置后, 依旧达不到理想的速度. 于是我试着将其完全迁移至了自己的服务器, 直接使用官方提供的 docker compose 部署, 数据库采用的是mysql. 但是一直不满意其 评论时的速度. 因为我使用了邮件推送. 但是Waline貌似不支持 异步发信. 导致评论速度 很慢. 无意中了解到了 Artalk, 他是使用 Golang 开发的一款评论系统, 并且很好的支持了异步发信(应该是得益于Golang的goroutine). 并且Artalk也提供了一个叫做Artransfer的cli工具, 支持从原先的多种评论系统直接导出至Artalk. 于是我便尝试使用其工具导出评论, 可能我服务器的 linux 内核版本较老, 貌似只支持到GLIBC_2.2.6, 而 Artalk 需要GLIBC_2.28. 其实在之前使用 nvm 安装 nodejs-18.2.0 时, 就曾遇到该问题. 但我那时因为麻烦, 直接选择了 nodejs-17.9.0. 安装 glibc-2.28 1 2 3 4 5 6 7 8 9 10 11 # 下载并解压 glibc-2.28 $ wget https://ftp.gnu.org/gnu/glibc/glibc-2.28.tar.gz $ tar -xzvf glibc-2.28.tar.gz $ cd glibc-2.28 # 创建临时文件 $ mkdir build && cd build $ ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin # 这一步时, 发生了错误, 提示大致为 These critical programs are missing or too old: make compiler 升级gcc与make 安装GLIBC所需的依赖 可以在 glibc 目录下的INSTALL中找到, 该版本需要 GCC 4.9 以上 及 make 4.0 以上 升级gcc 1 2 3 4 5 # 直接安装 GCC-8 $ yum install -y devtoolset-8-gcc devtoolset-8-gcc-c++ devtoolset-8-binutils # 设置环境变量 $ echo "source /opt/rh/devtoolset-8/enable" >> /etc/profile $ source /etc/profile 升级 make 1 2 3 4 5 6 7 8 9 10 11 $ wget https://ftp.gnu.org/gnu/make/make-4.3.tar.gz $ tar -xzvf make-4.3.tar.gz $ cd make-4.3/ # 安装到指定目录 $ ./configure --prefix=/usr/local/make $ make $ make install # 创建软链接 $ cd /usr/bin/ $ mv make make.bak # backup $ ln -sv /usr/local/make/bin/make /usr/bin/make 继续编译 glibc 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 进入之前的 `~/glibc-2.28/build`目录下 $ cd /root/glibc-2.28/build $ ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin $ make $ make install # 查询 $ strings /lib64/libc.so.6 | grep GLIBC ... GLIBC_2.22 GLIBC_2.23 GLIBC_2.24 GLIBC_2.25 GLIBC_2.26 GLIBC_2.27 GLIBC_2.28 GLIBC_PRIVATE ... 参考 https://blog.csdn.net/CLinuxF/article/details/108705142 https://blog.csdn.net/weixin_38586230/article/details/107057646 https://blog.csdn.net/ncdx111/article/details/106047228

2022/6/2
articleCard.readMore

Nginx 重写 Query 参数

由于旧版项目, 依旧使用php-fpm模式提供api服务, 采用 类似 /api.php?m=account&act=login类似这种方式进行控制器分类. 目前的话 打算更换为其他框架, 使用路由来分配控制器. 由于前端及软件迁移成本较高, 就想着是否可以通过Nginx的伪静态来重写. 于是一开始尝试使用 1 2 3 4 location / { proxy_pass https://127.0.0.1:8787; rewrite ^api.php\?m=(.*)&act=(.*) /$1/$2 break; } 直接对其进行重写, 但测试后发现并为达到预期的效果, 服务端接收到的 依旧只有/api.php 貌似并未被nginx匹配到, 查询过后发现 这样貌似是匹配不到路径的? 最终在查询过后, 发现可以通过 query_string 来对其进行匹配 1 2 3 4 5 6 7 8 9 10 11 12 location /api.php { proxy_pass http://127.0.0.1:8787; if ( $query_string ~ ^m=(.*)&act=(.*)) { set $a $1; set $b $2; rewrite ^/(.*)$ /$a/$b break; } } location / { proxy_pass http://127.0.0.1:8787; } 修改配置文件后, 再次对其进行测试, 成功将/api.php?m=account&act=login重写为/account/login

2022/5/25
articleCard.readMore