<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>口袋助手 on 豆子技术站</title><link>https://blog.91demo.top/tags/%E5%8F%A3%E8%A2%8B%E5%8A%A9%E6%89%8B/</link><description>Recent content in 口袋助手 on 豆子技术站</description><generator>Hugo -- 0.155.1</generator><language>zh-cn</language><lastBuildDate>Wed, 04 Feb 2026 18:00:00 +0800</lastBuildDate><atom:link href="https://blog.91demo.top/tags/%E5%8F%A3%E8%A2%8B%E5%8A%A9%E6%89%8B/index.xml" rel="self" type="application/rss+xml"/><item><title>基于 Go + 小程序构建“口袋指令中心”，实现远程发布控制</title><link>https://blog.91demo.top/bag-script/</link><pubDate>Wed, 04 Feb 2026 18:00:00 +0800</pubDate><guid>https://blog.91demo.top/bag-script/</guid><description>&lt;p&gt;我日常涉及 Hugo 博客发布、客户端打包、Nginx 运维等多种重复性脚本。每次都要 SSH 连服务器并执行命令，操作链过长，也不方便，特别是在身边没有电脑的情况。&lt;/p&gt;
&lt;p&gt;曾经想过使用HTML 远程调用，又担心安全，使用了微信公众号发消息，也特适合这个场景，但是因为微信更新，私信入口现在非常难进入。所以就想能否通过自己的小程序实现远程控制和鉴权。构建一个通用的执行引擎，通过小程序远程触发，且具备零前端修改（免于小程序上线审核）的扩展能力。&lt;/p&gt;
&lt;h2 id="系统架构设计"&gt;系统架构设计&lt;/h2&gt;
&lt;p&gt;为了实现“明天增加脚本，小程序不发版”的目标，采用了“配置驱动” 模式。即“配置在云端，指令在指尖”。通过将业务逻辑（脚本路径与名称）完全从前端小程序中解耦，实现一套代码支持无限扩展的运维能力。&lt;/p&gt;
&lt;h3 id="核心流程"&gt;核心流程&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;后端 (Go)：维护一个脚本配置列表（数据库或配置文件）。&lt;/li&gt;
&lt;li&gt;前端 (小程序)：启动时请求后端接口，拉取可用脚本列表。&lt;/li&gt;
&lt;li&gt;触发：使用时选择脚本名称，点击执行。&lt;/li&gt;
&lt;li&gt;鉴权：后端校验小程序 OpenID，仅允许本人指令生效。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="技术实现"&gt;技术实现&lt;/h2&gt;
&lt;h3 id="系统分为三层确保安全性与扩展性的统一"&gt;系统分为三层，确保安全性与扩展性的统一：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;配置层 (Go Config)：在服务器端定义脚本的 ID、名称和实际路径。&lt;/li&gt;
&lt;li&gt;鉴权层 (WeChat Auth)：利用微信小程序 OpenID 建立强一致性的身份白名单。&lt;/li&gt;
&lt;li&gt;展示层 (Mini Program UI)：动态拉取后端配置，仅负责“展示列表”与“触发指令”。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="技术实现方案"&gt;技术实现方案&lt;/h3&gt;
&lt;p&gt;A. 后端：动态脚本引擎 (Go)&lt;/p&gt;
&lt;p&gt;后端不再硬编码脚本路径，而是定义一个结构体：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 脚本任务定义&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ScriptTask&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ID&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;id&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 前端传递的任务标识&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;name&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 小程序界面显示的文字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Command&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`json:&amp;#34;-&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 实际执行的脚本路径 (对前端保密)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 示例配置（可存放在 JSON 文件或数据库中）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tasks&lt;/span&gt; = []&lt;span style="color:#a6e22e"&gt;ScriptTask&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;ID&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;hugo-post&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;发布 Hugo 文章&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Command&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/scripts/deploy_hugo.sh&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;ID&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;build-client&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;构建客户端&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Command&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;/scripts/build_mole_go.sh&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&lt;span style="color:#a6e22e"&gt;ID&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;nginx-restart&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Name&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;重启 Nginx 服务&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;Command&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;systemctl restart nginx&amp;#34;&lt;/span&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对外接口定义：&lt;/p&gt;</description></item></channel></rss>