<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>木它 &#8211; 岁月细碎点滴快查</title>
	<atom:link href="https://blog.mutadecheng.com/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.mutadecheng.com</link>
	<description></description>
	<lastBuildDate>Wed, 14 Jan 2026 04:02:32 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>
	<item>
		<title>Watchtower 实现自动化容器更新</title>
		<link>https://blog.mutadecheng.com/2026/01/14/watchtower-%e5%ae%9e%e7%8e%b0%e8%87%aa%e5%8a%a8%e5%8c%96%e5%ae%b9%e5%99%a8%e6%9b%b4%e6%96%b0/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 04:02:30 +0000</pubDate>
				<category><![CDATA[DI/CI]]></category>
		<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=676</guid>

					<description><![CDATA[在日常的容器化部署中，应用的镜像经常会有新版本发布。手动更新和重启容器既繁琐又容易出错。为了解决这一问题，我们 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>在日常的容器化部署中，应用的镜像经常会有新版本发布。手动更新和重启容器既繁琐又容易出错。为了解决这一问题，我们可以借助 <a href="https://containrrr.dev/watchtower/">Watchtower</a> 工具，实现容器的自动化更新。本文将结合一个实际的 <code>docker-compose.yml</code> 配置，详细讲解如何配置和使用 Watchtower。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">什么是 Watchtower？</h2>



<p>Watchtower 是一个开源工具，用于自动监控和更新运行中的 Docker 容器。当检测到关联镜像有新版本时，Watchtower 会自动拉取新镜像，重建并重启对应的容器。这样可以实现应用的自动“滚动升级”，极大提升运维效率。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Docker Compose 配置示例</h2>



<p>下面是一个典型的 <code>docker-compose.yml</code> 配置片段，加入了 Watchtower 服务：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: &quot;3.8&quot;

services: 

  watchtower:
    image: registry.cn-beijing.aliyuncs.com/muta/watchtower:amd64
    restart: unless-stopped
    # 挂载 docker.sock 以便 Watchtower 能管理容器
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /root/.docker/:/config/
    environment:
      - DOCKER_CONFIG=/config
    # 监控项目的容器（tuechpresentation-api-1），这样不会影响其他容器
    command: --cleanup --interval 60 tuechpresentation-api-1" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3.8&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">: </span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">watchtower</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/watchtower:amd64</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">unless-stopped</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># 挂载 docker.sock 以便 Watchtower 能管理容器</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/var/run/docker.sock:/var/run/docker.sock</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/root/.docker/:/config/</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">DOCKER_CONFIG=/config</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># 监控项目的容器（tuechpresentation-api-1），这样不会影响其他容器</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">command</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">--cleanup --interval 60 tuechpresentation-api-1</span></span></code></pre></div>



<p>下面我们详细解释每一部分的作用。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">配置详解</h2>



<h3 class="wp-block-heading">1. 镜像设置</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="image: registry.cn-beijing.aliyuncs.com/muta/watchtower:amd64" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/watchtower:amd64</span></span></code></pre></div>



<p>这里使用的是阿里云镜像仓库中的 Watchtower 镜像，适合国内用户加速下载。</p>



<h3 class="wp-block-heading">2. 容器重启策略</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="restart: unless-stopped" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">unless-stopped</span></span></code></pre></div>



<p>表示除非手动停止容器，否则 Watchtower 会一直保持运行状态。</p>



<h3 class="wp-block-heading">3. 挂载 Docker Socket</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="volumes:
  - /var/run/docker.sock:/var/run/docker.sock
  - /root/.docker/:/config/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  - </span><span style="color: #CE9178">/var/run/docker.sock:/var/run/docker.sock</span></span>
<span class="line"><span style="color: #D4D4D4">  - </span><span style="color: #CE9178">/root/.docker/:/config/</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>/var/run/docker.sock:/var/run/docker.sock</code><br>Watchtower 需要通过 Docker 的 Unix Socket 与 Docker Daemon 通信，从而管理和重启其他容器。</li>



<li><code>/root/.docker/:/config/</code><br>挂载主机上的 Docker 配置目录，便于 Watchtower 使用 Docker 配置（如私有仓库认证信息等）。</li>
</ul>



<h3 class="wp-block-heading">4. 环境变量</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="environment:
  - DOCKER_CONFIG=/config" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  - </span><span style="color: #CE9178">DOCKER_CONFIG=/config</span></span></code></pre></div>



<p>指定 Docker 配置的路径为 <code>/config</code>，即上面挂载的 <code>/root/.docker/</code>。</p>



<h3 class="wp-block-heading">5. 启动命令</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="command: --cleanup --interval 60 tuechpresentation-api-1" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">command</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">--cleanup --interval 60 tuechpresentation-api-1</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>--cleanup</code><br>更新后自动删除旧的无用镜像，节省磁盘空间。</li>



<li><code>--interval 60</code><br>每 60 秒检查一次镜像是否有更新。</li>



<li><code>tuechpresentation-api-1</code><br>只监控名为 <code>tuechpresentation-api-1</code> 的容器，不会影响其他容器的运行和更新。</li>
</ul>



<p>这样配置后，Watchtower 只会自动更新指定的 API 容器，非常适合只希望自动维护某个服务的场景。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">使用建议</h2>



<ul class="wp-block-list">
<li><strong>安全性</strong>：挂载 Docker Socket 具有一定风险，建议只在可信环境下使用。</li>



<li><strong>精细化控制</strong>：通过在 command 部分指定容器名，可以避免 Watchtower 无差别地更新所有容器，更加灵活。</li>



<li><strong>日志查看</strong>：可以通过 <code>docker logs watchtower</code> 查看 Watchtower 的工作日志，了解其自动更新的动态。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">总结</h2>



<p>通过在 Docker Compose 中集成 Watchtower，可以实现容器的自动更新，极大降低了运维成本。合理配置后，还能做到只更新指定容器，安全高效。你可以根据自己的实际需求调整监控容器的范围和更新频率，让你的 Docker 环境始终保持最新和安全。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>游戏开发学习笔记-NPC的AI开发</title>
		<link>https://blog.mutadecheng.com/2026/01/07/%e6%b8%b8%e6%88%8f%e5%bc%80%e5%8f%91%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0-npc%e7%9a%84ai%e5%bc%80%e5%8f%91/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Wed, 07 Jan 2026 05:56:59 +0000</pubDate>
				<category><![CDATA[游戏开发]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=669</guid>

					<description><![CDATA[在游戏开发中，NPC（非玩家角色）的智能行为设计十分重要。不同的AI开发方式适用于不同复杂度和类型的NPC。本 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>在游戏开发中，NPC（非玩家角色）的智能行为设计十分重要。不同的AI开发方式适用于不同复杂度和类型的NPC。本篇详细介绍主流的NPC AI开发方法，并配有树状图示例，帮助初学者轻松理解。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">一、有限状态机（FSM，Finite State Machine）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>有限状态机是一种把NPC行为分成几个“状态”的设计方式，比如“巡逻”、“攻击”、“逃跑”等。NPC任意时刻只会处于某一个状态，满足条件才会切换到其他状态。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li><strong>状态</strong>：NPC所处的行为阶段。</li>



<li><strong>切换条件</strong>：决定何时从一个状态跳转到另一个状态。</li>



<li><strong>每个状态的具体行为</strong>：比如巡逻状态下，NPC会在场景中来回走动。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="巡逻
└─ 发现敌人? 是 → 追击敌人
    └─ 距离很近? 是 → 攻击敌人
        └─ 血量很低? 是 → 逃跑" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">巡逻</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">发现敌人?</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">追击敌人</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">距离很近?</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">攻击敌人</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">血量很低?</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">逃跑</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>比如一个警卫巡逻，发现敌人就追击，靠近了就攻击，受伤严重就逃跑。每个行为就是一个“状态”，切换条件清晰简单，非常适合新手入门和简单AI。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">二、决策树（Decision Tree）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>决策树就像一系列嵌套的“如果……那么……”的判断题。NPC会沿着判断条件，一步步选择最终要做的事情。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li>每一层是一个判断问题。</li>



<li>满足条件就继续往下判断，直到找到适合当前情况的行为。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="发现敌人?
├─ 是
│   └─ 距离近?
│       ├─ 是 → 攻击
│       └─ 否 → 追击
└─ 否 → 巡逻" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">发现敌人?</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">距离近?</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">       </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">攻击</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">       </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">否</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">追击</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">否</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">巡逻</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>比如NPC先问自己“看到敌人了吗？”如果看到，再问“敌人近吗？”，如果近就攻击，不近就追。如果没看到，就继续巡逻。适合逻辑不复杂的NPC。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">三、行为树（Behavior Tree）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>行为树是一种模块化的设计，把复杂行为拆解成一个个“小动作”，再像拼积木一样组合起来。每个“树枝”表示一个决策流程，叶子节点是具体动作。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li>从根节点出发，按顺序或优先级检查每个子节点。</li>



<li>组合复杂行为，比如“先做A，如果不行再做B”。</li>



<li>节点可以复用，易于扩展。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="选择器
├─ 行为1：发现敌人?
│   └─ 是 → 顺序器
│       ├─ 面向敌人
│       ├─ 接近敌人
│       └─ 攻击敌人
├─ 行为2：血量低?
│   └─ 是 → 寻找掩体
└─ 行为3：巡逻" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">选择器</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">行为1：发现敌人?</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">顺序器</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">       </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">面向敌人</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">       </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">接近敌人</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">       </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">攻击敌人</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">行为2：血量低?</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">寻找掩体</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">行为3：巡逻</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>行为树就像一个智能化的流程表，先判断优先级高的事（比如有敌人就先攻击），否则做次要的事（比如巡逻）。树的结构让每个行为都能灵活组合，非常适合复杂NPC。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">四、GOAP（目标导向动作规划，Goal-Oriented Action Planning）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>GOAP不是提前写好所有流程，而是让NPC根据“目标”动态规划怎么做。比如目标是“活下来”，NPC会自动选择“找药包”“找掩体”等步骤。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li>给NPC设定多个目标，如“消灭敌人”“保持安全”。</li>



<li>每个动作有“前提条件”和“结果”。</li>



<li>NPC根据当前情况，自动规划一系列动作达成目标。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例（目标：消灭敌人）</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="目标：消灭敌人
├─ 需要武器?
│   └─ 是 → 去找武器
├─ 有武器 → 靠近敌人
└─ 接近后 → 攻击敌人" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">目标：消灭敌人</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">需要武器?</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">是</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">去找武器</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">有武器</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">靠近敌人</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">接近后</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">攻击敌人</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>比如NPC没有武器，就会先去找武器；有了武器后再去接近敌人，最后攻击。GOAP让NPC像“思考”一样，灵活应对不同情况，行为更智能。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">五、黑板系统（Blackboard System）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>黑板系统是一个信息共享平台，NPC的各个模块（比如感知、决策、行动）都可以在黑板上读写信息，实现协同。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li>黑板就像一个公告栏，大家都能看到。</li>



<li>感知模块发现敌人后，把信息写到黑板上。</li>



<li>行为模块读取这些信息，决定要做什么。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="黑板
├─ 发现敌人 → 决策模块读取 → 切换到攻击状态
├─ 发现血包 → 决策模块读取 → 前往拾取
└─ 其他信息" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">黑板</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">发现敌人</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">决策模块读取</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">切换到攻击状态</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">发现血包</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">决策模块读取</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">前往拾取</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">其他信息</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>黑板让NPC的不同部分可以互相沟通，比如“感知”发现敌人，“决策”模块就能知道要攻击。这种方式多用于复杂AI系统。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">六、基于规则的系统（Rule-based System）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>基于规则的系统，就是提前写好一堆“如果……那么……”的规则，NPC遇到情况就一条条检查，满足条件就执行相应行为。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li>规则库里存着各种条件和结果。</li>



<li>NPC不断检查当前所有规则，执行最先匹配的行为。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="规则库
├─ 如果血量低 → 寻找医疗包
├─ 如果敌人靠近 → 攻击
└─ 否则 → 巡逻" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">规则库</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">如果血量低</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">寻找医疗包</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">如果敌人靠近</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">攻击</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">否则</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">巡逻</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>比如“如果血量低，去找药包；如果敌人靠近，先攻击”。适合简单或者中等复杂度的AI，但规则多了后管理会变复杂。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">七、机器学习/深度学习方法</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p>机器学习让NPC通过“学习”来变得更聪明，比如通过反复试错，自动学会最佳行为。</p>



<h3 class="wp-block-heading">2. 原理</h3>



<ul class="wp-block-list">
<li>通过大量训练，AI模型掌握在不同情况下的最佳反应。</li>



<li>强化学习：NPC每做一次选择，都会得到奖励或惩罚，通过不断尝试，学会最优策略。</li>
</ul>



<h3 class="wp-block-heading">3. 树图示例（简化思路）</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="环境反馈
├─ 尝试动作A → 得到奖励 → 增强动作A
├─ 尝试动作B → 得到惩罚 → 减少动作B
└─ 反复迭代 → 学习到最佳行为" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">环境反馈</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">尝试动作A</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">得到奖励</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">增强动作A</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">尝试动作B</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">得到惩罚</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">减少动作B</span></span>
<span class="line"><span style="color: #DCDCAA">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">反复迭代</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">→</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">学习到最佳行为</span></span></code></pre></div>



<h3 class="wp-block-heading">4. 讲解</h3>



<p>比如NPC在模拟环境里尝试“攻击”“逃跑”“躲避”，每次尝试后都通过奖励机制调整行为，最终学会如何做得最好。这种方法适合做高智能NPC，但开发和训练成本高。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">八、基于大语言模型的生成式智能体架构（以斯坦福AI小人虚拟小镇为例）</h2>



<h3 class="wp-block-heading">1. 概念</h3>



<p><strong>生成式智能体</strong>（Generative Agent）是一种借助大语言模型（如GPT）作为“智能大脑”，结合记忆、检索、反思、计划等模块，模拟出高度拟人的行为和交互。其典型代表是斯坦福大学提出的“AI小人虚拟小镇”，在开源社区（如a16z重写版）得到了广泛应用。</p>



<p>传统AI方法如有限状态机、行为树、GOAP等，行为多为“脚本化”或“规则化”。生成式智能体则通过自然语言驱动行为，能够自我进化、动态适应环境，表现出类似人类的复杂行为。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. 技术架构与整体思路</h3>



<h4 class="wp-block-heading">2.1 架构树状图</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="生成式智能体架构
├─ 记忆流（Memory Stream）
│   ├─ 观察（Observations）
│   ├─ 反思（Reflections）
│   └─ 计划（Plans）
├─ 检索机制（Retrieval）
│   ├─ 近因性
│   ├─ 重要性
│   └─ 相关性（向量数据库）
├─ 反思机制（Reflection）
│   └─ 抽象/推理（生成反思树）
├─ 计划与反应（Planning &amp; Reaction）
│   ├─ 高层计划
│   └─ 递归细化
├─ 行为生成（Action Generation）
│   ├─ 环境互动
│   └─ 代理对话
├─ 用户交互
│   └─ 用户输入（自然语言）
├─ 外部支持系统
│   ├─ 游戏引擎、数据库
│   ├─ 向量数据库
│   ├─ 文字生成模型（LLM）
│   └─ 像素图生成等" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">生成式智能体架构</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">记忆流（Memory</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">Stream）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">观察（Observations）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">反思（Reflections）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">计划（Plans）</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">检索机制（Retrieval）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">近因性</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">重要性</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">相关性（向量数据库）</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">反思机制（Reflection）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">抽象/推理（生成反思树）</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">计划与反应（Planning</span><span style="color: #D4D4D4"> &amp; </span><span style="color: #DCDCAA">Reaction）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">高层计划</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">递归细化</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">行为生成（Action</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">Generation）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">环境互动</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">代理对话</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">用户交互</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">用户输入（自然语言）</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">外部支持系统</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">游戏引擎、数据库</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">向量数据库</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">文字生成模型（LLM）</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">像素图生成等</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading">2.2 架构详细讲解</h4>



<p><strong>A. 记忆流（Memory Stream）</strong></p>



<ul class="wp-block-list">
<li>每个智能体都有自己的“记忆数据库”，记录着所有经历过的事件、对话、计划、反思等。</li>



<li>记忆以自然语言形式存储，包含时间戳和访问时间，既有“观测”也有“抽象反思”。</li>



<li>例如：AI小人“伊莎贝拉”会记得“今天早上在厨房遇到朋友做早餐”。</li>
</ul>



<p><strong>B. 检索机制（Retrieval）</strong></p>



<ul class="wp-block-list">
<li>智能体需要从大量记忆中检索出“当前最相关”的记忆，指导当下行为。</li>



<li>检索包括三大指标：
<ul class="wp-block-list">
<li><strong>近因性</strong>：越新发生的事件，分数越高。</li>



<li><strong>重要性</strong>：事件越重要，分数越高（如“分手”比“刷牙”重要）。</li>



<li><strong>相关性</strong>：用向量数据库（如Pinecone）计算与当前情境的相似度。</li>
</ul>
</li>



<li>例如，AI小人要决定是否去见某人，会回忆最近有关此人的经历和情感。</li>
</ul>



<p><strong>C. 反思机制（Reflection）</strong></p>



<ul class="wp-block-list">
<li>不只是被动记忆，还会主动“总结归纳”，形成“反思”。</li>



<li>反思是对多个相关记忆的抽象，比如“我和朋友的关系变得更亲密了”。</li>



<li>反思会形成“树状结构”，叶节点是具体事件，高层节点是抽象见解。</li>



<li>反思周期性发生，重要事件累积到阈值时触发。</li>
</ul>



<p><strong>D. 计划与反应（Planning &amp; Reaction）</strong></p>



<ul class="wp-block-list">
<li>智能体会制定自己的“日程计划”，比如“早上做早餐、上午去公园、下午工作”。</li>



<li>计划可以递归细化成更小的行动步骤，并随时根据环境变化做出调整。</li>



<li>每当环境或其他智能体行为发生变化，计划会实时更新。</li>
</ul>



<p><strong>E. 行为生成（Action Generation）</strong></p>



<ul class="wp-block-list">
<li>智能体的每一步行为由大语言模型（如GPT）生成，行为描述为自然语言，并映射到具体动作。</li>



<li>智能体之间的对话、与环境的交互都通过自然语言描述和解释。</li>
</ul>



<p><strong>F. 用户交互</strong></p>



<ul class="wp-block-list">
<li>用户可以通过自然语言输入影响智能体（如指派任务、修改属性）。</li>



<li>用户也可以“化身”进入虚拟小镇，成为其中一员。</li>
</ul>



<p><strong>G. 外部支持系统</strong></p>



<ul class="wp-block-list">
<li>游戏引擎（Convex）、数据库、向量数据库（Pinecone）、文字生成模型（OpenAI）、像素图生成（Replicate/Fal.ai）等，构成整个技术栈的基础设施。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. 与传统AI方法的对比</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>传统方法</th><th>特点</th><th>生成式智能体</th></tr></thead><tbody><tr><td>有限状态机、行为树、GOAP等</td><td>规则/脚本驱动，行为固定，扩展性差</td><td>记忆驱动，行为高度拟人，动态自适应</td></tr><tr><td>规则系统</td><td>依赖开发者预设规则</td><td>通过大语言模型自动推理与规划</td></tr><tr><td>强化学习</td><td>需大量训练，适应性有限</td><td>通过记忆、环境、反思即时适应新情境</td></tr><tr><td>机器学习</td><td>难以解释、训练成本高</td><td>LLM强提示+外逻辑架构，易于扩展</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4. 生成式智能体的创新点</h3>



<ul class="wp-block-list">
<li><strong>内逻辑与外逻辑结合</strong>：大语言模型负责“想”，外部系统负责“管”数据和操作。</li>



<li><strong>记忆驱动行为</strong>：不再依赖死板脚本，行为由“记忆-检索-反思-计划”动态生成。</li>



<li><strong>行为高度拟人</strong>：能模拟人类的长期记忆、情感变化、临场反应、社会互动。</li>



<li><strong>自进化能力</strong>：环境或用户输入变化时，智能体能自动适应，无需修改代码。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5. 示例：AI小人的一天（树状图）</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="伊莎贝拉的一天
├─ 记忆流
│   ├─ 早上做早餐
│   ├─ 与朋友聊天
│   ├─ 计划去公园
│   └─ 下午工作
├─ 检索
│   ├─ 最近与朋友的对话
│   └─ 上次工作时的反思
├─ 反思
│   ├─ 今天与朋友关系更亲密
│   └─ 工作效率提升
├─ 计划
│   ├─ 上午：社交
│   └─ 下午：工作
├─ 行为
│   ├─ 与朋友互动
│   └─ 执行工作任务" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">伊莎贝拉的一天</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">记忆流</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">早上做早餐</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">与朋友聊天</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">计划去公园</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">下午工作</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">检索</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">最近与朋友的对话</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">上次工作时的反思</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">反思</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">今天与朋友关系更亲密</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">工作效率提升</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">计划</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">上午：社交</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">下午：工作</span></span>
<span class="line"><span style="color: #DCDCAA">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">行为</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">├─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">与朋友互动</span></span>
<span class="line"><span style="color: #DCDCAA">│</span><span style="color: #D4D4D4">   </span><span style="color: #CE9178">└─</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">执行工作任务</span></span></code></pre></div>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>这些行为全自动生成，AI小人会根据记忆和环境调整自己的计划和反应。</p>
</blockquote>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">6. 适用场景与未来趋势</h3>



<ul class="wp-block-list">
<li><strong>虚拟世界/元宇宙</strong>：高度拟人NPC、虚拟居民。</li>



<li><strong>游戏开发</strong>：复杂剧情与开放世界中的真实NPC行为。</li>



<li><strong>社交/教育/陪伴</strong>：情感丰富、可自我进化的AI伙伴。</li>



<li><strong>智能体系统</strong>：自动化办公、协作机器人等。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">7. 相关资源</h3>



<ul class="wp-block-list">
<li><a href="https://github.com/joonspk-research/generative_agents">项目地址（GitHub）</a></li>



<li><a href="https://arxiv.org/pdf/2304.03442.pdf">论文原文（英文）</a></li>



<li><a href="http://cyberxz.com/aiweb/file/Chinese_GenerativeAgentsInteractiveSimulacraofHumanBehavior.pdf">论文（中文机翻）</a></li>



<li><a href="https://www.convex.dev/ai-town?continueFlag=cd9be6edc56bfb72f6d0dc908d439184">官方演示</a></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">总结</h2>



<p>斯坦福AI小人虚拟小镇项目开启了大语言模型驱动的AI智能体新时代。它打破了传统脚本和规则系统的限制，让AI像“人”一样，有记忆、会反思、能规划、会交流，真正实现了“虚拟居民”的可信模拟。这一架构的理解，对设计下一代AI应用极具参考价值。</p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>一些想要实现的构思&#8211;厨房设计</title>
		<link>https://blog.mutadecheng.com/2026/01/04/%e4%b8%80%e4%ba%9b%e6%83%b3%e8%a6%81%e5%ae%9e%e7%8e%b0%e7%9a%84%e6%9e%84%e6%80%9d/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Sun, 04 Jan 2026 10:37:06 +0000</pubDate>
				<category><![CDATA[设计构思]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=659</guid>

					<description><![CDATA[这是用来展示我构思, 啊 当然现在这里啥都没有 那 玩一下鸭子吧]]></description>
										<content:encoded><![CDATA[
<p>这是用来展示我构思,</p>



<p>啊</p>



<p>当然现在这里啥都没有</p>



<p>那</p>



<p>玩一下鸭子吧</p>



<!-- 引入 model-viewer 组件 -->
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<!-- 3D模型展示 -->
<model-viewer
  src="https://blog.mutadecheng.com/wp-content/uploads/2026/01/Duck.glb"
  alt="Duck 3D模型"
  auto-rotate
  camera-controls
  ar
  style="width: 500px; height: 400px; background: white; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); display: block; margin: 40px auto;"
></model-viewer>




<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>工作记录&#8211;振动MQTT接收与处理</title>
		<link>https://blog.mutadecheng.com/2026/01/04/%e5%b7%a5%e4%bd%9c%e8%ae%b0%e5%bd%95-%e6%8c%af%e5%8a%a8mqtt%e6%8e%a5%e6%94%b6%e4%b8%8e%e5%a4%84%e7%90%86/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Sun, 04 Jan 2026 08:56:23 +0000</pubDate>
				<category><![CDATA[工作记录]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=650</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.8'

services:  
  emqx:
    image: registry.cn-beijing.aliyuncs.com/muta/emqx:amd64
    restart: always
    container_name: emqx
    ports:
      - &quot;1883:1883&quot;   # MQTT 协议端口
      - &quot;8083:8083&quot;   # WebSocket 端口
      - &quot;8084:8084&quot;   # WebSocket(SSL) 端口
      - &quot;18083:18083&quot; # 管理后台端口
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;

  rabbitmq:
    image: registry.cn-beijing.aliyuncs.com/muta/rabbitmq:management-amd64
    restart: always
    container_name: rabbitmq
    ports:
      - &quot;5672:5672&quot;   # AMQP 协议端口
      - &quot;15672:15672&quot; # 管理页面端口
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin123
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;

  mqtt2rabbitmq:
    image: registry.cn-beijing.aliyuncs.com/dfzh/mqtt2rabbitmq:latest
    restart: always
    container_name: mqtt2rabbitmq
    environment:
      RabbitMQ__Hostname: rabbitmq
      RabbitMQ__Username: admin
      RabbitMQ__Password: admin123
      RabbitMQ__QueueName: Sensor 
      MQTT__Broker: emqx
      MQTT__Topic: /dev/luna/# 
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;

  rabbitmqvbrationwebapi:
    image: registry.cn-beijing.aliyuncs.com/dfzh/rabbitmqvibrationwebapi:latest
    restart: always
    container_name: rabbitmqvbrationwebapi
    ports:
      - &quot;8222:5759&quot;   
    volumes:
      - /home/HisDatas:/app/HisDatas
    environment:
      RabbitMQ__Hostname: rabbitmq
      RABBITMQ__Port: 5672
      RabbitMQ__Username: admin
      RabbitMQ__Password: admin123
      RabbitMQ__QueueName: vibhex  
      RABBITMQ__ProductionEnvironment: true
    logging:
      driver: &quot;json-file&quot;
      options:
        max-size: &quot;100m&quot;
        max-file: &quot;3&quot;
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.8&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">emqx</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/emqx:amd64</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">container_name</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">emqx</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">ports</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;1883:1883&quot;</span><span style="color: #D4D4D4">   </span><span style="color: #6A9955"># MQTT 协议端口</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;8083:8083&quot;</span><span style="color: #D4D4D4">   </span><span style="color: #6A9955"># WebSocket 端口</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;8084:8084&quot;</span><span style="color: #D4D4D4">   </span><span style="color: #6A9955"># WebSocket(SSL) 端口</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;18083:18083&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955"># 管理后台端口</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">rabbitmq</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/muta/rabbitmq:management-amd64</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">container_name</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">rabbitmq</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">ports</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;5672:5672&quot;</span><span style="color: #D4D4D4">   </span><span style="color: #6A9955"># AMQP 协议端口</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;15672:15672&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #6A9955"># 管理页面端口</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RABBITMQ_DEFAULT_USER</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">admin</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RABBITMQ_DEFAULT_PASS</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">admin123</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">mqtt2rabbitmq</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/dfzh/mqtt2rabbitmq:latest</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">container_name</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">mqtt2rabbitmq</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__Hostname</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">rabbitmq</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__Username</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">admin</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__Password</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">admin123</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__QueueName</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">Sensor</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">MQTT__Broker</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">emqx</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">MQTT__Topic</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">/dev/luna/#</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">rabbitmqvbrationwebapi</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">registry.cn-beijing.aliyuncs.com/dfzh/rabbitmqvibrationwebapi:latest</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">restart</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">always</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">container_name</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">rabbitmqvbrationwebapi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">ports</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;8222:5759&quot;</span><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">volumes</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">/home/HisDatas:/app/HisDatas</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">environment</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__Hostname</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">rabbitmq</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RABBITMQ__Port</span><span style="color: #D4D4D4">: </span><span style="color: #B5CEA8">5672</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__Username</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">admin</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__Password</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">admin123</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RabbitMQ__QueueName</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">vibhex</span><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">RABBITMQ__ProductionEnvironment</span><span style="color: #D4D4D4">: </span><span style="color: #569CD6">true</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">logging</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">driver</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;json-file&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">options</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-size</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;100m&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">max-file</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&quot;3&quot;</span></span>
<span class="line"></span></code></pre></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>浅谈视觉运动检测中光流法和帧差法</title>
		<link>https://blog.mutadecheng.com/2025/12/30/%e6%b5%85%e8%b0%88%e8%a7%86%e8%a7%89%e8%bf%90%e5%8a%a8%e6%a3%80%e6%b5%8b%e4%b8%ad%e5%85%89%e6%b5%81%e6%b3%95%e5%92%8c%e5%b8%a7%e5%b7%ae%e6%b3%95/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Tue, 30 Dec 2025 01:05:16 +0000</pubDate>
				<category><![CDATA[未分类]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=646</guid>

					<description><![CDATA[光流法和帧差法都是视频图像处理领域常用的运动检测/分析方法，但它们的原理、输出和适用场景有明显区别。下面详细对 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>光流法和帧差法都是视频图像处理领域常用的运动检测/分析方法，但它们的原理、输出和适用场景有明显区别。下面详细对比说明：</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1. 原理区别</h3>



<p><strong>帧差法（Frame Difference）</strong></p>



<ul class="wp-block-list">
<li><strong>基本思想</strong>：直接对连续两帧图像的像素灰度值做差分，若差值大于阈值，则判定为运动区域。</li>



<li><strong>输出结果</strong>：主要得到运动的“掩膜”或“区域”，即哪个像素发生了变化。</li>



<li><strong>适用场景</strong>：简单的运动检测和目标分割。</li>
</ul>



<p><strong>光流法（Optical Flow）</strong></p>



<ul class="wp-block-list">
<li><strong>基本思想</strong>：基于亮度一致性假设，通过分析连续帧间像素灰度分布的变化，估计每个像素的速度矢量（即运动方向和幅度）。</li>



<li><strong>输出结果</strong>：每个像素的运动矢量场（速度场），可进一步分析位移、速度、振动等物理量。</li>



<li><strong>适用场景</strong>：需要精确估计物体运动、结构振动、速度场、位移场等场景。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. 结果对比</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>方法</th><th>输出类型</th><th>能否得出运动方向</th><th>能否得出运动幅值</th><th>适用场景</th></tr></thead><tbody><tr><td>帧差法</td><td>二值/灰度掩膜</td><td>否</td><td>否</td><td>运动检测、目标分割</td></tr><tr><td>光流法</td><td>运动矢量场</td><td>是</td><td>是</td><td>振动分析、速度估计、模态识别</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. 优缺点对比</h3>



<p><strong>帧差法：</strong></p>



<ul class="wp-block-list">
<li><strong>优点</strong>：实现简单，计算速度快，适合实时检测。</li>



<li><strong>缺点</strong>：只能检测运动区域，无法准确估计运动的方向和幅度，易受光照变化影响，对微小运动不敏感。</li>
</ul>



<p><strong>光流法：</strong></p>



<ul class="wp-block-list">
<li><strong>优点</strong>：可获得像素级别的运动方向和幅度信息，适合微小运动（如结构振动、模态识别、运动放大）。</li>



<li><strong>缺点</strong>：计算复杂度高，对噪声和光照变化较敏感，需较好的视频质量。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4. 应用举例</h3>



<ul class="wp-block-list">
<li><strong>帧差法</strong>：适合用于安防监控中检测是否有物体进入画面，或简单的运动目标检测。</li>



<li><strong>光流法</strong>：适合用于结构健康监测、桥梁/建筑物振动检测、模态参数识别、运动放大等需要高精度运动分析的场景。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">5. 总结</h3>



<p><strong>帧差法</strong>更偏向于“有没有运动”的检测，而<strong>光流法</strong>则能“量化运动”，包括运动的方向和幅度。在结构振动、模态识别、运动放大等需要定量分析运动的场景，光流法明显优于帧差法。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Portainer 基础知识</title>
		<link>https://blog.mutadecheng.com/2025/12/29/portainer-%e5%9f%ba%e7%a1%80%e7%9f%a5%e8%af%86/</link>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Mon, 29 Dec 2025 03:48:11 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=644</guid>

					<description><![CDATA[Portainer 入门详解教程 —— 用安卓应用商店类比，帮助初学者轻松理解 前言 对于很多初学者来说，Po [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Portainer 入门详解教程 —— 用安卓应用商店类比，帮助初学者轻松理解</p>



<p>前言</p>



<p>        对于很多初学者来说，Portainer 这个工具可能比较陌生。其实，Portainer 的作用和安卓手机上的“应用商店”非常类似。应用商店让我们方便地安装、管理和卸载各种手机应用，而 Portainer 则让我们在服务器上用可视化方式管理 Docker 容器（各种服务器应用）。本教程将用详细的类比和表格，帮助初学者快速理解 Portainer 的各项功能和实际操作细节。</p>



<p>一、Portainer 与安卓应用商店功能对照表</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>功能/场景</th><th>Portainer 细节说明</th><th>安卓应用商店细节说明</th></tr></thead><tbody><tr><td>管理对象</td><td>管理服务器上的 Docker 容器和镜像，包括应用、数据库等</td><td>管理手机上的各类应用</td></tr><tr><td>安装方式</td><td>需要先安装 Docker，然后通过命令或图形界面部署 Portainer</td><td>手机厂商预装或用户下载应用商店</td></tr><tr><td>应用安装</td><td>选择镜像或模板，填写参数，设置端口、存储路径等，点击部署</td><td>搜索应用，确认权限，点击安装</td></tr><tr><td>应用卸载</td><td>停止并删除容器，必要时清理相关数据和镜像</td><td>长按应用图标或在应用商店中卸载</td></tr><tr><td>应用启动/停止</td><td>选择容器，点击启动或停止，支持一键操作</td><td>点击应用图标打开或关闭</td></tr><tr><td>更新应用</td><td>拉取新镜像，重新部署容器，注意数据备份和兼容性</td><td>应用商店提示更新，点击升级</td></tr><tr><td>查看日志</td><td>进入容器详情页，查看实时日志，支持过滤和搜索错误信息</td><td>开发者选项或应用详情中查看崩溃日志</td></tr><tr><td>权限管理</td><td>支持多用户登录，分配不同角色和权限，适合团队协作</td><td>账号管理，家长控制、隐私权限设置</td></tr><tr><td>应用分类</td><td>分类展示常用服务类型，如数据库、内容管理、工具等</td><td>社交、游戏、工具等应用分类</td></tr><tr><td>多平台管理</td><td>可同时管理本地和远程服务器上的容器，适合多台设备场景</td><td>多台手机或平板统一管理应用</td></tr></tbody></table></figure>



<p>二、Portainer 安装与初次使用细节</p>



<ol class="wp-block-list">
<li>安装 Docker</li>
</ol>



<ul class="wp-block-list">
<li>Portainer 依赖 Docker 环境，需先在服务器上安装好 Docker。类似于安卓系统必须先准备好，才能安装应用商店。</li>



<li>初学者推荐在干净的服务器或虚拟机上操作，避免环境冲突。</li>
</ul>



<ol class="wp-block-list">
<li>部署 Portainer</li>
</ol>



<ul class="wp-block-list">
<li>Portainer 本身也是一个容器应用。部署后，会自动生成管理界面，通常通过浏览器访问。</li>



<li>访问方式为：http://服务器IP:9000，首次进入需要设置管理员账号和密码，确保安全性。</li>
</ul>



<ol class="wp-block-list">
<li>首次登录</li>
</ol>



<ul class="wp-block-list">
<li>建议初学者使用强密码，并妥善保存账号信息。</li>



<li>登录后会看到主界面，包括管理节点、容器、镜像、网络、卷等模块。</li>
</ul>



<p>三、Portainer 图形界面与应用商店界面细节对比</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Portainer 页面</th><th>安卓应用商店页面</th><th>细节说明</th></tr></thead><tbody><tr><td>首页（Home）</td><td>推荐页/首页</td><td>展示所有已管理的环境和服务，快速入口</td></tr><tr><td>容器列表（Containers）</td><td>已安装应用列表</td><td>展示已安装和运行的所有容器，支持筛选、排序、批量操作</td></tr><tr><td>镜像库（Images）</td><td>应用市场库</td><td>展示可用的容器镜像，相当于应用安装包，可手动拉取或删除</td></tr><tr><td>应用模板（App Templates）</td><td>精品推荐/分类应用</td><td>一键部署常用服务，内置参数简化部署流程，适合初学者</td></tr><tr><td>日志（Logs）</td><td>应用详情/崩溃日志</td><td>实时展示容器输出和运行日志，支持搜索错误信息</td></tr><tr><td>用户与权限（Users）</td><td>账号/家长控制</td><td>添加和管理不同用户，分配管理权限，适合多人协作</td></tr><tr><td>设置（Settings）</td><td>应用商店设置</td><td>配置 Portainer 的基本参数，包括界面语言、通知等</td></tr></tbody></table></figure>



<p>四、典型操作场景细节讲解</p>



<ol class="wp-block-list">
<li>安装新容器服务（如 WordPress 网站）</li>
</ol>



<ul class="wp-block-list">
<li>在应用模板中找到 WordPress，点击部署。</li>



<li>细致填写数据库密码、端口号等参数，确认后即可自动完成安装。</li>



<li>部署后自动跳转到容器列表，可一键启动、停止或重启服务。</li>



<li>类似于在应用商店中搜索微信，点击安装，填写账号信息后即可使用。</li>
</ul>



<ol class="wp-block-list">
<li>启动或停止容器</li>
</ol>



<ul class="wp-block-list">
<li>容器列表中，每个容器都有启动、停止、重启按钮。</li>



<li>可根据需要灵活操作，适合测试和维护环境。</li>



<li>类比于手机上打开或关闭应用。</li>
</ul>



<ol class="wp-block-list">
<li>卸载容器服务</li>
</ol>



<ul class="wp-block-list">
<li>停止容器后，点击删除即可完成卸载。</li>



<li>建议初学者在删除前备份重要数据（如数据库内容），避免误删。</li>



<li>类似于卸载手机应用时确认是否保留数据。</li>
</ul>



<ol class="wp-block-list">
<li>更新容器应用</li>
</ol>



<ul class="wp-block-list">
<li>检查镜像库是否有新版本，拉取最新镜像后重建容器。</li>



<li>更新前建议备份数据，并确认新版本兼容性。</li>



<li>类比于应用商店提示应用有新版本时，点击升级按钮。</li>
</ul>



<ol class="wp-block-list">
<li>查看容器日志</li>
</ol>



<ul class="wp-block-list">
<li>容器详情页可实时查看运行日志，支持搜索关键字（如“error”、“failed”）。</li>



<li>日志可帮助排查启动失败、配置错误等问题，是运维必备工具。</li>



<li>类似于应用崩溃后查看日志定位问题。</li>
</ul>



<p>五、常见问题与细节排查方法</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>问题场景</th><th>Portainer 细节排查方法</th><th>安卓应用商店类比说明</th></tr></thead><tbody><tr><td>容器无法启动</td><td>查看日志，检查端口冲突、环境变量设置、依赖问题</td><td>应用打不开，检查网络或重启手机</td></tr><tr><td>镜像下载慢或失败</td><td>切换国内镜像源，检查网络连接，重试拉取</td><td>应用下载缓慢，切换 Wi-Fi 或移动网络</td></tr><tr><td>权限不足</td><td>检查用户角色，调整权限设置，避免误操作</td><td>家长控制或权限限制导致无法安装应用</td></tr><tr><td>占用资源过多</td><td>停止或删除不常用容器，释放服务器内存和存储空间</td><td>清理不常用应用，释放手机空间</td></tr><tr><td>版本兼容性问题</td><td>查看容器日志，确认 Docker 和镜像版本匹配</td><td>应用不兼容当前系统版本，升级或降级系统</td></tr></tbody></table></figure>



<p>六、进阶建议</p>



<ul class="wp-block-list">
<li>初学者可优先使用模板部署常用服务，熟悉参数填写和基本管理流程。</li>



<li>建议定期查看容器日志，及时发现和解决潜在问题。</li>



<li>多用户协作时，合理分配权限，避免误操作影响整个环境。</li>



<li>学习数据卷和网络管理，提高服务的稳定性和安全性。</li>



<li>探索远程节点管理，适合多台服务器或云平台场景。</li>
</ul>



<p>结语</p>



<p>Portainer 就像服务器世界里的“应用商店”，让初学者无需复杂命令，就能像管理手机应用一样，轻松管理服务器上的各种服务。通过图形界面、详细日志和丰富模板，Portainer 不仅提升了管理效率，也降低了运维门槛。建议初学者在实践中多尝试、多探索，逐步掌握容器化应用的管理技巧。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>测试页面</title>
		<link>https://blog.mutadecheng.com/2025/12/23/%e6%b5%8b%e8%af%95%e9%a1%b5%e9%9d%a2/</link>
					<comments>https://blog.mutadecheng.com/2025/12/23/%e6%b5%8b%e8%af%95%e9%a1%b5%e9%9d%a2/#respond</comments>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Tue, 23 Dec 2025 08:50:14 +0000</pubDate>
				<category><![CDATA[未分类]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=585</guid>

					<description><![CDATA[这是一个测试页面,什么都可能发生]]></description>
										<content:encoded><![CDATA[
<p>这是一个测试页面,什么都可能发生</p>



<!-- 引入 model-viewer 组件 -->
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<!-- 3D模型展示 -->
<model-viewer
  src="https://blog.mutadecheng.com/wp-content/uploads/2026/01/Duck.glb"
  alt="Duck 3D模型"
  auto-rotate
  camera-controls
  ar
  style="width: 500px; height: 400px; background: white; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); display: block; margin: 40px auto;"
></model-viewer>

]]></content:encoded>
					
					<wfw:commentRss>https://blog.mutadecheng.com/2025/12/23/%e6%b5%8b%e8%af%95%e9%a1%b5%e9%9d%a2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>使用 Docker 和 Ultralytics YOLOv8 训练自定义目标检测模型全流程</title>
		<link>https://blog.mutadecheng.com/2025/12/18/%e4%bd%bf%e7%94%a8-docker-%e5%92%8c-ultralytics-yolov8-%e8%ae%ad%e7%bb%83%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9b%ae%e6%a0%87%e6%a3%80%e6%b5%8b%e6%a8%a1%e5%9e%8b%e5%85%a8%e6%b5%81%e7%a8%8b/</link>
					<comments>https://blog.mutadecheng.com/2025/12/18/%e4%bd%bf%e7%94%a8-docker-%e5%92%8c-ultralytics-yolov8-%e8%ae%ad%e7%bb%83%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9b%ae%e6%a0%87%e6%a3%80%e6%b5%8b%e6%a8%a1%e5%9e%8b%e5%85%a8%e6%b5%81%e7%a8%8b/#respond</comments>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Thu, 18 Dec 2025 05:30:08 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[YOLO]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=468</guid>

					<description><![CDATA[前言 最近在学习目标检测，想用 Ultralytics 的 YOLOv8 框架训练自己拍摄的“蓝色黄色小球”数 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">前言</h2>



<p>最近在学习目标检测，想用 Ultralytics 的 YOLOv8 框架训练自己拍摄的“蓝色黄色小球”数据集。由于本地环境复杂，决定用 Docker 来隔离环境，保证依赖一致性。本文记录整个流程，便于以后复用和查阅。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. 准备工作</h2>



<h3 class="wp-block-heading">1.1 安装 Docker</h3>



<p>请确保电脑已安装 <a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a>，并且已开启 GPU 支持（NVIDIA 驱动 &amp; CUDA 已配置好）。</p>



<h3 class="wp-block-heading">1.2 检查 GPU 驱动</h3>



<p>在命令行（PowerShell）输入：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="nvidia-smi" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">nvidia-smi</span></span></code></pre></div>



<p>如果能看到显卡信息，说明驱动没问题。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. 数据集准备</h2>



<p>我的数据集结构如下：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="E:\
└── 机器学习训练集\
    └── 蓝色黄色小球\
        └── boll\
            ├── train\
            │    ├── images\
            │    └── labels\
            └── val\
                 ├── images\
                 └── labels\" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">E:\</span></span>
<span class="line"><span style="color: #D4D4D4">└── </span><span style="color: #CE9178">机器学习训练集</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">└──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">蓝色黄色小球</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #CE9178">└──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">boll</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">├──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">train</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">│</span><span style="color: #D4D4D4">    </span><span style="color: #CE9178">├──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">images</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">│</span><span style="color: #D4D4D4">    </span><span style="color: #CE9178">└──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">labels</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">└──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">val</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #CE9178">├──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">images</span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #CE9178">└──</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">labels</span><span style="color: #D7BA7D">\</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>images</code> 目录下是图片（jpg/png等）</li>



<li><code>labels</code> 目录下是和图片同名的 txt 文件（YOLO 格式标注）</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. 使用 Docker 启动 YOLO 环境并挂载数据集</h2>



<p>在 PowerShell 中运行如下命令，将本地数据集挂载到 Docker 容器内：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker run -it --ipc=host --gpus all `
  -v &quot;E:/机器学习训练集/蓝色黄色小球/boll:/ultralytics/data/boll&quot; `
  ultralytics/ultralytics:latest" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-it</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--ipc=host</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--gpus</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">all</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">`</span></span>
<span class="line"><span style="color: #CE9178">  </span><span style="color: #DCDCAA">-v</span><span style="color: #CE9178"> &quot;E:/机器学习训练集/蓝色黄色小球/boll:/ultralytics/data/boll&quot; `</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">ultralytics/ultralytics:latest</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>-v</code> 参数用于挂载本地目录到容器内部。</li>



<li>挂载后，容器内的数据路径为 <code>/ultralytics/data/boll</code>。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. 准备 data.yaml 配置文件</h2>



<p>在本地 <code>E:/机器学习训练集/蓝色黄色小球/boll/</code> 下新建 <code>data.yaml</code> 文件，内容如下：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="train: /ultralytics/data/boll/train/images
val: /ultralytics/data/boll/val/images

nc: 2
names: ['blue_ball', 'yellow_ball']" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">train</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">/ultralytics/data/boll/train/images</span></span>
<span class="line"><span style="color: #569CD6">val</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">/ultralytics/data/boll/val/images</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">nc</span><span style="color: #D4D4D4">: </span><span style="color: #B5CEA8">2</span></span>
<span class="line"><span style="color: #569CD6">names</span><span style="color: #D4D4D4">: [</span><span style="color: #CE9178">&#39;blue_ball&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;yellow_ball&#39;</span><span style="color: #D4D4D4">]</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>nc</code>：类别数</li>



<li><code>names</code>：类别名称，顺序要和你的标注一致</li>



<li><code>train</code> 和 <code>val</code> 路径要用容器内的挂载路径</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. 在容器里开始训练</h2>



<p>进入容器后，执行以下命令开始训练：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="yolo task=detect mode=train model=yolov8n.pt data=/ultralytics/data/boll/data.yaml epochs=100 imgsz=640" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">yolo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">task=detect</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mode=train</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">model=yolov8n.pt</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">data=/ultralytics/data/boll/data.yaml</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">epochs=</span><span style="color: #B5CEA8">100</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">imgsz=</span><span style="color: #B5CEA8">640</span></span></code></pre></div>



<p>参数说明：</p>



<ul class="wp-block-list">
<li><code>model=yolov8n.pt</code>：使用 YOLOv8 nano 预训练模型</li>



<li><code>data</code>：指向 data.yaml 文件</li>



<li><code>epochs</code>：训练轮数</li>



<li><code>imgsz</code>：输入图片尺寸</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. 查看训练结果</h2>



<p>训练完成后，模型和日志会保存在 <code>/ultralytics/runs/detect/</code> 目录下。</p>



<p>可以通过如下命令查看：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="ls /ultralytics/runs/detect/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">ls</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/ultralytics/runs/detect/</span></span></code></pre></div>



<p>如果需要把结果拷贝回本地，可用 <code>docker cp</code> 命令。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7. 常见问题总结</h2>



<ul class="wp-block-list">
<li><strong>路径中有中文或空格</strong>：建议尽量用英文路径，或确保 Docker Desktop 已授权对应盘符。</li>



<li><strong>labels 格式</strong>：务必是 YOLO 标准格式，类别编号从 0 开始。</li>



<li><strong>挂载后目录为空</strong>：请检查路径拼写和 Docker 权限设置。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8. 参考资料</h2>



<ul class="wp-block-list">
<li><a href="https://docs.ultralytics.com/">Ultralytics YOLO 官方文档</a></li>



<li><a href="https://docs.docker.com/">Docker 官方文档</a></li>



<li></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9. 用命令行直接导出 YOLO 模型为 ONNX</h2>



<p><code>best.pt</code> 路径确保正确：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="yolo export model=/ultralytics/data/boll/train3/weights/best.pt format=onnx" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">yolo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">export</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">model=/ultralytics/data/boll/train3/weights/best.pt</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">format=onnx</span></span></code></pre></div>



<ul class="wp-block-list">
<li><code>model=...</code> 指定你的 .pt 文件路径</li>



<li><code>format=onnx</code> 指定导出格式为 ONNX</li>
</ul>



<p>导出后会在 <code>runs/</code> 目录下生成对应的 ONNX 文件。</p>



<p>还可以加其他参数，比如指定输出路径、导出的输入尺寸等：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="yolo export model=/ultralytics/data/boll/train3/weights/best.pt format=onnx imgsz=640" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">yolo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">export</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">model=/ultralytics/data/boll/train3/weights/best.pt</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">format=onnx</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">imgsz=</span><span style="color: #B5CEA8">640</span></span></code></pre></div>



<p>更多参数可以用 <code>yolo export --help</code> 查看。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.mutadecheng.com/2025/12/18/%e4%bd%bf%e7%94%a8-docker-%e5%92%8c-ultralytics-yolov8-%e8%ae%ad%e7%bb%83%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9b%ae%e6%a0%87%e6%a3%80%e6%b5%8b%e6%a8%a1%e5%9e%8b%e5%85%a8%e6%b5%81%e7%a8%8b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>在 Docker Compose 中实现容器到宿主机通信——host.docker.internal 与 host-gateway 的实战指南</title>
		<link>https://blog.mutadecheng.com/2025/12/16/%e5%9c%a8-docker-compose-%e4%b8%ad%e5%ae%9e%e7%8e%b0%e5%ae%b9%e5%99%a8%e5%88%b0%e5%ae%bf%e4%b8%bb%e6%9c%ba%e9%80%9a%e4%bf%a1-host-docker-internal-%e4%b8%8e-host-gateway-%e7%9a%84/</link>
					<comments>https://blog.mutadecheng.com/2025/12/16/%e5%9c%a8-docker-compose-%e4%b8%ad%e5%ae%9e%e7%8e%b0%e5%ae%b9%e5%99%a8%e5%88%b0%e5%ae%bf%e4%b8%bb%e6%9c%ba%e9%80%9a%e4%bf%a1-host-docker-internal-%e4%b8%8e-host-gateway-%e7%9a%84/#respond</comments>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Tue, 16 Dec 2025 03:28:47 +0000</pubDate>
				<category><![CDATA[Docker]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=464</guid>

					<description><![CDATA[一、前言 在容器化开发过程中，常常遇到容器需要访问宿主机上的服务，比如数据库、API 或其他本地应用。对于 m [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">一、前言</h2>



<p>在容器化开发过程中，常常遇到容器需要访问宿主机上的服务，比如数据库、API 或其他本地应用。对于 macOS 和 Windows 用户来说，Docker 官方提供了 host.docker.internal 这个 DNS 名称，方便容器自动识别宿主机。然而，Linux 用户则需要额外配置。自 Docker 20.10 起，host-gateway 关键字极大简化了这一过程。本篇将详细介绍如何在 Docker Compose 中实现容器访问宿主机的最佳实践，并结合实战案例帮助理解。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">二、容器访问宿主机的常见方式</h2>



<p>在 Linux 环境下，容器默认无法通过 host.docker.internal 访问宿主机上的服务。常见的几种做法包括：</p>



<ul class="wp-block-list">
<li><strong>手动指定宿主机 IP</strong>：在 extra_hosts 或命令行中写死宿主机 IP，缺点是 IP 可能变化，维护不便。</li>



<li><strong>使用 network_mode: host</strong>：容器与宿主机共享网络栈，虽然简单，但会牺牲隔离性，且端口暴露风险增加。</li>



<li><strong>利用 host-gateway</strong>：结合 Docker 20.10+ 的新特性，自动将 host.docker.internal 映射到宿主机网关 IP，推荐使用。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">三、Docker 命令行与 Compose 的实现方式</h2>



<h3 class="wp-block-heading">1. 命令行方式</h3>



<p>直接运行容器时，可以用如下参数：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker run \
  --add-host=host.docker.internal:host-gateway \
  <其他参数&gt; \
  <镜像名&gt;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">docker</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">run</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">--add-host=host.docker.internal:host-gateway</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;</span><span style="color: #CE9178">其他参</span><span style="color: #D4D4D4">数&gt; </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;</span><span style="color: #CE9178">镜像</span><span style="color: #D4D4D4">名&gt;</span></span></code></pre></div>



<p>这样容器内部的 <code>/etc/hosts</code> 会新增一条，把 <code>host.docker.internal</code> 指向宿主机网关 IP。</p>



<h3 class="wp-block-heading">2. Docker Compose 配置</h3>



<p>在 Compose 文件中，使用 <code>extra_hosts</code> 字段实现同样功能：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.9'
services:
  app:
    image: <镜像名&gt;
    extra_hosts:
      - &quot;host.docker.internal:host-gateway&quot;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.9&#39;</span></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">app</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&lt;镜像名&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">extra_hosts</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;host.docker.internal:host-gateway&quot;</span></span></code></pre></div>



<p>Compose 会自动查找 bridge 网络的网关地址，并注入到容器 hosts 文件中，跨平台兼容性极强。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">四、实战案例：容器访问宿主机 HTTP 服务</h2>



<h3 class="wp-block-heading">1. 宿主机启动 HTTP 服务</h3>



<p>在宿主机上运行如下 Python 命令：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="python3 -m http.server 8080" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">python3</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-m</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">http.server</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8080</span></span></code></pre></div>



<p>确保服务监听在 <code>0.0.0.0</code>，方便容器访问。</p>



<h3 class="wp-block-heading">2. 编写 docker-compose.yml</h3>



<p>创建如下 Compose 文件，实现容器内 curl 访问宿主机服务：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="version: '3.9'
services:
  curltest:
    image: curlimages/curl
    command: [&quot;curl&quot;, &quot;http://host.docker.internal:8080&quot;]
    extra_hosts:
      - &quot;host.docker.internal:host-gateway&quot;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">version</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">&#39;3.9&#39;</span></span>
<span class="line"><span style="color: #569CD6">services</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">curltest</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">image</span><span style="color: #D4D4D4">: </span><span style="color: #CE9178">curlimages/curl</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">command</span><span style="color: #D4D4D4">: [</span><span style="color: #CE9178">&quot;curl&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;http://host.docker.internal:8080&quot;</span><span style="color: #D4D4D4">]</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">extra_hosts</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">      - </span><span style="color: #CE9178">&quot;host.docker.internal:host-gateway&quot;</span></span></code></pre></div>



<h3 class="wp-block-heading">3. 启动并验证</h3>



<p>执行：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker-compose up" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">docker-compose</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">up</span></span></code></pre></div>



<p>如能看到 HTTP 服务返回内容，说明配置成功。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">五、常见问题与排查技巧</h2>



<h3 class="wp-block-heading">1. host-gateway 报错</h3>



<ul class="wp-block-list">
<li>报错信息：<code>invalid IP address in add-host: host-gateway</code></li>



<li>原因：Docker 版本过低。请升级至 20.10 或以上。</li>
</ul>



<h3 class="wp-block-heading">2. 无法访问宿主机服务</h3>



<ul class="wp-block-list">
<li>检查服务监听地址必须为 <code>0.0.0.0</code>，否则只在本地回环可用。</li>



<li>查看防火墙设置是否允许 Docker 网络访问指定端口。</li>



<li>确认 Compose 文件 <code>extra_hosts</code> 配置无误。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">六、适用场景与注意事项</h2>



<h3 class="wp-block-heading">适用场景</h3>



<ul class="wp-block-list">
<li>容器需要调用本地数据库或 API</li>



<li>开发环境下调试本地服务</li>



<li>跨平台项目需要兼容性配置</li>
</ul>



<h3 class="wp-block-heading">不推荐做法</h3>



<ul class="wp-block-list">
<li>使用 <code>network_mode: host</code>，丧失网络隔离</li>



<li>手动硬编码宿主机 IP，难以维护</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">七、结语</h2>



<p>通过 <code>extra_hosts</code> 配合 <code>host-gateway</code>，Docker Compose 能方便地实现容器到宿主机的通信，无需关心平台差异，配置简洁且易于迁移。无论是本地开发还是自动化测试，这一技巧都能显著提升开发效率与体验。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><strong>参考资料</strong></p>



<ul class="wp-block-list">
<li><a href="https://docs.docker.com/network/host/">Docker 官方文档</a></li>



<li><a href="https://docs.docker.com/compose/compose-file/compose-versioning/">Docker Compose 说明</a></li>



<li><a href="https://github.com/docker/cli/pull/2664">host-gateway 介绍</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.mutadecheng.com/2025/12/16/%e5%9c%a8-docker-compose-%e4%b8%ad%e5%ae%9e%e7%8e%b0%e5%ae%b9%e5%99%a8%e5%88%b0%e5%ae%bf%e4%b8%bb%e6%9c%ba%e9%80%9a%e4%bf%a1-host-docker-internal-%e4%b8%8e-host-gateway-%e7%9a%84/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Linux ARM串口测试常见命令详解</title>
		<link>https://blog.mutadecheng.com/2025/12/09/linux-arm%e4%b8%b2%e5%8f%a3%e6%b5%8b%e8%af%95%e5%b8%b8%e8%a7%81%e5%91%bd%e4%bb%a4%e8%af%a6%e8%a7%a3/</link>
					<comments>https://blog.mutadecheng.com/2025/12/09/linux-arm%e4%b8%b2%e5%8f%a3%e6%b5%8b%e8%af%95%e5%b8%b8%e8%a7%81%e5%91%bd%e4%bb%a4%e8%af%a6%e8%a7%a3/#respond</comments>
		
		<dc:creator><![CDATA[木它]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 07:41:11 +0000</pubDate>
				<category><![CDATA[Arm]]></category>
		<category><![CDATA[linux]]></category>
		<guid isPermaLink="false">https://blog.mutadecheng.com/?p=461</guid>

					<description><![CDATA[在嵌入式开发、单板机调试等场景下，串口（Serial port）是最常见的调试和通信接口之一。本文详细介绍在L [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>在嵌入式开发、单板机调试等场景下，串口（Serial port）是最常见的调试和通信接口之一。本文详细介绍在Linux（尤其是ARM架构）下进行串口测试的常用命令和方法。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">一、串口设备识别</h2>



<p>大多数Linux系统的串口设备节点如下：</p>



<ul class="wp-block-list">
<li>标准串口：<code>/dev/ttyS0</code>, <code>/dev/ttyS1</code> …</li>



<li>USB转串口：<code>/dev/ttyUSB0</code>, <code>/dev/ttyUSB1</code> …</li>



<li>FTDI类芯片：<code>/dev/ttyACM0</code>, <code>/dev/ttyACM1</code> …</li>
</ul>



<h3 class="wp-block-heading">查看串口设备</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="ls /dev/tty*" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">ls</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/tty</span><span style="color: #569CD6">*</span></span></code></pre></div>



<p>插拔USB转串口线后，可以用 <code>dmesg</code> 查看设备挂载情况：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="dmesg | tail -20" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">dmesg</span><span style="color: #D4D4D4"> | </span><span style="color: #DCDCAA">tail</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-20</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">二、串口参数配置</h2>



<h3 class="wp-block-heading">使用 <code>stty</code> 查看和设置串口参数</h3>



<h4 class="wp-block-heading">查看当前参数</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="stty -F /dev/ttyS0 -a" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">stty</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-F</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-a</span></span></code></pre></div>



<h4 class="wp-block-heading">设置波特率、数据位、校验位、停止位</h4>



<p>例如设置为115200 8N1（115200波特率，8数据位，无校验，1停止位）：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="stty -F /dev/ttyS0 speed 115200 cs8 -cstopb -parenb" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">stty</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-F</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">speed</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">115200</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">cs8</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-cstopb</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-parenb</span></span></code></pre></div>



<p>参数说明：</p>



<ul class="wp-block-list">
<li><code>speed 115200</code>：波特率</li>



<li><code>cs8</code>：8数据位</li>



<li><code>-cstopb</code>：1停止位</li>



<li><code>-parenb</code>：无校验</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">三、串口收发测试</h2>



<h3 class="wp-block-heading">1. 使用 <code>echo</code> 和 <code>cat</code> 简单测试</h3>



<p><strong>发送数据：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="echo &quot;hello world&quot; &gt; /dev/ttyS0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;hello world&quot;</span><span style="color: #D4D4D4"> &gt; </span><span style="color: #CE9178">/dev/ttyS0</span></span></code></pre></div>



<p><strong>接收数据：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="cat /dev/ttyS0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">cat</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span></span></code></pre></div>



<h3 class="wp-block-heading">2. 使用 <code>minicom</code> 图形化串口工具</h3>



<h4 class="wp-block-heading">安装</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo apt-get install minicom" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">apt-get</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">install</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">minicom</span></span></code></pre></div>



<h4 class="wp-block-heading">配置并打开串口</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo minicom -s" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">minicom</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-s</span></span></code></pre></div>



<p>进入设置菜单，选择“Serial port setup”进行端口、波特率等参数配置，然后保存并退出。</p>



<h4 class="wp-block-heading">直接打开</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo minicom -D /dev/ttyS0 -b 115200" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">minicom</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-D</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-b</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">115200</span></span></code></pre></div>



<h3 class="wp-block-heading">3. 使用 <code>screen</code> 作为串口终端</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="screen /dev/ttyS0 115200" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">screen</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">115200</span></span></code></pre></div>



<p>退出：同时按下 <code>Ctrl+A</code> 然后按 <code>K</code>，再按 <code>y</code>。</p>



<h3 class="wp-block-heading">4. 使用 <code>picocom</code>（轻量级串口工具）</h3>



<h4 class="wp-block-heading">安装</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo apt-get install picocom" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">apt-get</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">install</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">picocom</span></span></code></pre></div>



<h4 class="wp-block-heading">启动</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo picocom -b 115200 /dev/ttyS0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">picocom</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-b</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">115200</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span></span></code></pre></div>



<p>退出：<code>Ctrl+A</code> 再按 <code>Ctrl+X</code></p>



<h3 class="wp-block-heading">5. 使用 <code>cu</code> 命令</h3>



<h4 class="wp-block-heading">安装</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo apt-get install cu" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">apt-get</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">install</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">cu</span></span></code></pre></div>



<h4 class="wp-block-heading">启动</h4>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sudo cu -l /dev/ttyS0 -s 115200" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">sudo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">cu</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-l</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-s</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">115200</span></span></code></pre></div>



<p>退出：<code>~.</code></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">四、串口数据的十六进制查看</h2>



<p>有时候需要以十六进制方式查看串口数据：</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="cat /dev/ttyS0 | hexdump -C
# 或
cat /dev/ttyS0 | xxd" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">cat</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> | </span><span style="color: #DCDCAA">hexdump</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-C</span></span>
<span class="line"><span style="color: #6A9955"># 或</span></span>
<span class="line"><span style="color: #DCDCAA">cat</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> | </span><span style="color: #DCDCAA">xxd</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">五、常见问题排查</h2>



<ol class="wp-block-list">
<li><strong>权限不足</strong></li>
</ol>



<ul class="wp-block-list">
<li>添加用户到 <code>dialout</code> 组<br><code>bash sudo usermod -a -G dialout $USER</code></li>



<li>重新登录生效</li>
</ul>



<ol class="wp-block-list">
<li><strong>设备不存在</strong></li>
</ol>



<ul class="wp-block-list">
<li>检查驱动是否加载，<code>dmesg</code> 查看内核日志</li>



<li>检查硬件连接</li>
</ul>



<ol class="wp-block-list">
<li><strong>串口占用</strong></li>
</ol>



<ul class="wp-block-list">
<li>用 <code>lsof | grep ttyS0</code> 检查是否有进程占用</li>
</ul>



<ol class="wp-block-list">
<li><strong>收发异常</strong></li>
</ol>



<ul class="wp-block-list">
<li>检查串口参数、交叉线连接、GND是否共地</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">六、实用脚本举例</h2>



<p><strong>循环发送数据：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="while true; do echo &quot;test&quot; &gt; /dev/ttyS0; sleep 1; done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">true</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;test&quot;</span><span style="color: #D4D4D4"> &gt; </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4">; </span><span style="color: #DCDCAA">sleep</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">done</span></span></code></pre></div>



<p><strong>自动收数据并保存：</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="cat /dev/ttyS0 &gt; recv.log" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">cat</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/dev/ttyS0</span><span style="color: #D4D4D4"> &gt; </span><span style="color: #CE9178">recv.log</span></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.mutadecheng.com/2025/12/09/linux-arm%e4%b8%b2%e5%8f%a3%e6%b5%8b%e8%af%95%e5%b8%b8%e8%a7%81%e5%91%bd%e4%bb%a4%e8%af%a6%e8%a7%a3/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
