实战:为 Hugo 博客开发一个公网 IP 探测 Shortcode
工具说明:在进行内网穿透(如调试 mole-go)或配置服务器白名单时,频繁查询公网 IP 是刚需。为了告别繁琐的登录和搜索,我开发了这个集成在博客中的实时探测组件。 🌐 公网 IP 探测 🌐 当前公网 IP: 正在探测... 复制 🛠️ 核心实现逻辑 这个工具基于 Hugo 的 Shortcode 功能实现,采用了异步加载技术,确保不会影响页面的首屏渲染速度。 ...
Markdown 语法教程
我们使用 Markdown 作为我们内容的格式,所以学习 Markdown 就显得很必要了。 Markdown 是一种轻量级标记语言,后缀为.md。因我常用 Markdown 来写一些内容,记录下来常用语法格式。方便自己查找使用,也增加自己的一些流量。Markdown 可以用来撰写电子书,文章,博客等。介绍标题、段落的使用。 标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题 段落 Markd 段落没有特殊的格式,直接编写文件就好,段落的换行使用两个以上空格加上回车。也可以使用一个空行来表示重新开始一个段落。 字体 使用如下格式分别表示斜体,粗体,粗斜体。 *斜体文本* _斜体文本_ **粗体文本** __粗体文本__ ***粗斜体文本*** ___粗斜体文本___ 分割线 你可以在一行中用三个以上的星号、减号、底线来建立一个分割线,行内不能有其它东西。你也可以在星号或减号中间插入空格。 *** * * * ***** - - - --------- 删除线 如果段落上的文字要添加删除线,只需要在文字的两端加上两个波浪线~~即可。 ~~删除线~~ 下划线 下划线可以通过 HTML 的标签来实现: <u>下划线文本</u> 脚注 脚注是对文本的补充说明。 [^要注明的文本] 列表 支持有序列表和无序列表。 无序列表使用星号、加号、减号作为列表标记,这些标记后面要添加一个空格,然后再填写内容。 * 第一项 * 第二项 * 第三项 + 第一项 + 第二项 + 第三项 - 第一项 - 第二项 - 第三项 有序列表使用数字并加上.号来表示。 ...
基于 Go + 小程序创建的“口袋指令中心”
我日常涉及 Hugo 博客发布、客户端打包、Nginx 运维等多种重复性脚本。每次都要 SSH 连服务器并执行命令,操作链过长,也不方便,特别是在身边没有电脑的情况。所以我就想构建一个通用的执行引擎,通过小程序远程触发,且具备零前端修改的扩展能力。 系统架构设计 为了实现“明天增加脚本,小程序不发版”的目标,采用了“配置驱动” 模式。即“配置在云端,指令在指尖”。通过将业务逻辑(脚本路径与名称)完全从前端小程序中解耦,实现一套代码支持无限扩展的运维能力。 核心流程 后端 (Go):维护一个脚本配置列表(数据库或配置文件)。 前端 (小程序):启动时请求后端接口,拉取可用脚本列表。 触发:使用时选择脚本名称,点击执行。 鉴权:后端校验小程序 OpenID,仅允许本人指令生效。 技术实现 系统分为三层,确保安全性与扩展性的统一: 配置层 (Go Config):在服务器端定义脚本的 ID、名称和实际路径。 鉴权层 (WeChat Auth):利用微信小程序 OpenID 建立强一致性的身份白名单。 展示层 (Mini Program UI):动态拉取后端配置,仅负责“展示列表”与“触发指令”。 技术实现方案 A. 后端:动态脚本引擎 (Go) 后端不再硬编码脚本路径,而是定义一个结构体: // 脚本任务定义 type ScriptTask struct { ID string `json:"id"` // 前端传递的任务标识 Name string `json:"name"` // 小程序界面显示的文字 Command string `json:"-"` // 实际执行的脚本路径 (对前端保密) } // 示例配置(可存放在 JSON 文件或数据库中) var tasks = []ScriptTask{ {ID: "hugo-post", Name: "发布 Hugo 文章", Command: "/scripts/deploy_hugo.sh"}, {ID: "build-client", Name: "构建客户端", Command: "/scripts/build_mole_go.sh"}, {ID: "nginx-restart", Name: "重启 Nginx 服务", Command: "systemctl restart nginx"}, } 对外接口定义: ...
巧用Nginx重定向解决云存储文件地址变更的痛点
在移动应用分发、文件共享等场景中,我们常常会遇到这样的困境:云存储平台(如阿里云OSS、腾讯云COS、蓝奏云等)上传的文件地址一旦生成就无法修改,但客户端版本频繁迭代时,每次更新都需要重新生成下载链接和二维码。用户端需要不断更新访问入口,体验极差。我就碰到了此类问题,在上一篇文章,我介绍了自己的客户端,并分享了下载地址。但我发现当我需要重新升级版本时,已经生成的地址将无法变更。在我的文章中,我直接使用了文件下载地址。这就让我急需解决如何实现"一次分发,永久可用"的优雅方案?Nginx反向代理配合301重定向,正是解决这一痛点的利器。 一、问题根源:云存储的地址锁定机制 大多数云存储服务采用"对象存储"模式,文件上传后生成固定URL,该地址包含存储桶名称、地域、文件路径等不可变信息。这种设计虽然保证了数据一致性,却带来了分发难题:每次版本更新,开发者必须重新上传文件、生成新地址、制作新二维码,用户需要重新扫描或获取新链接。对于频繁迭代的应用,这种重复劳动不仅效率低下,更可能因用户未及时更新而影响使用体验。 二、解决方案:Nginx重定向的架构设计 核心思路是地址解耦——将"物理存储地址"与"用户访问入口"分离。通过Nginx服务器作为中间层,用户始终访问固定域名,Nginx根据配置将请求重定向到实际的云存储地址。当文件更新时,只需修改Nginx配置中的目标地址,用户端的访问入口保持不变。 具体架构如下: 用户 → 固定域名/短链接 → Nginx服务器(301重定向) → 云存储实际地址 这种设计实现了三个关键目标: 入口稳定性:用户扫描的二维码或保存的链接永久有效 维护灵活性:后台地址变更只需修改Nginx配置,无需重新分发 成本可控性:Nginx只做重定向,流量消耗极低,普通云服务器即可承载 三、技术实现:从配置到部署 环境准备购买一台云服务器(1核1G配置即可),安装Nginx,将自有域名解析到服务器IP。推荐申请SSL证书启用HTTPS。 Nginx配置示例 server { listen 80; server_name your-domain.com; # 方案一:直接重定向 location /download/app.apk { return 301 https://bucket.oss-cn-region.aliyuncs.com/v2.0/app.apk; } # 方案二:通配符匹配(更灵活) location ~ ^/app/(.*)$ { rewrite ^/app/(.*)$ https://new-bucket.oss-cn-region.aliyuncs.com/$1 permanent; } } 重定向类型选择 301永久重定向:搜索引擎会更新索引,客户端会缓存重定向结果,适合生产环境 302临时重定向:每次请求都会重定向,适合测试阶段频繁变更的场景 二维码生成 将固定地址(如https://your-domain.com/app/v2.0.apk)生成二维码,用户扫描即可下载。后续版本更新时,只需修改Nginx配置中的目标地址,二维码无需重新制作。 四、方案优势与注意事项 核心优势 零用户感知:用户无需关心后台地址变化 维护成本低:修改配置即可,无需重新上传二维码 扩展性强:可支持多版本共存、灰度发布等复杂场景 兼容性好:支持各种客户端(浏览器、APP、微信等) 实施建议 测试先行:在测试环境验证重定向逻辑,确保目标地址正确 监控告警:配置Nginx日志监控,及时发现重定向失败问题 备份机制:保留旧版本配置一段时间,避免新配置问题影响用户 性能优化:虽然重定向开销小,但高并发时需确保服务器性能 五、总结 Nginx重定向方案将复杂的地址管理问题转化为简单的配置变更,实现了"一次分发,永久可用"的理想状态。这种解耦思维不仅适用于文件分发场景,在API网关、微服务路由等场景中同样具有借鉴意义。对于中小型项目而言,这是成本最低、效果最直接的解决方案,值得每一位开发者掌握。 最后推荐一下我的豆子域名管家客户端,这个客户端可以解决域名证书到期忘记更换证书的问题。我是为了解决这个问题而想出来的这个方案。这是我的新的下载地址:https://lab.91demo.top/b011 这样当我修改下载地址时,我不用再变更这个地址,比如我最近刚刚优化了域名扫描逻辑,上传了新的版本,它生成了一个新的下载地址。 当然这个方案还是有一点瑕疵,它需要每次更新都登录服务器修改nginx配置文件,这对于非技术人员非常不方便。后期我还有再次进行优化,我将使用小程序完成新地址的更换。大致思路如下:开发一个轻量的Go服务,提供接口给小程序提交新的地址,然后保存编号和新地址到数据库,例如上面的b011是编号,它对应新的下载URL地址。然后使用Nginx代理这个服务,当用户访问b011时查询它的URL地址,然后返回301和新的地址。这样就不用每次都登录服务器修改Nginx配置,在手机上也方便操作,提供了极大的便利性,也可以交给非技术人员进行维护。
使用go生成DLL文件供第三方使用
我使用go写了一个http转WebSocket服务,这是一个命令行程序,双击可以直接运行,今天,有个新的需求,需要将这个命令行程序转为dll,然后供第三方使用。 1,改造程序 这个命令行程序很小,核心逻辑就是启动了一个HTTP服务,然后接收连接,然后通过WebSocket将内容转发出去。所以,在调整为dll时,仅仅需要导出两个函数即可。 1,StartServer,启动http服务,监听端口地址。因为不能阻塞,所以需要在监听服务时使用go方法启动一个携程。 2,StopServer,关闭http服务,需要提供给第三方,当它关闭时,需要调用它,释放监听地址等资源。 下面开始改造代码: package main import "C" // 必须导入 C 包 import ( // ... 原有导入 ... ) // 保持原有的全局变量和函数逻辑 (例如transDataGet, connWs 等) // 需要注意下面的//export这中间不能有空格,否则无法导出头文件 //export StartServer func StartServer() { // 将原本 main 函数里的逻辑放在这里 gin.SetMode(gin.ReleaseMode) r := gin.New() // ... 注册路由 ... r.Run("127.0.0.1:9988") } // 必须保留一个空的 main 函数 func main() {} // 其它参考StartServer,如果需要导出,一定要添加//export 2,编译命令 我是在windows环境,需要安装cgo环境,我安装了Mingw-w64支持C编译环境,执行以下命令: go build -buildmode=c-shared -o trans.dll main.go 执行后会生成trans.h和trans.dll两个文件。 3,验证dll 除了一些可以查看dll的工具外,还可以使用第三方语言进行测试。例如我这里使用Python。 import ctypes import time lib = ctypes.CDLL("./trans.dll") lib.StartServer() print("服务已在后台启动...") time.sleep(10) # 模拟第三方程序运行 lib.StopServer() print("服务已关闭") 4,再次优化代码 当实际测试的时候,我发现它会阻塞调用者,为了解决这个问题,我们需要再次改造程序。将启动服务改为非阻塞模式。将Gin的启动逻辑放入协程,并利用http.Server提供的Shutdown方法来实现优雅退出。 ...
告别域名过期焦虑,豆子域名管家支持批量检测加企微和钉钉通知
域名过期导致业务中断、流量缺失、品牌受损的案例比比皆是。手动记录域名的到期时间?是否会忘记,漏看? 我以前曾介绍过,我在微信小程序实现了域名证书监控功能。但是担心隐私,功能限制。这次我带来了豆子域名管家,本地化运行。 经过数月的规划和开发测试,豆子域名管家终于可以使用了。这是一款完全本地运行、支持批量导入管理以及可以企微和钉钉通知的域名证书检测工具。旨在解决域名过期监控难题。 特性 传统方式 豆子域名管家 运行方式 依赖云端服务 纯本地运行,数据不出本地 批量处理 手动逐个查询 一键导入,批量删除 通知渠道 单一(邮件/短信) 钉钉+企微双通道,支持Markdown格式 自定义提醒 固定时间提醒 可配置通知时间,提前预警天数 系统集成 无 系统托盘常驻,后台静默运行 隐私安全 数据上传第三方 域名数据和配置数据存本地 技术架构亮点: 工具基于Wails3框架构建,采用Vue3+NaiveUI前端技术栈,确保界面简洁美观,交互流畅,支持暗黑/浅色两种主题。 本地证书检测引擎,直接调用系统网络库进行TLS检测,无需依赖外部API。 多线程并发处理,使用go的特性批量进行域名检测。 跨平台兼容:支持Windows、macOS、Linux系统。 配置持久化,所有配置本地存储,重启后自动恢复。 支持域名证书检测,域名到期时间检测。 软件运行界面预览: 控制面板 配置页面 基本操作指南: 1,导入域名我们需要把要监控的域名按行录入到txt文档中,可以在软件配置界面下载示例模板,当准备完成后,选择刚才的文件,然后验证。没有问题后,点击确认导入即可。 2,配置机器人目前工具支持钉钉机器人和企业微信机器人,支持Markdown格式消息,可以查点击推送预览效果按钮查看推送效果。当输入机器人配置后,可以验证测试,当收到消息后说明配置成功,点击保存即可。可以同时配置企微和钉钉。这样会同时推送两份通知。 3,配置推送通知策略目前工具扫描调度间隔固定24小时,可以配置通知时间,和告警天数间隔。在通知时间,系统会将当天扫描的结果报表推送到机器人。如果用户更新某些域名证书后,可以在监控面板进行手动刷新。想查看效果,可以把通知时间设置为当前时间加几分钟,当到达时间后,将推送报表。确认无误后,可以调整为真正的推送时间。 4,系统托盘运行当完成域名导入和机器人以及通知策略配置后,可以关闭窗口,工具将自动缩放到系统托盘。如果需要退出,需要右键系统托盘退出。注意,如果退出工具,将不能监控域名,因为这是一个本地工具。所以需要工具长期运行。 5,监控面板监控面板的仪表板显示你的域名配置项统计信息,表格显示监视的域名列表。域名可以搜索,刷新以及删除。域名按照过期、告警、正常顺序排序。请查看最前面域名并及时处理。 工具按照自己的真实需求开发,如果你需要尝试,可以通过下方下载链接。目前仅提供了Windows版本。 https://lab.91demo.top/b011 如果您有任何问题和建议,欢迎反馈和交流。
拒绝频繁上传服务器!我用 Dufs + Mole-go 搭建了丝滑的内网穿透演示环境
最近开发完 Mole-go,想给它做个网站用来展示和下载。但我这个后端糙汉子,样式真搞不定,求助 AI 调了半天还是差点意思。最头疼的是,手机端调试得一遍遍输 IP,给朋友演示也得发一串 IP 端口,太不专业了!于是我一顿折腾,搞出了这套方案…… 为了解决这些痛点,我摸索出了一套“黄金组合”:Dufs + Mole-go + FRP + Caddy。这套方案打通了从本地到公网域名的全链路,实现了自动 HTTPS、域名访问以及极致的访问体验。 第一步:构建本地内容基石(Dufs) 一切的起点是本地文件服务。我选择使用 Dufs 作为静态服务器。它极其轻量,支持上传、搜索、打包下载甚至 WebDAV,是我演示 Web 应用或分发安装包的首选。 通过简单的命令,我在本地 5000 端口启动了服务。虽然此时它还被“困”在局域网内,但它为后续的展示提供了稳固的基础。 第二步:突破局域网束缚(FRP 与 Mole-go) 为了让公网流量能精准触达内网,我采用了经典的 FRP 方案,但在客户端层面,我使用了自己开发的 Mole-go。 服务端 (FRP Server):部署在具备公网 IP 的云服务器上,充当流量中转站。这个服务器配置可以很低,网站服务都在本地电脑,如果本地有数据库,也非常方便调试。 客户端 (Mole-go):这是我为 FRP 打造的桌面管理客户端。它封装了 frpc 核心,不仅提供了直观的 UI,还通过系统托盘设计彻底解决了“关闭窗口即断连”的痛点。 使用 Mole-go,我可以将本地 5000 端口通过加密隧道安全地映射到云端。它出色的资源管理和连接稳定性,确保了演示过程中即便网络波动,链接依然稳固如初。 第三步:优雅的网关入口(Caddy) 即便流量已到达公网,我也不希望朋友们通过 http://IP:端口 这种生硬的方式访问。我追求的是“域名+HTTPS”的专业感,这不仅是为了美观,更是为了开发环境需求,下次开发公众号等必须 HTTPS 环境时可以拿来就直接使用。 我选择了 Caddy 担任“守门人”。Caddy 的魅力在于其近乎零配置的 自动 HTTPS 功能。看中了它的简单方便,非常符合我的场景。在 Caddyfile 中,我只需写下: example.com { reverse_proxy localhost:7000 # 指向 FRP 映射出的本地端口 } 仅需这一行配置,Caddy 就会自动搞定 SSL 证书的申请与续签。当访问者输入域名时,映入眼帘的是受信任的绿色小锁头,所有的复杂端口逻辑都被完美隐藏。 ...
把项目做成像 frp 那样的多平台 Release
Mole 项目已经开源,打算把仓库在 GitHub Release 页面中发布各个平台的安装包/二进制(像 frp 那样),已经完成脚本,可参考.github/workflows/release.yml,这个用来记录实现过程与遇到的坑,便于自己回顾。 大致流程 查阅 GitHub Actions、goreleaser、actions/create-release、actions/upload-release-asset 等资料。 在仓库中写一个 matrix workflow,在 Windows / macOS / Ubuntu runner 上分别构建并打包。 修复构建中出现的依赖与环境差异问题。 将构建产物上传为 Release asset(先查找/创建 release,再上传各平台包)。 调试并保证上传在 Release 页面能看到各平台包。 今天遇到并解决的主要问题(按流程顺序) Ubuntu 图形库版本不一致 问题:教程写的是 libwebkit2gtk 4.0,但在新版 Ubuntu runner 上只能安装 4.1。 处理:在 CI 的 apt 安装里兼容 4.0 和 4.1(尝试 4.1,或用 || 逻辑兼容两种包名)。 wails3 安装地址写错导致安装失败 问题:go install 用错了模块路径,安装一直失败。 处理:修正为官方地址(例如 github.com/wailsapp/wails/v3/cmd/wails3@latest),并确保 GOPATH/bin 在 PATH 中。 wails3 的 -platform / -o 参数在我的环境不可用 问题:官方文档的参数在实际运行时报错或不生效(不能指定输出名)。 处理:不完全依赖 CLI 的跨平台参数,在对应 runner 上运行构建命令并从 bin/ 下输出文件打包;如有必要向 upstream 提交 issue。 macOS 的平台特有代码需要 build tag,而不是运行时判断 ...
git开发常用命令
如果你要开始项目开发,看看如下 Git 常用命令对你绝对有帮助。 在每次开发新功能时,拉出一个新分支,分支名称为开发的功能名称,格式为 func-xxxx。当开发的功能完成并测试没有问题后,合并到主分支。 当在开发新功能时,如果出现 bug,能够马上解决的,直接在主分支上修改,如果需要时间长,则新创建一个分支,格式为 bug-xxxx。当开发的功能完成并测试没有问题后,合并到主分支。 1,开发分支。 切换到 dev 分支,进行代码开发。开发完毕后,合并到主分支。 git checkout dev 2,合并到主分支。 git checkout master git merge dev git push origin master 3,主分支添加 tag,并发布到线上。 git checkout master git tag -a v1.0.0 -m "V1.0版本" git push origin v1.0.0 git push --tags 4,删除分支 git branch -d 分支名称 5,设置用户名和邮箱 git config --global user.name 你的用户名 git config --global user.email 你的邮箱 打标签 # 列出标签 git tag # 列出特定版本标签 git tag -l "v1.8.5*" # 创建标签 git tag -a v1.4 -m "my version 1.4" # 显示标签 git show v1.4 # 根据提交打标签 git tag -a v1.2 9fceb02 # 推送标签 git push origin v1.5 # 删除标签 git tag -d v1.4 # 检出标签,浏览使用 git checkout v1.4
豆子碎片的故事
豆子碎片小程序很早就注册了,刚开始做的功能就是浏览 Go Web 框架 Beego 的教程。当时,正在自学 Beego,而 Beego 的网站时常打不开,就想做一个小程序,可以浏览 Beego 内容。当时看到了 towxml 组件,正好可以实现 Markdown 转 Wxml,于是就将 Beego 的 内容文档写成 Markdown 格式,做成了小程序。小程序的项目名叫 visit,就是浏览的意思。 当时小程序还是使用的云环境,云环境免费,并提供 dev 和 pro 两个环境。将 Beego 的 Markdown 文件存在云存储中。使用云函数调用数据。在小程序端使用 towxml 解析 Markdown 数据。当时发布小程序后,还是很受欢迎的。 中间歇了一段时间,没有更新文章,也没有维护小程序,小程序日浏览人数就下降了。云环境收费后,就彻底不管了。 后来,买了一台云服务器,为了练习自己所学的 Golang 语言,就将小程序重新拾起来。新做的项目内容是浏览唐诗,使用 Gin 框架进行后端开发,小程序端的布局和现在的豆子碎片布局差不多,只有一个首页,首页包含标题、一个搜索框、几个快捷按钮。项目很快完成,将小学和初中的唐诗、宋词、古诗经都录入了数据库,维护了很长一段时间。小程序上线后,每天也有几个人访问。在录入高中的唐诗内容时,就无法坚持下去了,高中的唐诗等内容都比较长,页面排版非常不美,所以高中的内容就没有录入。小程序在展示唐诗内容时,刚开始使用 Markdown 展示。后来想添加拼音,就将 Markdown 去掉,手撸 wxml,最后,拼音也添加了,但是费了很大劲,自己不擅长前端,美工。本还计划添加录音,但实在没有素材,真正做起来,费时费力,没有精力和动力就搁置了。 2024 年微信平台要求小程序都要备案。我有三个小程序,本想都放弃了,但后来,在工作中要用到音频格式转换,在小程序端实现操作起来是真的很方便,省时省力,不需要开电脑,也可以在任何时间操作。所以计划留下一两个吧。在备案的时候,注销了一个,剩下了两个,目前还在使用和维护,一个是豆子工具,用来制作工具,平时我也在用,一个是豆子碎片,记录技术经验和代码片段。在备案豆子碎片小程序时,小程序原名称叫找唐诗,提交备案后,微信备案客服人员说唐诗这两字不让用,让换个名称。在换名称的时候,我就在想这个小程序要不要放弃?不放弃做什么内容?已经有一个豆子工具小程序做工具了,没有必要再做一个工具类小程序吧。一直没有想好,等微信备案人员二次打电话时(真的很负责),才确定下来,做笔记类应用,记录日常开发经验和技巧以及代码片段,本想叫代码碎片,为了和豆子工具保持一致,小程序名称就叫豆子碎片,寓意像玩积木一样,学了本小程序内容,你也可以制作一款你想要的小程序。 豆子碎片项目已经开源,项目地址:https://github.com/littletow/visit 豆子碎片目前没有实名认证,如果你喜欢就收藏一下。豆子碎片面对的人群是有技术门槛的,后续看情况再进行实名认证。 豆子碎片的文章也已经在我公众号发布。有兴趣可以查看一下,一个程序员之小程序的成长与蜕变 想要查看豆子碎片,可以扫下面的小程序码: