<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>MowMark的个人博客</title><link>https://mowmark.github.io/mowmark_blog/</link><description>Recent content on MowMark的个人博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 14 Jul 2026 17:59:42 +0800</lastBuildDate><atom:link href="https://mowmark.github.io/mowmark_blog/index.xml" rel="self" type="application/rss+xml"/><item><title>使用Syncthing进行文件同步</title><link>https://mowmark.github.io/mowmark_blog/computer/application/sync/000_syncthing/</link><pubDate>Tue, 14 Jul 2026 14:18:28 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/computer/application/sync/000_syncthing/</guid><description>&lt;h2 id="什么是syncthing"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%afsyncthing" class="header-anchor"&gt;&lt;/a&gt;什么是Syncthing?
&lt;/h2&gt;&lt;p&gt;简而言之, Syncthing 是一款专门用于文件同步的开源软件. 它自主设计了一套名为 BEP (Block Exchange Protocol) 的协议, 并基于此搭建了 P2P 架构, 每一端都能独立进行文件的发送与接收.&lt;/p&gt;
&lt;p&gt;需要说明的是, 文件内容本身是点对点直连传输的. 但两台设备要&amp;quot;找到彼此&amp;quot;, 默认还是依赖官方维护的 discovery server (设备发现) 和 relay server (NAT 穿透失败时的中继). 这两个服务器不经手你的文件内容, 只负责牵线搭桥. 如果你对隐私要求极高, 也可以自建这两个服务, 但对大多数人来说没有必要.&lt;/p&gt;
&lt;h2 id="为什么要使用-syncthing"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e4%bd%bf%e7%94%a8-syncthing" class="header-anchor"&gt;&lt;/a&gt;为什么要使用 Syncthing?
&lt;/h2&gt;&lt;p&gt;日常跨设备同步文件, 常见的做法无非是丢云盘或插移动硬盘倒来倒去. 但这两种方式各有各的问题: 云盘要经过第三方服务器, 大文件同步慢, 免费额度有限; 移动硬盘完全依赖人工操作, 谈不上&amp;quot;同步&amp;quot;.&lt;/p&gt;
&lt;p&gt;Syncthing 的优势在于:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;去中心化&lt;/strong&gt;: 不经过任何第三方存储, 文件只在你自己的设备之间流转.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;增量同步&lt;/strong&gt;: 只传输变化的部分, 不用每次全量拷贝.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨平台&lt;/strong&gt;: Windows, Linux, macOS, Android 都有对应客户端.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开源免费&lt;/strong&gt;: 没有容量限制, 也不用担心某天服务商跑路.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你有多台常驻设备 (比如台式机 + 笔记本 + NAS), 且不想依赖云盘, Syncthing 是一个相当稳妥的选择.&lt;/p&gt;
&lt;h2 id="步骤"&gt;&lt;a href="#%e6%ad%a5%e9%aa%a4" class="header-anchor"&gt;&lt;/a&gt;步骤
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;下载&lt;/strong&gt;: 前往 &lt;a class="link" href="https://syncthing.net/downloads/" target="_blank" rel="noopener"
 &gt;Syncthing&lt;/a&gt; 下载适合的架构版本, 解压或安装运行.
&lt;ul&gt;
&lt;li&gt;如果你的发行版软件源收录了 Syncthing, 也可以用包管理器安装 (比如 Ubuntu/Debian: &lt;code&gt;sudo apt install syncthing&lt;/code&gt;). 好处是系统自带了 systemd 服务模板, 后面开机启动省事很多. 坏处是版本会落后一些.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Windows 用户直接从官网下载安装包, 双击安装即可, 后续的 Web UI 操作和 Linux 完全一致, 不再赘述.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;ol start="2"&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;打开Web UI&lt;/strong&gt;: 启动后, 进入浏览器, 访问&lt;code&gt;http://localhost:8384&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;添加设备&lt;/strong&gt;: 点击&amp;quot;添加远程设备&amp;quot;, 填入另一台设备的 Device ID. Device ID 可以在对方的 Web UI 里点击右上角&amp;quot;操作 → 显示 ID&amp;quot;查到, 是一长串字符或者一个二维码. 添加之后, 需要在两台设备上分别完成这个操作 (互相添加对方), 并在对方的界面上手动接受连接请求, 双方才算配对成功.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;添加并共享文件夹&lt;/strong&gt;: 点击&amp;quot;添加文件夹&amp;quot;, 填写文件夹路径和文件夹标签 (Folder ID). 标签是两台设备之间识别同步关系的唯一标识, 两边必须一致. 保存后, 记得在文件夹的&amp;quot;共享&amp;quot;选项卡中勾选刚才配对好的目标设备. 对方会收到一条共享邀请, 接受后选择本地存放路径, 同步才会真正开始. 只加设备不共享文件夹, 或者加了文件夹不勾目标设备, 都不会触发任何同步.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在另一台电脑上重复上述操作即可.&lt;/p&gt;
&lt;h2 id="设置开机启动"&gt;&lt;a href="#%e8%ae%be%e7%bd%ae%e5%bc%80%e6%9c%ba%e5%90%af%e5%8a%a8" class="header-anchor"&gt;&lt;/a&gt;设置开机启动
&lt;/h2&gt;&lt;p&gt;Linux 通过 systemd 管理系统后台服务, 控制程序何时启动、以什么身份运行、异常退出后如何处理. Windows 则通过系统服务和任务计划程序管理. 下面按平台和安装方式分别说明.&lt;/p&gt;
&lt;h3 id="通过包管理器安装-linux"&gt;&lt;a href="#%e9%80%9a%e8%bf%87%e5%8c%85%e7%ae%a1%e7%90%86%e5%99%a8%e5%ae%89%e8%a3%85-linux" class="header-anchor"&gt;&lt;/a&gt;通过包管理器安装 (Linux)
&lt;/h3&gt;&lt;p&gt;如果你是用 &lt;code&gt;apt&lt;/code&gt; / &lt;code&gt;dnf&lt;/code&gt; 等包管理器安装的, 系统已经自带了 &lt;code&gt;syncthing@&amp;lt;user&amp;gt;.service&lt;/code&gt; 模板服务, 一条命令搞定:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; --now syncthing@&amp;lt;user&amp;gt;.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不需要手写 unit 文件, 手动安装的读者请继续往下看.&lt;/p&gt;
&lt;h3 id="手动安装-linux"&gt;&lt;a href="#%e6%89%8b%e5%8a%a8%e5%ae%89%e8%a3%85-linux" class="header-anchor"&gt;&lt;/a&gt;手动安装 (Linux)
&lt;/h3&gt;&lt;p&gt;如果你是手动下载的二进制文件, 才需要走完下面完整的流程:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;创建软链接&lt;/strong&gt;: 有些教程在 &lt;code&gt;/usr/bin/&lt;/code&gt; 下创建软链接, 但那是发行版包管理器管辖的目录, 自己放文件容易和系统更新冲突. 更推荐放在 &lt;code&gt;/usr/local/bin/&lt;/code&gt; 下&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ln -s &amp;lt;你的Syncthing可执行文件的绝对路径&amp;gt; /usr/local/bin/syncthing
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;编辑 service 服务文件&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo vim /etc/systemd/system/syncthing.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="3"&gt;
&lt;li&gt;&lt;strong&gt;粘贴如下内容&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Unit]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Description=Syncthing - Open Source Continuous File Synchronization
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;After=network.target
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Service]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;User=&amp;lt;user&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ExecStart=/usr/local/bin/syncthing
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Restart=on-failure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SuccessExitStatus=3 4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RestartForceExitStatus=3 4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[Install]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;WantedBy=multi-user.target
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;code&gt;Restart=on-failure&lt;/code&gt;: 服务异常退出时自动重启.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SuccessExitStatus=3 4&lt;/code&gt; + &lt;code&gt;RestartForceExitStatus=3 4&lt;/code&gt;: Syncthing 自动升级或手动重启时以退出码 3 或 4 退出. 不加这两行, systemd 会把正常重启当成崩溃, 触发不必要的报错.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;WantedBy=multi-user.target&lt;/code&gt;: 在多用户模式下启动.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;记得把 &lt;code&gt;User&lt;/code&gt; 换成你自己的用户名, 用 root 跑 Syncthing 没有必要, 也不安全.&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;strong&gt;重新加载 daemon&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl daemon-reload
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="5"&gt;
&lt;li&gt;&lt;strong&gt;设置开机启动&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; syncthing
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="6"&gt;
&lt;li&gt;&lt;strong&gt;手动启动&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl start syncthing
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果是包管理器安装的, 则用 &lt;code&gt;sudo systemctl start syncthing@&amp;lt;user&amp;gt;.service&lt;/code&gt; 启动.&lt;/p&gt;
&lt;p&gt;完成后, 用 &lt;code&gt;sudo systemctl status syncthing&lt;/code&gt; (或 &lt;code&gt;syncthing@&amp;lt;user&amp;gt;&lt;/code&gt;) 确认服务为 &lt;code&gt;active (running)&lt;/code&gt; 状态即可.&lt;/p&gt;
&lt;h3 id="安装版-windows"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e7%89%88-windows" class="header-anchor"&gt;&lt;/a&gt;安装版 (Windows)
&lt;/h3&gt;&lt;p&gt;Windows 安装包默认将 Syncthing 注册为系统服务. 打开 &lt;code&gt;Win+R&lt;/code&gt; 输入 &lt;code&gt;services.msc&lt;/code&gt;, 找到 &lt;code&gt;Syncthing&lt;/code&gt; 服务, 确认启动类型为&amp;quot;自动&amp;quot;即可.&lt;/p&gt;
&lt;h3 id="便携版-windows"&gt;&lt;a href="#%e4%be%bf%e6%90%ba%e7%89%88-windows" class="header-anchor"&gt;&lt;/a&gt;便携版 (Windows)
&lt;/h3&gt;&lt;p&gt;便携版不会注册系统服务. 可以在任务计划程序中创建一条基本任务: 触发器选&amp;quot;当前用户登录时&amp;quot;, 操作选&amp;quot;启动程序&amp;quot;, 填入 &lt;code&gt;syncthing.exe&lt;/code&gt; 的完整路径. 一般情况用安装版就够了.&lt;/p&gt;
&lt;h2 id="补充说明"&gt;&lt;a href="#%e8%a1%a5%e5%85%85%e8%af%b4%e6%98%8e" class="header-anchor"&gt;&lt;/a&gt;补充说明
&lt;/h2&gt;&lt;h3 id="忽略不需要同步的文件"&gt;&lt;a href="#%e5%bf%bd%e7%95%a5%e4%b8%8d%e9%9c%80%e8%a6%81%e5%90%8c%e6%ad%a5%e7%9a%84%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;忽略不需要同步的文件
&lt;/h3&gt;&lt;p&gt;有些文件夹或文件类型不需要也不应该被同步. 在同步文件夹根目录创建 &lt;code&gt;.stignore&lt;/code&gt;, 按行写入忽略模式, 语法和 &lt;code&gt;.gitignore&lt;/code&gt; 类似. 一个常见的配置如下:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 版本控制
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;.git/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 依赖目录
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;node_modules/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;__pycache__/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 编译产物
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.o
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.class
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 临时文件
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.tmp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;*.swp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;~*
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;配置后 Syncthing 会自动跳过这些路径, 不再传输和扫描.&lt;/p&gt;
&lt;h3 id="文件版本控制"&gt;&lt;a href="#%e6%96%87%e4%bb%b6%e7%89%88%e6%9c%ac%e6%8e%a7%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;文件版本控制
&lt;/h3&gt;&lt;p&gt;日常使用中误删或误覆盖的情况难以完全避免. 在 Web UI 中点击对应文件夹 → 编辑 → File Versioning, 可以启用版本控制. 推荐使用 &lt;code&gt;Simple File Versioning&lt;/code&gt;, 设置保留最近 N 个旧版本. 当文件被修改或删除时, 旧版本会被保留下来, 而不是被彻底丢弃.&lt;/p&gt;
&lt;h3 id="冲突处理"&gt;&lt;a href="#%e5%86%b2%e7%aa%81%e5%a4%84%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;冲突处理
&lt;/h3&gt;&lt;p&gt;两台设备同时在同一个文件上做了修改, Syncthing 不会静默覆盖任意一方. 它会保留最后一次同步的版本作为基础, 另一端的修改另存为冲突副本. 副本命名格式为 &lt;code&gt;文件名.sync-conflict-YYYYMMDD-HHMMSS.ext&lt;/code&gt;. 你发现冲突后手动核对两个版本的内容, 保留正确的, 删除多余的那个即可.&lt;/p&gt;
&lt;h3 id="纯局域网模式"&gt;&lt;a href="#%e7%ba%af%e5%b1%80%e5%9f%9f%e7%bd%91%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;纯局域网模式
&lt;/h3&gt;&lt;p&gt;如果所有设备都在同一个局域网内, 不需要经过公网的 discovery 和 relay 服务器. 进入 &lt;code&gt;操作 → 高级 → 连接&lt;/code&gt;, 取消勾选 &lt;code&gt;Global Discovery&lt;/code&gt; 和 &lt;code&gt;Enable Relaying&lt;/code&gt;, 只保留 &lt;code&gt;LAN Discovery&lt;/code&gt;. 这样 Syncthing 只会在局域网内广播和连接, 不走公网, 速度更快, 隐私性也更高.&lt;/p&gt;</description></item><item><title>代理协议与代理软件</title><link>https://mowmark.github.io/mowmark_blog/computer/application/vpn/000_protocol/</link><pubDate>Mon, 08 Jun 2026 00:00:00 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/computer/application/vpn/000_protocol/</guid><description>&lt;h2 id="前言"&gt;&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;前言
&lt;/h2&gt;&lt;p&gt;在写好 &lt;a class="link" href="https://mowmark.github.io/mowmark_blog/computer/linux/001_linuxinstallation/" &gt;Linux 双系统安装指南&lt;/a&gt; 后, 我原本想按照&lt;strong&gt;底层-&amp;gt;中间件-&amp;gt;高层&lt;/strong&gt;的顺序来规划文章, 结果在写&lt;strong&gt;Bash, Csh 和 Zsh&lt;/strong&gt;的时候, 发现寸步难行, 因为读者没法科学上网, 很多必要的软件都下载不了, 因此还是先把科学上网的相关内容写好.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="什么是代理"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%af%e4%bb%a3%e7%90%86" class="header-anchor"&gt;&lt;/a&gt;什么是代理?
&lt;/h2&gt;&lt;p&gt;顾名思义, 代理就是代替一个人去完成某个事情, 而在计算机领域中, 代理也是类似的道理: 代理服务器代替客户去访问某个特定域名, 以此规避某些限制, 或者获取某些资格.&lt;/p&gt;
&lt;p&gt;在这个过程中, 代理协议就是代理服务器和客户机的通信协议, 而代理软件则是基于这些协议开发出来的软件.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="代理协议"&gt;&lt;a href="#%e4%bb%a3%e7%90%86%e5%8d%8f%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;代理协议
&lt;/h2&gt;&lt;p&gt;目前的代理协议主要分为传统代理协议和现代隧道协议. 后者相当于在增加了加密和混淆的隧道中跑传统代理.&lt;/p&gt;
&lt;h3 id="传统代理协议"&gt;&lt;a href="#%e4%bc%a0%e7%bb%9f%e4%bb%a3%e7%90%86%e5%8d%8f%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;传统代理协议
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SOCKS5&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在 &lt;code&gt;OSI七层模型&lt;/code&gt; 中, 这个协议&lt;strong&gt;工作在会话层 (第五层)&lt;/strong&gt;, 不关心上层数据的内容. 客户端告诉代理服务器&amp;quot;我要连接某个 IP 的某个端口&amp;quot;, 服务器建立连接后双向转发, 仅此而已. 它的特点是握手简单, 无加密, 无混淆. 但是所有现代代理软件都支持 &lt;code&gt;SOCKS5&lt;/code&gt; 入站和出站, 是名副其实的通用接口.&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;HTTP Proxy&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个协议&lt;strong&gt;工作在应用层&lt;/strong&gt;, 只能代理 &lt;code&gt;HTTP/HTTPS&lt;/code&gt; 流量. 处理 &lt;code&gt;HTTPS&lt;/code&gt; 时用 &lt;code&gt;CONNECT&lt;/code&gt; 方法建立隧道, 所以也叫做 &lt;code&gt;HTTP Tunnel&lt;/code&gt;, 同样无加密.&lt;/p&gt;
&lt;p&gt;这两个协议只实现了基础的代理逻辑, 但是并没有增强流量转发过程中的安全性, 存在被劫持和数据泄露的风险. 因此才有后续隧道协议的诞生.&lt;/p&gt;
&lt;h3 id="现代隧道协议"&gt;&lt;a href="#%e7%8e%b0%e4%bb%a3%e9%9a%a7%e9%81%93%e5%8d%8f%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;现代隧道协议
&lt;/h3&gt;&lt;p&gt;这类协议基本都是在 &lt;code&gt;SOCKS5&lt;/code&gt; 和 &lt;code&gt;HTTP Proxy&lt;/code&gt; 外面包了一层加密和伪装. 它们具有两个核心设计目标:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;加密: 防止内容被识别.&lt;/li&gt;
&lt;li&gt;混淆: 伪装流量特征, 防止被识别和封锁.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要协议包括:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Shadowsocks (SS)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;特点是极简和高效. 客户端把原始数据用预共享密钥加密后直接发给服务端, 服务端解密后转发, 没有复杂的握手过程. 加密方式经历了多次迭代, 主流使用 &lt;code&gt;AEAD&lt;/code&gt; 加密 (如 &lt;code&gt;aes-256-gcm&lt;/code&gt;). 后来又出了 &lt;code&gt;Shadowsocks 2022&lt;/code&gt; 版本, 引入了基于 &lt;code&gt;PSK&lt;/code&gt; 的会话密钥, 进一步解决了重放攻击和主动探测的问题.&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;VMess (V2Ray 原生协议)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;V2Ray&lt;/code&gt; 项目的原生协议. 相比 &lt;code&gt;Shadowsocks&lt;/code&gt;, 核心改进在于在数据传输前增加了认证环节: 客户端用一个基于时间的 &lt;code&gt;UUID&lt;/code&gt; 生成请求头, 服务端能够验证请求的合法性, 不符合的直接丢弃. 支持 &lt;code&gt;AEAD&lt;/code&gt; 加密和多路复用.&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;strong&gt;VLESS&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以理解为去掉了内层加密的 &lt;code&gt;VMess&lt;/code&gt;. &lt;code&gt;VLESS&lt;/code&gt; 本身不负责加密, 而是把加密交给底层传输层 (&lt;code&gt;TLS / XTLS / Reality&lt;/code&gt;) 来做, 避免双重加密带来的性能开销.&lt;/p&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;strong&gt;Trojan&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;设计思路是拥抱标准 &lt;code&gt;TLS&lt;/code&gt;, 把代理流量伪装成普通的 &lt;code&gt;HTTPS&lt;/code&gt; 访问. 服务端看起来就是一个正常的 &lt;code&gt;HTTPS&lt;/code&gt; 网站, 客户端用标准 &lt;code&gt;TLS&lt;/code&gt; 连接, 在加密通道内传输代理数据. 外部无法区分这是代理流量还是正常的网页访问, 以此实现混淆.&lt;/p&gt;
&lt;ol start="5"&gt;
&lt;li&gt;&lt;strong&gt;Reality&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;Trojan&lt;/code&gt; 的伪装依赖你自己的域名和 &lt;code&gt;TLS&lt;/code&gt; 证书, 如果域名暴露了, 伪装就破了. &lt;code&gt;Reality&lt;/code&gt; 更进一步: 在 &lt;code&gt;TLS&lt;/code&gt; 握手时借用一个真实存在的知名网站 (比如微软、苹果) 的域名作为 &lt;code&gt;SNI&lt;/code&gt;, 从外部看来这就是一个访问大厂网站的正常连接. 不需要自己购买域名和证书, 伪装程度更高.&lt;/p&gt;
&lt;ol start="6"&gt;
&lt;li&gt;&lt;strong&gt;Hysteria / Hysteria2&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基于 &lt;code&gt;QUIC (UDP)&lt;/code&gt; 协议的代理. 核心优势在于弱网环境下的表现: 利用 &lt;code&gt;QUIC&lt;/code&gt; 的多路复用和 &lt;code&gt;0-RTT&lt;/code&gt; 特性, 在丢包严重的网络中比基于 &lt;code&gt;TCP&lt;/code&gt; 的协议快很多. 代价是 &lt;code&gt;UDP/QUIC&lt;/code&gt; 在某些网络环境下可能被限速或阻断.&lt;/p&gt;
&lt;ol start="7"&gt;
&lt;li&gt;&lt;strong&gt;TUIC&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;同样基于 &lt;code&gt;QUIC&lt;/code&gt;, 设计上比 &lt;code&gt;Hysteria&lt;/code&gt; 更轻量. 已经停止独立维护, 其实现被吸收进了 &lt;code&gt;sing-box&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;当然, 如果你只是正常使用, 不打算自建节点或者深入研究, 其实没有什么必要了解每个协议的细节──现在的代理软件基本都支持多种协议, 选哪个协议更多取决于你的节点提供商支持什么.&lt;/p&gt;
&lt;p&gt;协议演化的主线可以概括为:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;无加密 &amp;ndash;&amp;gt; 对称加密 &amp;ndash;&amp;gt; 认证 + 加密 &amp;ndash;&amp;gt; TLS 伪装 &amp;ndash;&amp;gt; 借用 TLS &amp;ndash;&amp;gt; QUIC 优化弱网&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="代理软件"&gt;&lt;a href="#%e4%bb%a3%e7%90%86%e8%bd%af%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;代理软件
&lt;/h2&gt;&lt;h3 id="核心架构"&gt;&lt;a href="#%e6%a0%b8%e5%bf%83%e6%9e%b6%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;核心架构
&lt;/h3&gt;&lt;p&gt;现代代理软件几乎都遵循同一个数据流模型:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;graph LR
A["应用程序"] --&gt; B["入站 Inbound"]
 B --&gt; C{"路由引擎"}
 C --&gt;|"规则 A"| D1["出站: 代理节点"]
 C --&gt;|"规则 B"| D2["出站: 直连"]
 C --&gt;|"规则 C"| D3["出站: 拒绝"]
 D1 --&gt; E["远端代理服务器"]
 D2 --&gt; F["目标网站"]&lt;/pre&gt;&lt;p&gt;其中三个核心组件:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;入站: 定义软件以什么方式接收流量. 常见的有本地 &lt;code&gt;SOCKS/HTTP&lt;/code&gt; 监听 (需要应用主动设置代理) 和 &lt;code&gt;TUN&lt;/code&gt; 虚拟网卡 (接管整个系统的流量, 无需逐个应用配置).&lt;/li&gt;
&lt;li&gt;路由引擎: 根据域名, IP, 进程名和端口等信息判断流量走哪个出站, 是实现&lt;strong&gt;国内直连, 国外走代理&lt;/strong&gt;的关键.&lt;/li&gt;
&lt;li&gt;出站: 定义流量的出口与发送协议, 可以直连, 代理或者拒绝.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不同软件的区别主要体现在: 配置格式, 支持的协议范围, 路由规则的表达能力, 以及是否支持策略组 (自动选择延迟最低的节点, 故障自动切换等).&lt;/p&gt;
&lt;h3 id="代理软件-1"&gt;&lt;a href="#%e4%bb%a3%e7%90%86%e8%bd%af%e4%bb%b6-1" class="header-anchor"&gt;&lt;/a&gt;代理软件
&lt;/h3&gt;&lt;p&gt;代理软件不计其数, 但追溯源头, 主要是三个分支和若干个独立项目:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;graph TD
 subgraph "V2Ray 系"
 direction TB
 V1["2015 · V2Ray Core&lt;br/&gt;Victoria Raymond 创建"] --&gt; V2["2020 · Xray Core&lt;br/&gt;社区 fork, 新增 XTLS/Reality"]
 V1 --&gt; V3["v2rayN (PC客户端)"]
 V1 --&gt; V4["v2rayA (Web 界面)"]
 V2 --&gt; V3
 end

 subgraph "Clash 系"
 direction TB
 C1["2018 · Clash&lt;br/&gt;Go 语言, 规则驱动"] --&gt; C2["2020 · Clash Premium&lt;br/&gt;闭源增强版, 已停更"]
 C1 --&gt; C3["2022 · Clash Meta&lt;br/&gt;开源 fork, 支持更多协议"]
 C3 --&gt; C4["2023 · mihomo&lt;br/&gt;Clash Meta 更名"]
 C1 --&gt; C5["Clash for Windows&lt;br/&gt;已删库"]
 C4 --&gt; C6["Clash Verge Rev"]
 end

 subgraph "sing-box 系"
 direction TB
 S1["2022 · sing-box&lt;br/&gt;SagerNet 作者新项目"] --&gt; S2["Hiddify Next"]
 S1 --&gt; S3["NekoBox"]
 end

 subgraph "独立项目"
 I1["Surge (macOS/iOS)"]
 I2["Shadowrocket (iOS)"]
 I3["dae / daed (eBPF)"]
 I4["NaïveProxy"]
 I5["Brook"]
 end&lt;/pre&gt;&lt;p&gt;简单说明各系的特点:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;V2Ray 系 (Xray Core)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置格式为 &lt;code&gt;JSON&lt;/code&gt;, 采用多入站/多出站/路由的架构.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Xray&lt;/code&gt; 是 &lt;code&gt;V2Ray&lt;/code&gt; 的活跃 &lt;code&gt;fork&lt;/code&gt;, 目前事实上已取代原版, 是 &lt;code&gt;VLESS + Reality&lt;/code&gt; 的主要实现者.&lt;/li&gt;
&lt;li&gt;适合需要精细控制流量走向的场景, 但配置复杂, 手写 &lt;code&gt;JSON&lt;/code&gt; 容易出错.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Clash 系 (mihomo)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置格式为 &lt;code&gt;YAML&lt;/code&gt;, 核心概念是&amp;quot;策略组 + 规则&amp;quot;. 策略组可以自动测速选最快节点, 也可以手动切换.&lt;/li&gt;
&lt;li&gt;原版 &lt;code&gt;Clash&lt;/code&gt; 和 &lt;code&gt;Clash Premium&lt;/code&gt; 已停更, 目前活跃的是 &lt;code&gt;mihomo&lt;/code&gt; (原 &lt;code&gt;Clash Meta&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;配置直观, 社区生态成熟, 有大量现成的规则集可以直接用.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;sing-box 系&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;配置格式为 &lt;code&gt;JSON&lt;/code&gt;, 设计目标是融合 &lt;code&gt;V2Ray&lt;/code&gt; 的灵活性和 &lt;code&gt;Clash&lt;/code&gt; 的易用性.&lt;/li&gt;
&lt;li&gt;协议支持最全面: &lt;code&gt;Shadowsocks&lt;/code&gt;, &lt;code&gt;VMess&lt;/code&gt;, &lt;code&gt;VLESS&lt;/code&gt;, &lt;code&gt;Trojan&lt;/code&gt;, &lt;code&gt;Hysteria&lt;/code&gt;, &lt;code&gt;TUIC&lt;/code&gt;, &lt;code&gt;WireGuard&lt;/code&gt;, &lt;code&gt;Reality&lt;/code&gt; 全都原生支持.&lt;/li&gt;
&lt;li&gt;相对较新, 文档和中文教程还不如前两者丰富.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;独立项目&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Surge&lt;/code&gt; / &lt;code&gt;Shadowrocket&lt;/code&gt;: Apple 生态下的成熟商业客户端.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dae&lt;/code&gt;: 基于 &lt;code&gt;eBPF&lt;/code&gt; 的 Linux 透明代理, 性能极高, 适合路由器场景.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NaïveProxy&lt;/code&gt;: 复用 Chromium 网络栈, TLS 指纹和 Chrome 浏览器完全一致, 抗识别能力极强但部署复杂.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="内核能力对比"&gt;&lt;a href="#%e5%86%85%e6%a0%b8%e8%83%bd%e5%8a%9b%e5%af%b9%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;内核能力对比
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;特性&lt;/th&gt;
					&lt;th&gt;Xray Core&lt;/th&gt;
					&lt;th&gt;mihomo&lt;/th&gt;
					&lt;th&gt;sing-box&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;配置格式&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;YAML&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;策略组&lt;/td&gt;
					&lt;td&gt;不原生支持&lt;/td&gt;
					&lt;td&gt;原生支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;VLESS + Reality&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Hysteria 2&lt;/td&gt;
					&lt;td&gt;不支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;WireGuard 出站&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
					&lt;td&gt;支持&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TUN 模式&lt;/td&gt;
					&lt;td&gt;需外部工具&lt;/td&gt;
					&lt;td&gt;原生支持&lt;/td&gt;
					&lt;td&gt;原生支持&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="gui-客户端与内核的关系"&gt;&lt;a href="#gui-%e5%ae%a2%e6%88%b7%e7%ab%af%e4%b8%8e%e5%86%85%e6%a0%b8%e7%9a%84%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;&lt;/a&gt;GUI 客户端与内核的关系
&lt;/h3&gt;&lt;p&gt;很多人容易把 GUI 客户端和内核混为一谈. 实际上 GUI 客户端只是一层壳, 负责提供界面、解析订阅、管理配置, 真正干活的是底层内核.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;GUI 客户端&lt;/th&gt;
					&lt;th&gt;底层内核&lt;/th&gt;
					&lt;th&gt;平台&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;v2rayN&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Xray&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Windows / MacOS / Linux&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;v2rayA&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Xray&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全平台 (Web)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;v2rayNG&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Xray&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Android&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Clash Verge Rev&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;mihomo&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Windows / MacOS / Linux&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Hiddify Next&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sing-box&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全平台&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;NekoBox&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Xray&lt;/code&gt; 或 &lt;code&gt;sing-box&lt;/code&gt; (可切换)&lt;/td&gt;
					&lt;td&gt;Windows / Linux&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Shadowrocket&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;自有实现&lt;/td&gt;
					&lt;td&gt;iOS&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Stash&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;mihomo&lt;/code&gt; 兼容&lt;/td&gt;
					&lt;td&gt;iOS&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结
&lt;/h2&gt;&lt;p&gt;这篇文章只做了一个总体的概括. &lt;strong&gt;协议决定了数据怎么加密和伪装, 软件决定了流量怎么分流和管理, 而 GUI 客户端决定了你日常的使用体验&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;我目前主要在 Linux 和 Windows 上使用 v2rayN 和 Clash Verge Rev, Android 上主要使用 v2rayNG 和 Clash Meta For Android, 相关的内容后续会逐步更新.&lt;/p&gt;</description></item><item><title>双系统计算机的键鼠共享, 外接显示器切换与文件共享方案分享</title><link>https://mowmark.github.io/mowmark_blog/computer/hardware/000_multiplecomputer/</link><pubDate>Sat, 06 Jun 2026 00:00:00 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/computer/hardware/000_multiplecomputer/</guid><description>&lt;h2 id="背景"&gt;&lt;a href="#%e8%83%8c%e6%99%af" class="header-anchor"&gt;&lt;/a&gt;背景
&lt;/h2&gt;&lt;p&gt;由于工作原因, 目前使用一台笔记本进行户外部署与测试, 而台式机则留在工位上进行仿真与开发. 工位上有两台显示器, 于是产生了一个需求: &lt;strong&gt;两台计算机共享显示器, 并且能在键鼠和文件传输上无缝切换&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;这篇文章记录我最终的解决方案, 包括三个部分:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;键鼠共享&lt;/strong&gt;: 一套键盘鼠标同时控制两台计算机.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;显示器输入源切换&lt;/strong&gt;: 通过命令行或脚本切换显示器的视频输入, 不需要伸手按物理按键.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文件共享&lt;/strong&gt;: 通过 RJ45 接口的网线在两台计算机之间共享文件.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上述三个部分都支持 Windows 和 Ubuntu 双系统, 对于其他的 Linux 发行版也有一定的参考价值.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="硬件情况"&gt;&lt;a href="#%e7%a1%ac%e4%bb%b6%e6%83%85%e5%86%b5" class="header-anchor"&gt;&lt;/a&gt;硬件情况
&lt;/h2&gt;&lt;p&gt;我的硬件配置如下:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;设备&lt;/th&gt;
					&lt;th&gt;CPU / 显卡&lt;/th&gt;
					&lt;th&gt;视频输出接口&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;台式机&lt;/td&gt;
					&lt;td&gt;AMD R7 9700X / RTX 5060 Ti 16GB&lt;/td&gt;
					&lt;td&gt;DP×3 + HDMI×1&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ThinkBook 14 G7+ AHP&lt;/td&gt;
					&lt;td&gt;AMD Ryzen 7 H 255 / Radeon 780M&lt;/td&gt;
					&lt;td&gt;Type-C×2（DP Alt Mode）+ HDMI&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;显示器&lt;/th&gt;
					&lt;th&gt;接口&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;SANC G72 Max（27 寸）&lt;/td&gt;
					&lt;td&gt;DP×2 + HDMI×2&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;HKC S24 Pro（24 寸）&lt;/td&gt;
					&lt;td&gt;HDMI×1 + VGA×1&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;连接方式如下:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;graph LR
 A0[台式机] &lt;--DP--&gt; B0[27 寸]
 A0 &lt;--HDMI--&gt; B1[24 寸]
 A1[笔记本] &lt;--Type-C 转 DP--&gt; B0
 A1 &lt;--HDMI 转 VGA--&gt; B1
 A0&lt;--RJ45--&gt;A1&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="键鼠共享"&gt;&lt;a href="#%e9%94%ae%e9%bc%a0%e5%85%b1%e4%ba%ab" class="header-anchor"&gt;&lt;/a&gt;键鼠共享
&lt;/h2&gt;&lt;h3 id="显示协议区别"&gt;&lt;a href="#%e6%98%be%e7%a4%ba%e5%8d%8f%e8%ae%ae%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;&lt;/a&gt;显示协议区别
&lt;/h3&gt;&lt;p&gt;键鼠共享软件与你的桌面环境使用的显示协议有关. Wayland 对键鼠焦点捕捉的限制比 X11 严格得多, 很多在 X11 下能用的软件在 Wayland 下失灵.&lt;/p&gt;
&lt;p&gt;对于 Barrier, Input Leap 和 Deskflow 这几个软件, 我尝试后最终的结论是:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;X11 环境&lt;/strong&gt;: 三个软件都能使用.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wayland 环境&lt;/strong&gt;: 只有 Deskflow 能够正常工作.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;顺带一提, 这几个软件其实是一脉相承的:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;graph TD
 A[1996 · CosmoSynergy&lt;br/&gt;SGI 内部工具] --&gt; B[2001 · Synergy&lt;br/&gt;Chris Schoeneman 重写, GPLv2 开源]
 B --&gt; C[2009 · Synergy+&lt;br/&gt;社区 fork, 后合并回主线]
 C --&gt; B
 B --&gt; D[2018 · Barrier&lt;br/&gt;因 Synergy 2 商业化, 社区 fork]
 D --&gt; E[2021 · Input Leap&lt;br/&gt;Barrier 维护停滞后社区 fork]
 B --&gt; F[2024 · Deskflow&lt;br/&gt;Symless 重新以 GPL 开源 Synergy 核心,&lt;br/&gt;作为统一的上游项目]&lt;/pre&gt;&lt;p&gt;Deskflow 更接近原始 Synergy, 再加上是 Symless 官方维护, Wayland 适配走在了前面. 而 Barrier 和 Input Leap 已经有相当长一段时间没有更新.&lt;/p&gt;
&lt;p&gt;如果你不知道自己当前用的是哪种协议, 在终端中执行:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$XDG_SESSION_TYPE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;查看结果是 &lt;code&gt;wayland&lt;/code&gt; 或 &lt;code&gt;x11&lt;/code&gt; 即可.&lt;/p&gt;
&lt;h3 id="安装和配置"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e5%92%8c%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;安装和配置
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;安装: 只需要在 &lt;a class="link" href="https://github.com/deskflow/deskflow" target="_blank" rel="noopener"
 &gt;GitHub release&lt;/a&gt; 上下载安装包, 安装即可.&lt;/li&gt;
&lt;li&gt;配置:
&lt;ul&gt;
&lt;li&gt;服务端: 新建虚拟屏幕, 配置相对关系, 记录右上角的&lt;strong&gt;建议IP&lt;/strong&gt;, 点击启动.&lt;/li&gt;
&lt;li&gt;客户端: 在&lt;strong&gt;连接到&lt;/strong&gt;输入框中填入&lt;strong&gt;建议IP&lt;/strong&gt;, 点击连接.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

 &lt;blockquote&gt;
 &lt;p&gt;如果客户端连不上, 检查服务端的防火墙是否放行了 24800 端口 (Ubuntu: &lt;code&gt;sudo ufw allow 24800/tcp&lt;/code&gt;, Windows 会有自动弹窗提示.)&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="显示器输入源切换"&gt;&lt;a href="#%e6%98%be%e7%a4%ba%e5%99%a8%e8%be%93%e5%85%a5%e6%ba%90%e5%88%87%e6%8d%a2" class="header-anchor"&gt;&lt;/a&gt;显示器输入源切换
&lt;/h2&gt;&lt;h3 id="ddcci-协议"&gt;&lt;a href="#ddcci-%e5%8d%8f%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;DDC/CI 协议
&lt;/h3&gt;&lt;p&gt;前面已经接好了视频信号线, 已经能够正常使用, 只是每次切换主机时都需要伸手按物理按键, 比较麻烦. 我希望我的大部分操作可以不离开键鼠.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DDC/CI&lt;/strong&gt; (Display Data Channel / Command Interface) 协议能够解决这个问题. 简单来说, 这是一个让计算机通过视频接口中的 I&lt;sup&gt;2&lt;/sup&gt;C 通信针脚直接控制显示器的协议, 让亮度, 对比度和输入源等信息都能从系统层面读写. 这是一个行业通用协议， 大多数显示器都支持, 不一定默认启用, 可以在显示器的 OSD 菜单中找一下&amp;quot;DDC/CI&amp;quot;开关.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;这里需要注意一个坑&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;DDC/CI 依赖 I&lt;sup&gt;2&lt;/sup&gt;C 信号透传. HDMI, DP, Type-C 都能正常透传 I&lt;sup&gt;2&lt;/sup&gt;C, 唯独 &lt;strong&gt;VGA 转接线不行&lt;/strong&gt;, 这是因为, VGA 接口里有 DDC 针脚，但廉价转接芯片普遍不会保留它. 所以在我的方案里，24 寸显示器走 VGA 接笔记本时，无法用 DDC/CI 控制, 只能在台式机这边用 DP 控制它.&lt;/p&gt;
&lt;p&gt;扩展坞、HDMI 一分二转接线之类的设备同样普遍不透传 I&lt;sup&gt;2&lt;/sup&gt;C.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;说完了原理, 下面分别说 Ubuntu 和 Windows 下的操作.&lt;/p&gt;
&lt;h3 id="ubuntu-系统"&gt;&lt;a href="#ubuntu-%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;Ubuntu 系统
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;安装与权限配置&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 安装 ddcutil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt install ddcutil
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 加载 I2C 模块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo modprobe i2c-dev
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 将当前用户加入 I2C 用户组&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo usermod -aG i2c &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;执行完注销重新登录, 让用户组生效.&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;切换输入源&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在 Ubuntu 系统上, 最终要执行的命令格式为:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ddcutil --bus&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;I2C 总线号&amp;gt; setvcp &lt;span class="m"&gt;60&lt;/span&gt; &amp;lt;输入源代码&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;需要的两个参数都可以从 &lt;code&gt;ddcutil&lt;/code&gt; 自身查到.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步: 查询总线号&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ddcutil detect
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;输出类似:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Display 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; I2C bus: /dev/i2c-7
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mfg id: HKC - HKC OVERSEAS LIMITED
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Model: S24 PRO
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Display 2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; I2C bus: /dev/i2c-10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Mfg id: SAC - UNK
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Model: G72 Max
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;每个显示器的 &lt;code&gt;I2C bus&lt;/code&gt; 后面带着的数字 (这里是 7 和 10) 就是总线号.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步: 查询输入源代号&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在终端中执行:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ddcutil --bus&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;上一步的总线号&amp;gt; capabilities
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在输出结果中寻找 &lt;code&gt;Feature: 60 (Input Source)&lt;/code&gt;这一部分:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Feature: 60 (Input Source)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Values:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 11: HDMI-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 12: HDMI-2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 0f: DisplayPort-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 10: DisplayPort-2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;下面列出来的就是这台显示器支持的输入源代号.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三步: 拼接完整命令&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;举个例子, 假设现在我要把 27寸显示器 (总线 10) 切到 DisplayPort-1:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ddcutil --bus&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt; setvcp &lt;span class="m"&gt;60&lt;/span&gt; 0x0f
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="自动化脚本"&gt;&lt;a href="#%e8%87%aa%e5%8a%a8%e5%8c%96%e8%84%9a%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;自动化脚本
&lt;/h4&gt;&lt;p&gt;每次手敲命令也很烦, 所以我 &lt;span class="spoiler"&gt;让 Gemini 3.1 Pro&lt;/span&gt;
 写了个交互式脚本 &lt;code&gt;SmartSwitch&lt;/code&gt;, 可以扫描所有显示器, 用颜色标注当前活跃的输入源, 记住每个端口接的是哪台主机, 并且一键切换.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ==========================================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SmartSwitch v3.0 — 带颜色状态标注的显示器输入源管理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ==========================================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 功能：&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 🟢 绿色标注当前活跃输入源（自动检测）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 🟡 黄色标注已连接但未活跃的输入源（手动标记）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. ⚪ 灰色标注未标记/未知状态的输入源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. 一键切换输入源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 5. 切换后自动验证&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 前置要求：sudo ddcutil detect 能扫描到显示器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ==========================================&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -euo pipefail
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -------------------- 配置 --------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/.config/smart-switch&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DEVICE_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFIG_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/devices.conf&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 记录哪些端口有设备&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 预定义输入源名称映射&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;declare&lt;/span&gt; -A &lt;span class="nv"&gt;SOURCE_MAP&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x01&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;VGA-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x03&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DVI-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x04&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DVI-2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x0f&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DisplayPort-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x10&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DisplayPort-2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x11&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HDMI-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x12&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HDMI-2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;0x1b&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;USB Type-C&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -------------------- 颜色定义 --------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 检测终端是否支持颜色（非管道/重定向时启用）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -t &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_GREEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\033[0;32m&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_YELLOW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\033[0;33m&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_GRAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\033[0;90m&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_RED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\033[0;31m&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# 仅用于真正的错误/警告&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_BOLD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\033[1m&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\033[0m&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 输出到文件或管道时禁用颜色&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_GREEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_YELLOW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_GRAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_RED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_BOLD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 图标（如果终端不支持 Unicode，回退到 ASCII）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LC_ALL&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; *&lt;span class="s2"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;* &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LC_ALL&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; *&lt;span class="s2"&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;* &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;ICON_ACTIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;●&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 活跃（实心圆）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;ICON_STANDBY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;○&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 待命（空心圆）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;ICON_OFF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;·&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;# 未连接（小点）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;ICON_ACTIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;ICON_STANDBY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;o&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;ICON_OFF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -------------------- 工具函数 --------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;to_lower&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;&amp;#39;[:upper:]&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;[:lower:]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ensure_config_dir&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; ! -d &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$CONFIG_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mkdir -p &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$CONFIG_DIR&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; ! -f &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; cat &amp;gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# ===========================================
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# SmartSwitch — 已连接设备标记
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# ===========================================
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 格式: BUS|HEX_CODE=设备名称
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 示例:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 7|0x0f=我的台式机
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 7|0x11=Surface Laptop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 10|0x11=Surface Laptop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;#
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 标记后的端口在非活跃时会显示为黄色（待命状态）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# 删除某行即可取消标记
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;# ===========================================
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 获取设备标记&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;get_device_label&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;=&amp;#39;&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r k v&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[[&lt;/span&gt;:space:&lt;span class="o"&gt;]]&lt;/span&gt;*# &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 检查端口是否已被标记（返回 0=已标记, 1=未标记）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;is_port_marked&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;escaped_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="p"&gt;//./&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; grep -q &lt;span class="s2"&gt;&amp;#34;^&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;escaped_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 读取当前活跃输入源（返回 16 进制字符串如 0x0f）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;get_current_source&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; terse_output
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;terse_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ddcutil --bus&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; getvcp &lt;span class="m"&gt;60&lt;/span&gt; --terse 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$terse_output&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# terse 格式: &amp;#34;VCP 60 &amp;lt;flags&amp;gt; &amp;lt;value&amp;gt;&amp;#34; value 以 x 开头表示16进制 (如 x0f)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; hex_val
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;hex_val&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$terse_output&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;/^VCP 60 / {print $NF}&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$hex_val&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$hex_val&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^x&lt;span class="o"&gt;[&lt;/span&gt;0-9a-fA-F&lt;span class="o"&gt;]&lt;/span&gt;+$ &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0x&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hex_val&lt;/span&gt;&lt;span class="p"&gt;#x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 标记/取消标记设备&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;toggle_device_mark&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;escaped_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="p"&gt;//./&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; current_label
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;current_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_device_label &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;port_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SOURCE_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;未知接口&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;━━━ 标记设备 ━━━&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;端口: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;port_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$current_label&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;当前标记: [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;current_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 1. 修改标记&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 2. 删除标记（端口将变为灰色）&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 0. 取消&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;👉 选择: &amp;#34;&lt;/span&gt; action
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;输入新名称: &amp;#34;&lt;/span&gt; new_label
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sed -i &lt;span class="s2"&gt;&amp;#34;/^&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;escaped_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=/d&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$new_label&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;✅ 已更新: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sed -i &lt;span class="s2"&gt;&amp;#34;/^&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;escaped_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=/d&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;✅ 已删除标记（端口状态变为灰色）&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; *&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;当前状态: ⚪ 未标记（灰色）&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;输入设备名称以标记此端口（如: 台式机）: &amp;#34;&lt;/span&gt; new_label
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$new_label&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;✅ 已标记: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;（端口状态变为黄色）&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 打印带颜色的输入源条目&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print_source_entry&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;current_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;port_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SOURCE_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;未知接口&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$current_source&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$COLOR_GREEN&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ICON_ACTIVE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34; ← 当前活跃&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; is_port_marked &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$COLOR_YELLOW&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ICON_STANDBY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;local&lt;/span&gt; device_label
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;device_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_device_label &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34; [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;device_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$COLOR_GRAY&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$ICON_OFF&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;color&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%s. %s %s (%s)%s&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$index&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$icon&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$port_name&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$suffix&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -------------------- 主循环 --------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ensure_config_dir
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 首次运行提示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; ! -s &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; ! grep -v &lt;span class="s1"&gt;&amp;#39;^#&amp;#39;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$DEVICE_FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -q &lt;span class="s1"&gt;&amp;#39;[^[:space:]]&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_BOLD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;💡 提示:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 这是首次运行。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 脚本可以自动检测当前活跃的输入源（绿色），&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 但需要你手动标记哪些端口连接了设备（黄色）。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 进入菜单后选择「🏷️ 标记设备」即可。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;按&amp;lt;Enter&amp;gt;键继续...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; clear
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; SmartSwitch v3.0 — 输入源状态管理&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;🟢 活跃 🟡 待命 ⚪ 未连接&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;==========================================&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;正在扫描 I2C 总线...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 扫描显示器&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;scan_result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ddcutil detect -t 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;declare&lt;/span&gt; -a &lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;declare&lt;/span&gt; -a &lt;span class="nv"&gt;models&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;in_valid_display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r line&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;%%[![:&lt;/span&gt;&lt;span class="nv"&gt;space&lt;/span&gt;&lt;span class="p"&gt;:]]*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Display &amp;#34;&lt;/span&gt;* &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Invalid display&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;in_valid_display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Invalid display&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;in_valid_display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$in_valid_display&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;I2C bus:&amp;#34;&lt;/span&gt;* &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;bus_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;##* &lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;bus_num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;bus_path&lt;/span&gt;&lt;span class="p"&gt;##*-&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="o"&gt;+=(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$bus_num&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Monitor:&amp;#34;&lt;/span&gt;* &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;mon_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed -E &lt;span class="s1"&gt;&amp;#39;s/^Monitor:[[:space:]]+//&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;mon_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$mon_str&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d&lt;span class="s1"&gt;&amp;#39;:&amp;#39;&lt;/span&gt; -f2&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;models&lt;/span&gt;&lt;span class="o"&gt;+=(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$mon_model&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$scan_result&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -eq &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RED&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;❌ 未检测到支持 DDC/CI 的显示器。&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;排查建议:&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 1. 执行: sudo ddcutil detect&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 2. 检查显示器 OSD 菜单中 DDC/CI 是否开启&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 3. 是否使用了 DisplayLink 扩展坞？&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# --- 显示器选择 ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;==== 可用的显示器 ====&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!buses[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;models&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (Bus: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0. 退出脚本&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;------------------------&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;👉 选择显示器 (0-&lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;): &amp;#34;&lt;/span&gt; monitor_choice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$monitor_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;👋 再见！&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; ! &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$monitor_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;+$ &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$monitor_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -lt &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$monitor_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -gt &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;⚠️ 输入错误！&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;selected_bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;buses&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;monitor_choice &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;selected_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;models&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;monitor_choice &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# --- 获取能力列表 ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;🔍 正在读取 [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;selected_model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] 的能力信息...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;raw_caps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ddcutil --bus&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; capabilities 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 提取 Feature 60 区块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;feature_60_block&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$raw_caps&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; /Feature: 60/ { flag=1; print; next }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; /Feature:/ { if(flag) exit }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; flag
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;declare&lt;/span&gt; -a &lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$feature_60_block&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r hex_code&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$hex_code&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$hex_code&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0x00&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="o"&gt;+=(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$hex_code&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$feature_60_block&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk -F: &lt;span class="s1"&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; /^[[:space:]]+[0-9a-fA-F]{2}:/ {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; gsub(/^[ \t]+/, &amp;#34;&amp;#34;, $1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; print &amp;#34;0x&amp;#34;$1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#39;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# --- 获取当前活跃输入源 ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;current_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_current_source &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# --- 输入源操作循环 ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;==== [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;selected_model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] 输入源状态 ====&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 打印图例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_GREEN&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;ICON_ACTIVE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 绿色&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = 当前活跃 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_YELLOW&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;ICON_STANDBY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 黄色&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = 已连接待命 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_GRAY&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;ICON_OFF&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 灰色&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = 未标记&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ─────────────────────────────────────&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 打印每个输入源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;option_index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -gt &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; vcp in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; print_source_entry &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$option_index&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$current_source&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;((&lt;/span&gt;option_index++&lt;span class="o"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RED&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;⚠️ 无法获取此显示器的输入源列表&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; ─────────────────────────────────────&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;switch_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$option_index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;switch_opt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. 🔄 切换输入源&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;mark_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;option_index &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;mark_opt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. 🏷️ 标记/取消标记设备&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;refresh_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;option_index &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;refresh_opt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. 🔃 刷新状态&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;return_opt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;option_index &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;return_opt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. 🔙 返回显示器列表&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0. ❌ 退出脚本&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;------------------------&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;👉 选择操作 (0-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;return_opt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;): &amp;#34;&lt;/span&gt; action_choice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# --- 处理选择 ---&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$action_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;👋 再见！&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$action_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$return_opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$action_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$refresh_opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 刷新：重新获取当前活跃源&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;current_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_current_source &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;✅ 状态已刷新&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$action_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$mark_opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 标记设备子菜单&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;--- 选择要标记的端口 ---&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!valid_vcps[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SOURCE_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;未知接口&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_device_label &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) → 已标记: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) → 未标记&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0. 返回&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;选择: &amp;#34;&lt;/span&gt; mark_choice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$mark_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;+$ &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$mark_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -ge &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$mark_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -le &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; toggle_device_mark &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;mark_choice &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;current_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_current_source &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$action_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$switch_opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 切换输入源子菜单&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;--- 切换到哪个输入源？---&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!valid_vcps[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SOURCE_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;未知接口&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_device_label &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$current_source&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) ← 当前活跃&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$label&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;) [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;i &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;. ✍️ 手动输入代码&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0. 取消&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;选择: &amp;#34;&lt;/span&gt; switch_choice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$switch_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;0&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$switch_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[&lt;/span&gt;0-9&lt;span class="o"&gt;]&lt;/span&gt;+$ &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$switch_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -ge &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$switch_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -le &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;switch_choice &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$switch_choice&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -eq &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;valid_vcps&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;输入 16 进制代码 (如 0x11): &amp;#34;&lt;/span&gt; target_vcp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_vcp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;⚠️ 无效选择&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 执行切换&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$current_source&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;⚠️ 该输入源已是当前活跃状态，无需切换。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;按&amp;lt;Enter&amp;gt;键继续...&amp;#34;&lt;/span&gt; -n &lt;span class="m"&gt;1&lt;/span&gt; -s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SOURCE_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;to_lower &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;未知接口&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_device_label &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_label&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;target_display&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;🚀 正在切换到: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_display&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 执行: ddcutil --bus=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;selected_bus&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; setvcp 60 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; ddcutil --bus&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; setvcp &lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &amp;gt; /dev/null 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; sleep 0.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;new_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_current_source &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$new_source&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$target_vcp&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_GREEN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;✅ 切换成功！&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;current_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$new_source&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;⚠️ 指令已发送，验证读取为 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_source&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;（预期 &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;target_vcp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;）&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 如果画面已切换，可忽略（可能是响应延迟）。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;current_source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_current_source &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$selected_bus&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RED&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;❌ 切换失败！&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COLOR_RESET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34; 请检查：权限、DDC/CI 开关、显示器休眠状态&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -rp &lt;span class="s2"&gt;&amp;#34;按&amp;lt;Enter&amp;gt;键继续...&amp;#34;&lt;/span&gt; -n &lt;span class="m"&gt;1&lt;/span&gt; -s
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;⚠️ 输入错误，请重新选择！&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="windows系统"&gt;&lt;a href="#windows%e7%b3%bb%e7%bb%9f" class="header-anchor"&gt;&lt;/a&gt;Windows系统
&lt;/h3&gt;&lt;p&gt;在 Windows 系统下, 可以使用 NirSoft 出品的 &lt;a class="link" href="https://www.nirsoft.net/utils/control_my_monitor.html" target="_blank" rel="noopener"
 &gt;ControlMyMonitor&lt;/a&gt; 软件进行检测与切换. 这个软件是免安装的图形界面 (GUI) 程序.&lt;/p&gt;
&lt;p&gt;打开之后会列出当前显示器的所有 VCP 控制项, 找到 &lt;code&gt;VCP Code = 60&lt;/code&gt; 的一行, 双击修改当前值, 输入对应的输入源代码 (和 Ubuntu 下查到的代码一致, 没有 &lt;code&gt;0x&lt;/code&gt; 十六进制前缀) 即可切换.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;由于这个软件本身就是图形界面, 操作直观, 我没有给它编写脚本.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="文件共享"&gt;&lt;a href="#%e6%96%87%e4%bb%b6%e5%85%b1%e4%ba%ab" class="header-anchor"&gt;&lt;/a&gt;文件共享
&lt;/h2&gt;&lt;p&gt;两台计算机的位置非常接近, 直接用一根网线对连传文件, 比走无线快得多, 也不依赖路由器.&lt;/p&gt;
&lt;h3 id="网络配置"&gt;&lt;a href="#%e7%bd%91%e7%bb%9c%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;网络配置
&lt;/h3&gt;&lt;p&gt;直连之后两台计算机不在一个由 DHCP 服务器管理的网段里, 需要手动设置静态 IP. 我的方案是把两台计算机放到 &lt;code&gt;192.168.10.0/24&lt;/code&gt; 这个段里:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;计算机&lt;/th&gt;
					&lt;th&gt;IP&lt;/th&gt;
					&lt;th&gt;子网掩码&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;台式机&lt;/td&gt;
					&lt;td&gt;192.168.10.1&lt;/td&gt;
					&lt;td&gt;255.255.255.0&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;笔记本&lt;/td&gt;
					&lt;td&gt;192.168.10.2&lt;/td&gt;
					&lt;td&gt;255.255.255.0&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;

 &lt;blockquote&gt;
 &lt;p&gt;笔记本如果没有 RJ45 接口, 可以使用 Type-C 转 RJ45 的转接器.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h4 id="ubuntu"&gt;&lt;a href="#ubuntu" class="header-anchor"&gt;&lt;/a&gt;Ubuntu
&lt;/h4&gt;&lt;p&gt;Gnome 桌面环境下打开 &lt;code&gt;设置 → 网络 → 有线&lt;/code&gt;, 点击齿轮按钮, 在 IPv4 选项卡里把方法改为&amp;quot;手动&amp;quot;, 填入对应的地址和子网掩码即可. KDE 也是类似操作.&lt;/p&gt;
&lt;h4 id="windows"&gt;&lt;a href="#windows" class="header-anchor"&gt;&lt;/a&gt;Windows
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;设置 → 网络和 Internet → 以太网 → IP 分配 → 编辑&lt;/code&gt;, 选择&amp;quot;手动&amp;quot;, 启用 IPv4 后填入对应的地址和子网掩码.&lt;/p&gt;
&lt;p&gt;配置完成后, 在两台计算机上互相 &lt;code&gt;ping&lt;/code&gt; 一下对方的 IP, 确认能通.&lt;/p&gt;
&lt;h3 id="可能情况"&gt;&lt;a href="#%e5%8f%af%e8%83%bd%e6%83%85%e5%86%b5" class="header-anchor"&gt;&lt;/a&gt;可能情况
&lt;/h3&gt;&lt;p&gt;由于两台计算机是 Windows + Ubuntu 双系统, 需要兼容性比较强的共享协议── &lt;strong&gt;SMB&lt;/strong&gt; (Windows 原生支持, Linux 通过 Samba 支持). 下面分几种情况说明:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;情况一&lt;/strong&gt;: Windows 共享文件夹.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;情况二&lt;/strong&gt;: Ubuntu 共享文件夹.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;情况三&lt;/strong&gt;: Windows 访问共享文件夹.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;情况四&lt;/strong&gt;: Ubuntu 访问共享文件夹.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;按需配置即可.&lt;/p&gt;
&lt;h3 id="情况一-windows-共享"&gt;&lt;a href="#%e6%83%85%e5%86%b5%e4%b8%80-windows-%e5%85%b1%e4%ba%ab" class="header-anchor"&gt;&lt;/a&gt;情况一: Windows 共享
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;右键想共享的文件夹 → &lt;code&gt;属性 → 共享 → 高级共享&lt;/code&gt;, 勾选&amp;quot;共享此文件夹&amp;quot;, 点击&amp;quot;权限&amp;quot;按钮设置访问权限.&lt;/li&gt;
&lt;li&gt;打开 &lt;code&gt;控制面板 → 网络和共享中心 → 高级共享设置&lt;/code&gt;, 在当前网络配置文件下启用&amp;quot;网络发现&amp;quot;和&amp;quot;文件和打印机共享&amp;quot;.&lt;/li&gt;
&lt;li&gt;防火墙放行 SMB: 进入 &lt;code&gt;Windows 安全中心 → 防火墙和网络保护 → 允许应用通过防火墙&lt;/code&gt;, 确认&amp;quot;文件和打印机共享&amp;quot;在当前网络下被勾选.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="情况二-ubuntu-共享"&gt;&lt;a href="#%e6%83%85%e5%86%b5%e4%ba%8c-ubuntu-%e5%85%b1%e4%ba%ab" class="header-anchor"&gt;&lt;/a&gt;情况二: Ubuntu 共享
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;安装Samba&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt install samba
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;修改配置文件&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;编辑 &lt;code&gt;/etc/samba/smb.conf&lt;/code&gt;, 在文件末尾追加:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[share]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 需要保证共享文件夹存在&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/home/&amp;lt;你的用户名&amp;gt;/&amp;lt;共享文件夹&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; browseable = yes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; read only = no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; guest ok = no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt; valid users = &amp;lt;你的用户名&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="3"&gt;
&lt;li&gt;为该用户设置 Samba 密码 (和系统密码独立):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo smbpasswd -a &amp;lt;你的用户名&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="4"&gt;
&lt;li&gt;重启服务&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl restart smbd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="5"&gt;
&lt;li&gt;开放防火墙端口&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果系统启用了 &lt;code&gt;ufw&lt;/code&gt;, 放行 Samba:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ufw allow samba
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="情况三-windows-访问"&gt;&lt;a href="#%e6%83%85%e5%86%b5%e4%b8%89-windows-%e8%ae%bf%e9%97%ae" class="header-anchor"&gt;&lt;/a&gt;情况三: Windows 访问
&lt;/h3&gt;&lt;p&gt;按 &lt;code&gt;Win + R&lt;/code&gt; 输入:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;\\192.168.10.2\share
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;弹窗中输入 Ubuntu 的用户名和刚才设置的 Samba 密码即可. 也可以右键&amp;quot;映射网络驱动器&amp;quot;, 把它挂成本地盘符方便日常使用.&lt;/p&gt;
&lt;h3 id="情况四-ubuntu-访问"&gt;&lt;a href="#%e6%83%85%e5%86%b5%e5%9b%9b-ubuntu-%e8%ae%bf%e9%97%ae" class="header-anchor"&gt;&lt;/a&gt;情况四: Ubuntu 访问
&lt;/h3&gt;&lt;p&gt;打开文件管理器, 在地址栏输入:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;smb://192.168.10.1/共享文件夹名
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;首次访问会要求输入 Windows 这一端的用户名和密码, 输入即可. 勾选&amp;quot;永久记住&amp;quot;可以避免下次重复输入.&lt;/p&gt;
&lt;p&gt;如果想从命令行访问, 可以安装 &lt;code&gt;cifs-utils&lt;/code&gt; 后挂载:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install cifs-utils
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p /mnt/win-share
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mount -t cifs //192.168.10.1/共享文件夹名 /mnt/win-share &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -o &lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;Windows 用户名&amp;gt;,uid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -u&lt;span class="k"&gt;)&lt;/span&gt;,gid&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -g&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结
&lt;/h2&gt;&lt;p&gt;到这里, 键鼠, 显示器, 文件三个部分都打通了. 尽管还存在或多或少的体验问题, 但这确实是我目前能够找到的最优方案.&lt;/p&gt;</description></item><item><title>Linux 双系统安装指南</title><link>https://mowmark.github.io/mowmark_blog/computer/linux/001_linuxinstallation/</link><pubDate>Thu, 04 Jun 2026 00:00:00 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/computer/linux/001_linuxinstallation/</guid><description>&lt;p&gt;最近在新电脑上安装了 Windows + Ubuntu 双系统, 顺手把流程整理成文章. 这篇文章假设你已经决定安装 Linux, 关于&amp;quot;该不该用 Linux&amp;quot;以及&amp;quot;选哪个发行版&amp;quot;的问题, 可以先看 &lt;a class="link" href="https://mowmark.github.io/mowmark_blog/computer/linux/000_linuxdistributionacquaintance/" &gt;Linux 发行版选型经验分享&lt;/a&gt;. 本文以 Ubuntu 为例, 其他主流发行版的安装流程大同小异, 可以作为参考.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="准备工作"&gt;&lt;a href="#%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;准备工作
&lt;/h2&gt;&lt;h3 id="你需要准备什么"&gt;&lt;a href="#%e4%bd%a0%e9%9c%80%e8%a6%81%e5%87%86%e5%a4%87%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;你需要准备什么
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;一台已经安装 Windows 10+ 的电脑&lt;/li&gt;
&lt;li&gt;一个 16GB 以上的 U 盘 (制作启动盘会清空 U 盘内所有数据, 提前备份)&lt;/li&gt;
&lt;li&gt;系统镜像: 从 &lt;a class="link" href="https://cn.ubuntu.com/download" target="_blank" rel="noopener"
 &gt;Ubuntu 官网&lt;/a&gt; 下载对应版本的 ISO 文件&lt;/li&gt;
&lt;li&gt;烧录软件: 推荐 &lt;a class="link" href="https://rufus.ie/zh/" target="_blank" rel="noopener"
 &gt;Rufus&lt;/a&gt; (Windows 专用, 免安装, 操作直观) 或 &lt;a class="link" href="https://www.ventoy.net/cn/" target="_blank" rel="noopener"
 &gt;Ventoy&lt;/a&gt; (支持一个 U 盘存放多个镜像，适合经常折腾的用户). MacOS 或 Linux 用户可以选跨平台的 &lt;a class="link" href="https://etcher.balena.io/" target="_blank" rel="noopener"
 &gt;Etcher&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="确定版本"&gt;&lt;a href="#%e7%a1%ae%e5%ae%9a%e7%89%88%e6%9c%ac" class="header-anchor"&gt;&lt;/a&gt;确定版本
&lt;/h3&gt;&lt;p&gt;版本号的选择取决于硬件兼容性和项目需求, 前者优先级更高——新硬件 (尤其是新显卡) 需要较新的内核才能正常驱动, 装一个版本过老的系统往往会在驱动上碰壁. 没有特殊需求的话, 选最新的 LTS(长期支持)版本是最稳妥的选择.&lt;/p&gt;
&lt;p&gt;桌面环境方面, Gnome 和 KDE 是最常见的两个选择, 前者简洁, 后者可定制性更强. 如果有特定偏好, 可以在 &lt;a class="link" href="https://ubuntu.com/desktop/flavors" target="_blank" rel="noopener"
 &gt;Ubuntu Flavors&lt;/a&gt; 里选择对应的风味版本下载, 不需要另外安装.&lt;/p&gt;
&lt;h3 id="为-linux-准备硬盘空间"&gt;&lt;a href="#%e4%b8%ba-linux-%e5%87%86%e5%a4%87%e7%a1%ac%e7%9b%98%e7%a9%ba%e9%97%b4" class="header-anchor"&gt;&lt;/a&gt;为 Linux 准备硬盘空间
&lt;/h3&gt;&lt;p&gt;这是双系统安装中最容易出问题的一步, 建议在开始之前想清楚用哪种方案.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方案一 (推荐): 安装到另一块物理硬盘&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果电脑有两块硬盘, 直接把 Ubuntu 装到第二块上, 不需要事先进行任何操作. 这种方案下, 两个系统物理隔离, 引导程序互不干扰, Ubuntu 的 GRUB 不容易被 Windows 更新覆盖. 这也是我目前采用的方案.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方案二：在同一块硬盘上划出未分配空间&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果只有一块硬盘, 需要提前在 Windows 下为 Linux 划出空间: 右键&amp;quot;此电脑&amp;quot; -&amp;gt; 管理 -&amp;gt; 磁盘管理, 找到容量充裕的分区, 右键选择&amp;quot;压缩卷&amp;quot;, 划出至少 50GB. 完成后会出现一块灰色的&amp;quot;未分配&amp;quot;区域, 保持这个状态即可, 不要新建卷.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;后文中, 方案一简称&lt;strong&gt;双硬盘方案&lt;/strong&gt;, 方案二简称&lt;strong&gt;单硬盘方案&lt;/strong&gt;.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="制作启动-u-盘"&gt;&lt;a href="#%e5%88%b6%e4%bd%9c%e5%90%af%e5%8a%a8-u-%e7%9b%98" class="header-anchor"&gt;&lt;/a&gt;制作启动 U 盘
&lt;/h3&gt;
 &lt;blockquote&gt;
 &lt;p&gt;不管是 Rufus 还是 Etcher，原理都一样，步骤大同小异。Ventoy 的使用方式略有不同, 我会在后续文章中单独说明. 下面以 Rufus 为例.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;插入 U 盘, 打开 Rufus.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设备&lt;/strong&gt;: 确认下拉菜单中选中的是 U 盘, 不是电脑的内置硬盘.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引导类型&lt;/strong&gt;: 点击右侧&amp;quot;选择&amp;quot;, 加载下载好的 ISO 文件.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分区类型&lt;/strong&gt;: 现代电脑选 GPT, 目标系统选 UEFI (非 CSM). 电脑较老, 只支持传统 BIOS 的话选 MBR.&lt;/li&gt;
&lt;li&gt;其余保持默认, 点击&amp;quot;开始&amp;quot;. 弹窗提示写入模式时, 保持默认的&amp;quot;以 ISO 镜像模式写入&amp;quot;即可.&lt;/li&gt;
&lt;li&gt;等待进度条完成.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="安装步骤"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e6%ad%a5%e9%aa%a4" class="header-anchor"&gt;&lt;/a&gt;安装步骤
&lt;/h2&gt;&lt;h3 id="从-u-盘启动"&gt;&lt;a href="#%e4%bb%8e-u-%e7%9b%98%e5%90%af%e5%8a%a8" class="header-anchor"&gt;&lt;/a&gt;从 U 盘启动
&lt;/h3&gt;&lt;p&gt;重启电脑, 开机亮屏的瞬间连续按下启动热键, 进入 Boot Menu（启动菜单）或 BIOS 界面. 不同主板/笔记本的热键不同, 常见的有 F2, F12, Del, Esc, 可以在开机画面上留意提示, 或提前查一下主板型号.&lt;/p&gt;
&lt;p&gt;进入 Boot Menu 后, 选择带有 UEFI 前缀的 U 盘选项，回车确认.&lt;/p&gt;
&lt;h3 id="安装向导"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e5%90%91%e5%af%bc" class="header-anchor"&gt;&lt;/a&gt;安装向导
&lt;/h3&gt;&lt;p&gt;从 U 盘启动后会进入 GRUB 菜单, 选择 &lt;code&gt;Try or Install Ubuntu&lt;/code&gt;, 稍等片刻进入图形化安装界面. 大部分步骤跟着向导走即可, 有两个地方需要特别注意:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;建议在安装阶段选择 English. 如果选了中文, 系统可能会把&amp;quot;桌面&amp;quot;&amp;ldquo;下载&amp;quot;等目录以中文命名, 终端里输入路径时很不方便. 安装完成后可以在系统设置里把界面语言改回中文, 同时选择保留英文目录名.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分区&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是整个安装过程中最关键的一步, 双硬盘和单硬盘的处理方式不同.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;双硬盘方案&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;注意选中空硬盘, 而不是 Windows 系统所在的那块&lt;/li&gt;
&lt;li&gt;可以自动分区, 也可以手动分区, 手动分区的推荐方案如下:&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;挂载点&lt;/th&gt;
					&lt;th&gt;分区格式&lt;/th&gt;
					&lt;th&gt;大小&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;/boot/efi&lt;/td&gt;
					&lt;td&gt;FAT32&lt;/td&gt;
					&lt;td&gt;500MB&lt;/td&gt;
					&lt;td&gt;ESP 引导分区, 存储 GRUB 等引导文件&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;/boot&lt;/td&gt;
					&lt;td&gt;ext4&lt;/td&gt;
					&lt;td&gt;1GB&lt;/td&gt;
					&lt;td&gt;存储内核 (vmlinuz) 和初始化镜像 (initramfs)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;swap&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;swap&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;内存的1~2倍&lt;/td&gt;
					&lt;td&gt;内存不足时的交换空间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;/&lt;/td&gt;
					&lt;td&gt;ext4&lt;/td&gt;
					&lt;td&gt;剩余全部空间&lt;/td&gt;
					&lt;td&gt;根目录, 存储系统和用户数据&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;/home&lt;/code&gt; 和 &lt;code&gt;/var&lt;/code&gt; 也可以单独划分, 但对于个人用户来说意义不大, 反而容易因某个分区塞满而需要花时间调整. 非服务器场景下, 以上四个分区足够用了.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;分区格式补充&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;FAT32&lt;/strong&gt;: 只能识别 4GB 以下的文件, 现在几乎只用于 &lt;code&gt;/boot/efi&lt;/code&gt;, 属于历史遗留.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;swap&lt;/strong&gt;: 非独立文件系统, 专门换页空间. 内存不足时, 系统会把不活跃的内存页换出到 swap, 避免 &lt;strong&gt;OOM (Out Of Memory)&lt;/strong&gt; 崩溃. 有休眠需求的话, swap 大小建议不低于物理内存.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ext4 / btrfs / xfs&lt;/strong&gt;: 目前主流的 Linux 文件系统, 日常使用选用 ext4 最省心, btrfs 支持快照但稳定性相对差一些.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LVM (逻辑卷)&lt;/strong&gt;: 在物理分区上抽象出一层逻辑卷管理, 方便后续扩容和迁移, 也支持快照. 对有多块硬盘或后续可能扩容的用户来说值得考虑, 普通场景不必折腾.&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;单硬盘方案&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;省心方式: 选择 &lt;strong&gt;&amp;ldquo;Install Ubuntu alongside Windows Boot Manager&amp;rdquo;&lt;/strong&gt;, 安装程序会自动识别并使用之前划分出来的未分配空间&lt;/li&gt;
&lt;li&gt;手动分区: 选择 &lt;strong&gt;&amp;ldquo;Something else&amp;rdquo;&lt;/strong&gt;, 手动挂载 &lt;code&gt;/&lt;/code&gt; (根目录, 建议 30GB 以上). EFI 分区直接选用 Windows 已有的那个, &lt;strong&gt;不要格式化&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="安装之后"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e4%b9%8b%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;安装之后
&lt;/h2&gt;&lt;h3 id="关于双系统引导"&gt;&lt;a href="#%e5%85%b3%e4%ba%8e%e5%8f%8c%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%af%bc" class="header-anchor"&gt;&lt;/a&gt;关于双系统引导
&lt;/h3&gt;&lt;p&gt;安装完成后, 开机会出现 GRUB 菜单, 可以选择进入 Ubuntu 或 Windows.&lt;/p&gt;
&lt;p&gt;有一点需要提前知道: Windows 大版本更新有时会把 EFI 分区的默认启动项强制改回 Windows Boot Manager, 导致 GRUB 菜单消失, 开机直接进入 Windows. 这不意味着 Ubuntu 被删了——你的文件完好无损, 只是引导入口被覆盖了.&lt;/p&gt;
&lt;p&gt;遇到这种情况, 进入 BIOS, 把启动顺序改回 &lt;code&gt;ubuntu&lt;/code&gt; 或 &lt;code&gt;GRUB&lt;/code&gt; 就可以恢复. 如果引导损坏比较严重, 可以用 Ubuntu 启动盘进入 Live 环境, 用 &lt;code&gt;boot-repair&lt;/code&gt; 工具修复. 如果你用的是双硬盘方案, 这个问题基本不会出现.&lt;/p&gt;
&lt;h3 id="关于后续配置"&gt;&lt;a href="#%e5%85%b3%e4%ba%8e%e5%90%8e%e7%bb%ad%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;关于后续配置
&lt;/h3&gt;&lt;p&gt;装好系统只是开始. 换国内软件源, 安装显卡驱动, 配置开发环境等内容, 我会在后续文章里分别展开.&lt;/p&gt;</description></item><item><title>Linux 发行版选型经验分享</title><link>https://mowmark.github.io/mowmark_blog/computer/linux/000_linuxdistributionacquaintance/</link><pubDate>Wed, 03 Jun 2026 00:00:00 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/computer/linux/000_linuxdistributionacquaintance/</guid><description>&lt;p&gt;不少人接触 Linux 的第一道门槛不是安装, 而是选择──面对成千上百个发行版, 不知道应该选择哪个. 这篇文章把我对主流发行版的理解梳理一遍, 帮你在开始之前少走一点弯路.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="为什么要用-linux"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e7%94%a8-linux" class="header-anchor"&gt;&lt;/a&gt;为什么要用 Linux
&lt;/h2&gt;&lt;p&gt;Windows 已经足够成熟, 日常使用完全没有问题. 但&amp;quot;傻瓜式&amp;quot;的另一面是用户对底层的掌控权有限. 对于追求系统可控性的人来说, 走向 Linux 是自然而然的事.&lt;/p&gt;
&lt;p&gt;在专业场景下这一点更明显——无论是运维, 开发, 还是折腾 NAS 和软路由, Linux 往往能提供比 Windows 更好的原生支持和生态适配.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="选发行版之前-先想清楚三件事"&gt;&lt;a href="#%e9%80%89%e5%8f%91%e8%a1%8c%e7%89%88%e4%b9%8b%e5%89%8d-%e5%85%88%e6%83%b3%e6%b8%85%e6%a5%9a%e4%b8%89%e4%bb%b6%e4%ba%8b" class="header-anchor"&gt;&lt;/a&gt;选发行版之前, 先想清楚三件事
&lt;/h2&gt;&lt;h3 id="你的使用场景是什么"&gt;&lt;a href="#%e4%bd%a0%e7%9a%84%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;你的使用场景是什么
&lt;/h3&gt;&lt;p&gt;不同发行版有各自的定位, 选错了之后迁移的成本不低:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Gentoo&lt;/strong&gt;: 提倡用户自己完成编译, 难度高, 适合硬核玩家. 折腾的过程本身就是乐趣的一部分.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arch Linux&lt;/strong&gt;: 简洁自由, 组件自选, 滚动更新, 适合想深度掌控系统的玩家.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fedora&lt;/strong&gt;: 更新节奏快, 软件版本新, 由 Red Hat 社区主导, 定位是&amp;quot;前沿但可靠&amp;quot;, 适合开发者.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ubuntu&lt;/strong&gt;: 开箱即用, 适用面广, 是目前使用最广泛的 Linux 发行版, 对大多数开发工作都有良好的支持.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rocky Linux / AlmaLinux&lt;/strong&gt;: 以稳定性为第一优先级, 是旧时代 CentOS 的社区平替, 适合运维人员或对稳定性要求高的服务器场景.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="你需要的软件生态是否齐全"&gt;&lt;a href="#%e4%bd%a0%e9%9c%80%e8%a6%81%e7%9a%84%e8%bd%af%e4%bb%b6%e7%94%9f%e6%80%81%e6%98%af%e5%90%a6%e9%bd%90%e5%85%a8" class="header-anchor"&gt;&lt;/a&gt;你需要的软件生态是否齐全
&lt;/h3&gt;&lt;p&gt;主流发行版有各自的包管理体系:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Debian / Ubuntu 系: &lt;code&gt;dpkg&lt;/code&gt; + &lt;code&gt;apt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fedora / Red Hat 系: &lt;code&gt;rpm&lt;/code&gt; + &lt;code&gt;dnf&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Arch 和 Gentoo 各自有一套独立的包管理器&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此外, Snap 和 Flatpak 作为跨发行版的通用方案, 正在被越来越多的发行版支持. 选型前确认常用软件在目标发行版上是否容易获取, 可以省掉不少后续麻烦.&lt;/p&gt;
&lt;h3 id="遇到问题时能否快速找到答案"&gt;&lt;a href="#%e9%81%87%e5%88%b0%e9%97%ae%e9%a2%98%e6%97%b6%e8%83%bd%e5%90%a6%e5%bf%ab%e9%80%9f%e6%89%be%e5%88%b0%e7%ad%94%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;遇到问题时能否快速找到答案
&lt;/h3&gt;&lt;p&gt;社区文档的质量直接影响你的使用体验. Ubuntu 的中文资料最丰富, 上手阻力小; &lt;a class="link" href="https://wiki.archlinux.org/title/Main_page" target="_blank" rel="noopener"
 &gt;Arch Wiki&lt;/a&gt; 则是公认的 Linux 界最全面的参考文档之一——即使不用 Arch, 遇到问题时也值得去查一查.&lt;/p&gt;
&lt;p&gt;各发行版的整体情况和社区热度, 可以在 &lt;a class="link" href="https://distrowatch.com/" target="_blank" rel="noopener"
 &gt;DistroWatch&lt;/a&gt; 上浏览.&lt;/p&gt;
&lt;h2 id="新手从哪里开始"&gt;&lt;a href="#%e6%96%b0%e6%89%8b%e4%bb%8e%e5%93%aa%e9%87%8c%e5%bc%80%e5%a7%8b" class="header-anchor"&gt;&lt;/a&gt;新手从哪里开始
&lt;/h2&gt;&lt;p&gt;如果暂时没有特定的使用场景, &lt;strong&gt;从 Ubuntu 或其衍生版 (如 Linux Mint) 开始是门槛最低的选择&lt;/strong&gt;. 软件生态完善, 中文资料丰富, 遇到问题基本都能搜到答案.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="确定具体镜像"&gt;&lt;a href="#%e7%a1%ae%e5%ae%9a%e5%85%b7%e4%bd%93%e9%95%9c%e5%83%8f" class="header-anchor"&gt;&lt;/a&gt;确定具体镜像
&lt;/h2&gt;&lt;h3 id="版本号怎么定"&gt;&lt;a href="#%e7%89%88%e6%9c%ac%e5%8f%b7%e6%80%8e%e4%b9%88%e5%ae%9a" class="header-anchor"&gt;&lt;/a&gt;版本号怎么定
&lt;/h3&gt;&lt;p&gt;选完发行版后, 还需要确定具体的版本号. &lt;strong&gt;这取决于硬件兼容性和项目需求, 两者冲突时, 硬件优先&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;举个例子: 你有一个基于 Ubuntu 22.04 的项目需要复现, 按说应该装 22.04; 但如果你的电脑是新硬件, 22.04 默认的内核版本可能无法正常驱动对应设备. 一个折中的方案是装最新的 LTS 版本 (如 26.04), 然后用 Docker 拉一个 22.04 的容器来跑旧项目. 这也是我目前采用的方案.&lt;/p&gt;
&lt;p&gt;没有特殊需求的话, 选最新的 LTS(长期支持) 版本就好, 维护周期长, 社区资料也更完整.&lt;/p&gt;
&lt;h3 id="桌面环境怎么选"&gt;&lt;a href="#%e6%a1%8c%e9%9d%a2%e7%8e%af%e5%a2%83%e6%80%8e%e4%b9%88%e9%80%89" class="header-anchor"&gt;&lt;/a&gt;桌面环境怎么选
&lt;/h3&gt;&lt;p&gt;桌面环境主要影响视觉风格和资源占用, 不同发行版通常都会提供预装不同桌面环境的镜像:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Gnome&lt;/strong&gt; (Ubuntu 默认): 现代化, 简洁, 逻辑清晰, 上手门槛低.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KDE Plasma&lt;/strong&gt; (Kubuntu): 功能丰富, 高度自定义, 动效细腻.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Xfce / LXQt&lt;/strong&gt; (Xubuntu / Lubuntu): 轻量, 适合老旧设备.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;平铺式窗口管理器&lt;/strong&gt; (i3wm、Sway 等): 键盘驱动工作流, 学习曲线较陡, 适合进阶用户, 本文不展开.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;新手选 Gnome 或 KDE 都不会出错, 具体选哪个看个人口味.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结
&lt;/h2&gt;&lt;p&gt;选型的核心逻辑其实并不复杂: &lt;strong&gt;先看场景, 再看生态, 最后看社区&lt;/strong&gt;. 如果你非常纠结, 不如先选一个装上, 遇到问题再说. 试过一个后, 你对&amp;quot;自己到底需要什么&amp;quot;的判断会清晰得多.&lt;/p&gt;
&lt;p&gt;如果你是第一次接触 Linux, Ubuntu 是最不容易踩坑的起点. 选好之后, 下一步是把它装进电脑里──如果你打算保留 Windows, 可以参考我的另一篇文章: &lt;a class="link" href="https://mowmark.github.io/mowmark_blog/computer/linux/001_linuxinstallation/" &gt;Linux 双系统安装指南&lt;/a&gt;, 内容以 Ubuntu 为主, 但安装流程对其他主流发行版也有一定参考价值.&lt;/p&gt;</description></item><item><title>使用 Terminal 主题美化博客</title><link>https://mowmark.github.io/mowmark_blog/website/hugo/002_hugothemeterminal/</link><pubDate>Fri, 22 May 2026 09:12:24 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/website/hugo/002_hugothemeterminal/</guid><description>&lt;p&gt;承接上一篇文章: &lt;a class="link" href="https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/" &gt;使用 GitHub Pages 部署博客&lt;/a&gt;, 这篇文章我将分享使用 &lt;code&gt;Terminal&lt;/code&gt; 主题美化博客的个人经验. 由于个人精力有限, 可能有一些地方并没有涉及到, 欢迎讨论交流.&lt;/p&gt;
&lt;h2 id="hugo-配置文件的基本要求"&gt;&lt;a href="#hugo-%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e7%9a%84%e5%9f%ba%e6%9c%ac%e8%a6%81%e6%b1%82" class="header-anchor"&gt;&lt;/a&gt;Hugo 配置文件的基本要求
&lt;/h2&gt;&lt;p&gt;在正式开始之前, 我们需要先梳理 Hugo 主题的基本结构, 而这又绕不开 Hugo 项目的核心机制: &lt;strong&gt;配置文件的覆写机制&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="配置文件的覆写机制"&gt;&lt;a href="#%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e7%9a%84%e8%a6%86%e5%86%99%e6%9c%ba%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;配置文件的覆写机制
&lt;/h3&gt;&lt;p&gt;简单来说, 在新版Hugo中, &lt;strong&gt;&lt;code&gt;config/_default/&lt;/code&gt;目录下的配置文件优先级大于根目录下的配置文件大于主题目录(&lt;code&gt;themes/&lt;/code&gt;)下的配置文件&lt;/strong&gt;, 此外, 主题目录如果随 &lt;code&gt;Git&lt;/code&gt; 自动更新, 我们在里面做的任何修改都会被直接覆盖. 基于这两点, 如果我们要修改主题的配置, 就不能在主题目录下进行, 而要在根目录或者 &lt;code&gt;config/&lt;/code&gt; 目录下操作.&lt;/p&gt;
&lt;h3 id="配置文件的基本要求"&gt;&lt;a href="#%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e7%9a%84%e5%9f%ba%e6%9c%ac%e8%a6%81%e6%b1%82" class="header-anchor"&gt;&lt;/a&gt;配置文件的基本要求
&lt;/h3&gt;&lt;p&gt;除此之外, 配置文件的格式, 内容和作用域也需要厘清一下:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hugo 早期要求配置文件名字应该为 &lt;code&gt;config&lt;/code&gt;, 后来变成了 &lt;code&gt;hugo&lt;/code&gt;, 目前版本是两种名字都可以接受, 而格式则可以为 &lt;code&gt;yaml&lt;/code&gt;, &lt;code&gt;toml&lt;/code&gt; 或者 &lt;code&gt;json&lt;/code&gt; 当中的任意一种;&lt;/li&gt;
&lt;li&gt;Hugo 支持将所有配置信息都写在同一个文件中, 也可以拆分开来, 作为不同的配置文件, 但名称必须为 &lt;code&gt;params&lt;/code&gt;, &lt;code&gt;menu&lt;/code&gt; 或者 &lt;code&gt;languages&lt;/code&gt; 已经规定好的一级目录;&lt;/li&gt;
&lt;li&gt;Hugo 项目的全局配置控制整个网站的样式, 如网站主标题, 导航菜单, 默认语言等, 这些信息都存储在 &lt;code&gt;hugo.toml&lt;/code&gt; 或者从中拆分出来的配置文件里, 可能存放在根目录或者 &lt;code&gt;config/&lt;/code&gt; 目录下;&lt;/li&gt;
&lt;li&gt;写在每篇文章头部的 &lt;code&gt;Front Matter&lt;/code&gt; 控制这篇文章的元数据, 如标题, 日期, 标签等, 其优先级高于全局配置. 在使用 &lt;code&gt;hugo new ...&lt;/code&gt; 命令新建文章时, Hugo 会根据存放在 &lt;code&gt;archetypes/&lt;/code&gt; 目录下的文章模板, 自动创建新文章的 &lt;code&gt;Front Matter&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基于上述几个理由, 读者在使用不同主题时, 有可能会在根目录或者 &lt;code&gt;config/&lt;/code&gt; 目录下看到不同类型的配置文件&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="terminal-主题的配置"&gt;&lt;a href="#terminal-%e4%b8%bb%e9%a2%98%e7%9a%84%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;Terminal 主题的配置
&lt;/h2&gt;&lt;p&gt;Hugo 官方对主题结构没有严格规定, 所以每个主题的组织方式都不太一样, 以下内容基于 &lt;code&gt;Hugo Extended v0.161.1&lt;/code&gt; 和 &lt;code&gt;Terminal 2024-11-22&lt;/code&gt;, 仅供参考.&lt;/p&gt;
&lt;h3 id="复制初始文件"&gt;&lt;a href="#%e5%a4%8d%e5%88%b6%e5%88%9d%e5%a7%8b%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;复制初始文件
&lt;/h3&gt;&lt;p&gt;使用 &lt;code&gt;git submodule ...&lt;/code&gt; 命令安装好主题后, 将 &lt;code&gt;themes/terminal/exampleSite/&lt;/code&gt; 目录下的文件复制到根目录, 作为配置的初始模板. 作者给出的默认配置相当长, 但实际上大部分参数保持默认即可, 只有少数几个参数需要留意.&lt;/p&gt;
&lt;h3 id="修改配置文件"&gt;&lt;a href="#%e4%bf%ae%e6%94%b9%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;修改配置文件
&lt;/h3&gt;&lt;p&gt;打开根目录的 &lt;code&gt;hugo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;baseurl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://&amp;lt;Your-UserName&amp;gt;.github.io/&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 改成你的实际域名&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;languageCode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;zh-cn&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 当前 Hugo 规定的语言代码, 中文用户记得改这里&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;paginate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# 这个参数对应 content/ 目录下存放文章的文件夹名称&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# 如果你的文章放在 content/blog/ 下，这里就要改成 &amp;#34;blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# 不改的话首页会加载不出任何文章，是比较容易踩的坑&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;contentTypeName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;posts&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# 首页显示的菜单项数量，超出的部分会折叠进右上角&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# 如果你想让页面干净一点，设成 0 也没问题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showMenuItems&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="实际修改主题文件"&gt;&lt;a href="#%e5%ae%9e%e9%99%85%e4%bf%ae%e6%94%b9%e4%b8%bb%e9%a2%98%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;实际修改主题文件
&lt;/h2&gt;&lt;p&gt;前面提到不能在主题目录里改文件, 那如果我们确实需要修改主题的某个模板, 应该怎么做?&lt;/p&gt;
&lt;p&gt;以修改页脚为例. 假设你想在底部加上备案号, 或者就是单纯不喜欢默认的版权格式, 直觉上可能会去 &lt;code&gt;themes/terminal/layouts/partials/footer.html&lt;/code&gt; 里改, 但这样做下次主题更新就会丢失.&lt;/p&gt;
&lt;p&gt;正确的做法是:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在根目录下创建相同的路径 &lt;code&gt;layouts/partials/&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;把 &lt;code&gt;themes/terminal/layouts/partials/footer.html&lt;/code&gt; 复制到这个目录下;&lt;/li&gt;
&lt;li&gt;修改根目录下的这个副本.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hugo 在构建时会优先读取根目录下的 &lt;code&gt;layouts/&lt;/code&gt; 目录, 主题里的原版文件不会被动, 下次更新主题也不会影响你的改动. 其他模板文件的修改方式都是一样的道理.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="小结"&gt;&lt;a href="#%e5%b0%8f%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;小结
&lt;/h2&gt;&lt;p&gt;这篇文章到这里基本就结束了. Terminal 主题本身并不复杂, 配置文件改几个参数就能跑起来, 真正需要花时间理解的反而是 Hugo 本身的复写机制, 这个搞清楚了, 后续不管换什么主题, 修改起来都会顺手很多.&lt;/p&gt;
&lt;p&gt;如果读者想要使用 Stack 主题, 后面我会更新相关文章, Stack 主题的结构比 Terminal 复杂不少, 需要花费比较多的时间进行调试.&lt;/p&gt;</description></item><item><title>使用 GitHub Pages 发布个人博客</title><link>https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/</link><pubDate>Tue, 19 May 2026 22:01:19 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/</guid><description>&lt;p&gt;承接上一篇文章: &lt;strong&gt;&lt;a class="link" href="https://mowmark.github.io/mowmark_blog/website/hugo/000_hugoinit/" &gt;使用Hugo创建个人博客&lt;/a&gt;&lt;/strong&gt;, 在本地搭建好环境后, 本文将告诉你如何将博客手动以及自动化发布到公网.&lt;/p&gt;
&lt;h2 id="网络发布基础配置"&gt;&lt;a href="#%e7%bd%91%e7%bb%9c%e5%8f%91%e5%b8%83%e5%9f%ba%e7%a1%80%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;&lt;/a&gt;网络发布基础配置
&lt;/h2&gt;&lt;p&gt;想要将网站发布到公网, 需要满足三个条件: &lt;strong&gt;代码托管平台, 服务器(托管服务)以及域名&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;出于性价比与便利性, 本文采用 &lt;strong&gt;GitHub 仓库 + GitHub Pages (免费托管)&lt;/strong&gt; 的一站式方案, 并使用 GitHub 提供的免费域名.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;补充信息&lt;/strong&gt;:
上面三个条件中, 代码托管平台有GitHub, GitLab和Gitee等平台, 域名可以从 GitHub, 腾讯云, 阿里云等平台获取, 而托管服务则可以由 GitHub Pages, Cloudflare Pages, 腾讯云和阿里云提供, 后两者用的人不多, 喜欢挑战自己的伙伴可以尝试部署一下.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="创建-github-仓库"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba-github-%e4%bb%93%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;创建 GitHub 仓库
&lt;/h3&gt;&lt;p&gt;首先, 登录你的 &lt;strong&gt;&lt;a class="link" href="https://github.com" target="_blank" rel="noopener"
 &gt;GitHub 官网&lt;/a&gt;&lt;/strong&gt;, 新建一个仓库.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;这里有一个&lt;strong&gt;相当重要的命名规则&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果你希望博客最终的访问域名是简单的&lt;code&gt;https://&amp;lt;Your-UserName&amp;gt;.github.io&lt;/code&gt;, 那么仓库的名称&lt;strong&gt;必须&lt;/strong&gt;命名为&lt;code&gt;&amp;lt;Your-UserName&amp;gt;.github.io&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;如果你随便起了个名字 (例如&lt;code&gt;my-blog&lt;/code&gt;), 那后续的访问域名就会是&lt;code&gt;https://&amp;lt;Your-UserName&amp;gt;.github.io/my-blog&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

 &lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="GitHub 域名配置" class="gallery-image" data-flex-basis="564px" data-flex-grow="235" height="360" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/GitHub_Domain_Name.png" srcset="https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/GitHub_Domain_Name_hu_d223d1a3bfaf02d3.png 800w, https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/GitHub_Domain_Name.png 847w" width="847"&gt;&lt;/p&gt;
&lt;p&gt;权限请务必选择 &lt;strong&gt;Public(公开)&lt;/strong&gt;, 否则 GitHub Pages 无法免费提供服务. &lt;em&gt;更多信息可以查看 &lt;strong&gt;&lt;a class="link" href="https://githubdocs.cn/en/pages/getting-started-with-github-pages/what-is-github-pages" target="_blank" rel="noopener"
 &gt;GitHub Pages 说明&lt;/a&gt;&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="将本地代码推送到-github"&gt;&lt;a href="#%e5%b0%86%e6%9c%ac%e5%9c%b0%e4%bb%a3%e7%a0%81%e6%8e%a8%e9%80%81%e5%88%b0-github" class="header-anchor"&gt;&lt;/a&gt;将本地代码推送到 GitHub
&lt;/h3&gt;&lt;p&gt;在上一篇文章中, 我们已经在本地项目目录执行过了 &lt;code&gt;git init&lt;/code&gt;. 现在, 我们需要将本地内容推送到刚刚创建的 GitHub 远程仓库.&lt;/p&gt;
&lt;p&gt;首先, 配置 Git 用户信息 (如果之前没配置好全局账号):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config user.email &amp;lt;Your-EmailAddress&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git config user.name &amp;lt;Your-UserName&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;提示&lt;/strong&gt;: 加上 &lt;code&gt;--global&lt;/code&gt; 参数可以进行全局配置, 配置信息存放在 &lt;code&gt;~/.gitconfig&lt;/code&gt; 文件里. 局部配置则存放在项目隐藏文件 &lt;code&gt;.git/config&lt;/code&gt; 中.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;接下来, 将本地文件提交并推送到远程仓库:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 在项目根目录下:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 将所有文件加入暂存区并提交&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;Feat: 博客首次初始化&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 关联远程仓库 (请将下面的链接替换为你的仓库地址)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git remote add origin https://github.com/&amp;lt;Your-UserName&amp;gt;/&amp;lt;Your-Repository&amp;gt;.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 将本地代码推送到远程仓库的 main 分支&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push -u origin main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;提示&lt;/strong&gt;: 关于这个部分, 有非常多的教程会倾向于先在本地运行 &lt;code&gt;hugo&lt;/code&gt; 命令生成静态网页 (放在 &lt;code&gt;public/&lt;/code&gt; 目录下), 再把 &lt;code&gt;public&lt;/code&gt; 文件夹 &lt;code&gt;push&lt;/code&gt; 到 GitHub 仓库. 这种做法相当繁琐, 每次发布文章都需要本地编译.
所以这篇文章我们采用了另外一种做法: &lt;strong&gt;将包含 &lt;code&gt;.md&lt;/code&gt; 原稿的整个项目源码推送上去, 让 GitHub Actions 帮我们在云端自动部署并发布&lt;/strong&gt;.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="部署博客网站"&gt;&lt;a href="#%e9%83%a8%e7%bd%b2%e5%8d%9a%e5%ae%a2%e7%bd%91%e7%ab%99" class="header-anchor"&gt;&lt;/a&gt;部署博客网站
&lt;/h2&gt;&lt;h3 id="配置-github-pages"&gt;&lt;a href="#%e9%85%8d%e7%bd%ae-github-pages" class="header-anchor"&gt;&lt;/a&gt;配置 GitHub Pages
&lt;/h3&gt;&lt;p&gt;进入 GitHub 仓库, 点击顶部的 &lt;strong&gt;Settings&lt;/strong&gt;, 在左侧栏找到 &lt;strong&gt;Pages&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;Build and deployment&lt;/code&gt;（构建和部署）板块下, 将 &lt;code&gt;Source&lt;/code&gt; 的选项从默认的 &lt;code&gt;Deploy from a branch&lt;/code&gt; 改为 &lt;strong&gt;GitHub Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="配置 GitHub Pages " class="gallery-image" data-flex-basis="247px" data-flex-grow="103" height="1107" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/GitHub_Pages.png" srcset="https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/GitHub_Pages_hu_34d4e0835a0ed1b6.png 800w, https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/GitHub_Pages.png 1143w" width="1143"&gt;&lt;/p&gt;
&lt;h3 id="创建自动化部署工作流"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e8%87%aa%e5%8a%a8%e5%8c%96%e9%83%a8%e7%bd%b2%e5%b7%a5%e4%bd%9c%e6%b5%81" class="header-anchor"&gt;&lt;/a&gt;创建自动化部署工作流
&lt;/h3&gt;&lt;p&gt;我们需要在项目根目录下创建一个特定的文件, 告诉 GitHub 每当有代码推送时该怎么做.&lt;/p&gt;
&lt;p&gt;在项目根目录下执行:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vim .github/workflows/hugo.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将以下 &lt;em&gt;&lt;a class="link" href="https://hugo.opendocs.io/hosting-and-deployment/hosting-on-github/" target="_blank" rel="noopener"
 &gt;官方推荐的配置代码&lt;/a&gt;&lt;/em&gt; 粘贴到你的文件中, 根据需要更改分支名称和 Hugo 版本:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-YAML" data-lang="YAML"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 自动将 Hugo 站点部署到 GitHub Pages 的示例工作流&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy Hugo site to Pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 推送到 main 分支时出发&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 允许在 Actions 页面手动触发&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;read&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;write&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id-token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;write&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;concurrency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pages&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cancel-in-progress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;bash&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HUGO_VERSION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.141.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 建议填入本地使用的 Hugo 版本&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Install Hugo CLI&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;amp;&amp;amp; sudo dpkg -i ${{ runner.temp }}/hugo.deb&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Install Dart Sass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sudo snap install dart-sass&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Checkout&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;submodules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;recursive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 确保拉取主题子模块&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fetch-depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Setup Pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/configure-pages@v5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Install Node.js dependencies&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[[ -f package-lock.json || -f npm-shrinkwrap.json ]] &amp;amp;&amp;amp; npm ci || true&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Build with Hugo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HUGO_CACHEDIR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ runner.temp }}/hugo_cache&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HUGO_ENVIRONMENT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;production&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;America/Los_Angeles&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; hugo \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --gc \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --minify \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; --baseURL &amp;#34;${{ steps.pages.outputs.base_url }}/&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Upload artifact&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/upload-pages-artifact@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Deployment job&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github-pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ steps.deployment.outputs.page_url }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;needs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;build&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to GitHub Pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/deploy-pages@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;保存后, 将这个文件推送给 GitHub:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;添加 GitHub Actions 部署脚本&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;推送完成后, 点击 GitHub 仓库顶部的 &lt;strong&gt;Actions&lt;/strong&gt; 标签, 会看到一个正在转圈的任务, 等状态变成绿色的勾✅, 你的网站就已经成功发布到公网上了!&lt;/p&gt;
&lt;p&gt;访问你的域名(&lt;code&gt;https://&amp;lt;Your-UserName&amp;gt;.github.io&lt;/code&gt; 或者 &lt;code&gt;https://&amp;lt;Your-UserName&amp;gt;.github.io/&amp;lt;Your-Repository&amp;gt;&lt;/code&gt;)看看吧!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;到目前为止, Hugo 搭建并初始化个人博客的基本步骤就已经写完了, 如果读者对网站的样式没有特别要求, 其实现在已经完全可以开始写文章了.&lt;/p&gt;
&lt;p&gt;如果对 Terminal 主题不是特别满意的, 欢迎移步我的下一篇文章: &lt;a class="link" href="https://mowmark.github.io/mowmark_blog/website/hugo/002_hugothemeterminal/" &gt;使用 Terminal 主题美化博客&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;如果想要使用 Stack 主题美化博客的, 我后续会更新相关文章, 敬请关注!&lt;/p&gt;</description></item><item><title>使用 Hugo 搭建个人博客</title><link>https://mowmark.github.io/mowmark_blog/website/hugo/000_hugoinit/</link><pubDate>Wed, 13 May 2026 20:53:02 +0800</pubDate><guid>https://mowmark.github.io/mowmark_blog/website/hugo/000_hugoinit/</guid><description>&lt;h2 id="前言"&gt;&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;前言
&lt;/h2&gt;&lt;p&gt;由于学业原因, 最近一直在Ubuntu下学习SLAM算法以及开发, 有相当多操作学了又忘, 忘了再学. 为了打破这个循环, 我决定写一个个人博客进行技术沉淀与知识巩固, 顺便作为一个经验分享与交流的地方.&lt;/p&gt;
&lt;p&gt;第一篇文章, 就从&lt;strong&gt;如何搭建个人博客&lt;/strong&gt;开始!&lt;/p&gt;
&lt;h2 id="博客搭建"&gt;&lt;a href="#%e5%8d%9a%e5%ae%a2%e6%90%ad%e5%bb%ba" class="header-anchor"&gt;&lt;/a&gt;博客搭建
&lt;/h2&gt;&lt;p&gt;本质上, 搭建博客就是部署一个轻量化的个人网站, 如果要求不高, 完全可以使用&lt;a class="link" href="https://www.cnblogs.com" target="_blank" rel="noopener"
 &gt;博客园&lt;/a&gt;、&lt;a class="link" href="https://www.csdn.net" target="_blank" rel="noopener"
 &gt;CSDN&lt;/a&gt; 等现成的内容平台, 但作为一个&lt;strong&gt;喜欢折腾&lt;/strong&gt;的人, 我更希望能够拥有一个自己的独立站点.&lt;/p&gt;
&lt;h3 id="技术方案对比"&gt;&lt;a href="#%e6%8a%80%e6%9c%af%e6%96%b9%e6%a1%88%e5%af%b9%e6%af%94" class="header-anchor"&gt;&lt;/a&gt;技术方案对比
&lt;/h3&gt;&lt;p&gt;目前主流的独立博客方案大概分为两派：&lt;strong&gt;传统动态 CMS&lt;/strong&gt;（如 WordPress、Halo）和 &lt;strong&gt;静态站点生成器&lt;/strong&gt;（如 Hugo、Hexo）。由于静态站点不需要维护数据库，部署成本极低（甚至免费），我最终锁定了后者。&lt;/p&gt;
&lt;p&gt;常见的静态框架对比如下：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style="text-align: left"&gt;框架&lt;/th&gt;
					&lt;th style="text-align: left"&gt;底层语言&lt;/th&gt;
					&lt;th style="text-align: left"&gt;编译速度&lt;/th&gt;
					&lt;th style="text-align: left"&gt;特点与优势&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;Hugo&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;Go&lt;/td&gt;
					&lt;td style="text-align: left"&gt;极快 🚀&lt;/td&gt;
					&lt;td style="text-align: left"&gt;上手快，零依赖，适合喜欢专注内容写作的人&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;Hexo&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;Node.js&lt;/td&gt;
					&lt;td style="text-align: left"&gt;中等&lt;/td&gt;
					&lt;td style="text-align: left"&gt;中文社区庞大，插件丰富，但环境配置略繁琐&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;Astro&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;Astro.js&lt;/td&gt;
					&lt;td style="text-align: left"&gt;快&lt;/td&gt;
					&lt;td style="text-align: left"&gt;现代前端新宠，组件化强，适合有一定前端基础的玩家&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style="text-align: left"&gt;&lt;strong&gt;VitePress&lt;/strong&gt;&lt;/td&gt;
					&lt;td style="text-align: left"&gt;Vue/Vite&lt;/td&gt;
					&lt;td style="text-align: left"&gt;快&lt;/td&gt;
					&lt;td style="text-align: left"&gt;Vue 生态，文档风格利落，非常适合做技术文档&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;由于我对复杂的前端开发不太感冒, 且相对看重编译速度和本地环境的纯净度, &lt;strong&gt;Hugo&lt;/strong&gt; 成为了我的首选。&lt;/p&gt;
&lt;h2 id="环境准备与依赖安装"&gt;&lt;a href="#%e7%8e%af%e5%a2%83%e5%87%86%e5%a4%87%e4%b8%8e%e4%be%9d%e8%b5%96%e5%ae%89%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;环境准备与依赖安装
&lt;/h2&gt;&lt;p&gt;Hugo依赖于Go语言, 但从&lt;code&gt;v0.121.0&lt;/code&gt;起, Hugo已内置了Go工具链, 且包管理器能够自动处理依赖, 所以&lt;strong&gt;不管是手动安装二进制包还是使用包管理器安装的用户, 都可以跳过 Go 语言的安装部分&lt;/strong&gt; (除非需要安装其他依赖 Go 语言的软件)&lt;/p&gt;
&lt;p&gt;但是后续的代码托管与发布一定离不开Git, 因此, &lt;strong&gt;在安装 Hugo 之前, 我们必须先准备好Git&lt;/strong&gt;, 已经安装好了的读者则可以跳过这个部分.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;提示&lt;/strong&gt;: 以下部分网站可能需要科学上网环境, 请自行准备所需工具.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="安装go语言"&gt;&lt;a href="#%e5%ae%89%e8%a3%85go%e8%af%ad%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;安装Go语言
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Windows系统&lt;/strong&gt;: 打开&lt;a class="link" href="https://go.dev/dl/" target="_blank" rel="noopener"
 &gt;Go 官网&lt;/a&gt;, 下载&lt;code&gt;*.msi&lt;/code&gt;安装包, 一路 Next 即可. 如果习惯使用包管理器&lt;code&gt;Scoop&lt;/code&gt;或者&lt;code&gt;Chocolatey&lt;/code&gt;, 也可以通过执行以下命令来安装&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scoop install go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或者&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;choco install golang
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;Linux系统&lt;/strong&gt;: 官方推荐使用&lt;code&gt;snap&lt;/code&gt;安装, 会自动处理依赖, 该步骤可跳过.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="安装git"&gt;&lt;a href="#%e5%ae%89%e8%a3%85git" class="header-anchor"&gt;&lt;/a&gt;安装Git
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Windows系统&lt;/strong&gt;: 前往&lt;a class="link" href="https://git-scm.com/install/windows" target="_blank" rel="noopener"
 &gt;Git 官网&lt;/a&gt;, 根据系统架构下载合适的安装包, 运行即可. 或使用包管理器:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winget install Git.Git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或者&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scoop install git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或者&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;choco install git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;Linux系统&lt;/strong&gt;: 根据你的发行版执行对应命令:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 基于Debian&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo apt install git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 基于Fedora&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dnf update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; sudo dnf install git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 基于Arch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo pacman -Syu git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="搭建-hugo-博客环境"&gt;&lt;a href="#%e6%90%ad%e5%bb%ba-hugo-%e5%8d%9a%e5%ae%a2%e7%8e%af%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;搭建 Hugo 博客环境
&lt;/h2&gt;&lt;h3 id="安装-hugo-本体"&gt;&lt;a href="#%e5%ae%89%e8%a3%85-hugo-%e6%9c%ac%e4%bd%93" class="header-anchor"&gt;&lt;/a&gt;安装 Hugo 本体
&lt;/h3&gt;&lt;p&gt;与上面类似, 我们依然可以通过安装包或者包管理器安装 Hugo, 需要注意一点, Hugo本身不带样式, 需要安装主题, 而&lt;em&gt;部分主题依赖于Extended版的Hugo&lt;/em&gt;, 所以在这一步中, &lt;strong&gt;推荐安装Extended版本的Hugo&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Windows环境&lt;/strong&gt;: 前往&lt;a class="link" href="https://github.com/gohugoio/hugo/releases" target="_blank" rel="noopener"
 &gt;Hugo的Git仓库&lt;/a&gt;, 下载Extended版本的Hugo即可. 或使用包管理器快速安装:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winget install Hugo.Hugo.Extended
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或者&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scoop install hugo-extended
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 或者&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;choco install hugo-extended
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;Linux环境&lt;/strong&gt;: 使用snap安装&lt;!--, 如果没有安装snap, 则请查看[这一篇文章]() --&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo snap install hugo --channel&lt;span class="o"&gt;=&lt;/span&gt;extended
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装完成后, 在终端里运行&lt;code&gt;hugo version&lt;/code&gt;, 只要输出版本号信息, 就说明大功告成!&lt;/p&gt;
&lt;h3 id="初始化项目"&gt;&lt;a href="#%e5%88%9d%e5%a7%8b%e5%8c%96%e9%a1%b9%e7%9b%ae" class="header-anchor"&gt;&lt;/a&gt;初始化项目
&lt;/h3&gt;&lt;p&gt;找一个合适的目录, 进入终端执行以下命令:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo new site my-blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; my-blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git init
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;此时, Hugo 已经生成了标准的目录结构:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;my-blog/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── archetypes # 文章默认模板
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│   └── default.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── assets/ # 资源目录
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── content/ # 博客文章存放目录 ← 最重要
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── data/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── hugo.toml # 主配置文件 ← 最重要
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── i18n/ # 语言翻译
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── layouts/ # 自定义布局, 优先级高于主题
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── static/ # 静态资源(图片, 字体等)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── themes/ # 主题目录
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;9 directories, 2 files
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="安装与配置主题"&gt;&lt;a href="#%e5%ae%89%e8%a3%85%e4%b8%8e%e9%85%8d%e7%bd%ae%e4%b8%bb%e9%a2%98" class="header-anchor"&gt;&lt;/a&gt;安装与配置主题
&lt;/h3&gt;&lt;p&gt;Hugo 本身不带样式, 需要安装主题. 这里以极简风格的&lt;code&gt;Terminal&lt;/code&gt;主题为例:&lt;/p&gt;
&lt;p&gt;将主题作为 Git 子模块引入(强烈推荐这种方式, 方便后续更新):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git submodule add https://github.com/panr/hugo-theme-terminal.git themes/terminal
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;接着, 打开根目录下的&lt;code&gt;hugo.toml&lt;/code&gt;配置文件, 指定我们刚刚安装的主题, 并顺便修改一下基础配置:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;baseURL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://localhost:1313&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 沿用默认的本地调试地址&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;defaultContentLanguage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;zh-cn&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 博客语言&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MowMark 的技术博客&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 你的博客名称&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 必须与 themes 目录下的文件夹名称一致&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;到这一步, 博客的底层搭建已经完成了99%&lt;/p&gt;
&lt;h2 id="本地预览"&gt;&lt;a href="#%e6%9c%ac%e5%9c%b0%e9%a2%84%e8%a7%88" class="header-anchor"&gt;&lt;/a&gt;本地预览
&lt;/h2&gt;&lt;p&gt;在项目根目录下执行:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server -D &lt;span class="c1"&gt;# -D 参数表示渲染草稿文章(draft: true)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
 &lt;blockquote&gt;
 &lt;p&gt;&lt;code&gt;-D&lt;/code&gt; 参数表示渲染草稿文章(draft: true)&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;code&gt;hugo server&lt;/code&gt; 对应的常用参数还有 &lt;code&gt;--port 端口号&lt;/code&gt;, &lt;code&gt;--baseURL 域名&lt;/code&gt;等, 具体参数可以查看&lt;a class="link" href="https://hugo.opendocs.io/commands/hugo_server/" target="_blank" rel="noopener"
 &gt;hugo server&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;打开浏览器, 访问&lt;code&gt;http://localhost:1313&lt;/code&gt;, 就能看到个人博客已经在本地成功运行了!&lt;/p&gt;
&lt;p&gt;当然, 在本地运行是不够的, &lt;strong&gt;如何将它部署到公网上, 让所有人都能访问&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;这就需要用到GitHub Pages 和自动化的构建工具了.
由于篇幅原因, 这部分内容我会在&lt;a class="link" href="https://mowmark.github.io/mowmark_blog/website/hugo/001_githubpages/" &gt;使用GitHubPages部署博客&lt;/a&gt;中讲解.&lt;/p&gt;</description></item></channel></rss>