<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on pemako</title><link>http://pemako.cn/blog/posts/</link><description>Recent content in Posts on pemako</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 09 Apr 2026 20:00:00 +0800</lastBuildDate><atom:link href="http://pemako.cn/blog/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Alpine Linux</title><link>http://pemako.cn/blog/posts/alpine/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/alpine/</guid><description>&lt;p&gt;基于 alpine 打一个 atlantis 运行使用的基础镜像&lt;/p&gt;
&lt;p&gt;docker pull golang:1.19.5-alpine3.17&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改时区
&lt;ul&gt;
&lt;li&gt;apk add &amp;ndash;no-cache tzdata&lt;/li&gt;
&lt;li&gt;cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime&lt;/li&gt;
&lt;li&gt;echo &amp;ldquo;Asia/Shanghai&amp;rdquo; &amp;gt; /etc/timezone&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;添加 chromium 进行浏览器登录获取token使用
&lt;ul&gt;
&lt;li&gt;apk add chromium&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;安装 go 环境
&lt;ul&gt;
&lt;li&gt;apk add binutils go&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Awk</title><link>http://pemako.cn/blog/posts/awk/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/awk/</guid><description>&lt;p&gt;&lt;code&gt;AWK&lt;/code&gt;的工作模式 &lt;code&gt;awk 'Pattern {Action}'&lt;/code&gt; 其中 &lt;code&gt;Pattern&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="常用变量及函数"&gt;
 常用变量及函数
 &lt;a class="anchor" href="#%e5%b8%b8%e7%94%a8%e5%8f%98%e9%87%8f%e5%8f%8a%e5%87%bd%e6%95%b0"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="熟记的变量"&gt;
 熟记的变量
 &lt;a class="anchor" href="#%e7%86%9f%e8%ae%b0%e7%9a%84%e5%8f%98%e9%87%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;h4 id="nf"&gt;
 &lt;code&gt;NF&lt;/code&gt;
 &lt;a class="anchor" href="#nf"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;NF&lt;/code&gt; 最后一个域，&lt;code&gt;$NF&lt;/code&gt;获取最后一个域的值。如下&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;echo {a..d} | awk '{print NF, $NF}'&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;4 d&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="nrfnr"&gt;
 &lt;code&gt;NR/FNR&lt;/code&gt;
 &lt;a class="anchor" href="#nrfnr"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;NR&lt;/code&gt;表示&lt;code&gt;awk&lt;/code&gt;开始执行程序后所读取的数据行数。&lt;code&gt;FNR&lt;/code&gt;与&lt;code&gt;NR&lt;/code&gt;功用类似,不同的是&lt;code&gt;awk&lt;/code&gt;每打开一个新文件,FNR便从0重新累计。如果是一个文件的话，NF和FNR没有区别&lt;/p&gt;
&lt;p&gt;有两个文件格式如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;account&lt;/code&gt;文件&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;张三|000001
李四|000002
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cdr&lt;/code&gt;文件&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;000001|10
000001|20
000002|30
000002|15
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;想要得到的结果如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;张三|000001|10
张三|000001|20
李四|000002|30
李四|000002|15
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="fsofs"&gt;
 &lt;code&gt;FS/OFS&lt;/code&gt;
 &lt;a class="anchor" href="#fsofs"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;FS&lt;/code&gt;输入字段分隔符，默认为空格。&lt;code&gt;OFS&lt;/code&gt;输出字段分隔符，默认为空格。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;echo &amp;quot;1:2:3&amp;quot; | awk 'BEGIN{FS=&amp;quot;:&amp;quot;; OFS=&amp;quot;,&amp;quot;} {print $1, $2, $3}'&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1,2,3&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="rsorsrt"&gt;
 &lt;code&gt;RS/ORS/RT&lt;/code&gt;
 &lt;a class="anchor" href="#rsorsrt"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;RS&lt;/code&gt;输入记录分隔符，默认为换行符。&lt;code&gt;ORS&lt;/code&gt;输出记录的分隔符默认为换行符号。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;➜ cat file
a b:c d
e f:g h
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;下面这命令解释，首先修改了RS的，则上面的file文件中的行会变成下面三行内容。然后后面打印第2列，即输出的结果为&lt;code&gt;b d h&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Bash</title><link>http://pemako.cn/blog/posts/bash/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/bash/</guid><description>&lt;h2 id="bash基础"&gt;
 &lt;code&gt;Bash&lt;/code&gt;基础
 &lt;a class="anchor" href="#bash%e5%9f%ba%e7%a1%80"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="shell与bash"&gt;
 &lt;code&gt;Shell&lt;/code&gt;与&lt;code&gt;Bash&lt;/code&gt;
 &lt;a class="anchor" href="#shell%e4%b8%8ebash"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sh&lt;/code&gt; 是一种标准,&lt;code&gt;bash&lt;/code&gt;是符合这个标准的实现。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;下面的流程是双向的，由于目前markdown中的编辑器不支持双向箭头操作，故先暂时这样。&lt;a href="https://mermaid-js.github.io/mermaid/#/flowchart?id=beta-multi-directional-arrows"&gt;双向箭头&lt;/a&gt;, 同时也不支持&lt;a href="https://mermaid-js.github.io/mermaid/#/flowchart?id=subgraphs"&gt;subgraphs&lt;/a&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;flowchart LR
subgraph User
 用户
end
用户&amp;lt;--&amp;gt;伪终端
用户&amp;lt;--&amp;gt;控制台

subgraph Term
 伪终端&amp;lt;--&amp;gt;shell接收解析执行
 控制台&amp;lt;--&amp;gt;shell接收解析执行
end

shell接收解析执行&amp;lt;--&amp;gt;OS
subgraph Kernel
 OS&amp;lt;--&amp;gt;硬盘I/O
 OS&amp;lt;--&amp;gt;网络I/O
 OS&amp;lt;--&amp;gt;其它操作
end
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;这里上传到github按照图片存储展示&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/imgs/master/public/youdao/mermaid-diagram-20210818111907.png" alt="" /&gt;&lt;/p&gt;
&lt;h4 id="login-bash"&gt;
 &lt;code&gt;Login Bash&lt;/code&gt;
 &lt;a class="anchor" href="#login-bash"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Login Bash&lt;/code&gt;初始化的配置文件分为下面两类&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全局配置
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/etc/profile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;个人配置
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.bash_profile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.bash_login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.profile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="login-sh"&gt;
 &lt;code&gt;Login Sh&lt;/code&gt;
 &lt;a class="anchor" href="#login-sh"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Login Sh&lt;/code&gt;在初始话的时候只会加载下面两个配置文件&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/etc/profile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.profile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查看用户使用的&lt;code&gt;sh&lt;/code&gt;类型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/ect/passwd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;创建用户的时候指定 &lt;code&gt;sh&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useradd -s /bin/bash&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;修改用户的&lt;code&gt;sh&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;usermod, chsh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了统一两种 &lt;code&gt;Bash&lt;/code&gt;的配置，在&lt;code&gt;login bash&lt;/code&gt;里应用&lt;code&gt;interactive bash&lt;/code&gt;的配置&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; -f &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$HOME&lt;span style="color:#e6db74"&gt;/.bashrc&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; source &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$HOME&lt;span style="color:#e6db74"&gt;/.bashrc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="脚本执行顺序"&gt;
 脚本执行顺序
 &lt;a class="anchor" href="#%e8%84%9a%e6%9c%ac%e6%89%a7%e8%a1%8c%e9%a1%ba%e5%ba%8f"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;父&lt;code&gt;shell&lt;/code&gt; &lt;code&gt;Fork&lt;/code&gt; &amp;ndash; &lt;code&gt;Sub-shell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sub-shell&lt;/code&gt; 继承父&lt;code&gt;shell&lt;/code&gt;环境&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sub-shell&lt;/code&gt; 调用指定的解释器执行该脚本&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sub-shell&lt;/code&gt; 退出，相关环境被销毁&lt;/li&gt;
&lt;li&gt;父&lt;code&gt;shell&lt;/code&gt;取得&lt;code&gt;Sub-shell&lt;/code&gt;的退出状态&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="bash命令的解析过程"&gt;
 &lt;code&gt;Bash&lt;/code&gt;命令的解析过程
 &lt;a class="anchor" href="#bash%e5%91%bd%e4%bb%a4%e7%9a%84%e8%a7%a3%e6%9e%90%e8%bf%87%e7%a8%8b"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;命令解析的时候一定按照下面的7个步骤进行执行&lt;/p&gt;</description></item><item><title>Clean Code 笔记</title><link>http://pemako.cn/blog/posts/clean-code/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/clean-code/</guid><description>&lt;p&gt;Code is clean if it can be understood easily – by everyone on the team. Clean code can be read and enhanced by a developer other than its original author. With understandability comes readability, changeability, extensibility and maintainability.&lt;/p&gt;
&lt;p&gt;参考: &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29"&gt;https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="general-rules"&gt;
 General rules &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#general-rules"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#general-rules"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Follow standard conventions.&lt;/li&gt;
&lt;li&gt;Keep it simple stupid. Simpler is always better. Reduce complexity as much as possible.&lt;/li&gt;
&lt;li&gt;Boy scout rule. Leave the campground cleaner than you found it.&lt;/li&gt;
&lt;li&gt;Always find root cause. Always look for the root cause of a problem.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="design-rules"&gt;
 Design rules&lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#design-rules"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#design-rules"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Keep configurable data at high levels.&lt;/li&gt;
&lt;li&gt;Prefer polymorphism to if/else or switch/case.&lt;/li&gt;
&lt;li&gt;Separate multi-threading code.&lt;/li&gt;
&lt;li&gt;Prevent over-configurability.&lt;/li&gt;
&lt;li&gt;Use dependency injection.&lt;/li&gt;
&lt;li&gt;Follow Law of Demeter. A class should know only its direct dependencies.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="understandability-tips"&gt;
 Understandability tips&lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#understandability-tips"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#understandability-tips"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Be consistent. If you do something a certain way, do all similar things in the same way.&lt;/li&gt;
&lt;li&gt;Use explanatory variables.&lt;/li&gt;
&lt;li&gt;Encapsulate boundary conditions. Boundary conditions are hard to keep track of. Put the processing for them in one place.&lt;/li&gt;
&lt;li&gt;Prefer dedicated value objects to primitive type.&lt;/li&gt;
&lt;li&gt;Avoid logical dependency. Don&amp;rsquo;t write methods which works correctly depending on something else in the same class.&lt;/li&gt;
&lt;li&gt;Avoid negative conditionals.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="names-rules"&gt;
 Names rules &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#names-rules"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#names-rules"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Choose descriptive and unambiguous names.&lt;/li&gt;
&lt;li&gt;Make meaningful distinction.&lt;/li&gt;
&lt;li&gt;Use pronounceable names.&lt;/li&gt;
&lt;li&gt;Use searchable names.&lt;/li&gt;
&lt;li&gt;Replace magic numbers with named constants.&lt;/li&gt;
&lt;li&gt;Avoid encodings. Don&amp;rsquo;t append prefixes or type information.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="functions-rules"&gt;
 Functions rules &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#functions-rules"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#functions-rules"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Small.&lt;/li&gt;
&lt;li&gt;Do one thing.&lt;/li&gt;
&lt;li&gt;Use descriptive names.&lt;/li&gt;
&lt;li&gt;Prefer fewer arguments.&lt;/li&gt;
&lt;li&gt;Have no side effects.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t use flag arguments. Split method into several independent methods that can be called from the client without the flag.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="comments-rules"&gt;
 Comments rules &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#comments-rules"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#comments-rules"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Always try to explain yourself in code.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t be redundant.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t add obvious noise.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t use closing brace comments.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t comment out code. Just remove.&lt;/li&gt;
&lt;li&gt;Use as explanation of intent.&lt;/li&gt;
&lt;li&gt;Use as clarification of code.&lt;/li&gt;
&lt;li&gt;Use as warning of consequences.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="source-code-structure"&gt;
 Source code structure &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#source-code-structure"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#source-code-structure"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Separate concepts vertically.&lt;/li&gt;
&lt;li&gt;Related code should appear vertically dense.&lt;/li&gt;
&lt;li&gt;Declare variables close to their usage.&lt;/li&gt;
&lt;li&gt;Dependent functions should be close.&lt;/li&gt;
&lt;li&gt;Similar functions should be close.&lt;/li&gt;
&lt;li&gt;Place functions in the downward direction.&lt;/li&gt;
&lt;li&gt;Keep lines short.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t use horizontal alignment.&lt;/li&gt;
&lt;li&gt;Use white space to associate related things and disassociate weakly related.&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t break indentation.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="objects-and-data-structures"&gt;
 Objects and data structures &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#objects-and-data-structures"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#objects-and-data-structures"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Hide internal structure.&lt;/li&gt;
&lt;li&gt;Prefer data structures.&lt;/li&gt;
&lt;li&gt;Avoid hybrids structures (half object and half data).&lt;/li&gt;
&lt;li&gt;Should be small.&lt;/li&gt;
&lt;li&gt;Do one thing.&lt;/li&gt;
&lt;li&gt;Small number of instance variables.&lt;/li&gt;
&lt;li&gt;Base class should know nothing about their derivatives.&lt;/li&gt;
&lt;li&gt;Better to have many functions than to pass some code into a function to select a behavior.&lt;/li&gt;
&lt;li&gt;Prefer non-static methods to static methods.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="tests"&gt;
 Tests &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#tests"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#tests"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;One assert per test.&lt;/li&gt;
&lt;li&gt;Readable.&lt;/li&gt;
&lt;li&gt;Fast.&lt;/li&gt;
&lt;li&gt;Independent.&lt;/li&gt;
&lt;li&gt;Repeatable.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="code-smells"&gt;
 Code smells &lt;a href="https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29#code-smells"&gt;&lt;/a&gt;
 &lt;a class="anchor" href="#code-smells"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Rigidity. The software is difficult to change. A small change causes a cascade of subsequent changes.&lt;/li&gt;
&lt;li&gt;Fragility. The software breaks in many places due to a single change.&lt;/li&gt;
&lt;li&gt;Immobility. You cannot reuse parts of the code in other projects because of involved risks and high effort.&lt;/li&gt;
&lt;li&gt;Needless Complexity.&lt;/li&gt;
&lt;li&gt;Needless Repetition.&lt;/li&gt;
&lt;li&gt;Opacity. The code is hard to understand.&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>CS 学习工作流</title><link>http://pemako.cn/blog/posts/cs-learning-workflow/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/cs-learning-workflow/</guid><description>&lt;blockquote&gt;
&lt;p&gt;本文由 &lt;a href="http://ksria.com/simpread/"&gt;简悦 SimpRead&lt;/a&gt; 转码， 原文地址 &lt;a href="https://csdiy.wiki/%E5%BF%85%E5%AD%A6%E5%B7%A5%E5%85%B7/workflow/#_10"&gt;csdiy.wiki&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;CS 自学指南&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Contributed by &lt;a href="https://github.com/HardwayLinka"&gt;@HardwayLinka&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;计算机领域的知识覆盖面很广并且更新速度很快，因此保持终身学习的习惯很重要。但在日常开发和学习的过程中，我们获取知识的来源相对复杂且细碎。有成百上千页的文档手册，也有寥寥数语的博客，甚至闲暇时手机上划过的某则新闻和公众号都有可能包含我们感兴趣的知识。因此，如何利用现有的各类工具，形成一套适合自己的学习工作流，将不同来源的知识碎片整合进属于自己的知识库，方便之后的查阅与复习，就显得尤为重要。经过两年工作之余的学习后，我磨合出了以下学习工作流：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/imgs/master/public/2025/202502071745219.png" alt="" /&gt;&lt;/p&gt;
&lt;h2 id="底层核心逻辑"&gt;
 底层核心逻辑
 &lt;a class="anchor" href="#%e5%ba%95%e5%b1%82%e6%a0%b8%e5%bf%83%e9%80%bb%e8%be%91"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;一开始我学习新知识时会参考中文博客，但在代码实践时往往会发现漏洞和 bug。我逐渐意识到我参考的信息可能是错误的，毕竟发博客的门槛低，文章可信度不高，于是我开始查阅一些相关的中文书籍。&lt;/p&gt;
&lt;p&gt;中文书籍的确是比较全面且系统地讲解了知识点，但众所周知，计算机技术更迭迅速，又因为老美在 CS 方面一直都是灯塔，所以一般中文书籍里的内容会滞后于当前最新的知识，导致我跟着中文书籍实践会出现软件版本差异的问题。这时我开始意识到一手信息的重要性，有些中文书籍是翻译英文书籍的，一般翻译一本书也要一两年，这会导致信息传递的延迟，还有就是翻译的过程中信息会有损失。如果一本中文书籍不是翻译的呢，那么它大概率也参考了其他书籍，参考的过程会带有对英文原著中语义理解的偏差。&lt;/p&gt;
&lt;p&gt;于是我就顺其自然地开始翻阅英文书籍。不得不说，英文书籍内容的质量整体是比中文书籍高的。后来随着学习的层层深入，以知识的时效性和完整性出发，我发现 &lt;code&gt;源代码&lt;/code&gt; &amp;gt; &lt;code&gt;官方文档&lt;/code&gt; &amp;gt; &lt;code&gt;英文书籍&lt;/code&gt; &amp;gt; &lt;code&gt;英文博客&lt;/code&gt; &amp;gt; &lt;code&gt;中文博客&lt;/code&gt;，最后我得出了一张 &lt;code&gt;信息损失图&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/imgs/master/public/2025/202502071745221.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;虽然一手信息很重要，但后面的 N 手信息并非一无是处，因为这 N 手资料里包含了作者对源知识的转化——例如基于某种逻辑的梳理（流程图、思维导图等）或是一些自己的理解（对源知识的抽象、类比、延伸到其他知识点），这些转化可以帮助我们更快地掌握和巩固知识的核心内容，就如同初高中学习时使用的辅导书。 此外，学习的过程中和别人的交流十分重要，这些 N 手信息同时起了和其他作者交流的作用，让我们能采百家之长。所以这提示我们学习一个知识点时先尽量选择质量更高的，信息损失较少的信息源，同时不妨参考多个信息源，让自己的理解更加全面准确。&lt;/p&gt;
&lt;p&gt;现实工作生活中的学习很难像学校里一样围绕某个单一知识点由浅入深，经常会在学习过程中涉及到其他知识点，比如一些新的专有名词，一篇没有读过的经典论文，一段未曾接触过的代码等等。这就要求我们勤于思考，刨根究底地 “递归” 学习，给多个知识点之间建立联系。&lt;/p&gt;
&lt;h2 id="选择合适的笔记软件"&gt;
 选择合适的笔记软件
 &lt;a class="anchor" href="#%e9%80%89%e6%8b%a9%e5%90%88%e9%80%82%e7%9a%84%e7%ac%94%e8%ae%b0%e8%bd%af%e4%bb%b6"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;工作流的骨架围绕 &lt;code&gt;单个知识点多参考源，勤于提问给多个知识点之间建立联系&lt;/code&gt; 的底层核心逻辑建立。我们写论文其实就是遵循这个底层逻辑的。论文一般会有脚注去解释一些关键字，并且论文末尾会有多个参考的来源，但是我们平时写笔记会随意得多，因此需要更灵活的方式。&lt;/p&gt;
&lt;p&gt;平时写代码习惯在 IDE 里一键跳转，把相关的函数和实现很好地联系在了一起。你也许会想，如果笔记也能像代码那样可以跳转就好了。现在市面上 &lt;code&gt;双链笔记软件&lt;/code&gt; 就可以很好地解决这一痛点，例如 Roam Research、Logseq、Notion 和 Obsidian。Roam Research 和 Logseq 都是基于大纲结构的笔记软件，而 &lt;code&gt;大纲结构&lt;/code&gt; 是劝退我使用这两款软件的原因。一是 &lt;code&gt;大纲结构&lt;/code&gt; 做笔记容易使文章纵向篇幅太长，二是如果嵌套结构过多会占横向的篇幅。Notion 页面打开慢，弃之。最终我选择了 Obsidian，原因如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Obsidian 基于本地，打开速度快，且可存放很多电子书。我的笔记本是 32g 内存的华硕天选一代，拿来跑 Obsidian 可以快到飞起&lt;/li&gt;
&lt;li&gt;Obsidian 基于 Markdown。这也是一个优势，如果笔记软件写的笔记格式是自家的编码格式，那么不方便其他第三方拓展，也不方便将笔记用其他软件打开，比如 qq 音乐下载歌曲有自己的格式，其他播放器播放不了，这挺恶心人的&lt;/li&gt;
&lt;li&gt;Obsidian 有丰富的插件生态，并且这个生态既大又活跃，即插件数量多，且热门插件的 star 多，开发者会反馈用户 issue，版本会持续迭代。借助这些插件，可以使 Obsidian 达到 &lt;code&gt;all in one&lt;/code&gt; 的效果，即各类知识来源可以统一整合于一处&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="信息的来源"&gt;
 信息的来源
 &lt;a class="anchor" href="#%e4%bf%a1%e6%81%af%e7%9a%84%e6%9d%a5%e6%ba%90"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Obsidian 的插件使其可以支持 pdf 格式，而其本身又支持 Markdown 格式。如果想要 &lt;code&gt;all in one&lt;/code&gt;，那么可以基于这两个格式，将其他格式文件转换为 pdf 或者 Markdown。 那么现在就面临着两个问题：&lt;/p&gt;</description></item><item><title>Docker</title><link>http://pemako.cn/blog/posts/docker/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/docker/</guid><description>&lt;p&gt;使用Mac上进行docker的学习,使用的版本信息如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Client: Docker Engine - Community
 Version: 18.09.2
 API version: 1.39
 Go version: go1.10.8
 Git commit: 6247962
 Built: Sun Feb 10 04:12:39 2019
 OS/Arch: darwin/amd64
 Experimental: false

Server: Docker Engine - Community
 Engine:
 Version: 18.09.2
 API version: 1.39 (minimum version 1.12)
 Go version: go1.10.6
 Git commit: 6247962
 Built: Sun Feb 10 04:13:06 2019
 OS/Arch: linux/amd64
 Experimental: false
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="0环境初始化"&gt;
 0、环境初始化
 &lt;a class="anchor" href="#0%e7%8e%af%e5%a2%83%e5%88%9d%e5%a7%8b%e5%8c%96"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;方式一 &lt;code&gt;brew cask install docker&lt;/code&gt; 这种安装方式不带GUI存命令行操作&lt;/li&gt;
&lt;li&gt;方式二 下载 &lt;a href="https://hub.docker.com/editions/community/docker-ce-desktop-mac"&gt;Docker Desktop for Mac&lt;/a&gt; 带一套可视化软件和Docker环境&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="1docker-的安装和配置"&gt;
 1、Docker 的安装和配置
 &lt;a class="anchor" href="#1docker-%e7%9a%84%e5%ae%89%e8%a3%85%e5%92%8c%e9%85%8d%e7%bd%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="11-在ubuntu中安装"&gt;
 1.1 在Ubuntu中安装
 &lt;a class="anchor" href="#11-%e5%9c%a8ubuntu%e4%b8%ad%e5%ae%89%e8%a3%85"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;检查环境是否支持&lt;/p&gt;</description></item><item><title>Linux 内核</title><link>http://pemako.cn/blog/posts/linux-kernel/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/linux-kernel/</guid><description>&lt;h1 id="深入理解-linux-内核2611--linux-6x-源码结构对照与学习导引"&gt;
 &lt;strong&gt;🧭《深入理解 Linux 内核（2.6.11）》 → Linux 6.x 源码结构对照与学习导引&lt;/strong&gt;
 &lt;a class="anchor" href="#%e6%b7%b1%e5%85%a5%e7%90%86%e8%a7%a3-linux-%e5%86%85%e6%a0%b82611--linux-6x-%e6%ba%90%e7%a0%81%e7%bb%93%e6%9e%84%e5%af%b9%e7%85%a7%e4%b8%8e%e5%ad%a6%e4%b9%a0%e5%af%bc%e5%bc%95"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;hr&gt;
&lt;h2 id="-一系统整体结构"&gt;
 &lt;strong&gt;🧩 一、系统整体结构&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%b8%80%e7%b3%bb%e7%bb%9f%e6%95%b4%e4%bd%93%e7%bb%93%e6%9e%84"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;Linux 2.6 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;Linux 6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;内核入口（启动流程）&lt;/td&gt;
 &lt;td&gt;第 2 章&lt;/td&gt;
 &lt;td&gt;arch/i386/kernel/head.S, init/main.c&lt;/td&gt;
 &lt;td&gt;arch/x86/kernel/head_64.S, init/main.c&lt;/td&gt;
 &lt;td&gt;入口逻辑相似：仍是 start_kernel()，但支持多架构（x86, ARM, RISC-V）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;系统调用入口&lt;/td&gt;
 &lt;td&gt;第 10 章&lt;/td&gt;
 &lt;td&gt;arch/i386/kernel/entry.S, arch/i386/kernel/traps.c&lt;/td&gt;
 &lt;td&gt;arch/x86/entry/entry_64.S, kernel/syscall_table.S&lt;/td&gt;
 &lt;td&gt;系统调用表机制相同，但入口汇编和 syscall wrapper 重写&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;内核初始化流程&lt;/td&gt;
 &lt;td&gt;第 3 章&lt;/td&gt;
 &lt;td&gt;init/main.c&lt;/td&gt;
 &lt;td&gt;init/main.c&lt;/td&gt;
 &lt;td&gt;主干逻辑仍是 start_kernel() → rest_init()&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-二进程与调度process--scheduler"&gt;
 &lt;strong&gt;🧠 二、进程与调度（Process &amp;amp; Scheduler）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%ba%8c%e8%bf%9b%e7%a8%8b%e4%b8%8e%e8%b0%83%e5%ba%a6process--scheduler"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;进程描述符&lt;/td&gt;
 &lt;td&gt;第 3–4 章&lt;/td&gt;
 &lt;td&gt;include/linux/sched.h, kernel/fork.c&lt;/td&gt;
 &lt;td&gt;include/linux/sched.h, kernel/fork.c&lt;/td&gt;
 &lt;td&gt;task_struct 结构仍然存在，字段大幅扩展（多 CPU、NUMA 支持）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;进程创建&lt;/td&gt;
 &lt;td&gt;第 3 章&lt;/td&gt;
 &lt;td&gt;kernel/fork.c&lt;/td&gt;
 &lt;td&gt;kernel/fork.c&lt;/td&gt;
 &lt;td&gt;核心函数仍是 do_fork() / copy_process()&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;进程终止&lt;/td&gt;
 &lt;td&gt;第 3 章&lt;/td&gt;
 &lt;td&gt;kernel/exit.c&lt;/td&gt;
 &lt;td&gt;kernel/exit.c&lt;/td&gt;
 &lt;td&gt;逻辑基本相同&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;调度器&lt;/td&gt;
 &lt;td&gt;第 7 章&lt;/td&gt;
 &lt;td&gt;kernel/sched.c（O(1) 调度器）&lt;/td&gt;
 &lt;td&gt;kernel/sched/core.c, kernel/sched/fair.c（CFS 调度器）&lt;/td&gt;
 &lt;td&gt;📌 &lt;strong&gt;最大差异&lt;/strong&gt;：现代内核使用 CFS（完全公平调度器）取代了 O(1)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;睡眠与唤醒&lt;/td&gt;
 &lt;td&gt;第 7 章&lt;/td&gt;
 &lt;td&gt;kernel/sched.c&lt;/td&gt;
 &lt;td&gt;kernel/sched/core.c&lt;/td&gt;
 &lt;td&gt;同样通过 wait_queue 与 schedule()&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-三内存管理memory-management"&gt;
 &lt;strong&gt;🧮 三、内存管理（Memory Management）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%b8%89%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86memory-management"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;页框分配&lt;/td&gt;
 &lt;td&gt;第 8 章&lt;/td&gt;
 &lt;td&gt;mm/page_alloc.c&lt;/td&gt;
 &lt;td&gt;mm/page_alloc.c&lt;/td&gt;
 &lt;td&gt;概念一致（buddy system），但支持 NUMA / CMA / ZONE_DEVICE&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;虚拟内存管理&lt;/td&gt;
 &lt;td&gt;第 9 章&lt;/td&gt;
 &lt;td&gt;mm/mmap.c, mm/mprotect.c&lt;/td&gt;
 &lt;td&gt;mm/mmap.c, mm/mprotect.c&lt;/td&gt;
 &lt;td&gt;vm_area_struct、mm_struct 概念仍相同&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;页面换出&lt;/td&gt;
 &lt;td&gt;第 15 章&lt;/td&gt;
 &lt;td&gt;mm/vmscan.c&lt;/td&gt;
 &lt;td&gt;mm/vmscan.c&lt;/td&gt;
 &lt;td&gt;逻辑相似但复杂度大幅提升&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Slab 分配器&lt;/td&gt;
 &lt;td&gt;第 8 章&lt;/td&gt;
 &lt;td&gt;mm/slab.c&lt;/td&gt;
 &lt;td&gt;mm/slub.c, mm/slab_common.c&lt;/td&gt;
 &lt;td&gt;默认使用 SLUB（比 Slab 更简洁高效）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-四中断与异常interrupts--exceptions"&gt;
 &lt;strong&gt;🧱 四、中断与异常（Interrupts &amp;amp; Exceptions）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e5%9b%9b%e4%b8%ad%e6%96%ad%e4%b8%8e%e5%bc%82%e5%b8%b8interrupts--exceptions"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;中断描述&lt;/td&gt;
 &lt;td&gt;第 4 章&lt;/td&gt;
 &lt;td&gt;arch/i386/kernel/irq.c, kernel/irq/handle.c&lt;/td&gt;
 &lt;td&gt;kernel/irq/ 下多文件（manage.c, chip.c, spurious.c 等）&lt;/td&gt;
 &lt;td&gt;2.6 时是单文件，现在模块化程度更高&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;中断上下文切换&lt;/td&gt;
 &lt;td&gt;第 4–5 章&lt;/td&gt;
 &lt;td&gt;arch/i386/kernel/entry.S&lt;/td&gt;
 &lt;td&gt;arch/x86/entry/entry_64.S&lt;/td&gt;
 &lt;td&gt;汇编层实现更新为 x86_64 调用约定&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;软中断、tasklet、工作队列&lt;/td&gt;
 &lt;td&gt;第 4–5 章&lt;/td&gt;
 &lt;td&gt;kernel/softirq.c, kernel/workqueue.c&lt;/td&gt;
 &lt;td&gt;kernel/softirq.c, kernel/workqueue.c&lt;/td&gt;
 &lt;td&gt;概念完全保留&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-五文件系统vfs--fs"&gt;
 &lt;strong&gt;💾 五、文件系统（VFS &amp;amp; FS）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%ba%94%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9fvfs--fs"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;虚拟文件系统层（VFS）&lt;/td&gt;
 &lt;td&gt;第 12 章&lt;/td&gt;
 &lt;td&gt;fs/namei.c, fs/open.c, fs/read_write.c&lt;/td&gt;
 &lt;td&gt;fs/namei.c, fs/open.c, fs/read_write.c&lt;/td&gt;
 &lt;td&gt;几乎同名路径，代码更复杂&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;inode / dentry 机制&lt;/td&gt;
 &lt;td&gt;第 12 章&lt;/td&gt;
 &lt;td&gt;fs/inode.c, fs/dcache.c&lt;/td&gt;
 &lt;td&gt;fs/inode.c, fs/dcache.c&lt;/td&gt;
 &lt;td&gt;概念完全相同，接口丰富&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;文件系统注册&lt;/td&gt;
 &lt;td&gt;第 13 章&lt;/td&gt;
 &lt;td&gt;fs/super.c&lt;/td&gt;
 &lt;td&gt;fs/super.c&lt;/td&gt;
 &lt;td&gt;仍然是 register_filesystem()&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Ext2 文件系统&lt;/td&gt;
 &lt;td&gt;第 14 章&lt;/td&gt;
 &lt;td&gt;fs/ext2/&lt;/td&gt;
 &lt;td&gt;fs/ext4/&lt;/td&gt;
 &lt;td&gt;现代系统几乎都使用 ext4 取代 ext2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-六设备驱动与内核模块driver--module"&gt;
 &lt;strong&gt;🔌 六、设备驱动与内核模块（Driver &amp;amp; Module）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e5%85%ad%e8%ae%be%e5%a4%87%e9%a9%b1%e5%8a%a8%e4%b8%8e%e5%86%85%e6%a0%b8%e6%a8%a1%e5%9d%97driver--module"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;模块加载机制&lt;/td&gt;
 &lt;td&gt;第 20 章&lt;/td&gt;
 &lt;td&gt;kernel/module.c&lt;/td&gt;
 &lt;td&gt;kernel/module/（目录化）&lt;/td&gt;
 &lt;td&gt;模块系统大改：支持 LTO、压缩、Rust 模块等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;设备驱动模型&lt;/td&gt;
 &lt;td&gt;第 13 章&lt;/td&gt;
 &lt;td&gt;drivers/base/&lt;/td&gt;
 &lt;td&gt;drivers/base/&lt;/td&gt;
 &lt;td&gt;书中介绍的 kobject/kset/driver model 仍是基础&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;字符设备&lt;/td&gt;
 &lt;td&gt;第 13 章&lt;/td&gt;
 &lt;td&gt;drivers/char/&lt;/td&gt;
 &lt;td&gt;drivers/char/&lt;/td&gt;
 &lt;td&gt;仍可用同样机制注册字符设备&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-七同步机制synchronization"&gt;
 &lt;strong&gt;⚙️ 七、同步机制（Synchronization）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%b8%83%e5%90%8c%e6%ad%a5%e6%9c%ba%e5%88%b6synchronization"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;自旋锁、信号量&lt;/td&gt;
 &lt;td&gt;第 5 章&lt;/td&gt;
 &lt;td&gt;kernel/spinlock.c, kernel/semaphore.c&lt;/td&gt;
 &lt;td&gt;kernel/locking/&lt;/td&gt;
 &lt;td&gt;完全独立成 kernel/locking/ 模块&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;RCU（Read-Copy-Update）&lt;/td&gt;
 &lt;td&gt;第 5 章&lt;/td&gt;
 &lt;td&gt;初步存在&lt;/td&gt;
 &lt;td&gt;kernel/rcu/&lt;/td&gt;
 &lt;td&gt;现代内核的核心机制之一&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;原子操作&lt;/td&gt;
 &lt;td&gt;第 5 章&lt;/td&gt;
 &lt;td&gt;include/asm/atomic.h&lt;/td&gt;
 &lt;td&gt;include/linux/atomic/&lt;/td&gt;
 &lt;td&gt;已高度泛化并支持多架构实现&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-八网络子系统networking"&gt;
 &lt;strong&gt;🌐 八、网络子系统（Networking）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e5%85%ab%e7%bd%91%e7%bb%9c%e5%ad%90%e7%b3%bb%e7%bb%9fnetworking"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;模块&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;书中章节&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;2.6.11 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;6.x 路径&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;网络协议栈&lt;/td&gt;
 &lt;td&gt;第 18–19 章&lt;/td&gt;
 &lt;td&gt;net/ipv4/, net/core/&lt;/td&gt;
 &lt;td&gt;net/ipv4/, net/core/, net/ipv6/&lt;/td&gt;
 &lt;td&gt;路径相同，但功能极大增强（XDP、eBPF）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Socket 实现&lt;/td&gt;
 &lt;td&gt;第 18 章&lt;/td&gt;
 &lt;td&gt;net/socket.c&lt;/td&gt;
 &lt;td&gt;net/socket.c&lt;/td&gt;
 &lt;td&gt;接口一致，内部实现复杂化&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;eBPF&lt;/td&gt;
 &lt;td&gt;无&lt;/td&gt;
 &lt;td&gt;无&lt;/td&gt;
 &lt;td&gt;kernel/bpf/, tools/bpf/&lt;/td&gt;
 &lt;td&gt;⚡ 新增：现代 Linux 内核的重大特性&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-九核心入口函数速览linux-6x-仍保留的经典符号"&gt;
 &lt;strong&gt;🧩 九、核心入口函数速览（Linux 6.x 仍保留的经典符号）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%b9%9d%e6%a0%b8%e5%bf%83%e5%85%a5%e5%8f%a3%e5%87%bd%e6%95%b0%e9%80%9f%e8%a7%88linux-6x-%e4%bb%8d%e4%bf%9d%e7%95%99%e7%9a%84%e7%bb%8f%e5%85%b8%e7%ac%a6%e5%8f%b7"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;功能&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;函数名&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;路径&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;内核启动&lt;/td&gt;
 &lt;td&gt;start_kernel()&lt;/td&gt;
 &lt;td&gt;init/main.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;系统调用&lt;/td&gt;
 &lt;td&gt;sys_* 系列&lt;/td&gt;
 &lt;td&gt;kernel/sys_*.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;进程调度&lt;/td&gt;
 &lt;td&gt;schedule()&lt;/td&gt;
 &lt;td&gt;kernel/sched/core.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;创建进程&lt;/td&gt;
 &lt;td&gt;do_fork(), copy_process()&lt;/td&gt;
 &lt;td&gt;kernel/fork.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;虚拟内存管理&lt;/td&gt;
 &lt;td&gt;do_mmap(), do_munmap()&lt;/td&gt;
 &lt;td&gt;mm/mmap.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;文件打开&lt;/td&gt;
 &lt;td&gt;do_sys_openat2()&lt;/td&gt;
 &lt;td&gt;fs/open.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;读写文件&lt;/td&gt;
 &lt;td&gt;vfs_read(), vfs_write()&lt;/td&gt;
 &lt;td&gt;fs/read_write.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-十推荐的现代学习路线图结合你的环境"&gt;
 &lt;strong&gt;🧭 十、推荐的现代学习路线图（结合你的环境）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e5%8d%81%e6%8e%a8%e8%8d%90%e7%9a%84%e7%8e%b0%e4%bb%a3%e5%ad%a6%e4%b9%a0%e8%b7%af%e7%ba%bf%e5%9b%be%e7%bb%93%e5%90%88%e4%bd%a0%e7%9a%84%e7%8e%af%e5%a2%83"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;阶段&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;内容&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;对应实践&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;阶段 1：结构导览&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;通读 ULK 前 3 章 + 对照 init/, kernel/, arch/x86/&lt;/td&gt;
 &lt;td&gt;阅读 init/main.c 中的 start_kernel()&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;阶段 2：进程调度与内存&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;对照书中第 3–9 章&lt;/td&gt;
 &lt;td&gt;阅读 kernel/sched/ 与 mm/page_alloc.c&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;阶段 3：VFS 与系统调用&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;书中第 10–14 章&lt;/td&gt;
 &lt;td&gt;对照 fs/ 与 arch/x86/entry/&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;阶段 4：同步与驱动模型&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;书中第 5、20 章&lt;/td&gt;
 &lt;td&gt;查看 kernel/locking/, drivers/base/&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;阶段 5：现代特性探索&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;eBPF、io_uring、cgroups、namespaces&lt;/td&gt;
 &lt;td&gt;阅读 kernel/bpf/, fs/io_uring.c, kernel/cgroup/&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-总结"&gt;
 &lt;strong&gt;✅ 总结&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e6%80%bb%e7%bb%93"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;你完全可以用 &lt;strong&gt;Linux 6.x + OrbStack&lt;/strong&gt; 学《深入理解 Linux 内核》。&lt;/p&gt;</description></item><item><title>Linux 基础</title><link>http://pemako.cn/blog/posts/linux-basics/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/linux-basics/</guid><description>&lt;p&gt;GUI (Graphical User Interface) 图形用户界面。用户界面的所有元素图形化，主要使用鼠标作为输入工具，点击图标执行程序，使用按钮、菜单、对话等尽心个交互，追求医用，看起来比较美&lt;/p&gt;
&lt;p&gt;CLI (Command Line Interface) 命令行界面。用户界面字符化，使用键盘作为输入工具，输入命令、选项、参数执行程序，追求高效，看起来比较酷&lt;/p&gt;
&lt;h2 id="缩写习惯"&gt;
 缩写习惯
 &lt;a class="anchor" href="#%e7%bc%a9%e5%86%99%e4%b9%a0%e6%83%af"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="1-最常见的缩写取每个单词的首字母"&gt;
 1. 最常见的缩写，取每个单词的首字母
 &lt;a class="anchor" href="#1-%e6%9c%80%e5%b8%b8%e8%a7%81%e7%9a%84%e7%bc%a9%e5%86%99%e5%8f%96%e6%af%8f%e4%b8%aa%e5%8d%95%e8%af%8d%e7%9a%84%e9%a6%96%e5%ad%97%e6%af%8d"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt; &lt;code&gt;Change Directory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dd&lt;/code&gt; &lt;code&gt;Disk Dump&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;df&lt;/code&gt; &lt;code&gt;Disk Free&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;du&lt;/code&gt; &lt;code&gt;Disk Usage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pwd&lt;/code&gt; &lt;code&gt;Print Working Directory&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ps&lt;/code&gt; &lt;code&gt;Processes Status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PS&lt;/code&gt; &lt;code&gt;Prompt Strings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;su&lt;/code&gt; &lt;code&gt;Substitute User&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rc&lt;/code&gt; &lt;code&gt;Run Command&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Tcl&lt;/code&gt; &lt;code&gt;Tool Command Language&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cups&lt;/code&gt; &lt;code&gt;Common Unix Printing System&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apt&lt;/code&gt; &lt;code&gt;Advanced Package Tool&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bg&lt;/code&gt; &lt;code&gt;BackGround&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ping&lt;/code&gt; &lt;code&gt;Packet InterNet Grouper&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-如果首字母后为h通常保留"&gt;
 2. 如果首字母后为&lt;code&gt;h&lt;/code&gt;,通常保留
 &lt;a class="anchor" href="#2-%e5%a6%82%e6%9e%9c%e9%a6%96%e5%ad%97%e6%af%8d%e5%90%8e%e4%b8%bah%e9%80%9a%e5%b8%b8%e4%bf%9d%e7%95%99"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;chsh&lt;/code&gt; &lt;code&gt;CHange SHell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chmod&lt;/code&gt; &lt;code&gt;CHange MODe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chown&lt;/code&gt; &lt;code&gt;CHange OWNer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chgrp&lt;/code&gt; &lt;code&gt;CHange GRouP&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bash&lt;/code&gt; &lt;code&gt;Bourne Again Shell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zsh&lt;/code&gt; &lt;code&gt;Z SHell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ksh&lt;/code&gt; &lt;code&gt;Korn SHell&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssh&lt;/code&gt; &lt;code&gt;Secure SHell&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-递归缩写类"&gt;
 3. 递归缩写类
 &lt;a class="anchor" href="#3-%e9%80%92%e5%bd%92%e7%bc%a9%e5%86%99%e7%b1%bb"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GNU&lt;/code&gt; &lt;code&gt;GUN's Not Unix&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PHP&lt;/code&gt; &lt;code&gt;PHP; Hypertext Pregrocessor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RPM&lt;/code&gt; &lt;code&gt;RPM Package Manager&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WINE&lt;/code&gt; &lt;code&gt;WINE Is Not an Emulator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PNG&lt;/code&gt; &lt;code&gt;PNG's Not GIF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nano&lt;/code&gt; &lt;code&gt;Nano's ANOther editor&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="4-如果只有一个单词通常取每个音节的首字母"&gt;
 4. 如果只有一个单词，通常取每个音节的首字母
 &lt;a class="anchor" href="#4-%e5%a6%82%e6%9e%9c%e5%8f%aa%e6%9c%89%e4%b8%80%e4%b8%aa%e5%8d%95%e8%af%8d%e9%80%9a%e5%b8%b8%e5%8f%96%e6%af%8f%e4%b8%aa%e9%9f%b3%e8%8a%82%e7%9a%84%e9%a6%96%e5%ad%97%e6%af%8d"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cp&lt;/code&gt; &lt;code&gt;CoPy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ln&lt;/code&gt; &lt;code&gt;LiNk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ls&lt;/code&gt; &lt;code&gt;LiSt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mv&lt;/code&gt; &lt;code&gt;MoVe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rm&lt;/code&gt; &lt;code&gt;ReMove&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="5-对于目录通常使用前几个字母作为缩写"&gt;
 5. 对于目录，通常使用前几个字母作为缩写
 &lt;a class="anchor" href="#5-%e5%af%b9%e4%ba%8e%e7%9b%ae%e5%bd%95%e9%80%9a%e5%b8%b8%e4%bd%bf%e7%94%a8%e5%89%8d%e5%87%a0%e4%b8%aa%e5%ad%97%e6%af%8d%e4%bd%9c%e4%b8%ba%e7%bc%a9%e5%86%99"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bin&lt;/code&gt; &lt;code&gt;BINaries&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev&lt;/code&gt; &lt;code&gt;DEVices&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;etc&lt;/code&gt; &lt;code&gt;ETCetera&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lib&lt;/code&gt; &lt;code&gt;LIBrary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;var&lt;/code&gt; &lt;code&gt;VARiable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;proc&lt;/code&gt; &lt;code&gt;PROCesses&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sbin&lt;/code&gt; &lt;code&gt;Superuser BINaries&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tmp&lt;/code&gt; &lt;code&gt;TemPorary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;usr&lt;/code&gt; &lt;code&gt;Unix Shared Resources&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;diff&lt;/code&gt; &lt;code&gt;DIFFerences&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cal&lt;/code&gt; &lt;code&gt;CALendar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cat&lt;/code&gt; &lt;code&gt;CATenate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ed&lt;/code&gt; &lt;code&gt;EDitor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exec&lt;/code&gt; &lt;code&gt;EXECute&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tab&lt;/code&gt; &lt;code&gt;TABle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;regexp&lt;/code&gt; &lt;code&gt;REGular EXPression&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="6-如果某种缩写比较深入人心例如mesg代表message在新的复合缩写中将沿用这种缩写方式"&gt;
 6. 如果某种缩写比较深入人心，例如&amp;quot;mesg&amp;quot;代表&amp;quot;message&amp;quot;，在新的复合缩写中，将沿用这种缩写方式
 &lt;a class="anchor" href="#6-%e5%a6%82%e6%9e%9c%e6%9f%90%e7%a7%8d%e7%bc%a9%e5%86%99%e6%af%94%e8%be%83%e6%b7%b1%e5%85%a5%e4%ba%ba%e5%bf%83%e4%be%8b%e5%a6%82mesg%e4%bb%a3%e8%a1%a8message%e5%9c%a8%e6%96%b0%e7%9a%84%e5%a4%8d%e5%90%88%e7%bc%a9%e5%86%99%e4%b8%ad%e5%b0%86%e6%b2%bf%e7%94%a8%e8%bf%99%e7%a7%8d%e7%bc%a9%e5%86%99%e6%96%b9%e5%bc%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dmesg&lt;/code&gt; &lt;code&gt;Diagnostic MESsaGe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sed&lt;/code&gt; &lt;code&gt;Stream EDitor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stty&lt;/code&gt; &lt;code&gt;Set TTY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fstab&lt;/code&gt; &lt;code&gt;FileSystem TABle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;passwd&lt;/code&gt; &lt;code&gt;PASSWorD&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="7-有些缩写中第一个字母g代表gnu"&gt;
 7. 有些缩写中，第一个字母&amp;rsquo;g&amp;rsquo;，代表&amp;rsquo;GNU'
 &lt;a class="anchor" href="#7-%e6%9c%89%e4%ba%9b%e7%bc%a9%e5%86%99%e4%b8%ad%e7%ac%ac%e4%b8%80%e4%b8%aa%e5%ad%97%e6%af%8dg%e4%bb%a3%e8%a1%a8gnu"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;awk&lt;/code&gt; &lt;code&gt;Aho Weiberger and Kernighan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gawk&lt;/code&gt; &lt;code&gt;GNU AWK&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpg&lt;/code&gt; &lt;code&gt;GNU Privacy Guard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;/code&gt; &lt;code&gt;GNU Regular Expression Print&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;egrep&lt;/code&gt; &lt;code&gt;Extended GREP&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="命令选项从a到z"&gt;
 命令选项，从a到z
 &lt;a class="anchor" href="#%e5%91%bd%e4%bb%a4%e9%80%89%e9%a1%b9%e4%bb%8ea%e5%88%b0z"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;a
&lt;ul&gt;
&lt;li&gt;all: 全部，所有（ls, uname, lsattr）&lt;/li&gt;
&lt;li&gt;archive: 存储(cp, rsync)&lt;/li&gt;
&lt;li&gt;append: 附加 (tar -A , 7z)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;b
&lt;ul&gt;
&lt;li&gt;blocksize: 块大小，带参数 (du , df)&lt;/li&gt;
&lt;li&gt;batch: 批处理模式 (交互模式的程序通常拥有此选项，如 top -b)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;c
&lt;ul&gt;
&lt;li&gt;commands : 执行命令，带参数 (bash , ksh , python)&lt;/li&gt;
&lt;li&gt;create : 创建 (tar)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;d
&lt;ul&gt;
&lt;li&gt;debug : 调试&lt;/li&gt;
&lt;li&gt;delete : 删除&lt;/li&gt;
&lt;li&gt;directory : 目录 (ls)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;e
&lt;ul&gt;
&lt;li&gt;execute : 执行，带参数 (xterm , perl)&lt;/li&gt;
&lt;li&gt;edit : 编辑&lt;/li&gt;
&lt;li&gt;exclude : 排除&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;f
&lt;ul&gt;
&lt;li&gt;force : 强制，不经确认(cp , rm ,mv)&lt;/li&gt;
&lt;li&gt;file : 文件，带参数 (tar)&lt;/li&gt;
&lt;li&gt;configuration file : 指定配置文件(有些守护进程拥有此选项，如 ssh , lighttpd)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;g&lt;/li&gt;
&lt;li&gt;h
&lt;ul&gt;
&lt;li&gt;&amp;ndash;help : 帮助&lt;/li&gt;
&lt;li&gt;human readable : 人性化显示(ls , du , df)&lt;/li&gt;
&lt;li&gt;headers : 头部&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;i
&lt;ul&gt;
&lt;li&gt;interactive : 交互模式，提示(rm , mv)&lt;/li&gt;
&lt;li&gt;include : 包含&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;k
&lt;ul&gt;
&lt;li&gt;keep : 保留&lt;/li&gt;
&lt;li&gt;kill&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;l
&lt;ul&gt;
&lt;li&gt;long listing format : 长格式(ls)&lt;/li&gt;
&lt;li&gt;list : 列表&lt;/li&gt;
&lt;li&gt;load : 读取 (gcc , emacs)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;m
&lt;ul&gt;
&lt;li&gt;message : 消息 (cvs)&lt;/li&gt;
&lt;li&gt;manual : 手册 (whereis)&lt;/li&gt;
&lt;li&gt;create home : 创建 home 目录 (usermod , useradd)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;n
&lt;ul&gt;
&lt;li&gt;number : 行号、编号 (cat , head , tail , pstree , lspci)&lt;/li&gt;
&lt;li&gt;no : (useradd , make)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;o
&lt;ul&gt;
&lt;li&gt;output : 输出 (cc , sort)&lt;/li&gt;
&lt;li&gt;options : 选项 (mount)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;p
&lt;ul&gt;
&lt;li&gt;port : 端口，带参数 (很多网络工具拥有此选项，如 ssh , lftp )&lt;/li&gt;
&lt;li&gt;protocol : 协议，带参数&lt;/li&gt;
&lt;li&gt;passwd : 密码，带参数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;q
&lt;ul&gt;
&lt;li&gt;quiet : 静默&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;r
&lt;ul&gt;
&lt;li&gt;reverse : 反转&lt;/li&gt;
&lt;li&gt;recursive : 递归 (cp , rm , chmod -R)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;s
&lt;ul&gt;
&lt;li&gt;silent : 安静&lt;/li&gt;
&lt;li&gt;size : 大小，带参数&lt;/li&gt;
&lt;li&gt;subject&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;t
&lt;ul&gt;
&lt;li&gt;tag&lt;/li&gt;
&lt;li&gt;type: 类型（mount）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;u
&lt;ul&gt;
&lt;li&gt;user：用户名、UID、带参数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;v
&lt;ul&gt;
&lt;li&gt;verbose : 冗长&lt;/li&gt;
&lt;li&gt;version : 版本&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;w
&lt;ul&gt;
&lt;li&gt;width : 宽度&lt;/li&gt;
&lt;li&gt;warning : 警告&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;x
&lt;ul&gt;
&lt;li&gt;exclude : 排除 (tar , zip)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;y
&lt;ul&gt;
&lt;li&gt;yes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;z
&lt;ul&gt;
&lt;li&gt;zip : 启用压缩 (bzip , tar , zcat , zip , cvs)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="学会使用man命令"&gt;
 学会使用&lt;code&gt;man&lt;/code&gt;命令
 &lt;a class="anchor" href="#%e5%ad%a6%e4%bc%9a%e4%bd%bf%e7%94%a8man%e5%91%bd%e4%bb%a4"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;下面以 &lt;code&gt;man date&lt;/code&gt; 为例进行说明
&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2022/202212081315728.png" alt="" /&gt;
&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2022/202212081316797.png" alt="" /&gt;&lt;/p&gt;</description></item><item><title>macOS 汇编</title><link>http://pemako.cn/blog/posts/macos-assembly/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/macos-assembly/</guid><description>&lt;h3 id="十进制与二进制的相互转换"&gt;
 十进制与二进制的相互转换
 &lt;a class="anchor" href="#%e5%8d%81%e8%bf%9b%e5%88%b6%e4%b8%8e%e4%ba%8c%e8%bf%9b%e5%88%b6%e7%9a%84%e7%9b%b8%e4%ba%92%e8%bd%ac%e6%8d%a2"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;h4 id="十进制转为二进制分为整数部分和小数部分"&gt;
 十进制转为二进制，分为整数部分和小数部分
 &lt;a class="anchor" href="#%e5%8d%81%e8%bf%9b%e5%88%b6%e8%bd%ac%e4%b8%ba%e4%ba%8c%e8%bf%9b%e5%88%b6%e5%88%86%e4%b8%ba%e6%95%b4%e6%95%b0%e9%83%a8%e5%88%86%e5%92%8c%e5%b0%8f%e6%95%b0%e9%83%a8%e5%88%86"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;整数部分采用除 2 倒取余法: 用2去除十进制整数，可以得到一个商和余数；在用2去除商，又会得到一个商和余数，如此进行，知道商为0时为止，然后把先的到的余数作为二进制的低位有效位，后得到的余数作为二进制数的高位有效位，依次排列起来。&lt;/p&gt;
&lt;p&gt;小数部分采用乘2取整法，具体做法：用2乘十进制小数，可以得到积，将积中的整数部分取出，在用2乘余下的小数部分，又得到一个积，在将积中的整数部分取出，如此进行，直到积中的小数部分为0，此时0或1为二进制的最后一位，或者达到所要求的精度为止，然后把取出的整数部分按顺序排列起来，先取得整数作为二进制小数的最高位有效位，后取的整数作为低位有效位。&lt;/p&gt;
&lt;h4 id="二进制转为十进制"&gt;
 二进制转为十进制
 &lt;a class="anchor" href="#%e4%ba%8c%e8%bf%9b%e5%88%b6%e8%bd%ac%e4%b8%ba%e5%8d%81%e8%bf%9b%e5%88%b6"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;按权相加法&lt;/strong&gt;，即将二进制每位上的数乘以权，然后相加之和即是十进制数&lt;/p&gt;
&lt;h3 id="预备知识"&gt;
 预备知识
 &lt;a class="anchor" href="#%e9%a2%84%e5%a4%87%e7%9f%a5%e8%af%86"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;由于计算机的硬件决定，&lt;strong&gt;任何存储于计算机中的数据，其本质都是以二进制码存储&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;根据冯·诺依曼提出的经典计算机体系结构框架，一台计算机由运算器、控制器、存储器、输入和输出设备组成。其中运算器&lt;strong&gt;只有加法运算器&lt;/strong&gt;，没有减法运算器（据说一开始是有的，后来由于减法运算器硬件开销太大，被废了）。&lt;/p&gt;
&lt;p&gt;所以计算机中没办法直接做减法的，它的减法是通过加法实现的。现实世界中所有的减法也可以当成加法的，减去一个数可以看作加上这个数的相反数，但前提是要先有负数的概念，这就是为什么不得不引入一个符号位。&lt;strong&gt;符号位在内存中存放的最左边一位，如果该位为0，则说明该数为正；若为1，则说明该数为负。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;而且从硬件的角度上看，只有正数加负数才算减法，正数与正数相加，负数与负数相加，其实都可以通过加法器直接相加。&lt;/p&gt;
&lt;p&gt;原码、反码、补码的产生过程就是为了解决计算机做减法和引入符号位的问题。&lt;/p&gt;
&lt;h3 id="原码"&gt;
 原码
 &lt;a class="anchor" href="#%e5%8e%9f%e7%a0%81"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;原码：&lt;strong&gt;是最简单的机器数表示法，用最高位表示符号位，其他位存放该数的二进制的绝对值&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;以带符号位的四位二进制数为例：1010，最高位为1表示这是一个负数，其它三位010，即0&lt;em&gt;2^2+1&lt;/em&gt;2^1+0*2^0=2，所以1010表示十进制数-2。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;正数&lt;/th&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;th&gt;负数&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;0000&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-0&lt;/td&gt;
 &lt;td&gt;1000&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;0001&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-1&lt;/td&gt;
 &lt;td&gt;1001&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;0010&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-2&lt;/td&gt;
 &lt;td&gt;1010&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;0011&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-3&lt;/td&gt;
 &lt;td&gt;1011&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;0100&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-4&lt;/td&gt;
 &lt;td&gt;1100&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;5&lt;/td&gt;
 &lt;td&gt;0101&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-5&lt;/td&gt;
 &lt;td&gt;1101&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;6&lt;/td&gt;
 &lt;td&gt;0110&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-6&lt;/td&gt;
 &lt;td&gt;1110&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;7&lt;/td&gt;
 &lt;td&gt;0111&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;-7&lt;/td&gt;
 &lt;td&gt;1111&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;原码的表示法很简单，虽然出现了+0和-0，但是直观易懂。于是开始运算 &amp;mdash;&lt;/p&gt;</description></item><item><title>MySQL</title><link>http://pemako.cn/blog/posts/mysql/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/mysql/</guid><description>&lt;h1 id="readme"&gt;
 README
 &lt;a class="anchor" href="#readme"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h3 id="导出数据"&gt;
 导出数据
 &lt;a class="anchor" href="#%e5%af%bc%e5%87%ba%e6%95%b0%e6%8d%ae"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;只导出表结构，不导出数据 &lt;code&gt;mysqldump -uroot -pxxx -d database &amp;gt; database.sql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;只导出表数据，不导出结构 &lt;code&gt;mysqldump -uroot -pxxx -t database &amp;gt; database.sql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;导出整个数据库，表结构&amp;amp;数据 &lt;code&gt;mysqldump -uroot -pxxx database &amp;gt; database.sql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;导出整个数据库，忽略&lt;code&gt;table1&lt;/code&gt;&amp;amp; &lt;code&gt;table2&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mysqldump -uroot -pxxx database -ignore-table=database.table1 -ignore-table=database.table2 &amp;gt; database.sql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;导出指定表中的数据 &lt;code&gt;mysqldump -uroot -pxxx -t database table1 table2 &amp;gt; databases.sql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="mysqldump-常用参数说明"&gt;
 mysqldump 常用参数说明
 &lt;a class="anchor" href="#mysqldump-%e5%b8%b8%e7%94%a8%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--host, -h&lt;/code&gt; 需要导出的主机信息&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--port, -P&lt;/code&gt; 链接数据库端口号&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--user, -u&lt;/code&gt; 指定连接的用户名&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--password, -p&lt;/code&gt; 指定链接mysql的密码&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--socket, -S&lt;/code&gt;指定连接 &lt;code&gt;mysql&lt;/code&gt;的&lt;code&gt;socket&lt;/code&gt;文件位置，默认路径为 &lt;code&gt;/tmp/mysql.sock&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--tables&lt;/code&gt; 覆盖 &lt;code&gt;--databases (-B)参数&lt;/code&gt;，指定需要导出的表名&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--no-data, -d&lt;/code&gt;不导出数据，只导出数据库表结构&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--no-create-info, -t&lt;/code&gt; 只导出数据，而不添加&lt;code&gt;CREATE TABLE&lt;/code&gt;语句&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--default-character-set&lt;/code&gt; 设置默认字符集，默认值为 &lt;code&gt;utf8&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="导入数据"&gt;
 导入数据
 &lt;a class="anchor" href="#%e5%af%bc%e5%85%a5%e6%95%b0%e6%8d%ae"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mysql -uroot -pxxx -d databases &amp;lt; database.sql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="mysql查看库表索引大小"&gt;
 MySQL查看库表索引大小
 &lt;a class="anchor" href="#mysql%e6%9f%a5%e7%9c%8b%e5%ba%93%e8%a1%a8%e7%b4%a2%e5%bc%95%e5%a4%a7%e5%b0%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;通过MySQL的 information_schema 数据库，可查询数据库中每个表占用的空间、表记录的行数；该库中有一个 TABLES 表，这个表主要字段分别是：&lt;/p&gt;</description></item><item><title>OpenTelemetry</title><link>http://pemako.cn/blog/posts/opentelemetry/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/opentelemetry/</guid><description>&lt;h1 id="opentelemetry"&gt;
 OpenTelemetry
 &lt;a class="anchor" href="#opentelemetry"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;OpenTelemetry&lt;/code&gt; 简称 &lt;code&gt;&amp;quot;OTel&amp;quot;&lt;/code&gt;, 在 &lt;code&gt;OpenTelemetry&lt;/code&gt; 中典型的 &lt;code&gt;OTel&lt;/code&gt; 方案可以被细分为几个逻辑组件，他们包括 &lt;code&gt;APIs&lt;/code&gt;, &lt;code&gt;SDKs&lt;/code&gt;, 收集器。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;API&lt;/code&gt; 负责收集遥测数据及其中的所有数据&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SDK&lt;/code&gt; 负责将这些数据从当前被观测的进程中提取出来，转给另一个实体进行分析&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Collector&lt;/code&gt; 统一接收 &lt;code&gt;SDK&lt;/code&gt; 从进程中获取到的观测数据。收集器是一个处理遥测数据的 &lt;code&gt;ETL(Extract, Transform, Load)&lt;/code&gt; 管道。
&lt;ul&gt;
&lt;li&gt;接收遥测数据&lt;/li&gt;
&lt;li&gt;处理遥测数据&lt;/li&gt;
&lt;li&gt;导出遥测数据&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在链路追踪和可观测性中，有下面三方面信息&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;链路追踪 &lt;code&gt;Traces&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;指标数据 &lt;code&gt;metrics&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;服务日志 &lt;code&gt;logs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="otel-collector-工作原理"&gt;
 &lt;code&gt;OTel Collector&lt;/code&gt; 工作原理
 &lt;a class="anchor" href="#otel-collector-%e5%b7%a5%e4%bd%9c%e5%8e%9f%e7%90%86"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2024/01/202403011354562.png" alt="20230814203245" /&gt;&lt;/p&gt;
&lt;p&gt;收集器的主要组件包括&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;接收模块 - 从收集器外部接收jj遥测数据（例如: &lt;code&gt;OTLP&lt;/code&gt; 、&lt;code&gt;Kafak&lt;/code&gt; &lt;code&gt;MySQL&lt;/code&gt; &lt;code&gt;syslog&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;处理模块 - 处理或转换数据（例如属性、批次、Kubernetes 属性）&lt;/li&gt;
&lt;li&gt;导出模块 - 将处理后的数据发送到另一个目标（例如：&lt;code&gt;Jaeger&lt;/code&gt; &lt;code&gt;AWS Cloud Watch&lt;/code&gt; &lt;code&gt;Zipkin&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;扩展模块 - 收集器增强功能的插件（例如: &lt;code&gt;HTTP&lt;/code&gt; 转发器）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="progagation--baggage"&gt;
 Progagation &amp;amp; Baggage
 &lt;a class="anchor" href="#progagation--baggage"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;progagation(传播) Baggage(行李)&lt;/code&gt; 为了解决分布式链路追踪。&lt;/p&gt;</description></item><item><title>PostgreSQL</title><link>http://pemako.cn/blog/posts/postgresql/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/postgresql/</guid><description>&lt;h2 id="basic-tutorial"&gt;
 Basic Tutorial
 &lt;a class="anchor" href="#basic-tutorial"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="section-1-querying-data"&gt;
 Section 1. Querying Data
 &lt;a class="anchor" href="#section-1-querying-data"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://neon.com/postgresql/postgresql-tutorial/postgresql-select/" title="PostgreSQL SELECT"&gt;Select&lt;/a&gt; – show you how to query data from a single table.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neon.com/postgresql/postgresql-tutorial/postgresql-column-alias/"&gt;Column aliases&lt;/a&gt; – learn how to assign temporary names to columns or expressions within a query.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neon.com/postgresql/postgresql-tutorial/postgresql-order-by/" title="PostgreSQL ORDER BY"&gt;Order By&lt;/a&gt; – guide you on how to sort the result set returned by a query.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neon.com/postgresql/postgresql-tutorial/postgresql-select-distinct/" title="PostgreSQL SELECT DISTINCT"&gt;Select Distinct&lt;/a&gt; – show you how to remove duplicate rows from the result set.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="section-2-filtering-data"&gt;
 Section 2. Filtering Data
 &lt;a class="anchor" href="#section-2-filtering-data"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://neon.com/postgresql/postgresql-tutorial/postgresql-where/" title="PostgreSQL WHERE"&gt;Where&lt;/a&gt; – filter rows based on a specified condition.&lt;/p&gt;</description></item><item><title>React</title><link>http://pemako.cn/blog/posts/react/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/react/</guid><description>&lt;h2 id="基础知识"&gt;
 基础知识
 &lt;a class="anchor" href="#%e5%9f%ba%e7%a1%80%e7%9f%a5%e8%af%86"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="props"&gt;
 &lt;strong&gt;props&lt;/strong&gt;
 &lt;a class="anchor" href="#props"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;props 是配置组件行为和外观的外部输入，它决定组件渲染什么，但组件不能修改它。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="props-的三个核心含义"&gt;
 &lt;strong&gt;props 的三个核心含义&lt;/strong&gt;
 &lt;a class="anchor" href="#props-%e7%9a%84%e4%b8%89%e4%b8%aa%e6%a0%b8%e5%bf%83%e5%90%ab%e4%b9%89"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;h4 id="1-组件的外部数据输入"&gt;
 &lt;strong&gt;1. 组件的外部数据输入&lt;/strong&gt;
 &lt;a class="anchor" href="#1-%e7%bb%84%e4%bb%b6%e7%9a%84%e5%a4%96%e9%83%a8%e6%95%b0%e6%8d%ae%e8%be%93%e5%85%a5"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;组件不是凭空渲染，它需要“数据”，而 props 就是数据来源。&lt;/p&gt;
&lt;h4 id="2-父组件--子组件的数据流单向数据流"&gt;
 &lt;strong&gt;2. 父组件 → 子组件的数据流（单向数据流）&lt;/strong&gt;
 &lt;a class="anchor" href="#2-%e7%88%b6%e7%bb%84%e4%bb%b6--%e5%ad%90%e7%bb%84%e4%bb%b6%e7%9a%84%e6%95%b0%e6%8d%ae%e6%b5%81%e5%8d%95%e5%90%91%e6%95%b0%e6%8d%ae%e6%b5%81"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;React 明确规定：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据只能从父流向子&lt;/li&gt;
&lt;li&gt;子组件不能直接改 props
这个规则保证了 UI 是可预测的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-组件之间的通信方式父传子"&gt;
 &lt;strong&gt;3. 组件之间的通信方式（父传子）&lt;/strong&gt;
 &lt;a class="anchor" href="#3-%e7%bb%84%e4%bb%b6%e4%b9%8b%e9%97%b4%e7%9a%84%e9%80%9a%e4%bf%a1%e6%96%b9%e5%bc%8f%e7%88%b6%e4%bc%a0%e5%ad%90"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;子组件不直接知道父组件是谁，只知道父组件给它的 props。&lt;/p&gt;
&lt;p&gt;在声明 props 时， &lt;strong&gt;不要忘记 &lt;code&gt;(&lt;/code&gt; 和 &lt;code&gt;)&lt;/code&gt; 之间的一对花括号 &lt;code&gt;{&lt;/code&gt; 和 &lt;code&gt;}&lt;/code&gt;&lt;/strong&gt; ：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;function Avatar({ person, size }) { 

}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;这种语法被称为 &lt;a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Unpacking_fields_from_objects_passed_as_a_function_parameter"&gt;“解构”&lt;/a&gt;，等价于于从函数参数中读取属性：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;function Avatar(props) { 
	let person = props.person; 
	let size = props.size; 
	// ... 
}
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="state"&gt;
 &lt;strong&gt;state&lt;/strong&gt;
 &lt;a class="anchor" href="#state"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;state 是组件&lt;strong&gt;内部可变的&lt;/strong&gt;数据，用来驱动组件的渲染与行为。它由组件自己拥有和管理（或通过 useReducer/外部管理器协调），当 state 变化时 React 会重新渲染该组件（及其子树）。&lt;/p&gt;</description></item><item><title>Sed</title><link>http://pemako.cn/blog/posts/sed/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/sed/</guid><description>&lt;h2 id="重要函数说明"&gt;
 重要函数说明
 &lt;a class="anchor" href="#%e9%87%8d%e8%a6%81%e5%87%bd%e6%95%b0%e8%af%b4%e6%98%8e"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;q&lt;/code&gt; 提前退出命令，不执行后续命令，也不读入后续行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;d&lt;/code&gt; 删除&lt;code&gt;pattern space&lt;/code&gt;(模式空间)中的所有内容，包括换行符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;D&lt;/code&gt; 删除模式空间中的首行，即第一个&lt;code&gt;\n&lt;/code&gt;之前的所有内容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;h&lt;/code&gt; &lt;strong&gt;拷贝&lt;/strong&gt;模式空间中的所有内容到&lt;code&gt;hold space&lt;/code&gt;(交换空间)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;H&lt;/code&gt; &lt;strong&gt;追加&lt;/strong&gt;模式空间中的所有内容到交换空间&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g&lt;/code&gt; &lt;strong&gt;拷贝&lt;/strong&gt;交换空间中的所有内容到模式空间&lt;/li&gt;
&lt;li&gt;&lt;code&gt;G&lt;/code&gt; &lt;strong&gt;追加&lt;/strong&gt;交换空间中的所有内容到模式空间&lt;/li&gt;
&lt;li&gt;&lt;code&gt;n&lt;/code&gt; &lt;strong&gt;读取&lt;/strong&gt;下一个输入行，使用接下来的命令继续对下一行进行处理&lt;/li&gt;
&lt;li&gt;&lt;code&gt;N&lt;/code&gt; &lt;strong&gt;追加&lt;/strong&gt;下一个输入行到当前模式空间，并改变当前行号&lt;/li&gt;
&lt;li&gt;&lt;code&gt;p&lt;/code&gt; 打印当前行所有模式空间中的内容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P&lt;/code&gt; 打印当前行模式空间中的首行，即第一个&lt;code&gt;\n&lt;/code&gt;之前的所有内容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt; 将模式空间和交换空间的内容进行交换&lt;/li&gt;
&lt;li&gt;&lt;code&gt;t label&lt;/code&gt; 如果条件满足，则跳转到标签所在地继续执行，若无标签，则到命令末尾&lt;/li&gt;
&lt;li&gt;&lt;code&gt;b label&lt;/code&gt; 直接跳转到标签所在地继续执行，若无标签，则到命令末尾&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;模式空间和交换空间都属于缓存区&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="模式空间-pattern-space"&gt;
 模式空间 (pattern space)
 &lt;a class="anchor" href="#%e6%a8%a1%e5%bc%8f%e7%a9%ba%e9%97%b4-pattern-space"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;默认情况下 &lt;code&gt;sed&lt;/code&gt; 逐行处理空间&lt;/li&gt;
&lt;li&gt;编辑指令支队该空间生效&lt;/li&gt;
&lt;li&gt;该空间如无&lt;code&gt;d/D&lt;/code&gt;命令，必打印&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="交换空间保持空间-hold-space"&gt;
 交换空间/保持空间 (hold space)
 &lt;a class="anchor" href="#%e4%ba%a4%e6%8d%a2%e7%a9%ba%e9%97%b4%e4%bf%9d%e6%8c%81%e7%a9%ba%e9%97%b4-hold-space"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;按指令进行存取处理&lt;/li&gt;
&lt;li&gt;如需编辑该空间，需交换出去&lt;/li&gt;
&lt;li&gt;如需打印，需交换出去&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="入门例子详解"&gt;
 入门例子详解
 &lt;a class="anchor" href="#%e5%85%a5%e9%97%a8%e4%be%8b%e5%ad%90%e8%af%a6%e8%a7%a3"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;sed&lt;/code&gt;的命令参数有： &lt;code&gt;-n&lt;/code&gt; &lt;code&gt;-i&lt;/code&gt; &lt;code&gt;-e&lt;/code&gt; &lt;code&gt;-r&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;sed&lt;/code&gt;的函数参数有: &lt;code&gt;i&lt;/code&gt; &lt;code&gt;c&lt;/code&gt; &lt;code&gt;a&lt;/code&gt; &lt;code&gt;r&lt;/code&gt; &lt;code&gt;w&lt;/code&gt; &lt;code&gt;y&lt;/code&gt; &lt;code&gt;q&lt;/code&gt; &lt;code&gt;s&lt;/code&gt; &lt;code&gt;n&lt;/code&gt; &lt;code&gt;N&lt;/code&gt; &lt;code&gt;d&lt;/code&gt; &lt;code&gt;D&lt;/code&gt; &lt;code&gt;p&lt;/code&gt; &lt;code&gt;P&lt;/code&gt; &lt;code&gt;h&lt;/code&gt; &lt;code&gt;H&lt;/code&gt; &lt;code&gt;g&lt;/code&gt; &lt;code&gt;G&lt;/code&gt; &lt;code&gt;x&lt;/code&gt; &lt;code&gt;t&lt;/code&gt; &lt;code&gt;b&lt;/code&gt;&lt;/p&gt;</description></item><item><title>XAPK 转 APK 安装</title><link>http://pemako.cn/blog/posts/xapk-to-apk/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/xapk-to-apk/</guid><description>&lt;h1 id="xapk-转-apk-安装到-android-手机"&gt;
 XAPK 转 APK 安装到 Android 手机
 &lt;a class="anchor" href="#xapk-%e8%bd%ac-apk-%e5%ae%89%e8%a3%85%e5%88%b0-android-%e6%89%8b%e6%9c%ba"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;XAPK 是包含主 APK 和 Split APK（语言包、架构包等）的压缩包格式，不能直接用 &lt;code&gt;adb install&lt;/code&gt; 安装，需要解压后用 &lt;code&gt;adb install-multiple&lt;/code&gt; 安装。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="前置条件"&gt;
 前置条件
 &lt;a class="anchor" href="#%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOS 已安装 &lt;code&gt;adb&lt;/code&gt;（Android Debug Bridge）&lt;/li&gt;
&lt;li&gt;手机开启&lt;strong&gt;开发者模式&lt;/strong&gt;并启用 &lt;strong&gt;USB 调试&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;手机通过 USB 连接电脑&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="步骤一确认设备已连接"&gt;
 步骤一：确认设备已连接
 &lt;a class="anchor" href="#%e6%ad%a5%e9%aa%a4%e4%b8%80%e7%a1%ae%e8%ae%a4%e8%ae%be%e5%a4%87%e5%b7%b2%e8%bf%9e%e6%8e%a5"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb devices
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;输出示例：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;List of devices attached
MPX0223213001305 device
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;若显示 &lt;code&gt;unauthorized&lt;/code&gt;，在手机上弹出的「允许 USB 调试」对话框点击&lt;strong&gt;允许&lt;/strong&gt;（建议勾选「始终允许」）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="步骤二解压-xapk"&gt;
 步骤二：解压 XAPK
 &lt;a class="anchor" href="#%e6%ad%a5%e9%aa%a4%e4%ba%8c%e8%a7%a3%e5%8e%8b-xapk"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;XAPK 本质是 ZIP 文件，直接解压即可：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p /tmp/xapk_extracted
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;cd /tmp/xapk_extracted
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;unzip /path/to/your.xapk -d extracted/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;解压后结构示例：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;extracted/
├── com.example.app.apk # 主 APK
├── config.armeabi_v7a.apk # 架构包
├── config.zh.apk # 中文语言包
├── config.en.apk # 英文语言包
├── config.mdpi.apk # 屏幕密度包
├── manifest.json
└── icon.png
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="步骤三确认手机架构"&gt;
 步骤三：确认手机架构
 &lt;a class="anchor" href="#%e6%ad%a5%e9%aa%a4%e4%b8%89%e7%a1%ae%e8%ae%a4%e6%89%8b%e6%9c%ba%e6%9e%b6%e6%9e%84"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb shell getprop ro.product.cpu.abi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;常见输出：&lt;/p&gt;</description></item><item><title>传输层</title><link>http://pemako.cn/blog/posts/transport-layer/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/transport-layer/</guid><description>&lt;h1 id="传输层"&gt;
 传输层
 &lt;a class="anchor" href="#%e4%bc%a0%e8%be%93%e5%b1%82"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;理解传输层原理：复用/分用，可靠数据传输，流量控制，拥塞控制。&lt;/p&gt;
&lt;p&gt;Internet 传输层的实现和示例&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305232249276.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305232256479.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305232256662.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305232258860.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305232259313.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305232302614.png" alt="" /&gt;&lt;/p&gt;</description></item><item><title>位掩码</title><link>http://pemako.cn/blog/posts/bitmask/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/bitmask/</guid><description>&lt;p&gt;位掩码（BitMask）是 “位” (Bit) 和 “掩码” (Mask) 的组合词。“位”指代着二进制数据当中的二进制位，而“掩码”指的是一串用于目标数据进行按位操作的二进制数字。组合起来就是“用一串二进制数字（掩码）去操作另一串二进制数字”的意思。&lt;/p&gt;
&lt;p&gt;掩码就是一串二进制代码对目标字段进行&lt;code&gt;位与&lt;/code&gt;运算，屏蔽当前的输入位，最终得到一个合理的需求。&lt;/p&gt;
&lt;h3 id="场景应用"&gt;
 场景应用
 &lt;a class="anchor" href="#%e5%9c%ba%e6%99%af%e5%ba%94%e7%94%a8"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;h4 id="权限"&gt;
 权限
 &lt;a class="anchor" href="#%e6%9d%83%e9%99%90"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;假设系统中有4中权限: 增删改查，使用位运算来表示权限，定义四个变量如下&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Insert = 1 // 0001
Delete = 2 // 0010
Update = 4 // 0100
Select = 8 // 1000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;假设初始权限为 &lt;code&gt;0000&lt;/code&gt; 如果想给用户增加权限，则使用 &lt;code&gt;|&lt;/code&gt; 或运算&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;给用户增加 Insert 权限 &lt;code&gt;0000 | 0001 = 0001&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;给用户同时增加 Insert 和 Delete 权限 &lt;code&gt;0000 | 0001 | 0010 = 0011&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;此时获取到的 &lt;code&gt;0011&lt;/code&gt; 十进制为 &lt;code&gt;3&lt;/code&gt; 则怎么知道用户拥有哪些权限呢？ 只需要采用 &lt;code&gt;&amp;amp;&lt;/code&gt; 运算&lt;/li&gt;
&lt;li&gt;是否有 Insert 权限 &lt;code&gt;b0011 &amp;amp; b0001 = b0001 = 1&lt;/code&gt; 有权限&lt;/li&gt;
&lt;li&gt;是否有 Delete 权限 &lt;code&gt;b0011 &amp;amp; b0010 = b0010 = 2&lt;/code&gt; 有权限&lt;/li&gt;
&lt;li&gt;是否有 Update 权限 &lt;code&gt;b0011 &amp;amp; b0100 = b0000 = 0&lt;/code&gt; 无权限&lt;/li&gt;
&lt;li&gt;是否有 Select 权限 &lt;code&gt;b0011 &amp;amp; b1000 = b0000 = 0&lt;/code&gt; 无权限&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;删除权限 如用户有 Insert 和 Delete 权限，现在需要删除 Insert 权限&lt;/p&gt;</description></item><item><title>字符编码</title><link>http://pemako.cn/blog/posts/character-encoding/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/character-encoding/</guid><description>&lt;h3 id="1-字节"&gt;
 1. 字节
 &lt;a class="anchor" href="#1-%e5%ad%97%e8%8a%82"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;字节是计算机中存储数据的最小单元，一个字节有 &lt;code&gt;8&lt;/code&gt; 个位（即二进制位，也叫 &lt;code&gt;bit&lt;/code&gt;），也可以表示 &lt;code&gt;0~255&lt;/code&gt; 之间的任何一个数（即二进制的 &lt;code&gt;0000 0000&lt;/code&gt; 到 &lt;code&gt;1111 1111&lt;/code&gt; 之间）。可以用字节表示任何东西，如数字、字符、图像、音乐等，这取决于你如何解释这个字节。&lt;/p&gt;
&lt;h3 id="2-ascii-字符集"&gt;
 2. ASCII 字符集
 &lt;a class="anchor" href="#2-ascii-%e5%ad%97%e7%ac%a6%e9%9b%86"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;在标准 ASCII 码中，用一个字节来表示不同的字符，字节的最高位（也就是二进制代码的左边第一位）被用来做奇偶校验，所以只剩下 7 个位用来表示不同的字符，这样能表示的字符范围就变成了 &lt;code&gt;0～127&lt;/code&gt; 之间。其中 &lt;code&gt;0～31&lt;/code&gt;、&lt;code&gt;127&lt;/code&gt; 这些数值被定义为控制字符，他们是不能显示的。&lt;code&gt;32～126&lt;/code&gt; 这些数值被定义为下面的字符：&lt;/p&gt;
&lt;p&gt;!&amp;quot;#$%&amp;amp;&amp;rsquo;()*+,-./0123456789:;&amp;lt;=&amp;gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy&lt;/p&gt;
&lt;p&gt;如果要在计算机中存储 ASCII 字符串，只需要将这些字符所对应的数值（用来表示字符的数值也叫做码点）按字节依次存放即可，读取的时候也只要按字节依次读出即可。ASCII 字符集无法表示汉字。&lt;/p&gt;
&lt;h3 id="3-latin1-字符集"&gt;
 3. Latin1 字符集
 &lt;a class="anchor" href="#3-latin1-%e5%ad%97%e7%ac%a6%e9%9b%86"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;如果将标准 ASCII 码的最高位不用作奇偶校验，而也用来表示字符的话，那么就可以表示 256 个字符，在 ASCII 的基础上多出了 128 个字符，这个字符集叫做 Latin1 字符集，Latin1 是 ISO-8859-1 的别名，也可写作 Latin-1。其中 0～127 这些数值的定义与 ASCII 字符集一样，128～159 这些数值被定义为控制字符，160～255 这些数值被定义为下面的字符：&lt;/p&gt;
&lt;p&gt;¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ&lt;/p&gt;
&lt;p&gt;如果要在计算机中存储 Latin1 字符串，只需要将这些字符所对应的码点（码点就是字符所对应的数值）按字节依次存放即可，读取的时候也只要按字节依次读出即可。Latin1 字符集无法表示汉字。&lt;/p&gt;
&lt;h3 id="4-ansi-字符集"&gt;
 4. ANSI 字符集
 &lt;a class="anchor" href="#4-ansi-%e5%ad%97%e7%ac%a6%e9%9b%86"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;由于 ASCII 字符集或 Latin1 字符集只能表示有限的字符，对于亚洲字符（例如中文、日文、韩文）则无法表示，所以为了使计算机支持更多语言，出现了 ANSI 字符集，ANSI 字符集中 0～127 这些数值的定义与 ASCII 字符集一样，而 128～255 这些数值被定义为双字节字符的一个编码，即“用其中的 2 个数值来表示 1 个字符”，这样的双字节可以表示的字符数量就达到了 1.6 万多个。&lt;/p&gt;</description></item><item><title>应用层</title><link>http://pemako.cn/blog/posts/application-layer/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/application-layer/</guid><description>&lt;h1 id="应用层"&gt;
 应用层
 &lt;a class="anchor" href="#%e5%ba%94%e7%94%a8%e5%b1%82"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;目标&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;网络应用层的概念和实现
&lt;ul&gt;
&lt;li&gt;客户端-服务器模型&lt;/li&gt;
&lt;li&gt;服务模型&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;通过对常用应用层协议的探讨和分析来学习网络协议&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;深层次目标&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;特定协议
&lt;ul&gt;
&lt;li&gt;http&lt;/li&gt;
&lt;li&gt;ftp&lt;/li&gt;
&lt;li&gt;smtp&lt;/li&gt;
&lt;li&gt;pop&lt;/li&gt;
&lt;li&gt;dns&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="应用程序-和-应用层协议"&gt;
 应用程序 和 应用层协议
 &lt;a class="anchor" href="#%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f-%e5%92%8c-%e5%ba%94%e7%94%a8%e5%b1%82%e5%8d%8f%e8%ae%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;应用程序：&lt;strong&gt;沟通，分布式的进程&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;运行在网络主机的“用户空间”&lt;/li&gt;
&lt;li&gt;在应用程序间交换报文&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;应用层协议&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;应用程序的一个“组成部分”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;定义应用程序需要交换的报文和所需采取的动作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用较低层次所提供的通信服务（TCP， UDP）&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305170032952.png" alt="image-20230517003220736" style="zoom:50%;" /&gt;
&lt;h3 id="一些术语"&gt;
 一些术语
 &lt;a class="anchor" href="#%e4%b8%80%e4%ba%9b%e6%9c%af%e8%af%ad"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;进程（Process）主机中运行的程序
&lt;ul&gt;
&lt;li&gt;在某些主机中，两个进程使用 &lt;strong&gt;进程间通信&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;而运行在不同主机上的进程则使用应用层协议进行通信&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;用户代理（User agent）：软件进程，是介于用户和网络之间的接口
&lt;ul&gt;
&lt;li&gt;实现应用级协议&lt;/li&gt;
&lt;li&gt;Web：浏览器&lt;/li&gt;
&lt;li&gt;E-mail&lt;/li&gt;
&lt;li&gt;流媒体：media player&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="客户端-服务器模式"&gt;
 客户端-服务器模式
 &lt;a class="anchor" href="#%e5%ae%a2%e6%88%b7%e7%ab%af-%e6%9c%8d%e5%8a%a1%e5%99%a8%e6%a8%a1%e5%bc%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;典型的网络应用都是由两个部分组成：客户端和服务器&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户端
&lt;ul&gt;
&lt;li&gt;发起同服务器的联系 speaks first&lt;/li&gt;
&lt;li&gt;一般都从服务器请求服务&lt;/li&gt;
&lt;li&gt;web: 客户端由浏览器实现&lt;/li&gt;
&lt;li&gt;Email: 通过 OE，Foxmail 实现&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;服务器
&lt;ul&gt;
&lt;li&gt;向客户端提供所请求的服务&lt;/li&gt;
&lt;li&gt;e.g. Web 服务器发送被请求的 web 页面，邮件服务器传递 e-mail&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="应用程序接口"&gt;
 应用程序接口
 &lt;a class="anchor" href="#%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e6%8e%a5%e5%8f%a3"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;API：application programming interface&lt;/p&gt;</description></item><item><title>汇编入门</title><link>http://pemako.cn/blog/posts/assembly-intro/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/assembly-intro/</guid><description>&lt;pre tabindex="0"&gt;&lt;code&gt;# exit.s
 .section __TEXT, __text
 .globl _main
_main:
 mov1 $0, %rax
 retq
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="注释"&gt;
 注释
 &lt;a class="anchor" href="#%e6%b3%a8%e9%87%8a"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;程序的第一行是注释。在macOS的&lt;code&gt;as&lt;/code&gt;汇编器语法下，注释由&lt;code&gt;#&lt;/code&gt;开头，在进行汇编的时候会自动将其处理为空白字符。&lt;/p&gt;
&lt;p&gt;我们习惯上将注释写在语句的上方（如例程）或后方，如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;movq $0, %rax # mov 0 to register rax
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="缩进"&gt;
 缩进
 &lt;a class="anchor" href="#%e7%bc%a9%e8%bf%9b"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;在最古老的机器上，汇编代码的文本包含四列：标签、助记符、操作数与注释。汇编器通过识别一个文本在哪个列来判断该文本有什么作用。现代的汇编器已经抛弃了这种方法，采用先进的词法分析技术来判断。但是，我们最好仍然按照这种格式来缩进。&lt;/p&gt;
&lt;h2 id="汇编器指令directive"&gt;
 汇编器指令(Directive)
 &lt;a class="anchor" href="#%e6%b1%87%e7%bc%96%e5%99%a8%e6%8c%87%e4%bb%a4directive"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Directive&amp;quot;是汇编语言中一个重要的组成部分，然而它的中文译名似乎还不固定，这里暂且叫它汇编器指令。在汇编语言中，以&lt;code&gt;.&lt;/code&gt;开头的都是汇编器指令，如例程中的&lt;code&gt;.section&lt;/code&gt;, &lt;code&gt;.globl&lt;/code&gt;等。由汇编器指令开头的语句，一般不会被直接翻译成机器码。汇编器指令并不是告诉汇编器&lt;strong&gt;做什么&lt;/strong&gt;, 而是告诉汇编器&lt;strong&gt;如何做&lt;/strong&gt;。就比如说例程中，&lt;code&gt;movq $0, %rax&lt;/code&gt; 会被汇编器直接翻译为机器码，最终会由CPU直接执行，而&lt;code&gt;.section __TEXT,__text&lt;/code&gt;, 则不会被翻译成机器码，在最终的可执行文件中也不会找到这句话的踪影。它的作用是告诉汇编器如何汇编。下面，就介绍一下&lt;code&gt;.section&lt;/code&gt;的作用&lt;/p&gt;
&lt;h3 id="section"&gt;
 .section
 &lt;a class="anchor" href="#section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;我们之前在&lt;a href="https://zhuanlan.zhihu.com/p/73544165"&gt;操作系统基础&lt;/a&gt;中提到，mach-o可执行文件的Data部分拥有许多段(Segment), 每个段又有许多节(section). 同一个段的作用往往是类似的，同时在执行的时候一个段会被分配到一个页之中。而&lt;code&gt;.section&lt;/code&gt;最常用的格式，就是&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.section segname, sectname
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中&lt;code&gt;segment&lt;/code&gt;是段名，&lt;code&gt;sectname&lt;/code&gt;是节名。我们目前编写的第一个汇编语言程序，只包含纯代码。在macho中，纯代码被放在了&lt;code&gt;__TEXT&lt;/code&gt;段的&lt;code&gt;__text&lt;/code&gt;节中，因此，我们在文件的第二行写了&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;.section __TEXT, __text
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;代表之后的语句都是&lt;code&gt;__TEXT&lt;/code&gt;段的&lt;code&gt;__text&lt;/code&gt;节中。&lt;/p&gt;
&lt;p&gt;此外，由于这个节过于常用，因此，汇编器给予了我们一个简单的记号：&lt;code&gt;.text&lt;/code&gt;. 我们可以直接用&lt;code&gt;.text&lt;/code&gt;代替&lt;code&gt;.section __TEXT, __text&lt;/code&gt;. 在以后的程序中，我也都会用这种记号。&lt;/p&gt;
&lt;p&gt;除了&lt;code&gt;__TEXT&lt;/code&gt;段&lt;code&gt;__text&lt;/code&gt;节后，还有许多段和节。常用的段和节的名称和作用可参见&lt;a href="https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/Assembler/040-Assembler_Directives/asm_directives.html"&gt;Assembler Directives&lt;/a&gt;. 我们之后更复杂的程序中也会用到更多的段和节。&lt;/p&gt;
&lt;h3 id="globl"&gt;
 .globl
 &lt;a class="anchor" href="#globl"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;我们在由汇编语言翻译机器码的时候，得到的文件并不仅仅包含操作的指令，还需要包含一些名字和记号。比如说，C语言中，程序执行的起点是&lt;code&gt;main&lt;/code&gt;函数。那么，这个函数的名字&lt;code&gt;main&lt;/code&gt;就要包含在文件中，使得程序执行的时候知道执行哪个函数。&lt;/p&gt;
&lt;h3 id="_main"&gt;
 _main
 &lt;a class="anchor" href="#_main"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;macOS中，汇编语言程序执行的起点是&lt;code&gt;_main&lt;/code&gt;函数。关于函数与下一行的&lt;code&gt;_main:&lt;/code&gt;标签，我会在之后的文章中提到。是谁决定它叫这个名字的呢，是链接器。如果我们写的程序想把它主函数叫做&lt;code&gt;_start&lt;/code&gt;, 那么只需要在链接的时候写上即可。&lt;/p&gt;</description></item><item><title>汇编语言</title><link>http://pemako.cn/blog/posts/assembly/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/assembly/</guid><description>&lt;h1 id="汇编语言"&gt;
 汇编语言
 &lt;a class="anchor" href="#%e6%b1%87%e7%bc%96%e8%af%ad%e8%a8%80"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="第一章-基础知识"&gt;
 第一章: 基础知识
 &lt;a class="anchor" href="#%e7%ac%ac%e4%b8%80%e7%ab%a0-%e5%9f%ba%e7%a1%80%e7%9f%a5%e8%af%86"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="13-汇编语言的组成"&gt;
 1.3 汇编语言的组成
 &lt;a class="anchor" href="#13-%e6%b1%87%e7%bc%96%e8%af%ad%e8%a8%80%e7%9a%84%e7%bb%84%e6%88%90"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;汇编指令：机器码的助记符，有对应的机器码。&lt;/li&gt;
&lt;li&gt;伪指令：没有对应的机器码，由编译器执行，计算机并不执行。&lt;/li&gt;
&lt;li&gt;其它符号：如 &lt;code&gt;+&lt;/code&gt; &lt;code&gt;-&lt;/code&gt; &lt;code&gt;*&lt;/code&gt; &lt;code&gt;/&lt;/code&gt;等，由编译器识别，没有对应的机器码。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;汇编语言的核心是汇编指令，它决定了汇编语言的特性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="小结11110"&gt;
 小结（1.1~1.10）
 &lt;a class="anchor" href="#%e5%b0%8f%e7%bb%9311110"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;1）. 汇编指令是机器指令的助记符，同机器指令一一对应。
2）. 每一种 CPU 都有自己的汇编指令集。
3）. CPU 可以直接使用的信息在存储器中存放。
4）. 在存储器中指令和数据没有任何区别，都是二进制信息。
5）. 存储单元从零开始顺序编号。
6）. 一个存储单元可以存储 8 个 &lt;code&gt;bit&lt;/code&gt;,即 8 位二进制数。
7）. 1Byte=8bit 1KB=1024B 1MB=1024KB 1GB=1024MB
8）. 每一个 CPU 芯片都有许多管脚，这些管脚和总线相连。也可以说，这些管脚引出总线。一个 CPU 可以引出 3 种总线的宽度标志了这个 CPU 的不同方面的性能&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;地址总线的宽度决定了 CPU 的寻址能力&lt;/li&gt;
&lt;li&gt;数据总线的宽度决定了 CPU 与其它器件进行数据传送时的一次数据传送量&lt;/li&gt;
&lt;li&gt;控制总线的宽度决定了 CPU 对系统中其它器件的控制能力&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="检测点-11"&gt;
 检测点 1.1
 &lt;a class="anchor" href="#%e6%a3%80%e6%b5%8b%e7%82%b9-11"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;（1） 1个CPU的寻址能力为8KB，那么他的地址总线的宽度为【 &lt;strong&gt;13&lt;/strong&gt; 】。
（2） 1KB的存储器有 【 &lt;strong&gt;1024&lt;/strong&gt; 】个存储单元。存储单元编号从【 &lt;strong&gt;0000&lt;/strong&gt; 】到【 &lt;strong&gt;1023&lt;/strong&gt; 】。
（3） 1KB的存储器可以存储【 &lt;strong&gt;1024 x 8&lt;/strong&gt; 】个bit，【 &lt;strong&gt;1024&lt;/strong&gt; 】个Byte。
（4） 1GB、1MB、1KB分别是【&lt;strong&gt;1024x1024x1024、1024x1024、1024&lt;/strong&gt; 】Byte。
（5） 8080、8088、8026、80386的地址总线宽度分别为16根、20根、24根、32根，则他们的寻址能力分别为：【 &lt;strong&gt;64&lt;/strong&gt; 】(KB)、【 &lt;strong&gt;1&lt;/strong&gt; 】(MB)、【 &lt;strong&gt;16&lt;/strong&gt; 】(MB)、【 &lt;strong&gt;4&lt;/strong&gt; 】(GB)。
（6） 8080、8088、8086、8026、80386的数据总线宽度分别为8根、8根、16根、16根、32根。则它们一次可以传送的数据为：【 &lt;strong&gt;1&lt;/strong&gt; 】(B)、【 &lt;strong&gt;1&lt;/strong&gt; 】(B)、【 &lt;strong&gt;2&lt;/strong&gt; 】(B)、【 &lt;strong&gt;2&lt;/strong&gt; 】(B)、【 &lt;strong&gt;4&lt;/strong&gt; 】(B)。&lt;/p&gt;</description></item><item><title>程序基础知识</title><link>http://pemako.cn/blog/posts/program-fundamentals/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/program-fundamentals/</guid><description>&lt;ul&gt;
&lt;li&gt;对称多处理器 (SMP, Symmetrical Multi-Processing)&lt;/li&gt;
&lt;li&gt;多核处理器（Multi-core Processor）&lt;/li&gt;
&lt;li&gt;应用程序接口（Application Programming Interface）&lt;/li&gt;
&lt;li&gt;系统调用接口（System call Interface）&lt;/li&gt;
&lt;li&gt;软件中断（Software Interrupt）&lt;/li&gt;
&lt;li&gt;硬件规格（Hardware Specification）&lt;/li&gt;
&lt;li&gt;多道程序（Multiprogramming）&lt;/li&gt;
&lt;li&gt;分时系统（Time-Sharing System）&lt;/li&gt;
&lt;li&gt;多任务系统（Multi-tasking System）&lt;/li&gt;
&lt;li&gt;进程（Process）&lt;/li&gt;
&lt;li&gt;抢占式（Preemptive）&lt;/li&gt;
&lt;li&gt;硬件驱动（Device Driver）&lt;/li&gt;
&lt;li&gt;扇区（Sector）&lt;/li&gt;
&lt;li&gt;LBA（Logical Block Address）即整个硬盘中所有的扇区从0开始编号，一直到最后一个扇区，这个扇区编号叫做逻辑扇区号。逻辑扇区号抛弃了所有复杂的磁道、盘面之类的概念。&lt;/li&gt;
&lt;li&gt;虚拟地址空间（Virtual Address Space）&lt;/li&gt;
&lt;li&gt;物理地址空间（Physical Address Space）&lt;/li&gt;
&lt;li&gt;分段（Segmentation）基本思路是把一段与程序所需要的内存空间大小的虚拟空间映射到某个地址空间&lt;/li&gt;
&lt;li&gt;分页（Paging）基本方法是把地址空间人为地等分成固定大小的页，每一页的大小由硬件决定，或硬件支持多种大小的页，由操作系统选择决定页的大小。&lt;/li&gt;
&lt;li&gt;虚拟页（VP Virtual Page）&lt;/li&gt;
&lt;li&gt;物理页（PP Physical Page）&lt;/li&gt;
&lt;li&gt;磁盘页（DP Disk Page）&lt;/li&gt;
&lt;li&gt;页错误（Page Fault）&lt;/li&gt;
&lt;li&gt;MMU（Memory Management Unit）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;虚拟地址到物理地址的转换&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR 
	CPU --&amp;gt; |Vitual Address| MMU --&amp;gt; |Physical Address| PhysicalMemory
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;线程（Thread）有时被称为轻量级进程（Lightweight Process, LWP）是程序执行流的最小单元。一个标准的线程由线程 ID、当前指令指针（PC）、寄存器集合和堆栈组成。&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;线程私有&lt;/th&gt;
 &lt;th&gt;线程之间共享 (进程所有)&lt;/th&gt;
 &lt;th&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;局部变量&lt;/td&gt;
 &lt;td&gt;全局变量&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;函数的参数&lt;/td&gt;
 &lt;td&gt;堆上的数据&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;TLS(Thread Local Storage)数据&lt;/td&gt;
 &lt;td&gt;函数里的静态变量&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;程序代码，任何线程都有权利读取病执行任何代码&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;td&gt;打开的文件，A线程打开的文件可以由B线程读写&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在单处理器对应多线程的情况下，并发是一种模拟出来的状态。操作系统会让这些多线程程序轮流执行，每次仅执行一小段时间（通常是几十到几百毫秒），这样每个线程就“看起来”在同时执行。这样的一个不断在处理器上切换不同的线程的行为称之为&lt;strong&gt;线程调度&lt;/strong&gt; （Thread Schedule）。在线程调度中，线程通常拥有至少三种状态&lt;/p&gt;</description></item><item><title>自动化爬虫</title><link>http://pemako.cn/blog/posts/automated-crawler/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/automated-crawler/</guid><description>&lt;h2 id="docker-selenium"&gt;
 &lt;a href="https://github.com/SeleniumHQ/docker-selenium"&gt;docker-selenium&lt;/a&gt;
 &lt;a class="anchor" href="#docker-selenium"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h4 id="启动"&gt;
 启动
 &lt;a class="anchor" href="#%e5%90%af%e5%8a%a8"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;docker run -d -p 4444:4444 -p 7900:7900 --shm-size=&amp;quot;2g&amp;quot; selenium/standalone-chromium:latest&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;暴露 4444 和 7900 端口
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;4444 是&lt;/strong&gt; Selenium WebDriver HTTP API&lt;/li&gt;
&lt;li&gt;7900 vpc 端口
&lt;ul&gt;
&lt;li&gt;默认的密码是 &lt;code&gt;secret&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;启动浏览器 使用下面的浏览器就可以直接启动一个 chrome 在 VNC 中显示&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; selenium &lt;span style="color:#f92672"&gt;import&lt;/span&gt; webdriver
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;from&lt;/span&gt; selenium.webdriver.chrome.options &lt;span style="color:#f92672"&gt;import&lt;/span&gt; Options
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;options &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Options()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;options&lt;span style="color:#f92672"&gt;.&lt;/span&gt;add_argument(&lt;span style="color:#e6db74"&gt;&amp;#34;--start-maximized&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver &lt;span style="color:#f92672"&gt;=&lt;/span&gt; webdriver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;Remote(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; command_executor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;http://localhost:4444&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; options&lt;span style="color:#f92672"&gt;=&lt;/span&gt;options
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;driver&lt;span style="color:#f92672"&gt;.&lt;/span&gt;get(&lt;span style="color:#e6db74"&gt;&amp;#34;https://www.google.com&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="chromedp"&gt;
 chromedp
 &lt;a class="anchor" href="#chromedp"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h2 id="adspowser"&gt;
 AdsPowser
 &lt;a class="anchor" href="#adspowser"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h2 id="profiles"&gt;
 Profiles
 &lt;a class="anchor" href="#profiles"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h2 id="无gui的服务器如何启动-chrome-登录"&gt;
 无GUI的服务器如何启动 chrome 登录
 &lt;a class="anchor" href="#%e6%97%a0gui%e7%9a%84%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%a6%82%e4%bd%95%e5%90%af%e5%8a%a8-chrome-%e7%99%bb%e5%bd%95"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;机器上安装如下 最后主要是通过 noVNC 访问&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo apt install -y &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xvfb &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x11vnc &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xauth &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x11-utils &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chromium-browser &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbus-x11 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; git &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; python3 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; python3-websockify &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; fonts-liberation &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libnss3 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libgbm1 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libgtk-3-0 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libxrandr2 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libxdamage1 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; libdrm2 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; psmisc &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; procps &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; net-tools &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; curl &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; wget
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; ! -d /opt/noVNC &lt;span style="color:#f92672"&gt;]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sudo git clone https://github.com/novnc/noVNC.git /opt/noVNC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo mkdir -p /data/chrome/profile1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo chown -R &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$USER&lt;span style="color:#e6db74"&gt;:&lt;/span&gt;$USER&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; /data/chrome
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;控制启停脚本&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;set -e
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# ENV&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;BASE_DIR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;cd &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;dirname &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$0&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pwd&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# === 基础路径 ===&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PID_DIR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$BASE_DIR&lt;span style="color:#e6db74"&gt;/pids&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LOG_DIR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$BASE_DIR&lt;span style="color:#e6db74"&gt;/logs&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;mkdir -p &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$LOG_DIR&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# === 显示 &amp;amp; 网络 ===&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;export DISPLAY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;:99
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;SCREEN_RESOLUTION&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1280x800x24&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;VNC_PORT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5900&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NOVNC_PORT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;6080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# === Chrome ===&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHROME_BIN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/usr/bin/chromium-browser
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CHROME_PROFILE_DIR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$HOME/Work/chrome/profiles/pemako
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# === noVNC ===&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;NOVNC_DIR&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$HOME/Work/noVNC
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 工具函数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;is_running&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local pidfile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt; -f &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; kill -0 &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;cat &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; 2&amp;gt;/dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;start_bg&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local pidfile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; shift &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; is_running &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;[&lt;/span&gt;$name&lt;span style="color:#e6db74"&gt;] already running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;[&lt;/span&gt;$name&lt;span style="color:#e6db74"&gt;] starting...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$@&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo $! &amp;gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stop_bg&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local pidfile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; is_running &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; kill &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;cat &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -f &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;[&lt;/span&gt;$name&lt;span style="color:#e6db74"&gt;] stopped&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;[&lt;/span&gt;$name&lt;span style="color:#e6db74"&gt;] not running&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;status_bg&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local name&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; local pidfile&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; is_running &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;[&lt;/span&gt;$name&lt;span style="color:#e6db74"&gt;] running (pid &lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;cat &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$pidfile&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;[&lt;/span&gt;$name&lt;span style="color:#e6db74"&gt;] stopped&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Xvfb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xvfb_start&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_bg &lt;span style="color:#e6db74"&gt;&amp;#34;xvfb&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/xvfb.pid&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Xvfb &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$DISPLAY&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -screen &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$SCREEN_RESOLUTION&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$LOG_DIR&lt;span style="color:#e6db74"&gt;/xvfb.log&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xvfb_stop&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop_bg &lt;span style="color:#e6db74"&gt;&amp;#34;xvfb&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/xvfb.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;xvfb_status&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status_bg &lt;span style="color:#e6db74"&gt;&amp;#34;xvfb&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/xvfb.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Chrome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chrome_start&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mkdir -p &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$CHROME_PROFILE_DIR&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_bg &lt;span style="color:#e6db74"&gt;&amp;#34;chrome&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/chrome.pid&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; env DISPLAY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$DISPLAY&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$CHROME_BIN&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --user-data-dir&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$CHROME_PROFILE_DIR&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --no-sandbox &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --disable-dev-shm-usage &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$LOG_DIR&lt;span style="color:#e6db74"&gt;/chrome.log&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chrome_stop&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop_bg &lt;span style="color:#e6db74"&gt;&amp;#34;chrome&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/chrome.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chrome_status&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status_bg &lt;span style="color:#e6db74"&gt;&amp;#34;chrome&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/chrome.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# x11vnc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x11vnc_start&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_bg &lt;span style="color:#e6db74"&gt;&amp;#34;x11vnc&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/x11vnc.pid&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x11vnc &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -display &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$DISPLAY&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -rfbport &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$VNC_PORT&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -forever &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -shared &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -nopw &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$LOG_DIR&lt;span style="color:#e6db74"&gt;/x11vnc.log&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x11vnc_stop&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop_bg &lt;span style="color:#e6db74"&gt;&amp;#34;x11vnc&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/x11vnc.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;x11vnc_status&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status_bg &lt;span style="color:#e6db74"&gt;&amp;#34;x11vnc&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/x11vnc.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# noVNC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;novnc_start&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_bg &lt;span style="color:#e6db74"&gt;&amp;#34;novnc&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/novnc.pid&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$NOVNC_DIR&lt;span style="color:#e6db74"&gt;/utils/novnc_proxy&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --vnc &lt;span style="color:#e6db74"&gt;&amp;#34;localhost:&lt;/span&gt;$VNC_PORT&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; --listen &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$NOVNC_PORT&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$LOG_DIR&lt;span style="color:#e6db74"&gt;/novnc.log&amp;#34;&lt;/span&gt; 2&amp;gt;&amp;amp;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;novnc_stop&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop_bg &lt;span style="color:#e6db74"&gt;&amp;#34;novnc&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/novnc.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;novnc_status&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status_bg &lt;span style="color:#e6db74"&gt;&amp;#34;novnc&amp;#34;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$PID_DIR&lt;span style="color:#e6db74"&gt;/novnc.pid&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 总控&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;start_all&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xvfb_start
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chrome_start
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x11vnc_start
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; novnc_start
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;stop_all&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; novnc_stop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x11vnc_stop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chrome_stop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xvfb_stop
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;status_all&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; xvfb_status
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; chrome_status
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; x11vnc_status
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; novnc_status
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# CLI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;########################&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; in
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; start_all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; stop_all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; status_all
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; *&lt;span style="color:#f92672"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Usage: &lt;/span&gt;$0&lt;span style="color:#e6db74"&gt; {start|stop|status}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exit &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;esac&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>计算机网络</title><link>http://pemako.cn/blog/posts/computer-networks/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/computer-networks/</guid><description>&lt;p&gt;[TOC]&lt;/p&gt;
&lt;h1 id="计算机网络"&gt;
 计算机网络
 &lt;a class="anchor" href="#%e8%ae%a1%e7%ae%97%e6%9c%ba%e7%bd%91%e7%bb%9c"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;h2 id="因特网"&gt;
 因特网
 &lt;a class="anchor" href="#%e5%9b%a0%e7%89%b9%e7%bd%91"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="工程视角"&gt;
 工程视角
 &lt;a class="anchor" href="#%e5%b7%a5%e7%a8%8b%e8%a7%86%e8%a7%92"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;数以百万计的互联计算设备&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;运行 网络应用程序&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;主机，端节系统&lt;/li&gt;
&lt;li&gt;Pc 工作站，服务器&lt;/li&gt;
&lt;li&gt;PDA 电话，智能家电&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通信链路&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;光纤，铜缆，无线电，卫星&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;路由器：将数据分组（数据块）转发通过网络&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;协议：控制报文的收发&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;e.g TCP, IP, HTTP, FTP, PPP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;因特网：“万网之网”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;松散的层次结构&lt;/li&gt;
&lt;li&gt;公共的 Internet(因特网) vs 专有的 internet (内联网)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;因特网标准&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RFC：Request For Comments&lt;/li&gt;
&lt;li&gt;IETF: Internet Engineering Task Force(因特网工程部)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="服务视角"&gt;
 服务视角
 &lt;a class="anchor" href="#%e6%9c%8d%e5%8a%a1%e8%a7%86%e8%a7%92"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;通信系统基础上 运行分布式的应用程序
&lt;ul&gt;
&lt;li&gt;WWW, email, 网络游戏，电子商务，数据库应用，文件共享&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;所提供的通信服务
&lt;ul&gt;
&lt;li&gt;无连接 connectionless
&lt;ul&gt;
&lt;li&gt;类比电信局的电报服务&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;面向链接 connection-oriented&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="什么是协议"&gt;
 什么是协议
 &lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e5%8d%8f%e8%ae%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="网络协议"&gt;
 网络协议
 &lt;a class="anchor" href="#%e7%bd%91%e7%bb%9c%e5%8d%8f%e8%ae%ae"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;通信设备之间的交互而不是人们的交往&lt;/li&gt;
&lt;li&gt;所有在因特网上的通信活动全部由协议所控制&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;协议定义网络实体之间信息收发的格式和顺序，以及信息发送和接收后所采取的动作。（语法、语义、同步或规则）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;img src="https://raw.githubusercontent.com/pemako/assets/main/2023/network/202305121309808.png" alt="image-20230512020924339" style="zoom:50%;" /&gt;
&lt;h2 id="近观网络结构"&gt;
 近观网络结构
 &lt;a class="anchor" href="#%e8%bf%91%e8%a7%82%e7%bd%91%e7%bb%9c%e7%bb%93%e6%9e%84"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;网络边缘：应用程序和主机&lt;/li&gt;
&lt;li&gt;网络核心：路由器、万网之网&lt;/li&gt;
&lt;li&gt;访问网络，物理介质：通信链路&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="网络边缘"&gt;
 网络边缘
 &lt;a class="anchor" href="#%e7%bd%91%e7%bb%9c%e8%be%b9%e7%bc%98"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;端接系统（主机）
&lt;ul&gt;
&lt;li&gt;运行应用程序&lt;/li&gt;
&lt;li&gt;Eg: WWW, email&lt;/li&gt;
&lt;li&gt;在网络的边缘上&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;客户端/服务器(client/server)模型
&lt;ul&gt;
&lt;li&gt;客户端发出请求，接收来自服务器的服务&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;对等（peer-peer）模型
&lt;ul&gt;
&lt;li&gt;主机对称的进行交互&lt;/li&gt;
&lt;li&gt;e.g. Gnutella&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="面向连接的服务"&gt;
 面向连接的服务
 &lt;a class="anchor" href="#%e9%9d%a2%e5%90%91%e8%bf%9e%e6%8e%a5%e7%9a%84%e6%9c%8d%e5%8a%a1"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;目的：在端系统间进行数据传输&lt;/p&gt;</description></item><item><title>静态链接</title><link>http://pemako.cn/blog/posts/static-linking/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/static-linking/</guid><description>&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#include&lt;/span&gt; &lt;span style="color:#75715e"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style="color:#75715e"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Hello World&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;\n&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gcc hello.c
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./a.out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面的过程分解为4个步骤，分别是&lt;strong&gt;预处理&lt;/strong&gt;（Prepressing）、&lt;strong&gt;编译&lt;/strong&gt;（Compilation）、&lt;strong&gt;汇编&lt;/strong&gt;（Assembly）和&lt;strong&gt;链接&lt;/strong&gt;（Linking）。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-mermaid" data-lang="mermaid"&gt;flowchart LR
 src[&amp;#34;Source Code\nhello.c&amp;#34;]
 header[&amp;#34;Header Files\nstdio.h\n....&amp;#34;]
 lib[&amp;#34;Static Library\nlibc.a\n...&amp;#34;]
 cpp[&amp;#34;Preprocessing\n(cpp)&amp;#34;]
 hi[&amp;#34;Preprocessed\nhello.i&amp;#34;]
 gcc[&amp;#34;Compilation\n(gcc)&amp;#34;]
 hs[&amp;#34;Assembly\nhello.s&amp;#34;]
 as[&amp;#34;Assembly\n(as)&amp;#34;]
 ho[&amp;#34;Object File\nhello.o&amp;#34;]
 ld[&amp;#34;Linking\n(ld)&amp;#34;]
 out[&amp;#34;Executable\na.out&amp;#34;]

 src --&amp;gt; cpp
 header --&amp;gt; cpp
 cpp --&amp;gt; hi --&amp;gt; gcc --&amp;gt; hs --&amp;gt; as --&amp;gt; ho --&amp;gt; ld --&amp;gt; out
 lib --&amp;gt; ld
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="预编译"&gt;
 预编译
 &lt;a class="anchor" href="#%e9%a2%84%e7%bc%96%e8%af%91"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;第一步与预编译的过程相当于如下命令（-E 表示只进行预编译）
&lt;code&gt;gcc -E hello.c -o hello.i&lt;/code&gt; 或 &lt;code&gt;cpp hello.c &amp;gt; hello.i&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;预编译的处理规则如下&lt;/p&gt;</description></item><item><title>高效程序员的45个习惯</title><link>http://pemako.cn/blog/posts/45-habits-effective-programmers/</link><pubDate>Thu, 09 Apr 2026 20:00:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/45-habits-effective-programmers/</guid><description>&lt;h2 id="一态度决定一切"&gt;
 一、态度决定一切
 &lt;a class="anchor" href="#%e4%b8%80%e6%80%81%e5%ba%a6%e5%86%b3%e5%ae%9a%e4%b8%80%e5%88%87"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h4 id="1-做事"&gt;
 1. 做事
 &lt;a class="anchor" href="#1-%e5%81%9a%e4%ba%8b"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;应该把重点放到解决问题上，而不是在指责犯错者上面纠缠。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;把矛头对准问题的解决办法，而不是人，这是真正有用处的正面效应。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-欲速则不达"&gt;
 2. 欲速则不达
 &lt;a class="anchor" href="#2-%e6%ac%b2%e9%80%9f%e5%88%99%e4%b8%8d%e8%be%be"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;你必须要理解一块代码是如何工作的，但是不一定需要成为一位专家。只要你能使用它进行有效的工作就足够了，不需要把它当作毕生事业。&lt;/li&gt;
&lt;li&gt;如果有一位团队成员宣布，有一块代码其他人都很难看懂，这就意味着任何人（包括原作者）都很难维护它。请让它变得简单些。&lt;/li&gt;
&lt;li&gt;不要急于修复一段没能真正理解的代码。这种 &lt;code&gt;+1&lt;/code&gt; / &lt;code&gt;-1&lt;/code&gt; 的病症始于无形，但是很快会让代码一团糟。要解决真正的问题，不要治标不治本。&lt;/li&gt;
&lt;li&gt;多有的大型系统都非常复杂，因此没有一个人能完全明白所有的代码。除了深入了解你正在开发的那部分代码之外，你还需要从更高的层面来了解大部分代码的功能，这样就可以理解系统各个功能模块之间是如何交互的。&lt;/li&gt;
&lt;li&gt;如果系统的代码已经恶化，参考第4点(排除万难，奋勇前进) 。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-对事不对人"&gt;
 3. 对事不对人
 &lt;a class="anchor" href="#3-%e5%af%b9%e4%ba%8b%e4%b8%8d%e5%af%b9%e4%ba%ba"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;让我们骄傲的应该是解决了问题，而不是比较出谁的注意更好。&lt;/li&gt;
&lt;li&gt;尽力贡献自己的好想法，如果你的想法美欧被采纳也无需生气。不要因为只是想体现自己的想法而对拟定的好思路画蛇添足。&lt;/li&gt;
&lt;li&gt;脱离实际的反方观点会使争论变味。若对一个想法有成见，你很容易提出一堆不太可能发生或不太实际的情形去批驳它。这时，请先扪心自问：类似问题以前发生过吗？是否经常发生？&lt;/li&gt;
&lt;li&gt;只有更好，没有最好。尽管&amp;quot;最佳实践&amp;quot;这个术语到处在用，但实际上不存在”最佳“，只有在某个特定条件下更好的实践。&lt;/li&gt;
&lt;li&gt;不带个人情绪并不是要盲目地接受所有的观点。用合适的词和理由去解释为什么不赞同这个观点或方案，并提出明确的问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="4-排除万难奋勇前进"&gt;
 4. 排除万难，奋勇前进
 &lt;a class="anchor" href="#4-%e6%8e%92%e9%99%a4%e4%b8%87%e9%9a%be%e5%a5%8b%e5%8b%87%e5%89%8d%e8%bf%9b"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;如果你说天快要塌下来了，但其他团队成员都不赞同。反思一下，也许你是正确的，但是你没有解释清楚自己的理由。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果你说天快要塌下来了，但其他团队成员都不赞同。认真思考一下，他们也许是对的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果设计或代码中出现了奇怪的问题，花时间去理解为什么代码会是这样的。如果你找到了解决办法，但代码仍然令人费解，唯一的解决办法是重构代码，让它可读性更强。如果你没有马上理解这段代码，不要轻易地否定或重写它们。那不是勇气，而是鲁莽。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;当你勇敢地站出来时，如果收到了缺乏北京只是的抉择者的抵制，你需要用他们能够听懂的话语表达。”更清晰的代码“是无法打动生意人的。解决资金、获得更好的投资回报，避免诉讼以及增加用户利益，会让论点更有说服力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果你在压力下要对代码质量作出妥协，你可以指出，作为一名开发者，你没有职权毁坏公司的资产（所有的代码）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="二学无止境"&gt;
 二、学无止境
 &lt;a class="anchor" href="#%e4%ba%8c%e5%ad%a6%e6%97%a0%e6%ad%a2%e5%a2%83"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h4 id="5-跟踪变化"&gt;
 5. 跟踪变化
 &lt;a class="anchor" href="#5-%e8%b7%9f%e8%b8%aa%e5%8f%98%e5%8c%96"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;你先不要精通所有技术，但需要清楚知道行业的动向，从而规划你的项目和职业规划。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;许多新想法从未变得羽翼丰满，成为有用的技术。即使是大型、热门和资金充裕的项目也会有同样的下场。你要正确把握自己投入的精力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;你不可能精通每一项技术，梅雨哦必要去做这样的尝试。只要你在某一些方面成为专家，就能使用同样的方法，很容易地成功成为新领域的专家。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;你要明白为什么需要这项新技术&amp;ndash; 它试图解决什么样的问题？它可以被用在什么地方？&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;避免在一时冲动的情况下，只是一位内想学习而将应用切换到新的技术、框架或开发语言。在做决策之前，你必须评估新技术的优势。开发一个小的原型系统，是对付技术狂热者的一剂良药。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="6-对团队投资"&gt;
 6. 对团队投资
 &lt;a class="anchor" href="#6-%e5%af%b9%e5%9b%a2%e9%98%9f%e6%8a%95%e8%b5%84"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;尽量让讲座走进团队&lt;/li&gt;
&lt;li&gt;坚持有计划有规律地举行讲座。持续、小步前进才是敏捷。稀少、间隔时间长的马拉松式会议非敏捷也。&lt;/li&gt;
&lt;li&gt;不要局限于纯技术的图书和主题，相关的非技术主题也会退对有帮助。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="7-懂得丢弃"&gt;
 7. 懂得丢弃
 &lt;a class="anchor" href="#7-%e6%87%82%e5%be%97%e4%b8%a2%e5%bc%83"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;要果断丢弃旧习惯，一味遵循过时的就习惯会危害你的职业生涯。&lt;/li&gt;
&lt;li&gt;不是完全忘记旧的习惯，而是只在使用适当的技术时使用它。&lt;/li&gt;
&lt;li&gt;对所有使用的语言，要总结熟悉的语言特性。并且比较这些特性在新语言或新版本中有什么不同。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="8-打破沙锅问到底"&gt;
 8. 打破沙锅问到底
 &lt;a class="anchor" href="#8-%e6%89%93%e7%a0%b4%e6%b2%99%e9%94%85%e9%97%ae%e5%88%b0%e5%ba%95"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;你可能会跑题，问了一些于主题无关的问题。就好比是，如果汽车启动不了，你问是不是轮胎出了问题，者是没有任何帮助的。问“为什么”，但是要问到点子上。&lt;/li&gt;
&lt;li&gt;当你问“问什么”的时候，也许会被反问： “为什么你问这个问题？”在提问之前，想好你提问的理由，这会有助于你问出恰当的问题。&lt;/li&gt;
&lt;li&gt;“这个，我不知道”是一好的起点，应该由此进行更进一步的调查，而不应该嘎然结束。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="9-把握开发节奏"&gt;
 9. 把握开发节奏
 &lt;a class="anchor" href="#9-%e6%8a%8a%e6%8f%a1%e5%bc%80%e5%8f%91%e8%8a%82%e5%a5%8f"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;每天结束的时候，测试代码，提交代码，没有残留的代码。&lt;/li&gt;
&lt;li&gt;不要搞得经常加班。&lt;/li&gt;
&lt;li&gt;以固定、有规律的长度运行迭代。&lt;/li&gt;
&lt;li&gt;有规律的开发节奏会暴露很多问题，让你有更多鼓起勇气的借口。&lt;/li&gt;
&lt;li&gt;一点点的成功也是一个很大的激励。小而可达到目标会让每个人全速前进。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="三交付用户想要的软件"&gt;
 三、交付用户想要的软件
 &lt;a class="anchor" href="#%e4%b8%89%e4%ba%a4%e4%bb%98%e7%94%a8%e6%88%b7%e6%83%b3%e8%a6%81%e7%9a%84%e8%bd%af%e4%bb%b6"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h4 id="10-让客户做决定"&gt;
 10. 让客户做决定
 &lt;a class="anchor" href="#10-%e8%ae%a9%e5%ae%a2%e6%88%b7%e5%81%9a%e5%86%b3%e5%ae%9a"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;记录客户做出的决定，并注明原因。&lt;/li&gt;
&lt;li&gt;不要用低级别和没有价值的问题打扰繁忙的业务人员。如果问题对他们业务没有影响，就应该是没有价值的。&lt;/li&gt;
&lt;li&gt;不要随意假设低级别的问题不会影响他们的业务。如果能够影响他们的业务，就是有价值的问题。&lt;/li&gt;
&lt;li&gt;如果业务负责人回答“我不知道”，这时一个称心如意的答案。也许是他们还没有想那么远，也许是他们只有看到运行的实物才能评估出结果。尽你所能为他们提供建议，实现代码的时候也要考虑可能出现的变化。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="11-让设计指导而不是操纵开发"&gt;
 11. 让设计指导而不是操纵开发
 &lt;a class="anchor" href="#11-%e8%ae%a9%e8%ae%be%e8%ae%a1%e6%8c%87%e5%af%bc%e8%80%8c%e4%b8%8d%e6%98%af%e6%93%8d%e7%ba%b5%e5%bc%80%e5%8f%91"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;p&gt;设计可以分为两层：&lt;code&gt;战略&lt;/code&gt;和&lt;code&gt;战术&lt;/code&gt;。 前期的设计属于战略，通常只有在没有深入理解需求的时候需要这样的设计。良好的战略设计应该扮演地图的角色，指引你向正确的方向前进。任何设计仅是一个起跑点：它就像你的代码一样，在项目的生命周期中，会不停地进一步发展和提炼。&lt;/p&gt;</description></item><item><title>vue3 动态响应的原理</title><link>http://pemako.cn/blog/posts/vue3-dynamic-response-principle/</link><pubDate>Mon, 04 Aug 2025 09:57:04 +0800</pubDate><guid>http://pemako.cn/blog/posts/vue3-dynamic-response-principle/</guid><description>&lt;p&gt;Vue3 的核心原理，ChatGPT 老师给出来的内容，记录下来对于理解 vue 很有帮助&lt;/p&gt;
&lt;p&gt;我们来动手实现一个最小可运行的响应式系统，它能模拟 Vue 3 中 reactive、ref、effect、track 和 trigger 的核心逻辑。&lt;/p&gt;
&lt;h2 id="-目标功能"&gt;
 &lt;strong&gt;🧩 目标功能&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e7%9b%ae%e6%a0%87%e5%8a%9f%e8%83%bd"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;实现 reactive(obj) 和 ref(value)。&lt;/li&gt;
&lt;li&gt;实现 effect(fn)：收集依赖并在数据变更时重新运行。&lt;/li&gt;
&lt;li&gt;实现 track：读取属性时记录依赖。&lt;/li&gt;
&lt;li&gt;实现 trigger：写入属性时触发依赖。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="-最简实现代码"&gt;
 &lt;strong&gt;✅ 最简实现代码&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e6%9c%80%e7%ae%80%e5%ae%9e%e7%8e%b0%e4%bb%a3%e7%a0%81"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 用于记录当前正在执行的副作用函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;activeEffect&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// targetMap 用于存储依赖映射：target -&amp;gt; key -&amp;gt; effects
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;targetMap&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;WeakMap&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 收集依赖：在 get 时调用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;track&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;activeEffect&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;targetMap&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Map&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;targetMap&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Set&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;activeEffect&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 触发依赖：在 set 时调用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;trigger&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;targetMap&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;depsMap&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;effect&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;of&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;deps&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;effect&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 注册副作用函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;effect&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;activeEffect&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fn&lt;/span&gt;(); &lt;span style="color:#75715e"&gt;// 立即执行一次，触发 getter 从而 track
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;activeEffect&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 实现 reactive
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Proxy(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;receiver&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;track&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Reflect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;receiver&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;receiver&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Reflect&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;set&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;receiver&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;trigger&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;target&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;key&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;result&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 实现 ref
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;get&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;track&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;set&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;newVal&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;newVal&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;trigger&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;obj&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="-使用示例"&gt;
 &lt;strong&gt;🚀 使用示例&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%bd%bf%e7%94%a8%e7%a4%ba%e4%be%8b"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reactive&lt;/span&gt;({ &lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;effect&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;count changed to:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;state&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;count&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 会触发 effect 再次执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ref&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;18&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;effect&lt;/span&gt;(() =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;age is:&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;age&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;20&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// 会触发 effect 再次执行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="-总结"&gt;
 &lt;strong&gt;📌 总结&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e6%80%bb%e7%bb%93"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;功能&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;简述&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;effect(fn)&lt;/td&gt;
 &lt;td&gt;注册副作用函数（依赖收集器）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;track()&lt;/td&gt;
 &lt;td&gt;读取数据时记录当前副作用函数依赖&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;trigger()&lt;/td&gt;
 &lt;td&gt;写入数据时触发依赖函数重新运行&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;reactive()&lt;/td&gt;
 &lt;td&gt;用 Proxy 包装对象以支持响应式&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ref()&lt;/td&gt;
 &lt;td&gt;用 getter/setter 包装基本值&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这个模型就是 Vue 3 响应性系统的基本结构，当然 Vue 3 实现里更复杂，支持嵌套对象、effect 的调度与清理、懒执行等等，但核心思想就是这里的 track -&amp;gt; trigger。&lt;/p&gt;</description></item><item><title>Tailwind CSS 类名前缀总结</title><link>http://pemako.cn/blog/posts/tailwind-css/</link><pubDate>Wed, 30 Jul 2025 20:25:52 +0800</pubDate><guid>http://pemako.cn/blog/posts/tailwind-css/</guid><description>&lt;p&gt;下面是对 &lt;strong&gt;Tailwind CSS 类名前缀&lt;/strong&gt;（开头简写）的一个系统总结，涵盖了常用的样式类别以及它们控制的样式类型，便于查阅与理解：&lt;/p&gt;
&lt;h2 id="-tailwind-css-类名前缀速查表"&gt;
 &lt;strong&gt;🧩 Tailwind CSS 类名前缀速查表&lt;/strong&gt;
 &lt;a class="anchor" href="#-tailwind-css-%e7%b1%bb%e5%90%8d%e5%89%8d%e7%bc%80%e9%80%9f%e6%9f%a5%e8%a1%a8"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;类名前缀&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;作用描述&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;影响的 CSS 属性&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;w-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;宽度&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;width&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;h-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;高度&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;height&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;min-w-&lt;/td&gt;
 &lt;td&gt;最小宽度&lt;/td&gt;
 &lt;td&gt;min-width&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;min-h-&lt;/td&gt;
 &lt;td&gt;最小高度&lt;/td&gt;
 &lt;td&gt;min-height&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;max-w-&lt;/td&gt;
 &lt;td&gt;最大宽度&lt;/td&gt;
 &lt;td&gt;max-width&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;max-h-&lt;/td&gt;
 &lt;td&gt;最大高度&lt;/td&gt;
 &lt;td&gt;max-height&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;p-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;内边距 (padding)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;padding（所有）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;px-&lt;/td&gt;
 &lt;td&gt;水平内边距&lt;/td&gt;
 &lt;td&gt;padding-left、padding-right&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;py-&lt;/td&gt;
 &lt;td&gt;垂直内边距&lt;/td&gt;
 &lt;td&gt;padding-top、padding-bottom&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;pt-&lt;/td&gt;
 &lt;td&gt;上内边距&lt;/td&gt;
 &lt;td&gt;padding-top&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;pr-&lt;/td&gt;
 &lt;td&gt;右内边距&lt;/td&gt;
 &lt;td&gt;padding-right&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;pb-&lt;/td&gt;
 &lt;td&gt;下内边距&lt;/td&gt;
 &lt;td&gt;padding-bottom&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;pl-&lt;/td&gt;
 &lt;td&gt;左内边距&lt;/td&gt;
 &lt;td&gt;padding-left&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;m-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;外边距 (margin)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;margin（所有）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;mx-&lt;/td&gt;
 &lt;td&gt;水平外边距&lt;/td&gt;
 &lt;td&gt;margin-left、margin-right&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;my-&lt;/td&gt;
 &lt;td&gt;垂直外边距&lt;/td&gt;
 &lt;td&gt;margin-top、margin-bottom&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;mt-&lt;/td&gt;
 &lt;td&gt;上外边距&lt;/td&gt;
 &lt;td&gt;margin-top&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;mr-&lt;/td&gt;
 &lt;td&gt;右外边距&lt;/td&gt;
 &lt;td&gt;margin-right&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;mb-&lt;/td&gt;
 &lt;td&gt;下外边距&lt;/td&gt;
 &lt;td&gt;margin-bottom&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ml-&lt;/td&gt;
 &lt;td&gt;左外边距&lt;/td&gt;
 &lt;td&gt;margin-left&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;text-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;文字样式&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;color, align, size, weight, transform&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;font-&lt;/td&gt;
 &lt;td&gt;字体粗细、字体族&lt;/td&gt;
 &lt;td&gt;font-weight, font-family&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;leading-&lt;/td&gt;
 &lt;td&gt;行高&lt;/td&gt;
 &lt;td&gt;line-height&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;tracking-&lt;/td&gt;
 &lt;td&gt;字间距&lt;/td&gt;
 &lt;td&gt;letter-spacing&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;bg-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;背景样式&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;background-color, background-image, background-size 等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;border-&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;边框样式&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;border-width, border-color 等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;rounded-&lt;/td&gt;
 &lt;td&gt;圆角&lt;/td&gt;
 &lt;td&gt;border-radius&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;shadow-&lt;/td&gt;
 &lt;td&gt;阴影&lt;/td&gt;
 &lt;td&gt;box-shadow&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;flex、grid、inline-&lt;/td&gt;
 &lt;td&gt;布局模式&lt;/td&gt;
 &lt;td&gt;display&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;items-&lt;/td&gt;
 &lt;td&gt;垂直方向对齐&lt;/td&gt;
 &lt;td&gt;align-items&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;justify-&lt;/td&gt;
 &lt;td&gt;水平方向对齐&lt;/td&gt;
 &lt;td&gt;justify-content&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;gap-&lt;/td&gt;
 &lt;td&gt;容器子元素间距&lt;/td&gt;
 &lt;td&gt;gap&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;space-x-&lt;/td&gt;
 &lt;td&gt;横向子元素间距&lt;/td&gt;
 &lt;td&gt;margin-left&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;space-y-&lt;/td&gt;
 &lt;td&gt;纵向子元素间距&lt;/td&gt;
 &lt;td&gt;margin-top&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;z-&lt;/td&gt;
 &lt;td&gt;层级&lt;/td&gt;
 &lt;td&gt;z-index&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;opacity-&lt;/td&gt;
 &lt;td&gt;透明度&lt;/td&gt;
 &lt;td&gt;opacity&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;overflow-&lt;/td&gt;
 &lt;td&gt;溢出控制&lt;/td&gt;
 &lt;td&gt;overflow, overflow-x, overflow-y&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;cursor-&lt;/td&gt;
 &lt;td&gt;鼠标样式&lt;/td&gt;
 &lt;td&gt;cursor&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;transition、duration-&lt;/td&gt;
 &lt;td&gt;动画过渡&lt;/td&gt;
 &lt;td&gt;transition, transition-duration 等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ease-&lt;/td&gt;
 &lt;td&gt;缓动函数&lt;/td&gt;
 &lt;td&gt;transition-timing-function&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;scale-、rotate-、translate-&lt;/td&gt;
 &lt;td&gt;变换&lt;/td&gt;
 &lt;td&gt;transform&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;absolute、relative、fixed、sticky&lt;/td&gt;
 &lt;td&gt;定位模式&lt;/td&gt;
 &lt;td&gt;position&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;top-、left-、right-、bottom-&lt;/td&gt;
 &lt;td&gt;定位偏移&lt;/td&gt;
 &lt;td&gt;top, left 等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;hidden、block、inline-block&lt;/td&gt;
 &lt;td&gt;显示类型&lt;/td&gt;
 &lt;td&gt;display&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="-特殊响应式与状态前缀组合使用"&gt;
 &lt;strong&gt;📌 特殊响应式与状态前缀（组合使用）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e7%89%b9%e6%ae%8a%e5%93%8d%e5%ba%94%e5%bc%8f%e4%b8%8e%e7%8a%b6%e6%80%81%e5%89%8d%e7%bc%80%e7%bb%84%e5%90%88%e4%bd%bf%e7%94%a8"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;前缀&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;说明&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;示例&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;sm: / md: / lg: / xl: / 2xl:&lt;/td&gt;
 &lt;td&gt;响应式断点&lt;/td&gt;
 &lt;td&gt;md:w-1/2（中等屏幕宽度为 50%）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;hover:&lt;/td&gt;
 &lt;td&gt;悬停状态&lt;/td&gt;
 &lt;td&gt;hover:bg-blue-500&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;focus:&lt;/td&gt;
 &lt;td&gt;聚焦状态&lt;/td&gt;
 &lt;td&gt;focus:ring&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;disabled:&lt;/td&gt;
 &lt;td&gt;禁用状态&lt;/td&gt;
 &lt;td&gt;disabled:opacity-50&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;dark:&lt;/td&gt;
 &lt;td&gt;深色模式&lt;/td&gt;
 &lt;td&gt;dark:bg-gray-800&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;group-hover:&lt;/td&gt;
 &lt;td&gt;父元素悬停触发&lt;/td&gt;
 &lt;td&gt;group-hover:text-red-500&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>TypeScript 的三种特殊类型</title><link>http://pemako.cn/blog/posts/ts-any/</link><pubDate>Thu, 24 Jul 2025 11:01:00 +0800</pubDate><guid>http://pemako.cn/blog/posts/ts-any/</guid><description>&lt;h2 id="typescript-的三种特殊类型"&gt;
 TypeScript 的三种特殊类型
 &lt;a class="anchor" href="#typescript-%e7%9a%84%e4%b8%89%e7%a7%8d%e7%89%b9%e6%ae%8a%e7%b1%bb%e5%9e%8b"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="any"&gt;
 any
 &lt;a class="anchor" href="#any"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;表示任意类型，对 TypeScript 的类型检查器完全关闭检查。编译器不会对它进行任何类型检查，也不会自动补全类型信息。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-TypeScript" data-lang="TypeScript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;any&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toFixed&lt;/span&gt;()); &lt;span style="color:#75715e"&gt;// 编译器不会报错，但运行时可能出错
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;兼容所有类型（可以赋值给任何类型，也可以接受任何类型赋值）&lt;/li&gt;
&lt;li&gt;不安全，等于放弃了 TypeScript 的类型系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="unknown"&gt;
 unknown
 &lt;a class="anchor" href="#unknown"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;也是可以接受任何类型的变量，但不能直接使用，除非先做类型检查或断言。安全的任意类型&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-TypeScript" data-lang="TypeScript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;let&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;any&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; [&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// console.log(value.toFixed()); // 报错 Object is of the &amp;#39;unknown&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ( &lt;span style="color:#66d9ef"&gt;typeof&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;number&amp;#34;&lt;/span&gt; ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;toFixed&lt;/span&gt;()); &lt;span style="color:#75715e"&gt;// 先检查后使用
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;可以接受任何类型赋值（类似 any）&lt;/li&gt;
&lt;li&gt;不能直接使用（需要类型缩小或断言）&lt;/li&gt;
&lt;li&gt;更安全，更适合函数入参或外部数据&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="never-不可能的类型"&gt;
 never （不可能的类型）
 &lt;a class="anchor" href="#never-%e4%b8%8d%e5%8f%af%e8%83%bd%e7%9a%84%e7%b1%bb%e5%9e%8b"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;表示永远不会发生的值。 通用用于明确函数不会返回（抛错、死循环）；类型保护不完整时，确保类型覆盖完整性。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-TypeScript" data-lang="TypeScript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 抛出的异常函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;throwError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;never&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Error(&lt;span style="color:#a6e22e"&gt;msg&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 死循环函数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;loopForever&lt;/span&gt;(); &lt;span style="color:#66d9ef"&gt;never&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// 不可达的分支
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;function&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;exhaustiveCheck&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;b&amp;#34;&lt;/span&gt;)&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;number&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ( &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; ( &lt;span style="color:#a6e22e"&gt;value&lt;/span&gt; &lt;span style="color:#f92672"&gt;===&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;b&amp;#34;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// value 的类型为 never, 如果执行到这里说明之前的类型判断不完整
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;check&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;never&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;vlaue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;check&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="总结对比表"&gt;
 总结对比表
 &lt;a class="anchor" href="#%e6%80%bb%e7%bb%93%e5%af%b9%e6%af%94%e8%a1%a8"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;any&lt;/th&gt;
 &lt;th&gt;unknown&lt;/th&gt;
 &lt;th&gt;never&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;可接受任何值&lt;/td&gt;
 &lt;td&gt;✅ 是&lt;/td&gt;
 &lt;td&gt;✅ 是&lt;/td&gt;
 &lt;td&gt;❌ 否&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;可赋值给其他类型&lt;/td&gt;
 &lt;td&gt;✅ 是&lt;/td&gt;
 &lt;td&gt;❌ 否（需断言/缩小）&lt;/td&gt;
 &lt;td&gt;✅ 是&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;可被其他类型赋值&lt;/td&gt;
 &lt;td&gt;✅ 是&lt;/td&gt;
 &lt;td&gt;✅ 是&lt;/td&gt;
 &lt;td&gt;❌ 否&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;编译器检查&lt;/td&gt;
 &lt;td&gt;❌ 无类型检查&lt;/td&gt;
 &lt;td&gt;✅ 有（使用前需检查）&lt;/td&gt;
 &lt;td&gt;✅ 编译器保证类型不可达&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;安全性&lt;/td&gt;
 &lt;td&gt;❌ 不安全&lt;/td&gt;
 &lt;td&gt;✅ 安全&lt;/td&gt;
 &lt;td&gt;✅ 类型系统完整性保障&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;使用场景&lt;/td&gt;
 &lt;td&gt;快速开发、兼容旧代码&lt;/td&gt;
 &lt;td&gt;外部数据、泛型参数&lt;/td&gt;
 &lt;td&gt;永不返回函数、穷尽检查等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Javascript不同文件后缀的含义</title><link>http://pemako.cn/blog/posts/javascript-file-suffix-description/</link><pubDate>Wed, 23 Jul 2025 09:56:34 +0800</pubDate><guid>http://pemako.cn/blog/posts/javascript-file-suffix-description/</guid><description>&lt;h2 id="javascript-的不同文件后缀名的含义"&gt;
 JavaScript 的不同文件后缀名的含义
 &lt;a class="anchor" href="#javascript-%e7%9a%84%e4%b8%8d%e5%90%8c%e6%96%87%e4%bb%b6%e5%90%8e%e7%bc%80%e5%90%8d%e7%9a%84%e5%90%ab%e4%b9%89"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;后缀名&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;含义/用途&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;常见位置或用途说明&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;.js&lt;/td&gt;
 &lt;td&gt;JavaScript 文件，可能是 CommonJS 或 ESModule&lt;/td&gt;
 &lt;td&gt;项目源代码或编译产物&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.mjs&lt;/td&gt;
 &lt;td&gt;JavaScript ES Module（明确标注为模块）&lt;/td&gt;
 &lt;td&gt;Node.js 中使用 ESModule 时常见&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.cjs&lt;/td&gt;
 &lt;td&gt;JavaScript CommonJS 模块（明确标注）&lt;/td&gt;
 &lt;td&gt;当项目默认使用 ESModule，但某些文件需保留 CJS 语法&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.ts&lt;/td&gt;
 &lt;td&gt;TypeScript 源代码文件&lt;/td&gt;
 &lt;td&gt;支持类型系统和新语法特性，需编译为 .js 才能运行&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.cts&lt;/td&gt;
 &lt;td&gt;TypeScript 的 CommonJS 模块&lt;/td&gt;
 &lt;td&gt;.ts 的 CJS 对应，ESM 项目中显式指定 CJS 模块&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.mts&lt;/td&gt;
 &lt;td&gt;TypeScript 的 ES Module 模块&lt;/td&gt;
 &lt;td&gt;.ts 的 ESM 对应&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.d.ts&lt;/td&gt;
 &lt;td&gt;TypeScript 类型声明文件&lt;/td&gt;
 &lt;td&gt;只包含类型信息，无实现，用于类型补全或公共 API 描述&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.jsx&lt;/td&gt;
 &lt;td&gt;JavaScript + JSX（React）&lt;/td&gt;
 &lt;td&gt;React 组件的源代码，支持 JSX 语法&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.tsx&lt;/td&gt;
 &lt;td&gt;TypeScript + JSX（React）&lt;/td&gt;
 &lt;td&gt;结合 TypeScript 类型检查与 React JSX&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.json&lt;/td&gt;
 &lt;td&gt;JSON 文件&lt;/td&gt;
 &lt;td&gt;配置、数据、模块导入（Node.js / Vite / webpack 支持 import）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.node&lt;/td&gt;
 &lt;td&gt;原生 Node.js 模块（二进制）&lt;/td&gt;
 &lt;td&gt;C/C++ 编译生成的原生插件，Node.js 用于加载本地扩展&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.wasm&lt;/td&gt;
 &lt;td&gt;WebAssembly 模块&lt;/td&gt;
 &lt;td&gt;浏览器或 Node.js 中导入的高性能二进制模块&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.map&lt;/td&gt;
 &lt;td&gt;SourceMap 文件&lt;/td&gt;
 &lt;td&gt;用于调试编译后的代码（.js.map / .ts.map）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;.lock&lt;/td&gt;
 &lt;td&gt;锁定文件依赖版本（package-lock.json, pnpm-lock.yaml）&lt;/td&gt;
 &lt;td&gt;不是 JS 文件，但项目重要组成部分&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="-总结重点分类"&gt;
 &lt;strong&gt;✅ 总结重点分类&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e6%80%bb%e7%bb%93%e9%87%8d%e7%82%b9%e5%88%86%e7%b1%bb"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;代码类型&lt;/strong&gt;：.js, .ts, .mjs, .cjs, .jsx, .tsx, .vue&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型声明&lt;/strong&gt;：.d.ts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;编译产物&lt;/strong&gt;：.js, .map&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置文件&lt;/strong&gt;：.js, .ts, .json, .yaml, .env&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;模块说明&lt;/strong&gt;：.mjs, .cjs, .mts, .cts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;框架扩展&lt;/strong&gt;：.vue, .svelte, .astro, .ejs, .hbs&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Shell Conditional Test</title><link>http://pemako.cn/blog/posts/shell-conditional-test/</link><pubDate>Tue, 01 Jul 2025 19:08:51 +0800</pubDate><guid>http://pemako.cn/blog/posts/shell-conditional-test/</guid><description>&lt;p&gt;在 &lt;code&gt;shell&lt;/code&gt; 脚本判断逻辑中的一些操作符&lt;/p&gt;
&lt;h3 id="一字符串测试"&gt;
 &lt;strong&gt;一、字符串测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e4%b8%80%e5%ad%97%e7%ac%a6%e4%b8%b2%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;th&gt;说明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-z&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;字符串为空&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -z &amp;quot;$str&amp;quot; ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;变量未定义或值为空时为真&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;字符串非空&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -n &amp;quot;$str&amp;quot; ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;变量已定义且值不为空时为真&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;重要提示&lt;/strong&gt;：变量必须用双引号包裹，避免未定义变量导致语法错误：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 错误写法（未定义变量会报错）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; -n $var &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 正确写法&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;[&lt;/span&gt; -n &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$var&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id="二文件测试"&gt;
 &lt;strong&gt;二、文件测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e4%ba%8c%e6%96%87%e4%bb%b6%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;h4 id="文件存在性测试"&gt;
 &lt;strong&gt;文件存在性测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e6%96%87%e4%bb%b6%e5%ad%98%e5%9c%a8%e6%80%a7%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-e&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;文件/目录存在&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -e &amp;quot;/path&amp;quot; ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;同 &lt;code&gt;-e&lt;/code&gt;（已废弃）&lt;/td&gt;
 &lt;td&gt;不推荐使用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="文件类型测试"&gt;
 &lt;strong&gt;文件类型测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e6%96%87%e4%bb%b6%e7%b1%bb%e5%9e%8b%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-f&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;常规文件&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -f file.txt ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;目录&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -d &amp;quot;/dir&amp;quot; ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-L&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;符号链接&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -L link ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-h&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;同 &lt;code&gt;-L&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -h link ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-b&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;块设备&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -b /dev/sda ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-c&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;字符设备&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -c /dev/tty ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-p&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;命名管道&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -p pipe ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-S&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;套接字&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -S socket ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="权限测试"&gt;
 &lt;strong&gt;权限测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e6%9d%83%e9%99%90%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-r&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;可读&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -r file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-w&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;可写&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -w file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-x&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;可执行&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -x script.sh ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-g&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;设置了 setgid&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -g file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-u&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;设置了 setuid&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -u file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-k&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;设置了 sticky bit&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -k /tmp ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="文件属性测试"&gt;
 &lt;strong&gt;文件属性测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e6%96%87%e4%bb%b6%e5%b1%9e%e6%80%a7%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-s&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;文件非空&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -s data.log ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-N&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;修改后未读取&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -N file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-O&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;当前用户拥有&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -O file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-G&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;当前用户组拥有&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -G file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="文件比较测试"&gt;
 &lt;strong&gt;文件比较测试&lt;/strong&gt;
 &lt;a class="anchor" href="#%e6%96%87%e4%bb%b6%e6%af%94%e8%be%83%e6%b5%8b%e8%af%95"&gt;#&lt;/a&gt;
&lt;/h4&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-nt&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;文件1比文件2新&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ file1 -nt file2 ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-ot&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;文件1比文件2旧&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ file1 -ot file2 ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-ef&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;相同设备/Inode&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ file1 -ef file2 ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="三数值比较"&gt;
 &lt;strong&gt;三、数值比较&lt;/strong&gt;
 &lt;a class="anchor" href="#%e4%b8%89%e6%95%b0%e5%80%bc%e6%af%94%e8%be%83"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;th&gt;等价算术符&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-eq&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;等于&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ $a -eq 5 ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-ne&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;不等于&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ $a -ne 5 ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;!=&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-gt&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;大于&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ $a -gt 5 ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-ge&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;大于等于&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ $a -ge 5 ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;&amp;gt;=&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-lt&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;小于&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ $a -lt 5 ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-le&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;小于等于&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ $a -le 5 ]&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;&amp;lt;=&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="四组合逻辑"&gt;
 &lt;strong&gt;四、组合逻辑&lt;/strong&gt;
 &lt;a class="anchor" href="#%e5%9b%9b%e7%bb%84%e5%90%88%e9%80%bb%e8%be%91"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;选项&lt;/th&gt;
 &lt;th&gt;含义&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;逻辑非&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ ! -f file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;逻辑与&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -f file -a -r file ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;逻辑或&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;[ -d dir -o -L dir ]&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;现代写法&lt;/strong&gt;（推荐）：&lt;/p&gt;</description></item><item><title>iptables</title><link>http://pemako.cn/blog/posts/iptables/</link><pubDate>Thu, 26 Jun 2025 23:23:05 +0800</pubDate><guid>http://pemako.cn/blog/posts/iptables/</guid><description>&lt;blockquote&gt;
&lt;p&gt;图片引用 &lt;a href="https://mp.weixin.qq.com/s/GTAGMy2t0FIIUhq6CpFgWw"&gt;https://mp.weixin.qq.com/s/GTAGMy2t0FIIUhq6CpFgWw&lt;/a&gt;
&lt;img src="https://raw.githubusercontent.com/pemako/imgs/master/public/2025/202506271259911.png" alt="Pasted image 20250627125922" /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="-一iptables-五表详解"&gt;
 &lt;strong&gt;🧩 一、iptables 五表详解&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%b8%80iptables-%e4%ba%94%e8%a1%a8%e8%af%a6%e8%a7%a3"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;优先级顺序 raw &amp;gt; mangle &amp;gt; nat &amp;gt; filter &amp;gt; security&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;表名&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;用途&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;作用时机&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;优先级&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;常用规则&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;raw&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;关闭连接跟踪（conntrack）&lt;/td&gt;
 &lt;td&gt;最早阶段&lt;/td&gt;
 &lt;td&gt;⭐最高&lt;/td&gt;
 &lt;td&gt;NOTRACK&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;mangle&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;修改数据包（TTL、TOS、MARK等）&lt;/td&gt;
 &lt;td&gt;早期、中期、晚期都可插入&lt;/td&gt;
 &lt;td&gt;高&lt;/td&gt;
 &lt;td&gt;MARK, TTL, TOS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;nat&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;实现源地址或目标地址转换（NAT）&lt;/td&gt;
 &lt;td&gt;PREROUTING / POSTROUTING / OUTPUT&lt;/td&gt;
 &lt;td&gt;中&lt;/td&gt;
 &lt;td&gt;SNAT, DNAT, MASQUERADE&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;filter&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;数据包过滤（放行/丢弃）&lt;/td&gt;
 &lt;td&gt;处理末期&lt;/td&gt;
 &lt;td&gt;⭐最常用&lt;/td&gt;
 &lt;td&gt;ACCEPT, DROP&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;security&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;与 SELinux、AppArmor 结合的强制访问控制&lt;/td&gt;
 &lt;td&gt;最后阶段&lt;/td&gt;
 &lt;td&gt;低&lt;/td&gt;
 &lt;td&gt;配合 SELinux 使用&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="-二五链详解对应五个-hook-点"&gt;
 &lt;strong&gt;🔗 二、五链详解（对应五个 hook 点）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%ba%8c%e4%ba%94%e9%93%be%e8%af%a6%e8%a7%a3%e5%af%b9%e5%ba%94%e4%ba%94%e4%b8%aa-hook-%e7%82%b9"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;&lt;strong&gt;链名&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;描述&lt;/strong&gt;&lt;/th&gt;
 &lt;th&gt;&lt;strong&gt;属于哪些表&lt;/strong&gt;&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;PREROUTING&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;入站包一进内核就处理（在路由前）&lt;/td&gt;
 &lt;td&gt;raw, mangle, nat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;INPUT&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;进入本机的包&lt;/td&gt;
 &lt;td&gt;mangle, filter, security&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;FORWARD&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;转发到别处的包&lt;/td&gt;
 &lt;td&gt;mangle, filter, security&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;OUTPUT&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;本机发出的包&lt;/td&gt;
 &lt;td&gt;raw, mangle, nat, filter, security&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;POSTROUTING&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;所有出站包（包括转发）在离开前&lt;/td&gt;
 &lt;td&gt;mangle, nat, security&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="-三收发包流程图说明图下方"&gt;
 &lt;strong&gt;🚚 三、收发包流程图说明（图下方）&lt;/strong&gt;
 &lt;a class="anchor" href="#-%e4%b8%89%e6%94%b6%e5%8f%91%e5%8c%85%e6%b5%81%e7%a8%8b%e5%9b%be%e8%af%b4%e6%98%8e%e5%9b%be%e4%b8%8b%e6%96%b9"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;你贴的图，和 Netfilter 的真实流程图是基本一致的。下面我对照图帮你拆解下：&lt;/p&gt;</description></item><item><title>Shell 脚本中为何使用 `{ ... }` 包裹整个脚本</title><link>http://pemako.cn/blog/posts/shell-use-curly-braces-begin-and-end/</link><pubDate>Wed, 11 Jun 2025 23:23:05 +0800</pubDate><guid>http://pemako.cn/blog/posts/shell-use-curly-braces-begin-and-end/</guid><description>&lt;h2 id="-问题"&gt;
 📌 问题
 &lt;a class="anchor" href="#-%e9%97%ae%e9%a2%98"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;在一些 Shell 脚本中，常常看到以下结构：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#75715e"&gt;# this ensures the entire script is downloaded #&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 脚本内容&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;some_function&lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;some_function
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#75715e"&gt;# this ensures the entire script is downloaded #&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;为什么要用 &lt;code&gt;{ ... }&lt;/code&gt; 把整个脚本包裹起来？这样做有什么好处？&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="-答案"&gt;
 ✅ 答案
 &lt;a class="anchor" href="#-%e7%ad%94%e6%a1%88"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;这是一个 &lt;strong&gt;Shell 脚本技巧&lt;/strong&gt;，主要用于：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;确保整个脚本在下载完成并被完全解析之后再执行&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="-原因解释"&gt;
 🧠 原因解释
 &lt;a class="anchor" href="#-%e5%8e%9f%e5%9b%a0%e8%a7%a3%e9%87%8a"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;在执行远程脚本时，例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -s https://example.com/script.sh | bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;脚本是以&lt;strong&gt;流式方式&lt;/strong&gt;传给 &lt;code&gt;bash&lt;/code&gt; 的，会出现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;边下载边执行&lt;/li&gt;
&lt;li&gt;如果下载中断，脚本会只执行了一部分&lt;/li&gt;
&lt;li&gt;函数定义、变量赋值可能不完整，甚至执行危险命令&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="-加上----的作用"&gt;
 🛡 加上 &lt;code&gt;{ ... }&lt;/code&gt; 的作用
 &lt;a class="anchor" href="#-%e5%8a%a0%e4%b8%8a----%e7%9a%84%e4%bd%9c%e7%94%a8"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;使用大括号包裹：&lt;/p&gt;</description></item><item><title>MCP Introduction</title><link>http://pemako.cn/blog/posts/mcp-introduction/</link><pubDate>Wed, 14 May 2025 19:26:36 +0800</pubDate><guid>http://pemako.cn/blog/posts/mcp-introduction/</guid><description>&lt;p&gt;📡 MCP 协议简明说明文档&lt;/p&gt;
&lt;h2 id="什么是-mcp-协议"&gt;
 什么是 MCP 协议？
 &lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af-mcp-%e5%8d%8f%e8%ae%ae"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MCP（Message Calling Protocol）是一种用于“大模型调用工具”的通信协议标准。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它的目标是解决这个问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🧠 “模型说要调用工具 A 干点事，那我们怎么告诉它工具叫啥、怎么传参、怎么返回结果呢？”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="mcp-协议规定了什么共-4-点"&gt;
 MCP 协议规定了什么？（共 4 点）
 &lt;a class="anchor" href="#mcp-%e5%8d%8f%e8%ae%ae%e8%a7%84%e5%ae%9a%e4%ba%86%e4%bb%80%e4%b9%88%e5%85%b1-4-%e7%82%b9"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="1-工具定义格式"&gt;
 1. 工具定义格式
 &lt;a class="anchor" href="#1-%e5%b7%a5%e5%85%b7%e5%ae%9a%e4%b9%89%e6%a0%bc%e5%bc%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;使用 JSON Schema 定义工具的名称、描述和参数：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;get_weather&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;获取城市天气&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;object&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;: { &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;string&amp;#34;&lt;/span&gt;, &lt;span style="color:#f92672"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;城市名&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;required&amp;#34;&lt;/span&gt;: [&lt;span style="color:#e6db74"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="2-调用请求格式"&gt;
 2. 调用请求格式
 &lt;a class="anchor" href="#2-%e8%b0%83%e7%94%a8%e8%af%b7%e6%b1%82%e6%a0%bc%e5%bc%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;遵循 JSON-RPC 格式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;jsonrpc&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;method&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;tools/call&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;params&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;get_weather&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;arguments&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;city&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;北京&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="3-返回结果格式"&gt;
 3. 返回结果格式
 &lt;a class="anchor" href="#3-%e8%bf%94%e5%9b%9e%e7%bb%93%e6%9e%9c%e6%a0%bc%e5%bc%8f"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;jsonrpc&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;2.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;result&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;北京今天晴，最高25度。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;支持返回多种类型的数据（如文本、图片、文件等）。&lt;/p&gt;</description></item><item><title>Install Gitlab</title><link>http://pemako.cn/blog/posts/mac-gitlab-install/</link><pubDate>Fri, 09 May 2025 01:59:28 +0800</pubDate><guid>http://pemako.cn/blog/posts/mac-gitlab-install/</guid><description>&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;展示下启动完成后的效果
&lt;img src="http://pemako.cn/images/gitlab.png" alt="gitlab" /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;依赖 &lt;code&gt;docker&lt;/code&gt; 环境&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.env&lt;/code&gt; 文件&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-env" data-lang="env"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GITLAB_HOST_IP&lt;span style="color:#f92672"&gt;=&lt;/span&gt;192.168.1.8
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GITLAB_PORT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;8929&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GITLAB_ROOT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;/Users/mako/gitlab
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GITLAB_WEB_URL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;192.168.1.8:8929
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;GITLAB_SHELL_SSH_PORT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2224&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;docker compose&lt;/code&gt; 进行安装&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# yaml-language-server: $schema=https://cdn.jsdelivr.net/gh/compose-spec/compose-spec@master/schema/compose-spec.json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;web&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gitlab/gitlab-ce:latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gitlab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hostname&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gitlab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;GITLAB_OMNIBUS_CONFIG&lt;/span&gt;: |&lt;span style="color:#e6db74"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; external_url &amp;#39;http://${GITLAB_HOST_IP}:${GITLAB_PORT}&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; gitlab_rails[&amp;#39;gitlab_shell_ssh_port&amp;#39;] = ${GITLAB_SHELL_SSH_PORT}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_PORT}:${GITLAB_PORT}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_SHELL_SSH_PORT}:22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_ROOT}/config:/etc/gitlab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_ROOT}/logs:/var/log/gitlab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_ROOT}/data:/var/opt/gitlab&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;shm_size&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;256m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;runner&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gitlab/gitlab-runner:latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gitlab-runner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_ROOT}/runner/config:/etc/gitlab-runner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${GITLAB_ROOT}/runner/docker.sock:/var/run/docker.sock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;控制脚本 &lt;code&gt;control.sh&lt;/code&gt; 进行自动更新 &lt;code&gt;.env&lt;/code&gt;及启停&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;在不同网络下本机的 IP 地址变更，只需要 ./control.sh restart 即可，脚本中会自动重新配置 .env 内容&lt;/p&gt;</description></item></channel></rss>