<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>Sam&#39;s Blog</title>
        <link>https://blog.samchu.cn/</link>
        <description>A tech sharing blog.</description>
        <generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>samchu-social@outlook.com (Sam Chu)</managingEditor>
            <webMaster>samchu-social@outlook.com (Sam Chu)</webMaster><lastBuildDate>Wed, 13 Jul 2022 15:22:51 &#43;0800</lastBuildDate>
            <atom:link href="https://blog.samchu.cn/index.xml" rel="self" type="application/rss+xml" />
        <item>
    <title>Linux 文件权限</title>
    <link>https://blog.samchu.cn/posts/linux-file-permissions/</link>
    <pubDate>Wed, 13 Jul 2022 15:22:51 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/linux-file-permissions/</guid>
    <description><![CDATA[<p>在日常使用中，有意无意都会与权限打上交道，例如执行命令遇到 <strong>permission denied</strong> 或者无法修改主目录以外的文件，这些问题都是由于没有足够的权限去进行操作造成的。</p>
<p>由于在 Linux 中「一切皆文件」，所有系统的资源都被抽象成了文件，使得对系统资源的权限管理可以和文件权限管理一样。在实际使用中，系统中的每个文件都从属于一个用户（属主）以及一个用户组（属组），每次用户访问文件时可以根据用户是否是文件属主用户、属组用户来匹配对应的访问权限。一般而言，随着访问范围的扩大，文件权限会逐渐收紧，例如 <strong>rwxr-x---</strong>：属主用户可写可读可执行，属组用户可读可执行，其他用户无权限。</p>
<p>一般而言，文件的权限不可设置的过于宽松，例如设置为 <strong>777</strong>，这会使系统存在安全风险，并且一些系统文件的权限不可随意更改，例如 <strong>/etc/sudoers</strong>。</p>
<h2 id="超级用户">超级用户</h2>
<p>在 Linux 系统中，超级用户（也称 root 用户）拥有至高无上的管理权力，可以访问系统中的所有文件，例如一般用户难以执行的 <code>rm -rf /</code> （<strong>切勿</strong>尝试该命令）在超级用户的手中也可以轻松执行并删除整个系统根文件系统。</p>
<p>通常来说，超级用户只作为管理使用，使用非特权用户进行日常使用可以规避很多危险。在终端中，超级用户的提示符通常为「<code>#</code>」，而非特权用户为「<code>$</code>」。非特权用户虽然可以通过 <code>su</code> 或 <code>sudo</code> 临时提权，但是在多用户环境下，使用此类命令需要格外注意避免对其他已存在用户发生误操作。</p>
<h2 id="权限表示">权限表示</h2>
<p>Linux 的文件权限使用 9 个权限位（bit）来对属主、属组和其他用户权限进行标识，例如 <strong>rwxrwxrwx</strong>。3 个权限位为一组，表示读（<strong>r</strong>ead）、写（<strong>w</strong>rite）、执行（e<strong>x</strong>ecute）权限；共三组，表示属主（<strong>u</strong>ser）、属组（<strong>g</strong>roup）和其他用户（<strong>o</strong>ther）权限。其中每组权限位可以用八进制数来表示，具体如下表所示。</p>
<table>
<thead>
<tr>
<th>八进制数</th>
<th>权限说明</th>
<th>符号权限</th>
<th>二进制</th>
</tr>
</thead>
<tbody>
<tr>
<td>7</td>
<td>读 + 写 + 执行</td>
<td><code>rwx</code></td>
<td>111</td>
</tr>
<tr>
<td>6</td>
<td>读 + 写</td>
<td><code>rw-</code></td>
<td>110</td>
</tr>
<tr>
<td>5</td>
<td>读 + 执行</td>
<td><code>r-x</code></td>
<td>101</td>
</tr>
<tr>
<td>4</td>
<td>只读</td>
<td><code>r--</code></td>
<td>100</td>
</tr>
<tr>
<td>3</td>
<td>写 + 执行</td>
<td><code>-wx</code></td>
<td>011</td>
</tr>
<tr>
<td>2</td>
<td>只写</td>
<td><code>-w-</code></td>
<td>010</td>
</tr>
<tr>
<td>1</td>
<td>只执行</td>
<td><code>--x</code></td>
<td>001</td>
</tr>
<tr>
<td>0</td>
<td>无</td>
<td><code>---</code></td>
<td>000</td>
</tr>
</tbody>
</table>
<p>使用八进制的权限数可以与字符权限符号相互转换，例如在 <strong>755</strong> 权限中：属主用户权限为 7 = 4 + 2 + 1 = <strong>rwx</strong>；属组用户权限为 5 = 4 + 1 = <strong>r-x</strong>；其他用户权限为 5 = 4 + 1 = <strong>r-x</strong>。</p>]]></description>
</item>
<item>
    <title>Linux 文件链接</title>
    <link>https://blog.samchu.cn/posts/linux-links/</link>
    <pubDate>Wed, 06 Jul 2022 15:18:43 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/linux-links/</guid>
    <description><![CDATA[<p>在 Linux 系统中，存在一类特殊的文件：链接文件。使用 <code>ln</code> 命令创建链接是很多 Linux 入门教程都会提及的操作，但是创建的链接类型是什么样的，以及硬链接与符号链接之间有什么区别，并没有解释清楚。</p>
<div class="mermaid" id="id-1"></div>
<h2 id="硬链接">硬链接</h2>
<p>硬链接（hard link）在 Linux 系统中会指向被链接文件的 <strong>inode</strong> 号，也就是说，创建一个文件的硬链接只是创建了一个指向对应 inode 号的「入口」。这也就解释了为什么硬链接不能指向不存在的文件，并且必须在同一个文件系统下。此外，具有硬链接关系的文件彼此是平等的，即首个被创建的文件并没有特殊的「地位」，而删除这些文件实际上只是 inode 的硬链接数减一，并不影响其他硬链接。</p>
<p>可以使用以下示例来理解硬链接：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">## 创建新文件 file 并写入 hello! source file.</span>
</span></span><span class="line"><span class="cl">$ <span class="nb">echo</span> <span class="s2">&#34;hello! source file.&#34;</span> &gt; file
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 检查该文件内容</span>
</span></span><span class="line"><span class="cl">$ cat file
</span></span><span class="line"><span class="cl">hello! <span class="nb">source</span> file.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 查看 file 文件的 inode 信息。inode 号为 6567274，硬链接数为 1</span>
</span></span><span class="line"><span class="cl">$ stat file
</span></span><span class="line"><span class="cl">  文件：file
</span></span><span class="line"><span class="cl">  大小：20        	块：8          IO 块大小：4096   普通文件
</span></span><span class="line"><span class="cl">设备：0,42	Inode: <span class="m">6567274</span>     硬链接：1
</span></span><span class="line"><span class="cl">权限：<span class="o">(</span>0644/-rw-r--r--<span class="o">)</span>  Uid: <span class="o">(</span> 1000/     sam<span class="o">)</span>   Gid: <span class="o">(</span> 1000/     sam<span class="o">)</span>
</span></span><span class="line"><span class="cl">访问时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">修改时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">变更时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">创建时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 创建 file 的硬链接 file.hard</span>
</span></span><span class="line"><span class="cl">$ ln file file.hard
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 查看现有文件</span>
</span></span><span class="line"><span class="cl">$ ls -l
</span></span><span class="line"><span class="cl">-rw-r--r-- <span class="m">2</span> sam sam  <span class="m">20</span>  6月29日 15:32 file
</span></span><span class="line"><span class="cl">-rw-r--r-- <span class="m">2</span> sam sam  <span class="m">20</span>  6月29日 15:32 file.hard
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 查看 file.hard 文件的 inode 信息。inode 号与 file 文件一致，并且硬链接数变为 2</span>
</span></span><span class="line"><span class="cl">$ stat file.hard
</span></span><span class="line"><span class="cl">  文件：file.hard
</span></span><span class="line"><span class="cl">  大小：20        	块：8          IO 块大小：4096   普通文件
</span></span><span class="line"><span class="cl">设备：0,42	Inode: <span class="m">6567274</span>     硬链接：2
</span></span><span class="line"><span class="cl">权限：<span class="o">(</span>0644/-rw-r--r--<span class="o">)</span>  Uid: <span class="o">(</span> 1000/     sam<span class="o">)</span>   Gid: <span class="o">(</span> 1000/     sam<span class="o">)</span>
</span></span><span class="line"><span class="cl">访问时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">修改时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">变更时间：2022-06-29 15:33:11.482896399 +0800
</span></span><span class="line"><span class="cl">创建时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 删除 file 文件</span>
</span></span><span class="line"><span class="cl">$ rm file
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 再次查看 file.hard 文件的 inode 信息。inode 号不变，但硬链接数减为 1</span>
</span></span><span class="line"><span class="cl">$ stat file.hard
</span></span><span class="line"><span class="cl">  文件：file.hard
</span></span><span class="line"><span class="cl">  大小：20        	块：8          IO 块大小：4096   普通文件
</span></span><span class="line"><span class="cl">设备：0,42	Inode: <span class="m">6567274</span>     硬链接：1
</span></span><span class="line"><span class="cl">权限：<span class="o">(</span>0644/-rw-r--r--<span class="o">)</span>  Uid: <span class="o">(</span> 1000/     sam<span class="o">)</span>   Gid: <span class="o">(</span> 1000/     sam<span class="o">)</span>
</span></span><span class="line"><span class="cl">访问时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">修改时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">变更时间：2022-06-29 15:41:15.547996868 +0800
</span></span><span class="line"><span class="cl">创建时间：2022-06-29 15:32:10.911018864 +0800
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 检查 file.hard 文件内容，与 file 文件一致</span>
</span></span><span class="line"><span class="cl">$ cat file.hard
</span></span><span class="line"><span class="cl">hello! <span class="nb">source</span> file.
</span></span></code></pre></div><h2 id="符号链接">符号链接</h2>
<p>符号链接（symbolic link，又称软链接）是一类特殊的<strong>文件</strong>，其中存储的是被链接的文件的路径。创建符号链接时，链接文件会被单独分配一个 inode 号，其存储的文本字符串会被操作系统解释为一条指向另一个文件或者目录的路径，从而实现链接。对符号链接的操作一般都是透明的，即对符号链接的访问会直接对目标文件进行操作。与硬链接不同，符号链接的存在并不依赖于目标文件或目录，并且符号链接可以指向目录。如果符号链接被删除，目标文件不受影响；如果目标文件被删除或者移动，符号链接依然存在，只是指向一个不存在的路径，这种情况被称为<strong>已断开的链接</strong>（dangling link）。</p>
<p>可以使用以下示例来理解符号链接：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">## 创建新文件 file 并写入 hello! source file.</span>
</span></span><span class="line"><span class="cl">$ <span class="nb">echo</span> <span class="s2">&#34;hello! source file.&#34;</span> &gt; file
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 检查该文件内容</span>
</span></span><span class="line"><span class="cl">$ cat file
</span></span><span class="line"><span class="cl">hello! <span class="nb">source</span> file.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 查看现有文件</span>
</span></span><span class="line"><span class="cl">$ ls -l
</span></span><span class="line"><span class="cl">-rw-r--r-- <span class="m">1</span> sam sam  <span class="m">20</span>  6月29日 16:49 file
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 创建 file 的符号链接 file.soft</span>
</span></span><span class="line"><span class="cl">$ ln -s file file.soft
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 再次查看现有文件，file.soft 指向 file</span>
</span></span><span class="line"><span class="cl">$ ls -l
</span></span><span class="line"><span class="cl">-rw-r--r-- <span class="m">1</span> sam sam  <span class="m">20</span>  6月29日 16:49 file
</span></span><span class="line"><span class="cl">lrwxrwxrwx <span class="m">1</span> sam sam   <span class="m">4</span>  6月29日 16:49 file.soft -&gt; file
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 检查 file.soft 文件内容，将直接访问 file 文件</span>
</span></span><span class="line"><span class="cl">$ cat file.soft
</span></span><span class="line"><span class="cl">hello! <span class="nb">source</span> file.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 删除 file 文件</span>
</span></span><span class="line"><span class="cl">$ rm file
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 再次检查 file.soft 文件内容，已无法访问 file 文件</span>
</span></span><span class="line"><span class="cl">$ cat file.soft
</span></span><span class="line"><span class="cl">cat: file.soft: 没有那个文件或目录
</span></span></code></pre></div>]]></description>
</item>
<item>
    <title>Linux 文件类型</title>
    <link>https://blog.samchu.cn/posts/linux-file-types/</link>
    <pubDate>Fri, 01 Jul 2022 14:43:35 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/linux-file-types/</guid>
    <description><![CDATA[<p>在 Linux 系统中，一切皆为文件，包括硬盘与键盘等外接设备，所以 Linux 规定了七种不同的文件类型来对系统的所有文件进行了功能性划分。对于文件类型的检查可以使用 <code>file</code> 命令直接检查文件的类型，或者使用 <code>ls</code> 命令检查文件的模式。下表列出了所有七种文件类型，并给出了模式字符串中文件标志位对应的标志。</p>
<table>
<thead>
<tr>
<th>文件类型</th>
<th>模式标志</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>普通文件</td>
<td><code>-</code></td>
<td>普通文件即日常使用的普通文件，如程序、文本或者数据等</td>
</tr>
<tr>
<td>目录文件</td>
<td><code>d</code></td>
<td>目录文件存放它所包含的每个文件和子目录的目录项</td>
</tr>
<tr>
<td>字符设备文件</td>
<td><code>c</code></td>
<td>字符设备文件提供对串行流设备的访问，如串口、tty 终端等</td>
</tr>
<tr>
<td>块设备文件</td>
<td><code>b</code></td>
<td>块设备文件为块设备提供文件接口，如硬盘等</td>
</tr>
<tr>
<td>符号链接文件</td>
<td><code>l</code></td>
<td>符号链接文件指向设备上的另一个文件或文件夹</td>
</tr>
<tr>
<td>管道文件</td>
<td><code>p</code></td>
<td>管道文件可以将数据先进先出（FIFO）的方式发送到另一个进程</td>
</tr>
<tr>
<td>套接字文件</td>
<td><code>s</code></td>
<td>套接字文件可以使进程之间通过本地套接字的方式通信</td>
</tr>
</tbody>
</table>
<h2 id="普通文件">普通文件</h2>
<p>普通文件是我们在日常使用中接触最多的一类文件，包含文本文件、二进制文件以及特殊格式文件。像代码文件、图片、压缩文件等都属于普通文件，并且文件扩展名或者幻数可以用来检测文件格式。这里要注意，Linux 的文件类型与文件格式并不是同一个概念，文件类型相对于文件格式更加底层，并且文件类型并不依赖文件扩展名，而文件格式通常使用扩展名来进行区分。</p>
<p>使用 <code>ls</code> 来查看文件系统的文件时，如果使用了 <code>--color=auto</code> 参数，普通文件一般显示为「白色」，如果使用了 <code>-l</code> 选项，模式一栏中的第一个字符为「-」为普通文件，例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~ $ ls -l .bashrc
</span></span><span class="line"><span class="cl">-rw-r--r--  <span class="m">1</span> sam  sam     <span class="m">3819</span> 2021年 5月26日 .bashrc
</span></span></code></pre></div><p>或者使用 <code>file</code> 命令来检查文件类型：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~ $ file .bashrc
</span></span><span class="line"><span class="cl">.bashrc: ASCII text
</span></span></code></pre></div><h2 id="目录文件">目录文件</h2>
<p>目录文件是我们日常接触第二多的一类文件，目录文件中存放有它所包含的每个子文件以及子目录的目录项。通过目录文件，Linux 的所有文件目录会形成树形结构，称之为做目录树，可以通过 <code>tree</code> 命令来生成某一目录的目录树。</p>
<p>使用 <code>ls</code> 来查看文件系统的目录时，如果使用了 <code>--color=auto</code> 参数，目录文件一般显示为「蓝色」，如果使用了 <code>-l</code> 选项，模式一栏中的第一个字符为「d」为目录文件，例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~ $ ls -l Documents
</span></span><span class="line"><span class="cl">drwxr-xr-x  <span class="m">1</span> sam  sam      <span class="m">198</span>  1月18日 11:10 Documents
</span></span></code></pre></div><p>或者使用 <code>file</code> 命令来检查文件类型：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">~ $ file Documents
</span></span><span class="line"><span class="cl">Documents: directory
</span></span></code></pre></div><h2 id="特殊文件">特殊文件</h2>
<h3 id="字符设备文件">字符设备文件</h3>
<p>字符设备文件为串行流设备提供了访问接口，例如串口、终端等，应用程序可以使用统一的调用方式对这些设备文件进行访问。字符设备文件通常位于 <strong>/dev</strong> 目录下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -l /dev <span class="p">|</span> grep <span class="s2">&#34;^c&#34;</span>
</span></span><span class="line"><span class="cl">crw-rw-rw-   <span class="m">1</span> root root     1,     <span class="m">3</span>  6月27日 11:58 null
</span></span><span class="line"><span class="cl">crw-rw-rw-   <span class="m">1</span> root tty      5,     <span class="m">0</span>  6月30日 16:37 tty
</span></span><span class="line"><span class="cl">crw-rw-rw-   <span class="m">1</span> root root     1,     <span class="m">8</span>  6月27日 11:58 random
</span></span><span class="line"><span class="cl">crw-rw-rw-   <span class="m">1</span> root root     1,     <span class="m">5</span>  6月27日 11:58 zero
</span></span></code></pre></div><p>可以通过向 <strong>/dev/tty</strong> 中写入字符，以向当前终端中打印字符：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">echo</span> <span class="s2">&#34;write to /dev/tty&#34;</span> &gt; /dev/tty
</span></span><span class="line"><span class="cl">write to /dev/tty
</span></span></code></pre></div><p>或者从随机数据流读取数据并转换成十六进制显示：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ cat /dev/random <span class="p">|</span> od -x <span class="p">|</span> head -n <span class="m">5</span>
</span></span><span class="line"><span class="cl"><span class="m">0000000</span> a85d 59aa 00e8 f49a ae47 93d2 ef25 <span class="m">8229</span>
</span></span><span class="line"><span class="cl"><span class="m">0000020</span> c2f4 250d 654e ef35 513d dd19 37cc e66f
</span></span><span class="line"><span class="cl"><span class="m">0000040</span> 85c8 cafe 658f <span class="m">3604</span> 53c8 a035 6f4e dd4e
</span></span><span class="line"><span class="cl"><span class="m">0000060</span> bc38 <span class="m">3173</span> 04f1 26ff 6d85 733b a536 3c17
</span></span><span class="line"><span class="cl"><span class="m">0000100</span> cfbd f162 e7a9 b940 fcd0 eca5 <span class="m">8787</span> <span class="m">3462</span>
</span></span></code></pre></div><h3 id="块设备文件">块设备文件</h3>
<p>块设备文件为块设备提供了访问接口，例如硬盘、可移动存储设备等，与字符设备文件类似，可以通过对块设备文件的读写来修改块设备的内容。块设备文件通常位于 <strong>/dev</strong> 目录下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -l /dev <span class="p">|</span> grep <span class="s2">&#34;^b&#34;</span>
</span></span><span class="line"><span class="cl">brw-rw----   <span class="m">1</span> root disk     8,     <span class="m">0</span>  6月30日 18:36 sda
</span></span><span class="line"><span class="cl">brw-rw----   <span class="m">1</span> root disk     8,     <span class="m">1</span>  6月30日 18:36 sda1
</span></span></code></pre></div><p>可以通过对块设备文件操作来直接读取文件信息。例如在块设备 <strong>/dev/sda1</strong> 的根目录下存在 <strong>file</strong> 文件：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">(</span>root of sda1<span class="o">)</span> $ cat file
</span></span><span class="line"><span class="cl">this is the <span class="s2">&#34;file&#34;</span>
</span></span></code></pre></div><p>通过 <code>debugfs</code> 程序输出 <strong>/dev/sda1</strong> 下的文件 <strong>file</strong> 的区块号：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo debugfs /dev/sda1
</span></span><span class="line"><span class="cl">debugfs:  blocks file
</span></span><span class="line"><span class="cl"><span class="m">34816</span>
</span></span></code></pre></div><p>随后使用 <code>dd</code> 命令输出该区块的数据：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo dd <span class="k">if</span><span class="o">=</span>/dev/sda1 <span class="nv">bs</span><span class="o">=</span>4k <span class="nv">count</span><span class="o">=</span><span class="m">1</span> <span class="nv">skip</span><span class="o">=</span><span class="m">34816</span>
</span></span><span class="line"><span class="cl">this is the <span class="s2">&#34;file&#34;</span>
</span></span><span class="line"><span class="cl">输入了 1+0 块记录
</span></span><span class="line"><span class="cl">输出了 1+0 块记录
</span></span><span class="line"><span class="cl"><span class="m">4096</span> 字节 <span class="o">(</span>4.1 kB, 4.0 KiB<span class="o">)</span> 已复制，2.6699e-05 s，153 MB/s
</span></span></code></pre></div><h3 id="符号链接文件">符号链接文件</h3>
<p>符号链接文件是一类存储着其他文件或目录路径的特殊文件，操作系统会将存储的文件路径解释为链接，从而使得对符号链接文件的操作是透明的，会直接生效于目标文件。</p>
<p>假设文本文件 <strong>file</strong> 的内容是「this is the &ldquo;file&rdquo;」，查看其 <strong>inode</strong> 信息：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -li file
</span></span><span class="line"><span class="cl"><span class="m">6599999</span> -rw-r--r-- <span class="m">1</span> sam sam <span class="m">19</span>  7月 1日 09:55 file
</span></span></code></pre></div><p>创建 <strong>file</strong> 文件的符号链接 <strong>file.symlink</strong>：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ln -s file file.symlink
</span></span></code></pre></div><p>查看 <strong>file.symlink</strong> 的 <strong>inode</strong> 信息：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -li file.symlink
</span></span><span class="line"><span class="cl"><span class="m">6600033</span> lrwxrwxrwx <span class="m">1</span> sam sam <span class="m">4</span>  7月 1日 09:57 file.symlink -&gt; file
</span></span></code></pre></div><p>可以看到 <strong>file</strong> 与 <strong>file.symlink</strong> 的 <strong>inode</strong> 不同，说明符号链接为一个单独的文件，同时 <strong>file.symlink</strong> 的模式一栏中标明了文件类型为 <code>l</code>，指向 <strong>file</strong>。</p>
<h3 id="管道文件">管道文件</h3>
<p>管道文件可以使两个不相关的进程之间进行通信，在日常使用中比较少见。Linux 中存在两种管道：匿名管道与命名管道，匿名管道只能用于父子进程之间进行通信，而命名管道则通过区分管道文件的文件名来实现不同进程的通信。实际上，在使用管道文件时，并不会向文件系统中写入数据，占用的仍然是内存空间。</p>
<p>使用 <code>mkfifo</code> 命令可以创建一个名为 <strong>pipe</strong> 的管道文件：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ mkfifo pipe
</span></span></code></pre></div><p>使用 <code>ls</code> 查看其类型：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -l pipe
</span></span><span class="line"><span class="cl">prw-r--r-- <span class="m">1</span> sam sam <span class="m">0</span>  7月 1日 10:51 pipe
</span></span></code></pre></div><p>下面可以通过这个 <strong>pipe</strong> 文件实现两个进程之间的通信：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nb">echo</span> <span class="s2">&#34;one:two:three:four:five:six:seven&#34;</span> &gt; pipe
</span></span></code></pre></div><p>此时该进程被阻塞，使用另一终端对 pipe 文件进行读取并输出第 5 栏至行尾：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ cut -d : -f 5- pipe
</span></span><span class="line"><span class="cl">five:six:seven
</span></span></code></pre></div><p>此时被阻塞的进程正常返回了。</p>
<h3 id="套接字文件">套接字文件</h3>
<p>套接字文件同样用来进行本地进程间通信，与管道文件单向不同，套接字文件可以实现进程的双向通信。套接字文件只能使用系统调用来创建，所以套接字文件常见于软件配置中。</p>
<p>套接字文件可以使用 <code>ls</code> 来查看：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ls -l /run/dbus <span class="p">|</span> grep <span class="s2">&#34;^s&#34;</span>
</span></span><span class="line"><span class="cl">srw-rw-rw- <span class="m">1</span> root root  <span class="m">0</span>  6月30日 18:11 system_bus_socket
</span></span></code></pre></div>]]></description>
</item>
<item>
    <title>使用 GnuPG 创建密钥对</title>
    <link>https://blog.samchu.cn/posts/creating-key-pair-using-gnupg/</link>
    <pubDate>Thu, 26 May 2022 23:02:55 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/creating-key-pair-using-gnupg/</guid>
    <description><![CDATA[<div class="details admonition warning open">
        <div class="details-summary admonition-title">
            <i class="icon fas fa-exclamation-triangle fa-fw" aria-hidden="true"></i>安全警告<i class="details-icon fas fa-angle-right fa-fw" aria-hidden="true"></i>
        </div>
        <div class="details-content">
            <div class="admonition-content">文中出现的密钥对信息均为演示作用，请勿信任与本文信息相同的密钥！</div>
        </div>
    </div>
<h2 id="安装与验证">安装与验证</h2>
<p>GnuPG（下称 GPG）的安装根据操作系统与发行版的不同，步骤不尽相同，需要参考系统发行版的官方文档来进行安装。安装完成后，使用 <code>gpg --version</code> 来查看 GPG 的安装信息以及版本信息，以及后续所生成的密钥文件的存放位置（即输出信息中的 <code>Home</code>）。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --version
</span></span><span class="line"><span class="cl">gpg <span class="o">(</span>GnuPG<span class="o">)</span> 2.x.xx
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Home: /home/&lt;your_username&gt;/.gnupg
</span></span><span class="line"><span class="cl">支持的算法：
</span></span><span class="line"><span class="cl">公钥： RSA, ELG, DSA, ECDH, ECDSA, EDDSA
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">压缩：  不压缩, ZIP, ZLIB, BZIP2
</span></span></code></pre></div><h2 id="生成第一对密钥">生成第一对密钥</h2>
<p>GPG 安装后，就可以使用以下命令来生成第一对公钥与密钥了：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --full-generate-key
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># interactive instructions</span>
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">pub   rsa4096 2022-05-26 <span class="o">[</span>SC<span class="o">]</span>
</span></span><span class="line"><span class="cl">      24C2C31B933B8CA63B5D538FE0772B35B2E02051
</span></span><span class="line"><span class="cl">uid                      Sam Chu <span class="o">(</span>Personal use only<span class="o">)</span> &lt;samchu-social@outlook.com&gt;
</span></span><span class="line"><span class="cl">sub   rsa4096 2022-05-26 <span class="o">[</span>E<span class="o">]</span>
</span></span></code></pre></div><p>接下来会在终端交互式的给出密钥生成的选项，需要依次对以下选项进行选择：</p>
<ul>
<li>密钥类型。目前已有研究表明，在密钥长度足够的情况下，各种类型的加密方式安全性相当，当然，这一结论未来可能会发生变化。一个好的加密软件会根据最新研究结果修改默认的加密方式，所以这里选择默认选项（RSA 和 RSA）即可。</li>
<li>密钥长度。为了保证密钥未来的安全性，这里选择最大长度（4096）。</li>
<li>密钥有效期限。一个好的密钥需要根据使用场景严格限定其有效期限，目前该密钥仅应用于个人信息加密，所以选择永不过期。</li>
<li>真实姓名。这里可以填入自己常用的用户名，作为他人识别该密钥的标识。</li>
<li>电子邮件。由于生成的公钥是公开的，所以这里需要填写常用的邮箱（如果有特殊用处，如 GitHub 认证提交，则需要使用对应邮箱）。</li>
<li>注释：填入对该密钥的注释，方便后期对该密钥用处进行识别。</li>
</ul>
<p>以上选项确定后，会要求对该密钥设置密码，后续进行密钥操作时都会用到，所以务必牢记该密码。最后 GPG 会提示你进行「敲打键盘、移动鼠标、读写硬盘之类的」其他操作以产生随机数。</p>
<p>生成好的密钥对会存放在 GPG 的 <code>Home</code> 目录（默认为 <code>/home/&lt;your_username&gt;/.gnupg</code>）下，同时还生成了一个吊销证书。吊销证书的作用是在你确认私钥已经泄露或丢失等情况下，帮助你可信地告知其他用户你的公钥已经失效。所以生成的私钥与吊销证书都必须保证安全，任何一个文件泄露都可能造成身份丢失。</p>
<p>密钥生成完毕后，会在终端上打印出生成的公钥信息。当然后续也可以通过以下命令查看已有的密钥。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg -k --keyid-format LONG
</span></span><span class="line"><span class="cl">/home/&lt;your_username&gt;/.gnupg/pubring.kbx
</span></span><span class="line"><span class="cl">----------------------------
</span></span><span class="line"><span class="cl">pub   rsa4096/E0772B35B2E02051 2022-05-26 <span class="o">[</span>SC<span class="o">]</span>
</span></span><span class="line"><span class="cl">      24C2C31B933B8CA63B5D538FE0772B35B2E02051
</span></span><span class="line"><span class="cl">uid                   <span class="o">[</span> 绝对 <span class="o">]</span> Sam Chu <span class="o">(</span>Personal use only<span class="o">)</span> &lt;samchu-social@outlook.com&gt;
</span></span><span class="line"><span class="cl">sub   rsa4096/E5B924315C3F59D1 2022-05-26 <span class="o">[</span>E<span class="o">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">$ gpg -K --keyid-format LONG
</span></span><span class="line"><span class="cl">/home/&lt;your_username&gt;/.gnupg/pubring.kbx
</span></span><span class="line"><span class="cl">----------------------------
</span></span><span class="line"><span class="cl">sec   rsa4096/E0772B35B2E02051 2022-05-26 <span class="o">[</span>SC<span class="o">]</span>
</span></span><span class="line"><span class="cl">      24C2C31B933B8CA63B5D538FE0772B35B2E02051
</span></span><span class="line"><span class="cl">uid                   <span class="o">[</span> 绝对 <span class="o">]</span> Sam Chu <span class="o">(</span>Personal use only<span class="o">)</span> &lt;samchu-social@outlook.com&gt;
</span></span><span class="line"><span class="cl">ssb   rsa4096/E5B924315C3F59D1 2022-05-26 <span class="o">[</span>E<span class="o">]</span>
</span></span></code></pre></div><p>上面的命令中，<code>-k/--list-public-keys</code> 列出公钥信息，<code>-K/--list-secret-keys</code> 列出私钥信息，<code>--keyid-format</code> 设置打印密钥 ID 的格式。每次列出密钥信息时都需要加上 <code>--keyid-format</code> 选项比较麻烦，可以通过执行 <code>echo &quot;keyid-format LONG&quot; &gt; ~/.gnupg/gpg.conf</code> 来将设置写进配置文件中。</p>
<p>在 GPG 打印出来的密钥信息中，<code>pub</code> 与 <code>sec</code> 表示主密钥的公钥与私钥，而 <code>sub</code> 与 <code>ssb</code> 表示子密钥的公钥与私钥。有关主密钥与子密钥的解释与应用场景请参阅 <a href="#%e5%8f%82%e8%80%83%e6%96%87%e7%ab%a0" rel="">参考文章</a> 中的文章。在 <code>pub</code> 、 <code>sec</code> 、<code>sub</code> 或 <code>ssb</code> 行中显示的是密钥的加密方式、密钥 ID、生成时间以及密钥用途（E/S/C/A 分别表示加密/签名/子密钥认证/身份认证）；下一行为密钥的指纹，通过 40 个十六进制数表示，指纹是密钥的唯一标识；<code>uid</code> 一行标识密钥的用户身份，以 <code>[信任值] 姓名 (注释) &lt;电子邮件&gt;</code> 显示，其中信任值用于表明对所有者的信任程度及密钥有效性，可能的值参见 <a href="https://man.archlinux.org/man/gpg.1.en#TRUST_VALUES" target="_blank" rel="noopener noreffer ">gpg(1) - Arch manual pages</a>。</p>
<h2 id="生成签名子密钥">生成签名子密钥</h2>
<p>在实际应用场景中，如果在多台设备上使用同一对密钥进行签名加密操作，一旦发生密钥泄露，则设备上所有的加密信息以及签名文件都会陷入被暴露的危险。此时除了撤销整个密钥没有其他办法。但是如果在不同机器上使用不同的子密钥进行加密或签名，就能够保证一个子密钥的泄露不会影响到其他子密钥的使用。而 GPG 支持一对主密钥与多个子密钥正是考虑到了这一点，在密钥对生成时就已经默认生成一对仅用于加密的子密钥。使用 <code>gpg --edit-key &lt;keyid|uid&gt;</code>进入密钥编辑模式，可以对已生成的主密钥进行编辑。下面将使用 <code>addkey</code> 命令生成一个仅用于签名的子密钥对。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --edit-key E0772B35B2E02051
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sec  rsa4096/E0772B35B2E02051
</span></span><span class="line"><span class="cl">     创建于：2022-05-26  有效至：永不       可用于：SC
</span></span><span class="line"><span class="cl">     信任度：绝对        有效性：绝对
</span></span><span class="line"><span class="cl">ssb  rsa4096/E5B924315C3F59D1
</span></span><span class="line"><span class="cl">     创建于：2022-05-26  有效至：永不       可用于：E
</span></span><span class="line"><span class="cl"><span class="o">[</span> 绝对 <span class="o">]</span> <span class="o">(</span>1<span class="o">)</span>. Sam Chu <span class="o">(</span>Personal use only<span class="o">)</span> &lt;samchu-social@outlook.com&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">gpg&gt; addkey
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># interactive instructions</span>
</span></span><span class="line"><span class="cl">...
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sec  rsa4096/E0772B35B2E02051
</span></span><span class="line"><span class="cl">     创建于：2022-05-26  有效至：永不       可用于：SC
</span></span><span class="line"><span class="cl">     信任度：绝对        有效性：绝对
</span></span><span class="line"><span class="cl">ssb  rsa4096/E5B924315C3F59D1
</span></span><span class="line"><span class="cl">     创建于：2022-05-26  有效至：永不       可用于：E
</span></span><span class="line"><span class="cl">ssb  rsa4096/823F7AE3713B71CB
</span></span><span class="line"><span class="cl">     创建于：2022-05-26  有效至：永不       可用于：S
</span></span><span class="line"><span class="cl"><span class="o">[</span> 绝对 <span class="o">]</span> <span class="o">(</span>1<span class="o">)</span>. Sam Chu <span class="o">(</span>Personal use only<span class="o">)</span> &lt;samchu-social@outlook.com&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">gpg&gt; save
</span></span></code></pre></div><p>生成过程与生成主密钥对类似，需要指定密钥类型、密钥长度、有效期限，随后会要求输入主密钥的密码，身份验证成功后便会收集用户动作以生成密钥。生成完毕后，可以看到新的仅用于签名的子密钥对已经添加到主密钥中了。最后输入 <code>save</code> 保存退出。</p>
<h2 id="导出公钥">导出公钥</h2>
<p>由于刚才生成的密钥对都是采用的非对称加密方式，所以我们需要分发自己的公钥来对消息进行加密或者签名。GPG 的子密钥的有效性都来自于主密钥的认证，所以导出的公钥实际为一组公钥，其中就有被主密钥认证之后的子公钥。使用以下命令可以将公钥以 ASCII 字符保存到 <code>public.key</code> 文件中。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --export --armor --output public.key E0772B35B2E02051
</span></span></code></pre></div><p>当其他人获取该公钥后，可以使用以下命令导入自己的密钥环，方便进行加密信息交换。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --import public.key
</span></span><span class="line"><span class="cl">gpg: 密钥 E0772B35B2E02051：公钥 “Sam Chu <span class="o">(</span>Personal use only<span class="o">)</span> &lt;samchu-social@outlook.com&gt;” 已导入
</span></span><span class="line"><span class="cl">gpg: 处理的总数：1
</span></span><span class="line"><span class="cl">gpg: 已导入：1
</span></span></code></pre></div><h2 id="备份私钥">备份私钥</h2>
<p>同样的，如果需要备份私钥，可以将私钥导出后存放在绝对安全的地方进行备份。使用以下命令以备份整个私钥，执行时会要求输入主密钥的密码。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --export-secret-keys --armor --output private.key E0772B35B2E02051
</span></span></code></pre></div><p>除了能够备份整个私钥，还能够单独将子密钥的私钥进行导出。导出时注意在 <code>&lt;subkeyid&gt;</code> 后加上 <code>!</code>，否则所有的子私钥都会被导出。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ gpg --export-secret-subkeys --armor --output encrypt.subkey E5B924315C3F59D1! <span class="c1"># export encrypt only subkey</span>
</span></span><span class="line"><span class="cl">$ gpg --export-secret-subkeys --armor --output sign.subkey F8A5FE5D5FA5BA9C!    <span class="c1"># export sign only subkey</span>
</span></span></code></pre></div><p>导入私钥时同样使用 <code>gpg --import &lt;file_of_private_key&gt;</code> 命令。</p>
<h2 id="参考文章">参考文章</h2>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/436962516" target="_blank" rel="noopener noreffer ">GPG 使用指南 - 来源：知乎</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/137801979" target="_blank" rel="noopener noreffer ">简明 GPG 概念 - 来源：知乎</a></li>
<li><a href="https://spencerwoo.com/blog/wait-this-is-not-my-commit" target="_blank" rel="noopener noreffer ">震惊！竟然有人在 GitHub 上冒充我的身份！- 来源：Spencer Woo</a></li>
<li><a href="https://wiki.archlinux.org/title/GnuPG" target="_blank" rel="noopener noreffer ">GnuPG - ArchWiki - 来源：ArchWiki</a></li>
</ul>]]></description>
</item>
<item>
    <title>Linux ext4 文件系统转 Btrfs</title>
    <link>https://blog.samchu.cn/posts/linux-ext4-to-btrfs/</link>
    <pubDate>Sat, 30 Jan 2021 20:47:35 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/linux-ext4-to-btrfs/</guid>
    <description><![CDATA[<p>最近扩展 Linux 分区的时候，由于年少轻狂，没有进行全盘备份，导致系统出现了灾难性事故，软件、配置，还有最近学习 Vim，写了快一个星期的配置文件，全部丢失。重装系统后便开始寻找适合备份的文件系统，便有了这篇文章。</p>
<h2 id="为什么是-btrfs">为什么是 Btrfs</h2>
<p>Btrfs 是 B-tree 文件系统，通常念做 「Butter FS」、「Better FS」或「B-tree FS」。是一种支持写入时复制（CoW）的 Linux 文件系统。相对于 ext4 文件系统有以下几个优点：</p>
<ul>
<li>Btrfs 支持快照，方便备份与恢复；</li>
<li>Btrfs 支持透明压缩，节省存储空间；</li>
<li>Btrfs 支持子卷功能，便于管理；</li>
<li>Btrfs 支持数据与元数据校验。</li>
</ul>
<p>这些优点使我产生了向 Btrfs 迁移的念头，幸运的是，Btrfs 支持从 ext4 转换。</p>
<h2 id="转换步骤">转换步骤</h2>
<p>以下步骤是在我自用电脑上操作的，磁盘 <code>/dev/nvme0n1p4</code> 挂载为 Linux 根分区，下文命令可能需要调整。由于操作时需要对根分区进行操作，强烈建议操作前进行全盘备份并在 LiveCD 环境下进行操作。</p>
<p><strong>注意</strong>：任何对数据的操作都是充满风险的，如果你不能承受数据丢失的风险，请勿操作。
<strong>注意</strong>：如果转换中出现任何异样，你都可以使用备份子卷 <code>/ext2_saved</code> 来回滚。请勿强行对转换失败的分区做出更改。使用 <code>btrfs-convert -r /dev/target_partition</code> 命令进行回滚。</p>
<h3 id="检查文件系统">检查文件系统</h3>
<p>首先使用 <code>fsck</code> 检查磁盘，保证现有分区没有问题。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> fsck.ext4 /dev/nvme0n1p4
</span></span></code></pre></div><h3 id="开始文件系统转换">开始文件系统转换</h3>
<p>分区检查通过后就可以开始转换。执行以下命令进行转换。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> btrfs-convert /dev/nvme0n1p4
</span></span></code></pre></div><p>待出现 <code>conversion complete</code> 表明转换完成。现在分区的文件系统已经是 Btrfs 了，但是还不能重启，还需要对现有的文件进行修改才能顺利引导进系统。</p>
<h3 id="挂载分区并修改-fstab">挂载分区并修改 <code>fstab</code></h3>
<p>首先需要挂载分区，方便我们修改文件。这里我们将分区挂载到 <code>/mnt</code> 目录下。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> mount /dev/nvme0n1p4 /mnt
</span></span></code></pre></div><p>使用磁盘工具检查分区的 UUID，这里使用 <code>lsblk</code> 命令。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">$</span> lsblk -f
</span></span><span class="line"><span class="cl"><span class="go">NAME        FSTYPE FSVER LABEL      UUID                                 FSAVAIL FSUSE% MOUNTPOINT
</span></span></span><span class="line"><span class="cl"><span class="go">nvme0n1
</span></span></span><span class="line"><span class="cl"><span class="go">...                                
</span></span></span><span class="line"><span class="cl"><span class="go">└─nvme0n1p4 btrfs        ...        82xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxeb     xxG     xx%    /mnt
</span></span></span></code></pre></div><p>使用文本编辑工具修改 <code>/mnt/etc/fstab</code> 文件，修改挂载到根目录的分区类型（type）为 <code>btrfs</code>、文件系统检查顺序（pass）为 <code>0</code>（启动时不进行磁盘检查），并检查转换后的分区 UUID 是否改变，修改挂载分区（file system）。</p>
<h3 id="重建初始化内存盘">重建初始化内存盘</h3>
<p>重建初始化内存盘需要在 chroot 环境中进行。首先需要设置对应的挂载点。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> mount -t proc none /mnt/proc
</span></span><span class="line"><span class="cl"><span class="gp">#</span> mount -t sysfs none /mnt/sys
</span></span><span class="line"><span class="cl"><span class="gp">#</span> mount -o <span class="nb">bind</span> /dev /mnt/dev
</span></span></code></pre></div><p>随后使用 <code>chroot</code> 命令进入原系统。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> chroot /mnt bash
</span></span></code></pre></div><p>进入原系统后，使用 <code>mkinitcpio</code> 重建初始化内存盘。这里可能需要替换命令参数，如果提示 <code>Fail to load preset</code>，需要检查 <code>/etc/mkinitcpio.d</code> 目录下是否存在对应的预设文件名。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> mkinitcpio --preset linux
</span></span></code></pre></div><p>如果使用 GRUB 启动，还需要重建 GRUB 引导。由于笔者使用 rEFInd 引导，故没有执行该步骤，如有需要参见 <a href="https://wiki.archlinux.org/index.php/Btrfs_%28%e7%ae%80%e4%bd%93%e4%b8%ad%e6%96%87%29#%e4%bb%8e_Ext3/4_%e8%bd%ac%e6%8d%a2" target="_blank" rel="noopener noreffer ">Btrfs - ArchWiki「6.2 从 Ext3/4 转换」</a>一节。</p>
<h3 id="tlp-设置">TLP 设置</h3>
<p>如果使用了 TLP 高级电源管理功能，需要对 TLP 进行设置，防止文件系统损坏。编辑位于 <code>/mnt/etc/tlp.conf</code> 的配置文件，找到 <code>SATA_LINKPWR_ON_BAT</code> 条目，取消注释并在选项中添加 <code>max_performance</code> 参数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">SATA_LINKPWR_ON_BAT=&#34;med_power_with_dipm max_performance&#34;
</span></span></span></code></pre></div><h3 id="启用透明压缩">启用透明压缩</h3>
<p>为了能够利用 Btrfs 的透明压缩功能，可以对转换好的分区进行压缩并修改 <code>fstab</code> 挂载选项。</p>
<p>首先需要对转换好的分区进行全盘压缩。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> btrfs filesystem defragment -r -v -czstd /mnt
</span></span></code></pre></div><p>随后需要修改 <code>fstab</code> 文件，在根目录文件系统的挂载选项（options）一栏中增加 <code>compress=zstd</code> 选项，以便系统启动时应用压缩选项。</p>
<h3 id="使用新文件系统启动及后续操作">使用新文件系统启动及后续操作</h3>
<p>完成上述步骤后，便可以使用转换后的分区启动。启动后，可以删除 <code>/ext2_saved</code> 子卷完成转换。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> btrfs subvolume delete /ext2_saved
</span></span></code></pre></div><p>最后通过 Balance 来回收数据。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> btrfs balance start /
</span></span><span class="line"><span class="cl"><span class="gp">#</span> btrfs balance status /
</span></span></code></pre></div><p>至此，分区文件系统转换就结束了。感受新文件系统所带来的惊喜吧。</p>
<h3 id="配置文件系统检修">配置文件系统检修</h3>
<p>在转换结束后，可以配置定时对根目录 <code>/</code> 的检修任务。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> systemctl <span class="nb">enable</span> --now btrfs-scrub@-.timer
</span></span></code></pre></div><p>或者你也可以手动执行。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="gp">#</span> btrfs scrub start /
</span></span><span class="line"><span class="cl"><span class="gp">#</span> btrfs scrub status /
</span></span></code></pre></div><h2 id="后记">后记</h2>
<p>对于数据的操作务必谨慎，如果有合适的文件系统也会使数据操作更加得心应手。使用了一段时间的 Btrfs 文件系统后，并没有感受到与 ext4 有什么不同，反而在快照、透明压缩上有更多的惊喜。如果让我说 Btrfs 适不适合作为一个 Linux 桌面用户的文件系统，我的答案会是肯定的，但是如果没有正确的、有效的数据冗余备份机制，再好的文件系统也会「不适合」。</p>
<h2 id="参考文章">参考文章</h2>
<ul>
<li><a href="https://zh.wikipedia.org/wiki/Btrfs" target="_blank" rel="noopener noreffer ">Btrfs - 维基百科</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Btrfs_%28%e7%ae%80%e4%bd%93%e4%b8%ad%e6%96%87%29" target="_blank" rel="noopener noreffer ">Btrfs - ArchWiki</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Install_Arch_Linux_from_existing_Linux_%28%e7%ae%80%e4%bd%93%e4%b8%ad%e6%96%87%29" target="_blank" rel="noopener noreffer ">从现有 Linux 安装 - ArchWiki</a></li>
<li><a href="https://wiki.archlinux.org/index.php/TLP_%28%e7%ae%80%e4%bd%93%e4%b8%ad%e6%96%87%29" target="_blank" rel="noopener noreffer ">TLP - ArchWiki</a></li>
<li><a href="https://xuanwo.io/2018/11/15/record-for-btrfs-conversion/" target="_blank" rel="noopener noreffer ">记一次 btrfs 的在线转换 - 漩涡的博客</a></li>
</ul>]]></description>
</item>
<item>
    <title>类 Unix 系统中 TTY 与 PTY 的区别</title>
    <link>https://blog.samchu.cn/posts/learn-about-tty-pty/</link>
    <pubDate>Fri, 20 Nov 2020 11:39:26 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/learn-about-tty-pty/</guid>
    <description><![CDATA[<p>使用 Linux 等类 Unix 系统的同学可能经常能看到 tty、pts、ptmx 等字样；玩过树莓派的同学会在登陆界面看到 <code>tty1</code> 的字样。这些东西对我们正常使用操作系统没有任何影响，但是理解它们可以让我们更加了解类 Unix 系统背后的机制。</p>
<h3 id="console">Console</h3>
<p>Console 意即控制台。Console 出现在操作系统诞生之前，那个时候的老式计算机还只能通过按钮开关等方式控制计算机的运转，而 Console 就是将控制计算机器件集中起来的面板。由于现代计算机不再使用控制台来控制电脑，所以现代操作系统中的 Console 一般指控制台终端。</p>
<h3 id="terminal">Terminal</h3>
<p>Terminal 意即终端。顾名思义，是连接到计算机上的终端设备。当操作系统出现之后，不再使用控制台与计算机交互，而是使用命令，为了能够输入这些命令，出现了电传打字机（Teletype），程序输入输出可以通过电传打字机打印到屏幕上。所以 Terminal 其实是指一种监视计算机输入输出的硬件。但是现代操作系统中使用更多的是软件仿真终端。</p>
<h3 id="tty">TTY</h3>
<p>TTY 即 TeleTYpe，意即电传打字机。TTY 与 Terminal 初期是同一个概念，电传打字机连接到计算机上便是一台终端设备。当时的 TTY 需要使用 UART 驱动来传输数据，而现代计算机中的 TTY 直接将输出数据渲染成视频信号，输出到显示器中，这些操作都运行在内核态。目前只能在连接键盘与显示器的计算机上使用 TTY。</p>
<h3 id="pty">PTY</h3>
<p>PTY 即 Pseudo TeleTYpe，意即伪 TTY。PTY 是现代计算机中使用终端模拟软件或者 SSH 连接所使用的伪终端，运行在用户态。现代操作系统使用的终端都是伪终端，通过终端软件对终端进行模拟。PTY 为了保证能够与 TTY 兼容，采用了主从结构，分为 PTY slave side 与 PTY master side。</p>
<h4 id="pty-slave-side">PTY slave side</h4>
<p>PTY slave side 的通过 TTY 驱动实现。PTY slave side 与 PTY master side 进行连接，将程序输入输出发送给 PTY master side 并显示出来。</p>
<h4 id="pty-master-side">PTY master side</h4>
<p>PTY master side 会将程序的输入输出显示在终端模拟软件中。例如当时用 SSH 远程连接时，PTY master side 与 SSH 连接，交换数据。</p>
<h2 id="参考文章">参考文章</h2>
<ul>
<li><a href="https://www.cnblogs.com/sparkdev/p/11460821.html" target="_blank" rel="noopener noreffer ">Linux 终端（TTY）- 来源：博客园</a></li>
<li><a href="https://www.zhihu.com/question/65280843" target="_blank" rel="noopener noreffer ">Linux 中的 console、terminal、tty、pty、pts 有哪些区别 - 来源：知乎</a></li>
</ul>]]></description>
</item>
<item>
    <title>服务器大升级</title>
    <link>https://blog.samchu.cn/posts/web-server-update/</link>
    <pubDate>Fri, 08 May 2020 23:10:36 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/web-server-update/</guid>
    <description><![CDATA[<p>这段时间在折腾自己的服务器。起因是在搭建 MCBE 服务器的时候，需要安装 WineHQ 环境，最后 MCBE 还是有一些问题没有启用。但是相信熟悉 Linux 的人都知道，删除程序时依赖环境不一定能全部删除，对于有“洁癖”的我来说，这是不能忍的。同时，这台服务器已经运行很长时间了，很多软件依赖已经忘记怎么配置的了。于是，便狠下决心重置了服务器系统，当然我的重要数据都是同步存储到本地和云端的。这篇博客就简单记录一下我服务器升级、博客迁移的过程。</p>
<h2 id="hugo">Hugo</h2>
<p><a href="https://gohugo.io/" target="_blank" rel="noopener noreffer ">Hugo</a> 是由 Go 语言实现的静态网站生成器。简单、易用、高效、易扩展、快速部署。对于我这样的博客，使用 Hugo 完全足够，虽然 Hugo 没有后台管理界面，但是为了网站能够加载及时（使用 Hugo 后，博客加载能感知得变快），还是选择了 Hugo。</p>
<p>Hugo 的安装网上教程一大把，稂莠不齐，各位有兴趣可以直接去官网查看文档安装。但是这里还是想多啰嗦几句，Hugo 只是个静态网站生成器，其工作仅仅是将你写的 Markdown 内容转换成网页文件。生成之后的部署等问题还需要自己解决。当然，由于个人喜欢服务上云，所以为了能够完整地实现博客撰写发布的工作流，我还在服务器上搭建了网页编辑器 <a href="https://coder.com/" target="_blank" rel="noopener noreffer ">Coder</a>，这样可以通过 Coder 在线撰写博客，然后通过提前编写好的部署脚本将写好的文章部署到博客文件夹下，就能实现网上撰写-发布-管理的工作流。</p>
<h2 id="nginx">Nginx</h2>
<p><a href="https://nginx.org/en/" target="_blank" rel="noopener noreffer ">Nginx</a>  是一款轻量级的 Web 服务器、反向代理服务器，由于它的内存占用少，启动极快，高并发能力强，在互联网项目中广泛应用。之前使用 WordPress 的时候，我使用的服务器软件是 Apache。Apache 更适合处理动态页面的的请求，由于我的博客从 WordPress 迁移到了 Hugo，我的服务器软件便换成了 Nginx。Nginx 更适合静态页面的请求，并且能更好的支持反向代理，这样一些服务不用暴露端口便能访问。</p>
<p>同样的，Nginx 的安装部署以及配置我不再赘述。</p>
<h2 id="coder">Coder</h2>
<p><a href="https://coder.com/" target="_blank" rel="noopener noreffer ">Coder</a> 是一款基于 VS Code 的云编辑器，能够轻松部署到服务器上。我在服务器上使用 Coder 可以实现很多目的：</p>
<ul>
<li>作为博客的后台管理界面</li>
<li>可以远程修改网页内容</li>
<li>可以在没有电脑的情况下使用完整的编程环境</li>
</ul>
<p>Coder的部署非常简单，官方的文档介绍的很清楚。Coder 默认监听服务器 8000 端口，我使用 Nginx 反向代理，将子域名「<a href="https://code.samchu.cn" target="_blank" rel="noopener noreffer ">code.samchu.cn</a>」的请求转发到本地 8000 端口上。这样便可以实现域名直接访问，而不需要暴露丑丑的端口了。当然，由于该功能的重要性，暂时不对外开放，大家可以到官网查看 Demo。</p>
<h2 id="个人主页">个人主页</h2>
<p>在博客升级完成之后，我还将自己的主页更新了一下。原来的主页只有简单的信息，现在的主页不仅包含我的简单信息，还包含了站点链接、联系方式等。个人主页是使用 <a href="https://blocsapp.com/" target="_blank" rel="noopener noreffer ">Blocs</a> 编写，方便快捷，这个软件目前仅支持 macOS。</p>
<h2 id="rss-服务器">RSS 服务器</h2>
<p>服务器新增加了 RSS 订阅服务器，之前使用 Inoreader 由于免费版会有广告，并且不支持插件，所以便想到了在服务器上自建 RSS 服务器。RSS 服务端软件使用的是 <a href="https://tt-rss.org/" target="_blank" rel="noopener noreffer ">Tiny Tiny RSS</a>，软件部署比较简单，主要是需要提前部署好 PHP、MySQL服务，并且需要在 MySQL 中创建好 RSS 服务器使用的账户和数据库。RSS 服务器通过 Nginx 绑定到了「<a href="https://rss.samchu.cn" target="_blank" rel="noopener noreffer ">rss.samchu.cn</a>」子域名上。</p>
<h2 id="服务器监控面板">服务器监控面板</h2>
<p>服务器监控面板还是使用的 <a href="https://www.netdata.cloud/" target="_blank" rel="noopener noreffer ">Netdata</a> 面板。监控数据全面，并且支持同步回放。同样的，Netdata 面板默认监听本地 19999 端口，所以我们需要使用 Nginx 反向代理到「<a href="https://panel.samchu.cn" target="_blank" rel="noopener noreffer ">panel.samchu.cn</a>」子域名。不过由于安全性考虑，该功能不对外开放，大家可以到官网查看 Live Demo。</p>
<h2 id="网站安全性及性能提升">网站安全性及性能提升</h2>
<p>这次升级，所有子域名全部使用 HTTPS 协议，更加安全，防止中间人劫持。同时，对网站服务器权限进行限制，只开放网站文件夹的权限。对于比较重要的站点服务进行鉴权，防止通过服务漏洞进行攻击。</p>
<p>除了对安全性的升级，这次还对网站的响应性能进行了提升，详细可以参见少数派的文章 <a href="https://sspai.com/post/60103" target="_blank" rel="noopener noreffer ">进阶指南 | 如何让你的静态网站极速打开</a>，里面详细介绍了对于静态网页加速的一些小技巧，大家有需求可以学习一下。</p>
<hr>
<p>总结一下吧，这次的服务器升级花了大概一周左右，在 Nginx 配置和个人主页升级上花的时间比较多，其他就只是普通升级。个人对这次升级很满意，特别是博客的打开速度有了明显提升，不夸张讲，1-2秒肉眼可见的提升。这篇博客只是记录一下这次升级的内容，有兴趣的朋友可以参考一下，自己研究研究。</p>]]></description>
</item>
<item>
    <title>Linux Windows 双系统时间不一致</title>
    <link>https://blog.samchu.cn/posts/linux-windows-dualsystem-time-conflict/</link>
    <pubDate>Wed, 31 Jul 2019 20:30:16 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/linux-windows-dualsystem-time-conflict/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="https://s3.samchu.cn/static/image/linux-windows-time.png" referrerpolicy="no-referrer">
            </div><p>大家在装完 Linux 系统后，可能会出现 Linux Windows 两个系统的时间不一致，一般是相差 8 小时。下面就来分析该问题，并给出解决办法。</p>
<h2 id="原因分析">原因分析</h2>
<p><a href="https://baike.baidu.com/item/%e4%b8%96%e7%95%8c%e6%97%b6/692237" target="_blank" rel="noopener noreffer ">GMT</a>：Greenwich Mean Time，即格林尼治标准时间，也就是世界时。GMT 以地球自转为基础的时间计量系统，但由于地球自转不均匀，导致 GMT 不精确，现在已经不再作为世界标准时间使用。</p>
<p><a href="https://baike.baidu.com/item/%e5%8d%8f%e8%b0%83%e4%b8%96%e7%95%8c%e6%97%b6/787659" target="_blank" rel="noopener noreffer ">UTC</a>：Universal Time Coordinated，即协调世界时。UTC 是以原子时秒长为基础，在时刻上尽量接近于 GMT 的一种时间计量系统。为确保 UTC 与 GMT 相差不会超过 0.9 秒，在有需要的情况下会在 UTC 内加上正或负闰秒。UTC 现在作为世界标准时间使用。</p>
<p>RTC：Real-Time Clock，即实时时钟，在计算机领域作为硬件时钟的简称。</p>
<p>世界上不同地区所在的时区是不同的，这些时区决定了当地的本地时间。比如北京处于东八区，即北京时间为 UTC + 8，如果 UTC 时间现在是上午 6 点整，那么北京时间为 14 点整。</p>
<p>Windows 与 Linux 看待硬件时间的方式不同。Windows 把电脑的硬件时钟（RTC）看成是本地时间，即 RTC = Local Time，Windows 会直接显示硬件时间；而 Linux 则是把电脑的硬件时钟看成 UTC 时间，即 RTC = UTC，那么 Linux 显示的时间就是硬件时间加上时区。</p>
<h2 id="解决办法">解决办法</h2>
<p>既然知道了问题原因，我们就知道如何去解决，大概思路分为两种，一是让 Windows 认为硬件时钟是 UTC 时间，二是让 Linux 认为硬件时钟是本地时间。</p>
<h3 id="修改-windows-硬件时钟为-utc-时间">修改 Windows 硬件时钟为 UTC 时间</h3>
<p>以管理员身份打开 「PowerShell」，输入以下命令：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-powershell" data-lang="powershell"><span class="line"><span class="cl"><span class="p">&gt;</span> <span class="n">Reg</span> <span class="n">add</span> <span class="n">HKLM</span><span class="p">\</span><span class="n">SYSTEM</span><span class="p">\</span><span class="n">CurrentControlSet</span><span class="p">\</span><span class="n">Control</span><span class="p">\</span><span class="n">TimeZoneInformation</span> <span class="p">/</span><span class="n">v</span> <span class="n">RealTimeIsUniversal</span> <span class="p">/</span><span class="n">t</span> <span class="n">REG_DWORD</span> <span class="p">/</span><span class="n">d</span> <span class="mf">1</span>
</span></span></code></pre></div><p>或者打开「注册表编辑器」，定位到 <code>计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation</code> 目录下，新建一个 <code>DWORD</code> 类型，名称为 <code>RealTimeIsUniversal</code> 的键，并修改键值为 <code>1</code> 即可。</p>
<h3 id="修改-linux-硬件时钟为本地时间">修改 Linux 硬件时钟为本地时间</h3>
<p>这里大家可以根据自己 Linux 发行版的方法来修改。我这里给出现在大多数发行版由 <code>timedatectl</code> 来管理时间的修改方法。</p>
<p>在终端中，输入以下命令：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ timedatectl set-local-rtc <span class="m">1</span> --adjust-system-clock
</span></span></code></pre></div><p>现在，系统时间显示正常了。</p>
<p>这两种方法中，本人推荐第一种方法，修改 Windows 的时间管理。因为在 Linux 系统中修改后，输入 <code>timedatectl</code> 命令后，会出现警告，提示你使用 RTC 时钟会导致一些程序错误；并且 Windows 也在更改时间管理方式为 UTC 时间。</p>]]></description>
</item>
<item>
    <title>Linux 系统引导失败，出现 grub rescue 恢复界面</title>
    <link>https://blog.samchu.cn/posts/linux-grub-rescue/</link>
    <pubDate>Wed, 24 Jul 2019 20:28:32 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/linux-grub-rescue/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="https://s3.samchu.cn/static/image/grub-rescue.png" referrerpolicy="no-referrer">
            </div><p>大家在使用 Linux 系统，特别是双系统，因为调整分区或者其他原因导致开机出现 <code>grub rescue&gt;</code> 界面时，不要惊慌，可能并不是系统文件损坏，大家通过一些恢复手段，能进行修复。下面就详细介绍一下。</p>
<h2 id="原因分析">原因分析</h2>
<p>造成该问题的原因可能有：</p>
<ol>
<li>对硬盘进行分区、修改使硬盘分区发生变化</li>
<li>重装系统时选择了不同分区</li>
<li>格式化了 Linux 分区</li>
</ol>
<p>其中，第 1、2 点原因造成的引导丢失比较容易修复，第 3 点原因造成的引导丢失无法修复。</p>
<h2 id="恢复步骤">恢复步骤</h2>
<h3 id="1列出硬盘分区">1.列出硬盘分区</h3>
<p>首先，使用 <code>ls</code> 命令列出所有分区：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">grub rescue&gt; ls
</span></span></code></pre></div><p>系统会显示出硬盘的所有分区，例如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">(</span>hd0<span class="o">)</span>,<span class="o">(</span>hd0,gpt0<span class="o">)</span>,<span class="o">(</span>hd0,gpt1<span class="o">)</span>,<span class="o">(</span>hd0,gpt2<span class="o">)</span>,<span class="o">(</span>hd0,gpt3<span class="o">)</span>,<span class="o">(</span>hd0,gpt4<span class="o">)</span>
</span></span></code></pre></div><h3 id="2找到-grub-文件夹所在分区">2.找到 grub 文件夹所在分区</h3>
<p>如果系统的「/boot」文件夹没有单独分区（大多数人应该是如此），那么使用 <code>ls (X,Y)/boot/grub</code> 命令浏览所有分区，其中 <code>X</code> 代表硬盘号，<code>Y</code> 代表分区号，如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">grub rescue&gt; ls <span class="o">(</span>hd0,gpt3<span class="o">)</span>/boot/grub
</span></span></code></pre></div><p>如果系统没有报错，显示出了文件夹下面的文件，那么该分区就是我们要找的分区，记下硬盘号和分区号。</p>
<p>同样的，如果系统的「/boot」文件夹单独为一个分区或者上一条指令没有找到需要的分区，则使用 <code>ls (X,Y)/grub</code> 命令，其中 <code>X</code> 代表硬盘号，<code>Y</code> 代表分区号。</p>
<h3 id="3设置-grub-启动位置">3.设置 grub 启动位置</h3>
<p>设置 grub 启动的分区和文件夹，如：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">grub rescue&gt; <span class="nb">set</span> <span class="nv">root</span><span class="o">=(</span>hd0,gpt3<span class="o">)</span>
</span></span><span class="line"><span class="cl">grub rescue&gt; <span class="nb">set</span> <span class="nv">prefix</span><span class="o">=(</span>hd0,gpt3<span class="o">)</span>/boot/grub
</span></span></code></pre></div><p>其中的硬盘号和分区号需要自行确定；grub 安装位置也需要自行确定，即第二行中，<code>/boot/grub</code> 根据需求替换为 <code>/grub</code>。</p>
<h3 id="4设置-grub-进入正常模式">4.设置 grub 进入正常模式</h3>
<p>通过以下命令，进入正常模式：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">grub rescue&gt; insmod normal
</span></span><span class="line"><span class="cl">grub rescue&gt; normal
</span></span></code></pre></div><p>现在，grub 由恢复模式进入了正常模式，丢失的启动菜单应该能正常显示了，可以通过 grub 引导至系统。</p>
<h3 id="5更新-grub-引导">5.更新 grub 引导</h3>
<p>如果此时重启，问题依旧存在。所以我们进入 Linux 系统后，需要马上更新 grub 引导，对 grub 进行修复。在进入 Linux 系统后，在终端执行：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ sudo update-grub
</span></span><span class="line"><span class="cl">$ sudo grub-install /dev/sda
</span></span></code></pre></div><p>至此，你可以重新启动，进入正常的引导界面了，丢失的引导就修复回来了。</p>]]></description>
</item>
<item>
    <title>Markdown 完全指南</title>
    <link>https://blog.samchu.cn/posts/markdown-guide/</link>
    <pubDate>Wed, 03 Jul 2019 17:07:01 &#43;0800</pubDate>
    <author>Sam Chu</author>
    <guid>https://blog.samchu.cn/posts/markdown-guide/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="https://s3.samchu.cn/static/image/markdown.png" referrerpolicy="no-referrer">
            </div><h2 id="初识-markdown">初识 Markdown</h2>
<p>Markdown 是一种可以使用普通文本编辑器编写的标记语言，通过简单的标记语法，它可以使普通文本内容具有一定的格式。Markdown 通过标记语法，使用预设的样式，简化我们的文字排版，使我们能够专心于创作内容。使用 Markdown，从内容到格式到配图，都可以使用键盘来控制。</p>
<p>现在，支持 Markdown 语法的编辑器越来越多，很多网站（如 <a href="https://www.jianshu.com/" target="_blank" rel="noopener noreffer ">简书</a>）都加入了对 Markdown 的支持。你可以将 Markdown 导出为 PDF 等格式，还可以导出成 HTML 格式在网页上发布。Markdown 可扩展性很高，很多解释器都会支持 LaTex、流程图、时序图等功能。</p>
<p>Markdown 的这些特性造就它方便使用，易于修改与版本控制，能兼容绝大多数的编辑器与网站，可以让创作者不被花样的格式打断思路。</p>
<h2 id="markdown-官方文档">Markdown 官方文档</h2>
<p><a href="https://daringfireball.net/projects/markdown/syntax" target="_blank" rel="noopener noreffer ">原版 Markdown 语法说明</a></p>
<h2 id="markdown-语法规则">Markdown 语法规则</h2>
<h3 id="标题">标题</h3>
<p>在 Markdown 中，表示文章标题，只需要在文字前面加上 <code>#</code> 即可。Markdown 支持六级标题。</p>
<p>示例：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="gh"># 一级标题
</span></span></span><span class="line"><span class="cl"><span class="gh"></span><span class="gu">## 二级标题
</span></span></span><span class="line"><span class="cl"><span class="gu">### 三级标题
</span></span></span><span class="line"><span class="cl"><span class="gu">#### 四级标题
</span></span></span><span class="line"><span class="cl"><span class="gu">##### 五级标题
</span></span></span><span class="line"><span class="cl"><span class="gu">###### 六级标题
</span></span></span></code></pre></div><p>效果：</p>
<h1 id="一级标题">一级标题</h1>
<h2 id="二级标题">二级标题</h2>
<h3 id="三级标题">三级标题</h3>
<h4 id="四级标题">四级标题</h4>
<h5 id="五级标题">五级标题</h5>
<h6 id="六级标题">六级标题</h6>
<h3 id="水平线">水平线</h3>
<p>如果需要在文章中加入水平分割线，可以在空行中输入三个或三个以上的 <code>-</code> 或者 <code>*</code>。</p>
<p>示例：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">***
</span></span><span class="line"><span class="cl">水平分割线可以将你的内容分开。
</span></span><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">水平分割线可以很明确的分开你的章节。
</span></span><span class="line"><span class="cl"><span class="ge">* *</span> *
</span></span><span class="line"><span class="cl">但是不要用太多水平分割线，使你的内容不连续。
</span></span><span class="line"><span class="cl">-----
</span></span></code></pre></div><p>效果：</p>
<hr>
<p>水平分割线可以将你的内容分开。</p>
<hr>
<p>水平分割线可以很明确的分开你的章节。</p>
<hr>
<p>但是不要用太多水平分割线，使你的内容不连续。</p>
<hr>
<h3 id="强调">强调</h3>
<ul>
<li>
<p>加粗<br>
将需要加粗的文字用两个 <code>*</code> 包含起来。</p>
</li>
<li>
<p>斜体<br>
将需要倾斜的文字用一个 <code>*</code> 包含起来。</p>
</li>
<li>
<p>斜体加粗<br>
将需要斜体加粗的文字用三个 <code>*</code> 包含起来。</p>
</li>
<li>
<p>删除线<br>
将需要加删除线的文字用两个 <code>~</code> 包含起来。</p>
</li>
</ul>
<p>示例：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">一段文字里面可能需要**加粗**、*斜体*、***斜体加粗***、~~删除线~~等文字格式。
</span></span></code></pre></div><p>效果：</p>
<p>一段文字里面可能需要<strong>加粗</strong>、<em>斜体</em>、<em><strong>斜体加粗</strong></em>、<del>删除线</del>等文字格式。</p>
<h3 id="引用">引用</h3>
<p>如果你需要引用别人的话，那么你可以在你引用的文字前面加上 <code>&gt;</code> 即可。</p>
<p>示例：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="k">&gt; </span><span class="ge">这是引用的其他人的话。
</span></span></span><span class="line"><span class="cl"><span class="ge"></span>&gt;&gt; 引用也可以嵌套。
</span></span></code></pre></div><p>效果：</p>
<blockquote>
<p>这是引用的其他人的话。</p>
<blockquote>
<p>引用也可以嵌套。</p>
</blockquote>
</blockquote>
<h3 id="列表">列表</h3>
<ul>
<li>
<p>无序列表<br>
在列表项前加上 <code>*</code> 、<code>-</code> 、<code>+</code> 其中的任意一种即可。</p>
</li>
<li>
<p>有序列表<br>
在列表项前加上 <code>1.</code> <code>2.</code> <code>3.</code> …… 即可。</p>
</li>
</ul>
<p>示例:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="k">*</span> 这是一个无序列表的例子
</span></span><span class="line"><span class="cl"><span class="k">*</span> 银河系
</span></span><span class="line"><span class="cl">    <span class="k">-</span> 太阳系
</span></span><span class="line"><span class="cl">        + 地球
</span></span><span class="line"><span class="cl">        + 火星
</span></span><span class="line"><span class="cl">        + ……
</span></span><span class="line"><span class="cl">    <span class="k">-</span> ……
</span></span><span class="line"><span class="cl"><span class="k">*</span> ……
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">1.</span> 这是一个有序列表的例子
</span></span><span class="line"><span class="cl"><span class="k">2.</span> 需求分析
</span></span><span class="line"><span class="cl"><span class="k">3.</span> 软件建模设计
</span></span><span class="line"><span class="cl">    <span class="k">*</span> 软件概要设计
</span></span><span class="line"><span class="cl">    <span class="k">*</span> 软件详细设计
</span></span><span class="line"><span class="cl">    <span class="k">*</span> 数据库设计
</span></span><span class="line"><span class="cl"><span class="k">4.</span> 编写程序
</span></span><span class="line"><span class="cl"><span class="k">5.</span> ……
</span></span></code></pre></div><p>效果：</p>
<ul>
<li>这是一个无序列表的例子</li>
<li>银河系
<ul>
<li>太阳系
<ul>
<li>地球</li>
<li>火星</li>
<li>……</li>
</ul>
</li>
<li>……</li>
</ul>
</li>
<li>……</li>
</ul>
<ol>
<li>这是一个有序列表的例子</li>
<li>需求分析</li>
<li>软件建模设计
<ul>
<li>软件概要设计</li>
<li>软件详细设计</li>
<li>数据库设计</li>
</ul>
</li>
<li>编写程序</li>
<li>……</li>
</ol>
<h3 id="表格">表格</h3>
<p>在 Markdown 中插入表格，比较复杂，如以下示例：</p>
<pre tabindex="0"><code>| 编号 | 品名  | 单价 |
| ---- | :---: | ---: |
| 1    | 西瓜  |   30 |
| 2    | 桃子  |    5 |
| 3    | 橘子  |    8 |
</code></pre><p>每列之间通过 <code>|</code> 分开，表头和内容通过第二行的分割线分开。第二行中，<code>-</code> 至少有一个，<code>-</code> 两边的 <code>:</code> 表示表格对其方式，两边都有表示该列为「居中」对齐，只在右边表示「靠右」对齐。</p>
<p>效果：</p>
<table>
<thead>
<tr>
<th>编号</th>
<th style="text-align:center">品名</th>
<th style="text-align:right">单价</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td style="text-align:center">西瓜</td>
<td style="text-align:right">30</td>
</tr>
<tr>
<td>2</td>
<td style="text-align:center">桃子</td>
<td style="text-align:right">5</td>
</tr>
<tr>
<td>3</td>
<td style="text-align:center">橘子</td>
<td style="text-align:right">8</td>
</tr>
</tbody>
</table>
<h3 id="代码">代码</h3>
<ul>
<li>
<p>行内代码<br>
行内代码是指在包含在一句话内的代码，将代码用一个 <code>`</code> 包含即可。</p>
</li>
<li>
<p>行间代码<br>
行间代码是指在两行之间的代码块，将代码块用独占一行的 <code>```</code> 包含即可。</p>
</li>
</ul>
<p>示例:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">你可能会遇到 <span class="sb">`**行内代码**`</span>；或者代码块的情况。
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">```
</span></span></span><span class="line"><span class="cl"><span class="s"></span>这是一个代码块，无论是行内代码或者行间代码，其内容或格式都不会被改变。
</span></span><span class="line"><span class="cl">如果代码中也存在「`」，那么需要使用「``」或者「````」来表示代码内容。
</span></span><span class="line"><span class="cl"><span class="s">```</span>
</span></span></code></pre></div><p>效果：</p>
<p>你可能会遇到 <code>**行内代码**</code>；或者代码块的情况。</p>
<pre tabindex="0"><code>这是一个代码块，无论是行内代码或者行间代码，其内容或格式都不会被改变。
如果代码中也存在「`」，那么需要使用「``」或者「````」来表示代码内容。
</code></pre><h3 id="链接">链接</h3>
<p>当你需要在文章中插入网页链接时，只需要使用 <code>[website](URL/to/website)</code> 就可以插入链接文字。其中 <code>[]</code> 中是链接显示文字，<code>()</code> 中是网站链接。</p>
<p>像 Email 之类的链接可以采取直接链接 <code>&lt;email or URL&gt;</code>。其中 <code>&lt;&gt;</code> 中为 Email 地址或者链接地址。</p>
<p>示例：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">点击 [<span class="nt">这里</span>](<span class="na">https://blog.samchu.cn/</span>) 回到我博客首页。
</span></span><span class="line"><span class="cl">我的电子邮箱：<span class="p">&lt;</span><span class="nt">samchu-social</span><span class="err">@</span><span class="na">outlook</span><span class="err">.</span><span class="na">com</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>效果：</p>
<p>点击 <a href="https://blog.samchu.cn/" target="_blank" rel="noopener noreffer ">这里</a> 回到我博客首页。<br>
我的电子邮箱：<a href="mailto:samchu-social@outlook.com" rel="">samchu-social@outlook.com</a></p>
<h3 id="图片">图片</h3>
<p>当你需要在文章中插入图片时，只需要使用 <code>![picture annotation](URL/to/picture &quot;picture title&quot;)</code> 就可以插入图片。其中 <code>[]</code> 中是图片下方的注解，可以省略，<code>()</code> 中是图片链接，<code>&quot;&quot;</code> 中是图片标题，当鼠标指向图片时会显示图片标题，可以省略。</p>
<p>示例：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">![<span class="nt">This is the icon of my blog</span>](<span class="na">https://static.samchu.cn/image/favicon/favicon_256x256.png &#34;favicon&#34;</span>)
</span></span></code></pre></div><p>效果:</p>
<p><figure><a class="lightgallery" href="https://static.samchu.cn/image/favicon/favicon_256x256.png" title="This is the icon of my blog" data-thumbnail="https://static.samchu.cn/image/favicon/favicon_256x256.png" data-sub-html="<h2>favicon</h2><p>This is the icon of my blog</p>">
        
    </a><figcaption class="image-caption">favicon</figcaption>
    </figure></p>
<h2 id="写在最后">写在最后</h2>
<p>Markdown 语言是一种易于掌握，便于利用的语言。其独特之处就是能够帮助创作者排除文字格式的干扰，专心创作。这篇文章就是用 Markdown 写出来的。Markdown 的语法很简单，标记符号只有十多个，相对于 HTML 语言来说，Markdown 可以说是很轻量化，学习门槛很低。学会了这门语言，对以后的工作学习生活有一劳永逸的作用。</p>
<blockquote>
<p>We believe that writing is about content, about what you want to say – not about fancy formatting.<br>
我们坚信写作写的是内容，所思所想，而不是花样格式<br>
— Ulysses for Mac</p>
</blockquote>]]></description>
</item>
</channel>
</rss>
