<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>linux 手册onDocs</title><link>https://hiraethecho.github.io/docs/linux/</link><description>Recent contentinlinux 手册onDocs</description><generator>Hugo --0.152.2</generator><language>en</language><managingEditor>wyz2016zxc@outlook.com(Hiraeth)</managingEditor><webMaster>wyz2016zxc@outlook.com(Hiraeth)</webMaster><atom:link href="https://hiraethecho.github.io/docs/linux/index.xml" rel="self" type="application/rss+xml"/><item><title>grub rescue</title><link>https://hiraethecho.github.io/docs/linux/grub-rescue/</link><pubDate>Tue, 06 Jan 2026 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/grub-rescue/</guid><description>在windows下搞坏grub又没有live系统，使用神秘的grub rescue启动linux</description><content:encoded><![CDATA[<h1 id="grub-rescure">
  <a class="anchor inpage" href="#grub-rescure">#</a>grub rescure</h1>
<p>全完蛋的时候还是要live iso进去搞</p>
<h2 id="启动">
  <a class="anchor inpage" href="#%e5%90%af%e5%8a%a8">##</a>启动</h2>
<p><code>ls</code> 查看分区</p>
<p>我用的是btrfs系统。查找 Btrfs 分区 <code>ls (hd0,gpt2)/</code></p>
<p>设置prefix <code>set prefix=(hd0,gpt2)/@/boot/grub</code><br>
或者，如果 @boot 是独立子卷 <code>set prefix=(hd0,gpt2)/@boot/grub</code><br>
或者，如果没有子卷结构（早期安装） <code>set prefix=(hd0,gpt2)/boot/grub</code></p>
<p>加载 Btrfs 模块 <code>insmod btrfs</code></p>
<p>继续正常流程</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">set root=(hd0,gpt2)
insmod normal
normal</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="修复grub">
  <a class="anchor inpage" href="#%e4%bf%ae%e5%a4%8dgrub">##</a>修复grub</h2>
<p>安装</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">grub-install --target=x86_64-efi --efi-directory=/efi  --bootloader-id=ARCH</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>配置</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">grub-mkconfig -o /boot/grub/grub.cfg</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="其他">
  <a class="anchor inpage" href="#%e5%85%b6%e4%bb%96">##</a>其他</h2>
<h3 id="核心命令">
  <a class="anchor inpage" href="#%e6%a0%b8%e5%bf%83%e5%91%bd%e4%bb%a4">###</a><strong>核心命令</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 1. ls - 列出设备和分区</span>
</span></span><span style="display:flex;"><span>ls                    <span style="color:#75715e"># 列出所有设备</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0<span style="color:#f92672">)</span>             <span style="color:#75715e"># 查看第一块磁盘</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,1<span style="color:#f92672">)</span>           <span style="color:#75715e"># 查看第一块磁盘的第一个分区</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,gpt1<span style="color:#f92672">)</span>/       <span style="color:#75715e"># 查看分区内容</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 2. set - 查看/设置环境变量</span>
</span></span><span style="display:flex;"><span>set                   <span style="color:#75715e"># 查看所有变量</span>
</span></span><span style="display:flex;"><span>set root<span style="color:#f92672">=(</span>hd0,1<span style="color:#f92672">)</span>     <span style="color:#75715e"># 设置根设备</span>
</span></span><span style="display:flex;"><span>set prefix<span style="color:#f92672">=(</span>hd0,1<span style="color:#f92672">)</span>/boot/grub</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="模块相关命令">
  <a class="anchor inpage" href="#%e6%a8%a1%e5%9d%97%e7%9b%b8%e5%85%b3%e5%91%bd%e4%bb%a4">###</a><strong>模块相关命令</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 3. insmod - 加载模块</span>
</span></span><span style="display:flex;"><span>insmod normal        <span style="color:#75715e"># 加载 normal 模块</span>
</span></span><span style="display:flex;"><span>insmod linux         <span style="color:#75715e"># 加载 Linux 引导模块</span>
</span></span><span style="display:flex;"><span>insmod chain         <span style="color:#75715e"># 加载链式引导模块</span>
</span></span><span style="display:flex;"><span>insmod part_msdos    <span style="color:#75715e"># MBR 分区支持</span>
</span></span><span style="display:flex;"><span>insmod part_gpt      <span style="color:#75715e"># GPT 分区支持</span>
</span></span><span style="display:flex;"><span>insmod ext2          <span style="color:#75715e"># ext2/3/4 支持</span>
</span></span><span style="display:flex;"><span>insmod btrfs         <span style="color:#75715e"># Btrfs 支持</span>
</span></span><span style="display:flex;"><span>insmod ntfs          <span style="color:#75715e"># NTFS 支持</span>
</span></span><span style="display:flex;"><span>insmod fat           <span style="color:#75715e"># FAT/FAT32 支持</span>
</span></span><span style="display:flex;"><span>insmod xfs           <span style="color:#75715e"># XFS 支持</span>
</span></span><span style="display:flex;"><span>insmod configfile    <span style="color:#75715e"># 配置文件支持</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 4. lsmod - 列出已加载模块</span>
</span></span><span style="display:flex;"><span>lsmod</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="引导相关命令">
  <a class="anchor inpage" href="#%e5%bc%95%e5%af%bc%e7%9b%b8%e5%85%b3%e5%91%bd%e4%bb%a4">###</a><strong>引导相关命令</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 5. normal - 进入正常模式</span>
</span></span><span style="display:flex;"><span>normal              <span style="color:#75715e"># 如果加载了 normal 模块</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 6. boot - 启动系统</span>
</span></span><span style="display:flex;"><span>boot               <span style="color:#75715e"># 启动已加载的系统</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 7. linux/initrd - 手动引导 Linux</span>
</span></span><span style="display:flex;"><span>linux <span style="color:#f92672">(</span>hd0,2<span style="color:#f92672">)</span>/vmlinuz-linux root<span style="color:#f92672">=</span>/dev/sda3
</span></span><span style="display:flex;"><span>initrd <span style="color:#f92672">(</span>hd0,2<span style="color:#f92672">)</span>/initramfs-linux.img
</span></span><span style="display:flex;"><span>boot</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="磁盘和分区侦察">
  <a class="anchor inpage" href="#%e7%a3%81%e7%9b%98%e5%92%8c%e5%88%86%e5%8c%ba%e4%be%a6%e5%af%9f">###</a><strong>磁盘和分区侦察</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 查看所有存储设备</span>
</span></span><span style="display:flex;"><span>ls
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 典型输出示例：</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 或者 UEFI/GPT：</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># (hd0) (hd0,gpt1) (hd0,gpt2) (hd0,gpt3)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 探查每个分区的内容</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,1<span style="color:#f92672">)</span>/
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,2<span style="color:#f92672">)</span>/
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,3<span style="color:#f92672">)</span>/</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="识别关键分区特征">
  <a class="anchor inpage" href="#%e8%af%86%e5%88%ab%e5%85%b3%e9%94%ae%e5%88%86%e5%8c%ba%e7%89%b9%e5%be%81">###</a><strong>识别关键分区特征</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 查找 Linux 分区特征</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,gptY<span style="color:#f92672">)</span>/boot/          <span style="color:#75715e"># 查找 /boot 目录</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,gptY<span style="color:#f92672">)</span>/etc/           <span style="color:#75715e"># 查找 /etc 目录</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,gptY<span style="color:#f92672">)</span>/usr/           <span style="color:#75715e"># 查找 /usr 目录</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 查找 GRUB 文件</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,gptY<span style="color:#f92672">)</span>/boot/grub/     <span style="color:#75715e"># GRUB 目录</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,gptY<span style="color:#f92672">)</span>/grub/          <span style="color:#75715e"># 独立 /boot 分区</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 查找 Windows 分区特征</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,msdos1<span style="color:#f92672">)</span>/Windows/     <span style="color:#75715e"># Windows 系统目录</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hdX,msdos1<span style="color:#f92672">)</span>/Users/       <span style="color:#75715e"># Windows 用户目录</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="文件系统特定探查">
  <a class="anchor inpage" href="#%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e7%89%b9%e5%ae%9a%e6%8e%a2%e6%9f%a5">###</a><strong>文件系统特定探查</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 先加载文件系统模块再查看</span>
</span></span><span style="display:flex;"><span>insmod ext2
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,1<span style="color:#f92672">)</span>/
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>insmod btrfs
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,2<span style="color:#f92672">)</span>/           <span style="color:#75715e"># 可能看到 @, @home 等子卷</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>insmod ntfs
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,3<span style="color:#f92672">)</span>/           <span style="color:#75715e"># Windows 分区</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>insmod fat
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,gpt1<span style="color:#f92672">)</span>/        <span style="color:#75715e"># EFI 系统分区</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="简单的-grub-文件丢失">
  <a class="anchor inpage" href="#%e7%ae%80%e5%8d%95%e7%9a%84-grub-%e6%96%87%e4%bb%b6%e4%b8%a2%e5%a4%b1">###</a><strong>简单的 GRUB 文件丢失</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>set prefix<span style="color:#f92672">=(</span>hd0,gpt2<span style="color:#f92672">)</span>/boot/grub
</span></span><span style="display:flex;"><span>set root<span style="color:#f92672">=(</span>hd0,gpt2<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>insmod normal
</span></span><span style="display:flex;"><span>normal</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>进入系统后运行：grub-install /dev/sda</p>
<h3 id="分区编号改变">
  <a class="anchor inpage" href="#%e5%88%86%e5%8c%ba%e7%bc%96%e5%8f%b7%e6%94%b9%e5%8f%98">###</a><strong>分区编号改变</strong></h3>
<p>原来的 (hd0,2) 现在变成了 (hd0,3)</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>set prefix<span style="color:#f92672">=(</span>hd0,gpt3<span style="color:#f92672">)</span>/boot/grub
</span></span><span style="display:flex;"><span>set root<span style="color:#f92672">=(</span>hd0,gpt3<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>insmod normal
</span></span><span style="display:flex;"><span>normal</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>进入系统后更新 /etc/fstab 和 GRUB</p>
<h3 id="手动引导进入系统">
  <a class="anchor inpage" href="#%e6%89%8b%e5%8a%a8%e5%bc%95%e5%af%bc%e8%bf%9b%e5%85%a5%e7%b3%bb%e7%bb%9f">###</a><strong>手动引导进入系统</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 1. 找到内核和 initramfs</span>
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,gpt2<span style="color:#f92672">)</span>/boot/
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 应该看到 vmlinuz-linux 和 initramfs-linux.img</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 2. 加载必要模块</span>
</span></span><span style="display:flex;"><span>insmod part_gpt
</span></span><span style="display:flex;"><span>insmod ext2
</span></span><span style="display:flex;"><span>insmod gzio
</span></span><span style="display:flex;"><span>insmod xzio
</span></span><span style="display:flex;"><span>insmod lzopio
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 3. 设置根设备</span>
</span></span><span style="display:flex;"><span>set root<span style="color:#f92672">=(</span>hd0,gpt2<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 4. 加载内核和 initramfs</span>
</span></span><span style="display:flex;"><span>linux /boot/vmlinuz-linux root<span style="color:#f92672">=</span>/dev/sda2 rw
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 或者使用 UUID</span>
</span></span><span style="display:flex;"><span>linux /boot/vmlinuz-linux root<span style="color:#f92672">=</span>UUID<span style="color:#f92672">=</span>xxxx-xxxx rw
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>initrd /boot/initramfs-linux.img
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 5. 启动</span>
</span></span><span style="display:flex;"><span>boot</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="引导-windows-系统">
  <a class="anchor inpage" href="#%e5%bc%95%e5%af%bc-windows-%e7%b3%bb%e7%bb%9f">###</a><strong>引导 Windows 系统</strong></h3>
<p>找到 Windows 分区
对于 UEFI</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>insmod part_gpt
</span></span><span style="display:flex;"><span>insmod fat
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>hd0,gpt1<span style="color:#f92672">)</span>/EFI/Microsoft/Boot/bootmgfw.efi
</span></span><span style="display:flex;"><span>chainloader /EFI/Microsoft/Boot/bootmgfw.efi
</span></span><span style="display:flex;"><span>boot</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="调试模式">
  <a class="anchor inpage" href="#%e8%b0%83%e8%af%95%e6%a8%a1%e5%bc%8f">###</a><strong>调试模式</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 进入 GRUB 时按 ESC 或 C</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 或者从 rescue 模式</span>
</span></span><span style="display:flex;"><span>set debug<span style="color:#f92672">=</span>all
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 查看详细的调试信息</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="查看环境变量">
  <a class="anchor inpage" href="#%e6%9f%a5%e7%9c%8b%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f">###</a><strong>查看环境变量</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>set
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 重要变量：</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># prefix - GRUB 文件路径</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># root - 根设备</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># cmdpath - GRUB 镜像路径</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># debug - 调试级别</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="修复常见错误">
  <a class="anchor inpage" href="#%e4%bf%ae%e5%a4%8d%e5%b8%b8%e8%a7%81%e9%94%99%e8%af%af">###</a><strong>修复常见错误</strong></h3>
<h4 id="unknown-filesystem">
  <a class="anchor inpage" href="#unknown-filesystem">####</a><strong>unknown filesystem</strong></h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 加载对应的文件系统模块</span>
</span></span><span style="display:flex;"><span>insmod ext2    <span style="color:#75715e"># 对于 ext2/3/4</span>
</span></span><span style="display:flex;"><span>insmod btrfs   <span style="color:#75715e"># 对于 Btrfs</span>
</span></span><span style="display:flex;"><span>insmod xfs     <span style="color:#75715e"># 对于 XFS</span>
</span></span><span style="display:flex;"><span>insmod fat     <span style="color:#75715e"># 对于 FAT/EFI 分区</span>
</span></span><span style="display:flex;"><span>insmod ntfs    <span style="color:#75715e"># 对于 NTFS</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="out-of-memory">
  <a class="anchor inpage" href="#out-of-memory">####</a><strong>out of memory</strong></h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 清除已加载的模块</span>
</span></span><span style="display:flex;"><span>rmmod 模块名
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 按需加载最小模块集</span>
</span></span><span style="display:flex;"><span>insmod part_gpt
</span></span><span style="display:flex;"><span>insmod ext2
</span></span><span style="display:flex;"><span>insmod linux</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="创建-grub-修复盘">
  <a class="anchor inpage" href="#%e5%88%9b%e5%bb%ba-grub-%e4%bf%ae%e5%a4%8d%e7%9b%98">###</a><strong>创建 GRUB 修复盘</strong></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 创建一个 GRUB 救援 USB</span>
</span></span><span style="display:flex;"><span>dd <span style="color:#66d9ef">if</span><span style="color:#f92672">=</span>/usr/lib/grub/i386-pc/boot.img of<span style="color:#f92672">=</span>/dev/sdX bs<span style="color:#f92672">=</span><span style="color:#ae81ff">446</span> count<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 或者使用更完整的方法</span>
</span></span><span style="display:flex;"><span>grub-install --target<span style="color:#f92672">=</span>i386-pc --boot-directory<span style="color:#f92672">=</span>/mnt/usb/boot /dev/sdX</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="配置-grub-更健壮">
  <a class="anchor inpage" href="#%e9%85%8d%e7%bd%ae-grub-%e6%9b%b4%e5%81%a5%e5%a3%ae">###</a><strong>配置 GRUB 更健壮</strong></h3>
<p>编辑 <code>/etc/default/grub</code>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 使用 UUID 而不是设备名（更稳定）</span>
</span></span><span style="display:flex;"><span>GRUB_DISABLE_LINUX_UUID<span style="color:#f92672">=</span>false
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 启用 OS 探测</span>
</span></span><span style="display:flex;"><span>GRUB_DISABLE_OS_PROBER<span style="color:#f92672">=</span>false
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 设置备用引导路径</span>
</span></span><span style="display:flex;"><span>GRUB_BACKUP_PATHS<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/boot/grub /grub&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 预加载必要模块</span>
</span></span><span style="display:flex;"><span>GRUB_PRELOAD_MODULES<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;part_gpt part_msdos ext2 btrfs xfs fat ntfs&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="八特殊文件系统注意事项">
  <a class="anchor inpage" href="#%e5%85%ab%e7%89%b9%e6%ae%8a%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9">###</a><strong>八、特殊文件系统注意事项</strong></h3>
<h4 id="zfs">
  <a class="anchor inpage" href="#zfs">####</a><strong>ZFS</strong></h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 需要额外模块</span>
</span></span><span style="display:flex;"><span>insmod zfs
</span></span><span style="display:flex;"><span>set root<span style="color:#f92672">=</span>ZFS<span style="color:#f92672">=</span>poolname/dataset</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="lvm">
  <a class="anchor inpage" href="#lvm">####</a><strong>LVM</strong></h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>insmod lvm
</span></span><span style="display:flex;"><span>ls <span style="color:#f92672">(</span>lvm/volume_group-logical_volume<span style="color:#f92672">)</span>/</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="加密分区luks">
  <a class="anchor inpage" href="#%e5%8a%a0%e5%af%86%e5%88%86%e5%8c%baluks">####</a><strong>加密分区（LUKS）</strong></h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 需要先解密</span>
</span></span><span style="display:flex;"><span>cryptomount <span style="color:#f92672">(</span>hd0,gpt2<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>set root<span style="color:#f92672">=(</span>crypto0<span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="常用命令速查表">
  <a class="anchor inpage" href="#%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4%e9%80%9f%e6%9f%a5%e8%a1%a8">##</a><strong>常用命令速查表</strong></h2>
<table>
  <thead>
      <tr>
          <th>命令</th>
          <th>用途</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>ls</code></td>
          <td>列出设备/分区</td>
          <td><code>ls (hd0,1)/</code></td>
      </tr>
      <tr>
          <td><code>set</code></td>
          <td>设置变量</td>
          <td><code>set root=(hd0,1)</code></td>
      </tr>
      <tr>
          <td><code>insmod</code></td>
          <td>加载模块</td>
          <td><code>insmod ext2</code></td>
      </tr>
      <tr>
          <td><code>normal</code></td>
          <td>进入正常模式</td>
          <td><code>normal</code></td>
      </tr>
      <tr>
          <td><code>linux</code></td>
          <td>加载内核</td>
          <td><code>linux /vmlinuz</code></td>
      </tr>
      <tr>
          <td><code>initrd</code></td>
          <td>加载initrd</td>
          <td><code>initrd /initramfs</code></td>
      </tr>
      <tr>
          <td><code>boot</code></td>
          <td>启动系统</td>
          <td><code>boot</code></td>
      </tr>
      <tr>
          <td><code>configfile</code></td>
          <td>加载配置</td>
          <td><code>configfile /grub.cfg</code></td>
      </tr>
      <tr>
          <td><code>chainloader</code></td>
          <td>链式引导</td>
          <td><code>chainloader +1</code></td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>niri</title><link>https://hiraethecho.github.io/docs/linux/niri/</link><pubDate>Tue, 02 Dec 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/niri/</guid><description>wayland下paper scroll 的 wm</description><content:encoded><![CDATA[<h1 id="滚动式窗口管理器niri">
  <a class="anchor inpage" href="#%e6%bb%9a%e5%8a%a8%e5%bc%8f%e7%aa%97%e5%8f%a3%e7%ae%a1%e7%90%86%e5%99%a8niri">#</a>滚动式窗口管理器niri</h1>
<p>长期使用dwm作为X11下的窗口管理器，一直想找一个舒服wayland下窗口管理器试试。hyprland太重了，dwl没力气再写了，river太像了，sway不习惯。<br>
最后发现了niri，水平滚动式WM，非常有趣好用。</p>
<h2 id="特点">
  <a class="anchor inpage" href="#%e7%89%b9%e7%82%b9">##</a>特点</h2>
<p>某种意义上niri是<em>反</em>窗口管理器：不管理窗口，就一排铺开。</p>
<ul>
<li>最大的优点应该是窗口不会变化大小和位置。</li>
<li>我用dwm时主要用monocle布局，并且尽量放在不同tag下（dwm的tag类似于工作区），通过切换tag来切换窗口。少数需要同时查看多个窗口时才会用grid或tile布局。<br>
在niri下用named workspace可以实现相同效果，并且更符合直觉，就像在一个大桌子上摊开文件一样。</li>
<li>另一个优势是niri的逻辑很适合触控板，在外出无鼠标使用笔记本的场景非常舒服。</li>
</ul>
<h2 id="set-up">
  <a class="anchor inpage" href="#set-up">##</a>set-up</h2>
<p>各种配置文档和实例已经很多了，所以只列出我选择的搭配的组合：</p>
<ul>
<li>niri</li>
<li>dms/noctalia</li>
<li>rofi</li>
<li>foot</li>
</ul>
<p>然后是我倾向的设定：</p>
<ul>
<li>虽然niri推荐动态工作区，但我还是习惯named space，所以用dms和noctalia这种quick-shell系的组件作为bar（waybar用不习惯）</li>
<li>我习惯少一点快捷键，不介意稍微多按几下，所以只使用
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">    Super&#43;H {
        consume-or-expel-window-left
    }
    Super&#43;L {
        consume-or-expel-window-right
    }
    Super&#43;J {
        move-window-down-or-to-workspace-down
    }
    Super&#43;K {
        move-window-up-or-to-workspace-up
    }</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>而且基本不用移动workspace或column的操作</li>
<li>使用rofi是因为X11下也可以用，保持一点一致性。</li>
</ul>
<h2 id="dot">
  <a class="anchor inpage" href="#dot">##</a>dot</h2>
<p>我的具体配置可以参考我的
，使用stow管理。<br>
niri相关的文件在<code>wm/.config/niri</code>，rofi相关的配置（没有整理）在<code>tools/.config/rofi</code>和<code>bin/.local/bin/</code></p>
]]></content:encoded></item><item><title>linux手册</title><link>https://hiraethecho.github.io/docs/linux/linux-handbook/</link><pubDate>Sat, 25 Oct 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/linux-handbook/</guid><description>&lt;h1 id="linux-handbook"&gt;
&lt;a class="anchor inpage" href="#linux-handbook"&gt;#&lt;/a&gt;Linux Handbook&lt;/h1&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;bash &amp;lt;(curl -sSL https://linuxmirrors.cn/main.sh)&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;bash &amp;lt;(curl -sSL https://linuxmirrors.cn/docker.sh)&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;details open&gt;
&lt;summary&gt;TEXT&lt;/summary&gt;&lt;pre
class="codeblock"
&gt;&lt;code class="language-" data-lang=""&gt;bash &amp;lt;(curl -sSL https://linuxmirrors.cn/docker.sh) --only-registry&lt;/code&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;h2 id="file"&gt;
&lt;a class="anchor inpage" href="#file"&gt;##&lt;/a&gt;file&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;filedialog&lt;/code&gt; 是其他应用需要选择文件时的弹窗&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="linux-handbook">
  <a class="anchor inpage" href="#linux-handbook">#</a>Linux Handbook</h1>
<p>
</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">bash &lt;(curl -sSL https://linuxmirrors.cn/main.sh)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">bash &lt;(curl -sSL https://linuxmirrors.cn/docker.sh)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">bash &lt;(curl -sSL https://linuxmirrors.cn/docker.sh) --only-registry</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="file">
  <a class="anchor inpage" href="#file">##</a>file</h2>
<p><code>filedialog</code> 是其他应用需要选择文件时的弹窗</p>
<h2 id="boot">
  <a class="anchor inpage" href="#boot">##</a>boot</h2>
<h2 id="display-manager">
  <a class="anchor inpage" href="#display-manager">##</a>display manager</h2>
<p>lightdm 有一堆莫名其妙的问题</p>
<p>gtk display还不知道怎么搞</p>
<h2 id="keyring">
  <a class="anchor inpage" href="#keyring">##</a>keyring</h2>
<p>
</p>
<p>use <code>gnome-keyring</code> and <code>thunar</code> to auto connect a webdav.

</p>
<h2 id="reference">
  <a class="anchor inpage" href="#reference">##</a>Reference</h2>
<p>
</p>
<h2 id="commands">
  <a class="anchor inpage" href="#commands">##</a>commands</h2>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>type something</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>example</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>type cd
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cd is a shell builtin</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="技巧">
  <a class="anchor inpage" href="#%e6%8a%80%e5%b7%a7">##</a>技巧</h2>
<details open>
    <summary>tldr</summary><pre
        class="codeblock"
      ><code class="language-tldr" data-lang="tldr">  Change attributes of files or directories.
  More information: &lt;https://manned.org/chattr&gt;.

  Make a file or directory [i]mmutable to changes and deletion, even by superuser:

      chattr &#43;i path/to/file_or_directory

  Make a file or directory mutable:

      chattr -i path/to/file_or_directory

  [R]ecursively make an entire directory and contents immutable:

      chattr -R &#43;i path/to/directory

  Mark a directory and its files to be interpreted in a case-insensitive manner (case-[F]olding):

      chattr &#43;F path/to/directory

  Set a file to only allow [a]ppending:

      chattr &#43;a path/to/file</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>]]></content:encoded></item><item><title>Filesystem Hierarchy Standard</title><link>https://hiraethecho.github.io/docs/linux/fhs/</link><pubDate>Mon, 09 Jun 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/fhs/</guid><description>linux文件结构标准</description><content:encoded><![CDATA[<h1 id="filesystem-hierarchy-standard">
  <a class="anchor inpage" href="#filesystem-hierarchy-standard">#</a>Filesystem Hierarchy Standard</h1>
<p>
</p>
<p>This standard consists of a set of requirements and guidelines for file and directory placement under UNIX-like operating systems. The guidelines are intended to support interoperability of applications, system administration tools, development tools, and scripts as well as greater uniformity of documentation for these systems.</p>
<h2 id="general-setting">
  <a class="anchor inpage" href="#general-setting">##</a>General setting</h2>
<h3 id="under-">
  <a class="anchor inpage" href="#under-">###</a>under <code>/</code></h3>
<p><code>/bin</code> : Essential user command binaries (for use by all users). <code>/sbin</code> : System binaries. stored in /sbin, /usr/sbin, and /usr/local/sbin.
<code>/lib</code> : Essential shared libraries and kernel modules <code>lib32</code> and <code>lib64</code>: Alternate format essential shared libraries (optional)
<code>/etc</code> : Host-specific system configuration. A &ldquo;configuration file&rdquo; is a local file used to control the operation of a program; it must be static and cannot be an executable binary.</p>
<p><code>/media</code> : Mount point for removable media
<code>/mnt</code> : Mount point for a temporarily mounted filesystem
<code>/opt</code> : Add-on application software packages
<code>/run</code> : Run-time variable data
<code>/srv</code> : Data for services provided by this system
<code>/tmp</code> : Temporary files</p>
<h3 id="usr">
  <a class="anchor inpage" href="#usr">###</a><code>/usr</code></h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
└── usr
    ├── bin
    ├── include
    ├── lib
    ├── sbin
    ├── share
    └── src</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>/usr</code> is the second major section of the filesystem. /usr is shareable, read-only data. That means that /usr should be shareable between various FHS-compliant hosts and must not be written to. Any information that is host-specific or varies with time is stored elsewhere.<br>
Large software packages must not use a direct subdirectory under the /usr hierarchy. (maybe <code>/opt</code>)</p>
<ul>
<li><code>/usr/share</code> : Architecture-independent data. The /usr/share hierarchy is for all read-only architecture independent data files.<br>
This hierarchy is intended to be shareable among all architecture platforms of a given OS; thus, for example, a site with i386, Alpha, and PPC platforms might maintain a single /usr/share directory that is centrally-mounted. Note, however, that /usr/share is generally not intended to be shared by different OSes or by different releases of the same OS.<br>
Any program or package which contains or requires data that doesn&rsquo;t need to be modified should store that data in /usr/share (or /usr/local/share, if installed locally). It is recommended that a subdirectory be used in /usr/share for this purpose. Applications using a single file may use /usr/share/misc.<br>
Game data stored in /usr/share/games must be purely static data. Any modifiable files, such as score files, game play logs, and so forth, should be placed in /var/games.</li>
<li><code>/usr/lib</code>: Includes object files and libraries. On some systems, it may also include internal binaries that are not intended to be executed directly by users or shell scripts.<br>
Applications may use a single subdirectory under /usr/lib. If an application uses a subdirectory, all architecture-dependent data exclusively used by the application must be placed within that subdirectory.</li>
<li><code>/usr/local</code> : Local hierarchy (empty after main installation) The /usr/local hierarchy is for use by the system administrator when installing software locally. It needs to be safe from being overwritten when the system software is updated. It may be used for programs and data that are shareable amongst a group of hosts, but not found in /usr.</li>
</ul>
<p>And others:</p>
<ul>
<li><code>games</code>: Games and educational binaries (optional)</li>
<li><code>include</code>: Header files included by C programs. This is where all of the system&rsquo;s general-use include files for the C programming language should be placed.</li>
<li><code>libexec</code>: Binaries run by other programs (optional)</li>
<li><code>src</code>: Source code (optional)</li>
</ul>
<h3 id="summary">
  <a class="anchor inpage" href="#summary">###</a>Summary</h3>
<table>
  <thead>
      <tr>
          <th></th>
          <th>shareable</th>
          <th>unshareable</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>static</td>
          <td><code>/usr</code>, <code>/opt</code></td>
          <td><code>/etc</code>, <code>/boot</code></td>
      </tr>
      <tr>
          <td>variable</td>
          <td><code>/var/mail</code>, <code>/var/spool/news</code></td>
          <td><code>/var/run</code>, <code>/var/lock</code></td>
      </tr>
  </tbody>
</table>
<ul>
<li>May under &lsquo;/&rsquo;,<code>/usr</code>,<code>/var</code></li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">├── bin # binary
├── lib # library
├── include # C header
├── games   # games
├── opt # opt
├── share   # data that share with other
└── src     # sources</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>only under <code>/</code></li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
├── boot
├── etc # configraturation
├── dev
├── media
├── mnt
├── proc
├── run
├── srv
├── sys
└── tmp</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="on-archlinux">
  <a class="anchor inpage" href="#on-archlinux">##</a>On archlinux,</h2>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
├── bin ⇒ usr/bin
├── boot
├── dev
├── etc
├── home
├── lib ⇒ usr/lib
├── lib64 ⇒ usr/lib
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin ⇒ usr/bin
├── srv
├── sys
├── tmp
├── usr
└── var</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>lib32</code> and <code>lib64</code> for 32-bit and 64-bit. <code>sbin</code> binaries for super user. (On debian, only root can <code>reboot</code>.)</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
└── opt
    ├── waterfox
    ├── wechat-universal
    └── wemeet</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
└── usr
    └── share
        ├── alsa
        ├── applications
        ├── awk
        ├── blueman
        ├── mime
        ├── nvim
        ├── wayland
        ├── wayland-sessions
        ├── X11
        └── zsh</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
└── usr
    └── local
        ├── bin
        ├── etc
        ├── games
        ├── include
        ├── lib
        ├── man
        ├── sbin
        ├── share
        └── src</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
└── var
    ├── cache
    ├── db
    ├── empty
    ├── games
    ├── lib
    ├── local
    ├── lock ⇒ ../run/lock
    ├── log
    ├── mail ⇒ spool/mail
    ├── opt
    ├── run ⇒ ../run
    ├── spool
    └── tmp</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="special-directories">
  <a class="anchor inpage" href="#special-directories">###</a>special directories</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
├── boot
│   ├── efi
│   ├── grub
│   ├── initramfs-linux.img
│   └── vmlinuz-linux
├── dev
│   ├── disk
│   ├── null
│   ├── random
│   └── zero
├── mnt
├── proc
│   ├── 1
│   ├── uptime
│   └── zoneinfo
├── run
│   ├── dhcpcd
│   ├── initramfs
│   ├── media # This is different
│   ├── libvirt
│   ├── systemd
│   └── xtables.lock
├── srv
│   ├── ftp
│   └── http
├── sys
│   ├── kernel
│   └── power
└── tmp</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="homes">
  <a class="anchor inpage" href="#homes">##</a>homes</h2>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">/
├── home
│   └── user
│       ├── Desktop
│       ├── Documents
│       ├── Downloads
│       ├── Music
│       ├── Pictures
│       ├── Public
│       ├── Templates
│       └── Videos
└── root
    ├── Desktop
    ├── Documents
    ├── Downloads
    ├── Music
    ├── Pictures
    ├── Public
    ├── Templates
    └── Videos</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>]]></content:encoded></item><item><title>Archlinux 上的包管理</title><link>https://hiraethecho.github.io/docs/linux/pacman/</link><pubDate>Sun, 08 Jun 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/pacman/</guid><description>pacman的一些使用技巧</description><content:encoded><![CDATA[<h1 id="package-manage-on-arch">
  <a class="anchor inpage" href="#package-manage-on-arch">#</a>Package manage on Arch</h1>
<h2 id="pacman">
  <a class="anchor inpage" href="#pacman">##</a>pacman</h2>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacman -Qqe | fzf --preview <span style="color:#e6db74">&#39;pacman -Qiil {}&#39;</span> --layout<span style="color:#f92672">=</span>reverse --bind <span style="color:#e6db74">&#39;enter:execute(pacman -Qiil {} | less)&#39;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacman -Slq | fzf --preview <span style="color:#e6db74">&#39;pacman -Si {}&#39;</span> --layout<span style="color:#f92672">=</span>reverse</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacman -D --asdeps <span style="color:#66d9ef">$(</span>pacman -Qqe<span style="color:#66d9ef">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacman -D --asexplicit base linux linux-firmware</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>cat explicit | sudo pacman -D --asexplicit -</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacman -Qii | awk <span style="color:#e6db74">&#39;/^MODIFIED/ {print $2}&#39;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacman -Qi | awk <span style="color:#e6db74">&#39;/^Name/{name=$3} /^Install Date/{print $4,$5,$6,name}&#39;</span> | sort</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="paru">
  <a class="anchor inpage" href="#paru">##</a>paru</h2>
<h2 id="tools">
  <a class="anchor inpage" href="#tools">##</a>tools</h2>
<h3 id="pacfiles">
  <a class="anchor inpage" href="#pacfiles">###</a>pacfiles</h3>
<h3 id="expac">
  <a class="anchor inpage" href="#expac">###</a>expac</h3>
<p>A data extraction tool for alpm databases, offering printf-like flexibility for pacman-based utilities.

</p>
<details open>
    <summary>man</summary><pre
        class="chroma codeblock"
      ><code class="language-man" data-lang="man"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>       Usage: expac [options] &lt;format&gt; targets...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>OPTIONS
</span></span><span style="display:flex;"><span>       -Q, --query
</span></span><span style="display:flex;"><span>           Search  the local database for provided targets. This is the default
</span></span><span style="display:flex;"><span>           behavior.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -S, --sync
</span></span><span style="display:flex;"><span>           Search the sync databases for provided targets.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -s, --search
</span></span><span style="display:flex;"><span>           Search for packages matching the strings specified by targets.  This
</span></span><span style="display:flex;"><span>           is a boolean AND query and regex is allowed.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -g, --group
</span></span><span style="display:flex;"><span>           Return packages matching the specified targets as package groups.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       --config &lt;file&gt;
</span></span><span style="display:flex;"><span>           Read from file for alpm initialization instead of /etc/pacman.conf.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -H, --humansize &lt;size&gt;
</span></span><span style="display:flex;"><span>           Format  package  sizes  in SI units according to size. Valid options
</span></span><span style="display:flex;"><span>           are:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>             B, K, M, G, T, P, E, Z, Y
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -1, --readone
</span></span><span style="display:flex;"><span>           Stop searching after the first result. This only has an effect on -S
</span></span><span style="display:flex;"><span>           operations without -s.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -d, --delim &lt;string&gt;
</span></span><span style="display:flex;"><span>           Separate each package with the specified string. The  default  value
</span></span><span style="display:flex;"><span>           is a newline character.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -l, --listdelim &lt;string&gt;
</span></span><span style="display:flex;"><span>           Separate  each  list  item  with the specified string. Lists are any
</span></span><span style="display:flex;"><span>           interpreted sequence specified with a capital  letter.  The  default
</span></span><span style="display:flex;"><span>           value is two spaces.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -p, --file
</span></span><span style="display:flex;"><span>           Interpret targets as paths to local files.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -t, --timefmt &lt;format&gt;
</span></span><span style="display:flex;"><span>           Output time described by the specified format. This string is passed
</span></span><span style="display:flex;"><span>           directly to strftime(3). The default format is %c.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -v, --verbose
</span></span><span style="display:flex;"><span>           Output  more.  ‘Package  not  found&#39; errors will be shown, and empty
</span></span><span style="display:flex;"><span>           field values will display as &#39;None&#39;.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -V, --version
</span></span><span style="display:flex;"><span>           Display version information and quit.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -h, --help
</span></span><span style="display:flex;"><span>           Display the help message and quit.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>FORMATTING
</span></span><span style="display:flex;"><span>       The format argument allows the following interpreted sequences:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %a    architecture
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %B    backup files
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %b    build date
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %C    conflicts with (no version strings)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %D    depends on
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %d    description
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %E    depends on (no version strings)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %e    package base
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %f    filename (only with -S)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %F    files (only with -Q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %g    base64 encoded PGP signature (only with -S)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %G    groups
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %H    conflicts with
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %h    sha256sum
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %i    has install scriptlet (only with -Q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %k    download size (only with -S)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %l    install date (only with -Q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %L    licenses
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %m    install size
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %M    modified backup files (only with -Q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %n    package name
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %N    required by
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %O    optional deps
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %o    optional deps (no descriptions)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %p    packager name
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %P    provides
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %R    replaces (no version strings)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %r    repo
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %s    md5sum
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %S    provides (no version strings)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %T    replaces
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %u    project URL
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %V    package validation method
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %v    version
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %w    install reason (only with -Q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %!    result number (auto-incremented counter, starts at 0)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         %%    literal %
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Note that for any lowercase tokens aside from %m  and  %k,  full  printf
</span></span><span style="display:flex;"><span>       support  is  allowed, e.g. %-20n. This does not apply to any list based,
</span></span><span style="display:flex;"><span>       date, or numerical output.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Standard backslash escape sequences are supported, as per printf(1).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXAMPLES
</span></span><span style="display:flex;"><span>       Emulate pacman&#39;s search function:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         $ expac -Ss &#39;%r/%n %v<span style="color:#ae81ff">\n</span>    %d&#39; &lt;search terms&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       List the oldest 10 installed packages (by build date):
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>         $ expac --timefmt=%s &#39;%b<span style="color:#ae81ff">\t</span>%n&#39; | sort -n | head -10</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>简短的用法</p>
<details open>
    <summary>tldr</summary><pre
        class="codeblock"
      ><code class="language-tldr" data-lang="tldr">  List the dependencies of a package:

      expac [-S|--sync] &#39;%D&#39; package

  List the optional dependencies of a package:

      expac [-S|--sync] &#34;%o&#34; package

  List the download size of packages in MiB:

      expac [-S|--sync] [-H|--humansize] M &#39;%k\t%n&#39; package1 package2 ...

  List packages marked for upgrade with their download size:

      expac [-S|--sync] [-H|--humansize] M &#39;%k\t%n&#39; $(pacman -Qqu) | sort [-sh|--sort --human-numeric-sort]

  List explicitly-installed packages with their optional dependencies:

      expac [-d|--delim] &#39;\n\n&#39; [-l|listdelim] &#39;\n\t&#39; [-Q|--query] &#39;%n\n\t%O&#39; $(pacman -Qeq)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">expac -Q &#34;%n %w %M&#34; | grep explicit | awk &#39;{print $3}&#39; | grep -v ^$</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="pacman-contrib">
  <a class="anchor inpage" href="#pacman-contrib">###</a>pacman-contrib</h3>
<h2 id="pkgbuild">
  <a class="anchor inpage" href="#pkgbuild">##</a>PKGBUILD</h2>
<h3 id="tips">
  <a class="anchor inpage" href="#tips">###</a>tips</h3>
<p>pacman 进行升级时会将修改后的软件包升级到仓库中的最新版本，可以通过下面方式避免这个行为：</p>
<p>在 PKGBUILD 中将软件包加入 modified 组：</p>
<details open>
    <summary>PKGBUILD</summary><pre
        class="chroma codeblock"
      ><code class="language-PKGBUILD" data-lang="PKGBUILD"
          ><span style="display:flex;"><span>groups<span style="color:#f92672">=(</span><span style="color:#e6db74">&#39;modified&#39;</span><span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>然后将此组加入 <code>/etc/pacman.conf</code> 的 <code>IgnoreGroup</code>：</p>
<details open>
    <summary>/etc/pacman.conf</summary><pre
        class="chroma codeblock"
      ><code class="language-/etc/pacman.conf" data-lang="/etc/pacman.conf"
          ><span style="display:flex;"><span><span style="color:#a6e22e">IgnoreGroup</span> <span style="color:#f92672">=</span> modified</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>当系统升级发现官方仓库中有新版本时，pacman 会显示软件包因为在 IgnoreGroup 中而被忽略的提示，这时需要从 ABS 编译更新的软件包以防止部分升级。</p>
]]></content:encoded></item><item><title>Display Manager</title><link>https://hiraethecho.github.io/docs/linux/sddm/</link><pubDate>Thu, 05 Jun 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/sddm/</guid><description>在Linux系统中配置显示管理器（Display Manager）的指南，包括无显示管理器和sddm的自动登录设置。</description><content:encoded><![CDATA[<h1 id="display-manager">
  <a class="anchor inpage" href="#display-manager">#</a>Display Manager</h1>
<h2 id="no-dm">
  <a class="anchor inpage" href="#no-dm">##</a>No DM</h2>
<p>skip username: <code>/etc/systemd/system/getty@tty1.service.d/skip-username.conf</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">[Service]
ExecStart=
ExecStart=-/sbin/agetty -o &#39;-p -- hiraeth&#39; --noclear --skip-login - $TERM</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="sddm">
  <a class="anchor inpage" href="#sddm">##</a>sddm</h2>
<h3 id="autologin">
  <a class="anchor inpage" href="#autologin">###</a>autologin</h3>
<p>默认session <code>/etc/sddm.conf</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">[Theme]
Current=chili

[Autologin]
User=hiraeth
Session=dwm.desktop</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>免密码
You must then also be part of the nopasswdlogin group to be able to login interactively without entering your password:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>groupadd -r nopasswdlogin
</span></span><span style="display:flex;"><span>gpasswd -a username nopasswdlogin</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>SDDM goes through PAM so you must configure the SDDM configuration of PAM: <code>/etc/pam.d/sddm</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">#%PAM-1.0
auth        sufficient  pam_succeed_if.so user ingroup nopasswdlogin
auth        include     system-login
-auth       optional    pam_gnome_keyring.so
-auth       optional    pam_kwallet5.so

account     include     system-login

password    include     system-login
-password   optional    pam_gnome_keyring.so    use_authtok

session     optional    pam_keyinit.so          force revoke
session     include     system-login
-session    optional    pam_gnome_keyring.so    auto_start
-session    optional    pam_kwallet5.so         auto_start</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>/etc/pam.d/sddm-autologin</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">#%PAM-1.0
auth        required    pam_env.so
auth        required    pam_faillock.so preauth
auth        required    pam_shells.so
auth        required    pam_nologin.so
auth        required    pam_permit.so
-auth       optional    pam_gnome_keyring.so
-auth       optional    pam_kwallet5.so
account     include     system-local-login
password    include     system-local-login
session     include     system-local-login
-session    optional    pam_gnome_keyring.so auto_start
-session    optional    pam_kwallet5.so auto_start</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="files">
  <a class="anchor inpage" href="#files">##</a>files</h2>
<details open>
    <summary>/etc/zsh/zshenv</summary><pre
        class="codeblock"
      ><code class="language-/etc/zsh/zshenv" data-lang="/etc/zsh/zshenv">export ERRFILE=&#34;$XDG_CACHE_HOME/X11/xsession-errors&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>]]></content:encoded></item><item><title>shell概览</title><link>https://hiraethecho.github.io/docs/linux/shell/</link><pubDate>Mon, 05 May 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/shell/</guid><description>主要靠ai生成的shell基本知识手册</description><content:encoded><![CDATA[<h1 id="shell">
  <a class="anchor inpage" href="#shell">#</a>shell</h1>
<h2 id="intro">
  <a class="anchor inpage" href="#intro">##</a>intro</h2>
<p>A shell is a command-line interpreter that provides a user interface for interacting with the operating system. It allows users to execute commands, run scripts, and manage system processes. Popular shells include bash, zsh, and fish.</p>
<h3 id="history">
  <a class="anchor inpage" href="#history">###</a>history</h3>
<p>The shell originated in the early days of UNIX, providing users a way to interact with the operating system. The Bourne Shell (sh) was one of the earliest, followed by more advanced shells like Bash, Zsh, and Fish. Each new shell introduced features that improved usability, scripting, and customization for users and administrators.</p>
<h3 id="posix">
  <a class="anchor inpage" href="#posix">###</a>posix</h3>
<p>POSIX stands for &ldquo;Portable Operating System Interface.&rdquo; It is a set of standardized operating system interfaces and shell command standards, maintained by the IEEE. POSIX ensures compatibility between Unix-like operating systems by defining common APIs, command-line utilities, and scripting interfaces.</p>
<p>In the context of shells, POSIX compliance ensures that shell scripts and commands written for one POSIX-compliant shell will work on another, regardless of the underlying operating system. For example, the <code>sh</code> shell is often used as a reference implementation for POSIX-compliant scripting. However, advanced shells like Bash and Zsh often extend POSIX standards with additional features and functionalities.</p>
<p>Key aspects of POSIX include:</p>
<ol>
<li><strong>Shell Command Language</strong>: Specifies syntax and utilities for scripting.</li>
<li><strong>System Interfaces</strong>: Defines APIs for file system operations, process control, and more.</li>
<li><strong>Utility Programs</strong>: Standardizes common tools like <code>grep</code>, <code>awk</code>, and <code>sed</code>.</li>
</ol>
<p>POSIX plays a critical role in ensuring interoperability and portability across different Unix-based systems, making it a cornerstone of modern shell environments.</p>
<h2 id="start-a-shell">
  <a class="anchor inpage" href="#start-a-shell">##</a>Start a shell</h2>
<p>There are three main cases that start a shell: login, interact, and in the shell scripts.</p>
<p>Linux starts a shell in the following situations:</p>
<ol>
<li><strong>Login Shell</strong>: Automatically invoked when a user logs in via TTY, SSH, or terminal emulator.</li>
<li><strong>Interactive Shell</strong>: When a user opens a new terminal window or manually starts a shell.</li>
<li><strong>Shell in Scripts</strong>: When a script containing a shebang (e.g., <code>#!/bin/bash</code>) is executed, the specified shell is started.</li>
</ol>
<p>there are also other cases, like ssh, getty, rescure mode etc</p>
<h3 id="login-shell">
  <a class="anchor inpage" href="#login-shell">###</a>login shell</h3>
<p>A shell starts automatically when you log in through a TTY, SSH, or terminal emulator. You can also start a shell manually by running its executable (e.g., bash, zsh, fish) from an existing shell or script. Shells start when prompted by the operating system or when explicitly invoked.</p>
<h3 id="interact-shell">
  <a class="anchor inpage" href="#interact-shell">###</a>interact shell</h3>
<p>After login, starting a new non-login shell (like opening a new terminal window) usually loads only the interactive shell configuration file (<code>~/.bashrc</code> for Bash, <code>~/.zshrc</code> for Zsh`). Environment variables and settings exported in the login shell are inherited by the new shell, unless overridden in the new shell&rsquo;s config file.</p>
<p>You can start most shells without loading configuration files by passing specific flags. For example, Bash: <code>bash --noprofile --norc</code>; Zsh: <code>zsh -f</code>. This launches the shell in a minimal state, ignoring personal and system-wide configuration files.</p>
<p>To start a shell as a different user, use the <code>su - username</code> or <code>sudo -i -u username</code> commands. The login shell for the specified user will be started, and it will load that user&rsquo;s configuration files (such as those in their home directory). Controlling which files are loaded depends on the shell and options passed; for example, you can use <code>bash --noprofile --norc</code> after switching users to avoid loading configs.</p>
<p>When starting a new shell with a different user, to avoid inheriting unwanted configuration, use options that bypass user config files (e.g. for Bash: <code>bash --noprofile --norc</code>; for Zsh: <code>zsh -f</code>). If you want to inherit configurations from the parent shell, you can manually export the desired environment variables before starting the new shell, or source config files as needed.</p>
<p>By default, when a new shell is started, the present working directory (PWD) is inherited from the parent process (the shell or terminal that launched it). If a shell is started during login (for example, via TTY or SSH), the default directory is usually the user&rsquo;s home directory (<code>$HOME</code>).</p>
<h3 id="shell-in-de">
  <a class="anchor inpage" href="#shell-in-de">###</a>shell in DE</h3>
<p>A special case is starting a shell in a DE (Desktop Environment).</p>
<p>Launcher programs like dmenu or rofi typically use the shell specified in the <code>SHELL</code> environment variable of the running user. If <code>SHELL</code> is not set, they may default to <code>/bin/sh</code> or whatever is configured in <code>/etc/passwd</code> for the user.</p>
<p>The default working directory (PWD) for a shell launched by a program like dmenu or rofi is typically the user&rsquo;s home directory (<code>$HOME</code>). However, this can be changed by the launcher or by the environment from which the launcher itself was started.</p>
<h3 id="shell-in-script">
  <a class="anchor inpage" href="#shell-in-script">###</a>shell in script</h3>
<p>Yes, when running a shell within a script (using shebang like <code>#!/bin/bash</code> or <code>#!/bin/zsh</code>), the script may behave differently depending on the shell used. Some shells have distinct syntax, built-ins, or environment handling. Scripts can also use subshells to isolate environments, and you can explicitly invoke subshells with commands like <code>(command)</code> or by calling another shell executable within the script.</p>
<p>When a shell is used in a script, it uses the environment variables defined in the parent shell or operating system environment where the script is executed. These may include system-wide variables (e.g., PATH, HOME) and user-defined variables from configuration files (e.g., ~/.bashrc, ~/.zshrc). The script can also define its own environment variables, which will only persist during the script&rsquo;s execution. Additionally, the shell may load configuration files specific to the shell being used, depending on whether the script is executed in a login or non-login context.</p>
<p>For example:</p>
<ul>
<li>A script that starts with <code>#!/bin/bash</code> as the shebang will inherit environment variables from the parent Bash shell.</li>
<li>If the script explicitly sources configuration files (e.g., <code>source ~/.bashrc</code>), it may load additional variables or settings.</li>
<li>Subshells started within the script can have isolated environments, which can either inherit variables or define new ones for their scope.</li>
</ul>
<p>To inspect or modify the environment variables in a script, commands like <code>export</code>, <code>printenv</code>, or <code>env</code> can be used.</p>
<p>Keep in mind that some shells have distinct syntax and behaviors concerning environment variables, so the choice of shell can influence the script&rsquo;s behavior.</p>
<p>To avoid unintended configurations, you can start the shell with options to bypass configuration files or explicitly define the environment variables needed by the script.</p>
<p>Example:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash --noprofile --norc
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>export MY_VARIABLE<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;value&#34;</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Current PATH: </span>$PATH<span style="color:#e6db74">&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="configuration">
  <a class="anchor inpage" href="#configuration">##</a>configuration</h2>
<h3 id="set-shell">
  <a class="anchor inpage" href="#set-shell">###</a>set shell</h3>
<p>To change the default shell for a user, use the command:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>chsh -s /path/to/shell</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>For example, to set Zsh as the default shell:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>chsh -s <span style="color:#66d9ef">$(</span>which zsh<span style="color:#66d9ef">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="configuration-files">
  <a class="anchor inpage" href="#configuration-files">###</a>configuration files</h3>
<p>zsh</p>
<table>
  <thead>
      <tr>
          <th>Shell Type</th>
          <th>System Configurations</th>
          <th>User Configurations</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Login Shell</td>
          <td><code>/etc/zprofile</code>, <code>/etc/zlogin</code></td>
          <td><code>~/.zprofile</code>, <code>~/.zlogin</code></td>
      </tr>
      <tr>
          <td>Interactive Shell</td>
          <td><code>/etc/zshrc</code></td>
          <td><code>~/.zshrc</code></td>
      </tr>
      <tr>
          <td>Shell in a Script</td>
          <td><code>/etc/zshenv</code></td>
          <td><code>~/.zshenv</code></td>
      </tr>
  </tbody>
</table>
<p>bash</p>
<table>
  <thead>
      <tr>
          <th>Shell Type</th>
          <th>System Configurations</th>
          <th>User Configurations</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Login Shell</td>
          <td><code>/etc/profile</code></td>
          <td><code>~/.bash_profile</code>, <code>~/.bash_login</code>, <code>~/.profile</code></td>
      </tr>
      <tr>
          <td>Interactive Shell</td>
          <td><code>/etc/bash.bashrc</code></td>
          <td><code>~/.bashrc</code></td>
      </tr>
      <tr>
          <td>Shell in a Script</td>
          <td>None (scripts do not load config files)</td>
          <td>None</td>
      </tr>
  </tbody>
</table>
<h3 id="syntax">
  <a class="anchor inpage" href="#syntax">###</a>syntax</h3>
<p>Zsh Configuration Files:</p>
<ol>
<li>
<p><strong>Setting Environment Variables</strong>:</p>
<details open>
    <summary>zsh</summary><pre
        class="chroma codeblock"
      ><code class="language-zsh" data-lang="zsh"
          ><span style="display:flex;"><span>export PATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$PATH<span style="color:#e6db74">:/new/path&#34;</span>
</span></span><span style="display:flex;"><span>export EDITOR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vim&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Defining Aliases</strong>:</p>
<details open>
    <summary>zsh</summary><pre
        class="chroma codeblock"
      ><code class="language-zsh" data-lang="zsh"
          ><span style="display:flex;"><span>alias ll<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;ls -la&#34;</span>
</span></span><span style="display:flex;"><span>alias gs<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;git status&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Creating Functions</strong>:</p>
<details open>
    <summary>zsh</summary><pre
        class="chroma codeblock"
      ><code class="language-zsh" data-lang="zsh"
          ><span style="display:flex;"><span><span style="color:#66d9ef">function</span> greet<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Hello, </span>$1<span style="color:#e6db74">!&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Sourcing Other Files</strong>:</p>
<details open>
    <summary>zsh</summary><pre
        class="chroma codeblock"
      ><code class="language-zsh" data-lang="zsh"
          ><span style="display:flex;"><span>source ~/.zshrc</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ol>
<p>Bash Configuration Files:</p>
<ol>
<li>
<p><strong>Setting Environment Variables</strong>:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>export PATH<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;</span>$PATH<span style="color:#e6db74">:/new/path&#34;</span>
</span></span><span style="display:flex;"><span>export EDITOR<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;vim&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Defining Aliases</strong>:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>alias ll<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;ls -la&#34;</span>
</span></span><span style="display:flex;"><span>alias gs<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;git status&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Creating Functions</strong>:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>greet<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Hello, </span>$1<span style="color:#e6db74">!&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Sourcing Other Files</strong>:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>source ~/.bashrc</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ol>
<h2 id="shells">
  <a class="anchor inpage" href="#shells">##</a>shells</h2>
<p>Commonly used shells include:</p>
<ul>
<li>Bash (Bourne Again SHell): Default on many Linux systems</li>
<li>Zsh (Z Shell): Known for advanced features and customization</li>
<li>Fish (Friendly Interactive Shell): User-friendly and interactive</li>
<li>sh (Bourne Shell): The original UNIX shell</li>
<li>tcsh/csh: C Shell and its enhanced version</li>
</ul>
<table>
  <thead>
      <tr>
          <th>Shell</th>
          <th>Pros</th>
          <th>Cons</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Bash</td>
          <td>Widely supported, strong scripting capabilities</td>
          <td>Less modern interactive features</td>
      </tr>
      <tr>
          <td>Zsh</td>
          <td>Powerful completion, interactive features, customization</td>
          <td>Slightly heavier than Bash</td>
      </tr>
      <tr>
          <td>Fish</td>
          <td>User-friendly syntax and autocompletion</td>
          <td>Less POSIX-compatible for scripting</td>
      </tr>
      <tr>
          <td>sh</td>
          <td>Minimal and portable</td>
          <td>Limited interactivity and scripting features</td>
      </tr>
      <tr>
          <td>tcsh/csh</td>
          <td>C-like syntax, good for some users</td>
          <td>Less common, some scripting limitations</td>
      </tr>
  </tbody>
</table>
]]></content:encoded></item><item><title>qemu虚拟机</title><link>https://hiraethecho.github.io/docs/linux/virtual-machine/</link><pubDate>Mon, 21 Apr 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/virtual-machine/</guid><description>在linux上配置使用qemu虚拟机</description><content:encoded><![CDATA[<h1 id="qemu虚拟机">
  <a class="anchor inpage" href="#qemu%e8%99%9a%e6%8b%9f%e6%9c%ba">#</a>qemu虚拟机</h1>
<h2 id="install">
  <a class="anchor inpage" href="#install">##</a>Install</h2>
<p>Install pakages</p>
<details open>
    <summary>arch</summary><pre
        class="codeblock"
      ><code class="language-arch" data-lang="arch">paru -S qemu-base # basic
paru -S libvirt # 虚拟机一些api的封装
virtual-manager # GUI
paru -S dnsmasq bridge-utils # net</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Add user into groups, and start services<br>
编辑文件<code>/etc/libvirt/libvirtd.conf</code></p>
<details open>
    <summary>conf</summary><pre
        class="codeblock"
      ><code class="language-conf" data-lang="conf">unix_sock_group = &#34;libvirt&#34;
unix_sock_rw_perms = &#34;0770&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">sudo usermod -a -G libvirt $(whoami)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo systemctl enable libvirtd.service</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="net">
  <a class="anchor inpage" href="#net">##</a>net</h2>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo virsh net-list --all
</span></span><span style="display:flex;"><span>sudo virsh net-start --all
</span></span><span style="display:flex;"><span>sudo virsh net-autostart default</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="windows">
  <a class="anchor inpage" href="#windows">##</a>Windows</h2>
<p>
 一个更迷你的win镜像</p>
]]></content:encoded></item><item><title>Archlinux从安装到配置</title><link>https://hiraethecho.github.io/docs/linux/archlinux/</link><pubDate>Sat, 04 Jan 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/archlinux/</guid><description>关于archlinux的一个汇总</description><content:encoded><![CDATA[<h1 id="关于arch的安装和配置">
  <a class="anchor inpage" href="#%e5%85%b3%e4%ba%8earch%e7%9a%84%e5%ae%89%e8%a3%85%e5%92%8c%e9%85%8d%e7%bd%ae">#</a>关于arch的安装和配置</h1>
<blockquote class="alert alert-important">
      <p class="alert-heading">IMPORTANT</p><p>I use Arch by the way.</p></blockquote><h2 id="start">
  <a class="anchor inpage" href="#start">##</a>start</h2>
<ul>
<li>
</li>
<li>
</li>
</ul>
<h2 id="usage">
  <a class="anchor inpage" href="#usage">##</a>usage</h2>
<ul>
<li>
</li>
</ul>
<h2 id="more">
  <a class="anchor inpage" href="#more">##</a>more</h2>
<ul>
<li>
</li>
<li>
</li>
</ul>
]]></content:encoded></item><item><title>ArchWiki摘抄</title><link>https://hiraethecho.github.io/docs/linux/archwiki/</link><pubDate>Fri, 03 Jan 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/archwiki/</guid><description>从archwiki找的一些有用的东西</description><content:encoded><![CDATA[<h1 id="archwiki摘抄">
  <a class="anchor inpage" href="#archwiki%e6%91%98%e6%8a%84">#</a>ArchWiki摘抄</h1>
<h2 id="font">
  <a class="anchor inpage" href="#font">##</a>font</h2>
<p>find the font that contains chinese</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>fc-list -f <span style="color:#e6db74">&#39;%{file}\n&#39;</span> :lang<span style="color:#f92672">=</span>zh</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>check monospace</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>fc-match monospace</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>set fallback fonts, edit <code>$XDG_CONFIG_HOME/fontconfig/fonts.conf</code>:</p>
<details open>
    <summary>text</summary><pre
        class="chroma codeblock"
      ><code class="language-text" data-lang="text"
          ><span style="display:flex;"><span>&lt;?xml version=&#34;1.0&#34;?&gt;
</span></span><span style="display:flex;"><span>&lt;!DOCTYPE fontconfig SYSTEM &#34;fonts.dtd&#34;&gt;
</span></span><span style="display:flex;"><span>&lt;fontconfig&gt;
</span></span><span style="display:flex;"><span>&lt;alias&gt;
</span></span><span style="display:flex;"><span>   &lt;family&gt;serif&lt;/family&gt;
</span></span><span style="display:flex;"><span>   &lt;prefer&gt;
</span></span><span style="display:flex;"><span>     &lt;family&gt;LXGW Wenkai mono&lt;/family&gt;
</span></span><span style="display:flex;"><span>   &lt;/prefer&gt;
</span></span><span style="display:flex;"><span> &lt;/alias&gt;
</span></span><span style="display:flex;"><span>&lt;alias&gt;
</span></span><span style="display:flex;"><span>   &lt;family&gt;monospace&lt;/family&gt;
</span></span><span style="display:flex;"><span>   &lt;prefer&gt;
</span></span><span style="display:flex;"><span>     &lt;family&gt;CodeNewRoman Nerd Font&lt;/family&gt;
</span></span><span style="display:flex;"><span>     &lt;family&gt;LXGW Wenkai mono&lt;/family&gt;
</span></span><span style="display:flex;"><span>   &lt;/prefer&gt;
</span></span><span style="display:flex;"><span> &lt;/alias&gt;
</span></span><span style="display:flex;"><span>&lt;/fontconfig&gt;</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="xorg">
  <a class="anchor inpage" href="#xorg">##</a>xorg</h2>
<blockquote class="alert alert-note">
      <p class="alert-heading">NOTE</p><p>注意：Arch 提供了位于 <code>/usr/share/X11/xorg.conf.d</code> 的默认配置文件。通常情况下，用户无需进行额外的配置与修改即可正常使用。</p></blockquote><h2 id="others-tricks">
  <a class="anchor inpage" href="#others-tricks">##</a>others tricks</h2>
<h3 id="short-cuts">
  <a class="anchor inpage" href="#short-cuts">###</a>short cuts</h3>
<p>
</p>
]]></content:encoded></item><item><title>Bash Scripts</title><link>https://hiraethecho.github.io/docs/linux/bash-scripts/</link><pubDate>Tue, 31 Dec 2024 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/bash-scripts/</guid><description>编写bash scripts的一些技巧</description><content:encoded><![CDATA[<h1 id="bash-scripts">
  <a class="anchor inpage" href="#bash-scripts">#</a>Bash Scripts</h1>
<h2 id="intro">
  <a class="anchor inpage" href="#intro">##</a>intro</h2>
<h3 id="run">
  <a class="anchor inpage" href="#run">###</a>run</h3>
<p>You can run the script in the following ways:</p>
<p><code>./hello_world.sh</code></p>
<p><code>bash hello_world.sh</code>.</p>
<h3 id="she-bang">
  <a class="anchor inpage" href="#she-bang">###</a>she-bang</h3>
<p>First line of shell Scripts usually is the <code>she-bang</code>:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">#!/bin/sh</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Means using <code>/bin/sh</code> to run the script.</p>
<p>但是<code>/bin/sh</code>通常是符号链接，在不同机器上实际上是不同的shell，有时会有以外情况。所以建议写成</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">#!/bin/bash</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="注释">
  <a class="anchor inpage" href="#%e6%b3%a8%e9%87%8a">###</a>注释</h3>
<p>以 # 开头的行就是注释，会被解释器忽略。</p>
<p>多行注释可以使用以下格式：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>:<span style="color:#e6db74">&lt;&lt;EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>以上例子中，: 是一个空命令，用于执行后面的 Here 文档， &laquo;&lsquo;EOF&rsquo; 表示开启 Here 文档，COMMENT 是 Here 文档的标识符，在这两个标识符之间的内容都会被视为注释，不会被执行。</p>
<p>EOF 也可以使用其他符号:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>: <span style="color:#e6db74">&lt;&lt;&#39;COMMENT&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">这是注释的部分。
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">可以有多行内容。
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">COMMENT</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>:&lt;&lt; <span style="color:#e6db74">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">注释内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>:&lt;&lt;!
</span></span><span style="display:flex;"><span>注释内容...
</span></span><span style="display:flex;"><span>注释内容...
</span></span><span style="display:flex;"><span>注释内容...
</span></span><span style="display:flex;"><span>!</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="variables">
  <a class="anchor inpage" href="#variables">##</a>variables</h2>
<h3 id="define">
  <a class="anchor inpage" href="#define">###</a>define</h3>
<p>We can define a variable by using the syntax <code>variable_name=value</code>. To get the value of the variable, add <code>$</code> before the variable.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#75715e"># A simple variable example</span>
</span></span><span style="display:flex;"><span>greeting<span style="color:#f92672">=</span>Hello
</span></span><span style="display:flex;"><span>name<span style="color:#f92672">=</span>Tux
</span></span><span style="display:flex;"><span>echo $greeting $name</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>注意，变量名和等号之间不能有空格</p>
<p>字符串：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>my_string<span style="color:#f92672">=</span><span style="color:#960050;background-color:#1e0010">&#39;</span>Hello, World!my_string<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Hello, World!&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">RUNOOB=&#34;www.runoob.com&#34;
LD_LIBRARY_PATH=&#34;/bin/&#34;
_var=&#34;123&#34;
var2=&#34;abc&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">for</span> file in <span style="color:#ae81ff">\`</span> ls / etc <span style="color:#ae81ff">\`</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> file in $ <span style="color:#f92672">(</span>ls / etc<span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>数组：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">my_array=(1 2 3 4 5)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>只读变量</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>myUrl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.google.com&#34;</span>
</span></span><span style="display:flex;"><span>readonly myUrl
</span></span><span style="display:flex;"><span>myUrl<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.runoob.com&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>使用 unset 命令可以删除变量。语法：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">unset variable_name</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="变量类型">
  <a class="anchor inpage" href="#%e5%8f%98%e9%87%8f%e7%b1%bb%e5%9e%8b">###</a>变量类型</h3>
<p><strong>字符串变量：</strong> 在 Shell中，变量通常被视为字符串。</p>
<p>你可以使用单引号 &rsquo; 或双引号 &quot; 来定义字符串，例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">my_string=&#39;Hello, World!&#39;
my_string=&#34;Hello, World!&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>单引号字符串的限制：</p>
<ul>
<li>单引号里的任何字符都会原样输出，单引号字符串中的变量是无效的；</li>
<li>单引号字符串中不能出现单独一个的单引号（对单引号使用转义符后也不行），但可成对出现，作为字符串拼接使用。</li>
</ul>
<p>双引号的优点：</p>
<ul>
<li>双引号里可以有变量</li>
<li>双引号里可以出现转义字符</li>
</ul>
<p>拼接字符串</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>your<span style="color:#ae81ff">\_</span>name <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;runoob&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 使用双引号拼接
</span></span><span style="display:flex;"><span>greeting <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello, &#34;</span> $your<span style="color:#ae81ff">\_</span>name <span style="color:#e6db74">&#34;!&#34;</span>
</span></span><span style="display:flex;"><span>greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">1</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello, </span><span style="color:#e6db74">${</span>your<span style="color:#ae81ff">\_</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">!&#34;</span>
</span></span><span style="display:flex;"><span>echo $greeting $greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 使用单引号拼接
</span></span><span style="display:flex;"><span>greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;hello, &#39;</span> $your<span style="color:#ae81ff">\_</span>name <span style="color:#e6db74">&#39;!&#39;</span>
</span></span><span style="display:flex;"><span>greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">3</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;hello, ${your\_name}!&#39;</span>
</span></span><span style="display:flex;"><span>echo $greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">2</span> $greeting<span style="color:#ae81ff">\_</span><span style="color:#ae81ff">3</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>输出结果为：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>获取字符串长度</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>string <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;abcd&#34;</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">${#</span>string<span style="color:#e6db74">}</span> <span style="color:#ae81ff">\#</span> 输出 <span style="color:#ae81ff">4</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="数组">
  <a class="anchor inpage" href="#%e6%95%b0%e7%bb%84">###</a>数组</h3>
<p>bash支持一维数组（不支持多维数组），并且没有限定数组的大小。</p>
<p>类似于 C 语言，数组元素的下标由 0 开始编号。获取数组中的元素要利用下标，下标可以是整数或算术表达式，其值应大于或等于 0。</p>
<p>在 Shell 中，用括号来表示数组，数组元素用&quot;空格&quot;符号分割开。定义数组的一般形式为：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">数组名=(值1 值2 ... 值n)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">array_name=(value0 value1 value2 value3)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>或者</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">array_name=(
value0
value1
value2
value3
)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>还可以单独定义数组的各个分量：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以不使用连续的下标，而且下标的范围没有限制。</p>
<p>读取数组元素值的一般格式是：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${数组名[下标]}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">valuen=${array_name[n]}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>使用 @ 符号可以获取数组中的所有元素，例如：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">echo ${array_name[@]}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>获取数组长度的方法与获取字符串长度的方法相同，例如：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 取得数组元素的个数
</span></span><span style="display:flex;"><span>length <span style="color:#f92672">=</span> <span style="color:#e6db74">${#</span>array<span style="color:#ae81ff">\_</span>name<span style="color:#ae81ff">\[</span>@<span style="color:#ae81ff">\]</span><span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 或者
</span></span><span style="display:flex;"><span>length <span style="color:#f92672">=</span> <span style="color:#e6db74">${#</span>array<span style="color:#ae81ff">\_</span>name<span style="color:#ae81ff">\[\*\]</span><span style="color:#e6db74">}</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">\#</span> 取得数组单个元素的长度
</span></span><span style="display:flex;"><span>length <span style="color:#f92672">=</span> <span style="color:#e6db74">${#</span>array<span style="color:#ae81ff">\_</span>name<span style="color:#ae81ff">\[</span>n<span style="color:#ae81ff">\]</span><span style="color:#e6db74">}</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="运算">
  <a class="anchor inpage" href="#%e8%bf%90%e7%ae%97">###</a>运算</h3>
<p>Arithmetic Expressions:</p>
<p>Below are the operators supported by bash for mathematical calculations:</p>
<table>
  <thead>
      <tr>
          <th>Operator</th>
          <th>Usage</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>+</td>
          <td>addition</td>
      </tr>
      <tr>
          <td>-</td>
          <td>subtraction</td>
      </tr>
      <tr>
          <td>*</td>
          <td>multiplication</td>
      </tr>
      <tr>
          <td>/</td>
          <td>division</td>
      </tr>
      <tr>
          <td>**</td>
          <td>exponentiation</td>
      </tr>
      <tr>
          <td>%</td>
          <td>modulus</td>
      </tr>
  </tbody>
</table>
<p>Numeric Comparison logical operators</p>
<p>Comparison is used to check if statements evaluate to <code>true</code> or <code>false</code>. We can use the below shown operators to compare two statements:</p>
<table>
  <thead>
      <tr>
          <th>Operation</th>
          <th>Syntax</th>
          <th>Explanation</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Equality</td>
          <td>num1 -eq num2</td>
          <td>is num1 equal to num2</td>
      </tr>
      <tr>
          <td>Greater than equal to</td>
          <td>num1 -ge num2</td>
          <td>is num1 greater than equal to num2</td>
      </tr>
      <tr>
          <td>Greater than</td>
          <td>num1 -gt num2</td>
          <td>is num1 greater than num2</td>
      </tr>
      <tr>
          <td>Less than equal to</td>
          <td>num1 -le num2</td>
          <td>is num1 less than equal to num2</td>
      </tr>
      <tr>
          <td>Less than</td>
          <td>num1 -lt num2</td>
          <td>is num1 less than num2</td>
      </tr>
      <tr>
          <td>Not Equal to</td>
          <td>num1 -ne num2</td>
          <td>is num1 not equal to num2</td>
      </tr>
  </tbody>
</table>
<h3 id="参数">
  <a class="anchor inpage" href="#%e5%8f%82%e6%95%b0">###</a>参数</h3>
<table>
  <thead>
      <tr>
          <th>名称</th>
          <th>含义</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>$#</td>
          <td>传给脚本的参数个数</td>
      </tr>
      <tr>
          <td>$0</td>
          <td>脚本本身的名字</td>
      </tr>
      <tr>
          <td>$1</td>
          <td>传递给该shell脚本的第一个参数</td>
      </tr>
      <tr>
          <td>$2</td>
          <td>传递给该shell脚本的第二个参数</td>
      </tr>
      <tr>
          <td>$@</td>
          <td>传给脚本的所有参数的列表</td>
      </tr>
      <tr>
          <td>$*</td>
          <td>以一个单字符串显示所有向脚本传递的参数，与位置变量不同，参数可超过9个</td>
      </tr>
      <tr>
          <td>$$</td>
          <td>脚本运行的当前进程ID号</td>
      </tr>
      <tr>
          <td>$?</td>
          <td>显示最后命令的退出状态，0表示没有错误，其他表示有错误</td>
      </tr>
  </tbody>
</table>
<p>假设执行 <code>./test.sh a b c</code> 这样一个命令，则可以使用下面的参数来获取一些值：</p>
<ul>
<li><code>$0</code><br>
对应 <em>./test.sh</em> 这个值。如果执行的是 <code>./work/test.sh</code> ， 则对应 <em>./work/test.sh</em> 这个值，而不是只返回文件名本身的部分。</li>
<li><code>$1</code><br>
会获取到 a，即 <code>$1</code> 对应传给脚本的第一个参数。</li>
<li><code>$2</code><br>
会获取到 b，即 <code>$2</code> 对应传给脚本的第二个参数。</li>
<li><code>$3</code><br>
会获取到 c，即 <code>$3</code> 对应传给脚本的第三个参数。 <code>$4</code> 、 <code>$5</code> 等参数的含义依此类推。</li>
<li><code>$#</code><br>
会获取到 3，对应传入脚本的参数个数，统计的参数不包括 <code>$0</code> 。</li>
<li><code>$@</code><br>
会获取到 &ldquo;a&rdquo; &ldquo;b&rdquo; &ldquo;c&rdquo;，也就是所有参数的列表，不包括 <code>$0</code> 。</li>
<li><code>$*</code><br>
也会获取到 &ldquo;a&rdquo; &ldquo;b&rdquo; &ldquo;c&rdquo;， 其值和 <code>$@</code> 相同。但 <code>&quot;$*&quot;</code> 和 <code>&quot;$@&quot;</code> 有所不同。<br>
<code>&quot;$*&quot;</code> 把所有参数合并成一个字符串，而 <code>&quot;$@&quot;</code> 会得到一个字符串参数数组。</li>
<li><code>$?</code><br>
可以获取到执行 <code>./test.sh a b c</code> 命令后的返回值。<br>
在执行一个前台命令后，可以立即用 <code>$?</code> 获取到该命令的返回值。<br>
该命令可以是系统自身的命令，可以是 shell 脚本，也可以是自定义的 bash 函数。</li>
</ul>
<p>当执行系统自身的命令时， <code>$?</code> 对应这个命令的返回值。<br>
当执行 shell 脚本时， <code>$?</code> 对应该脚本调用 <code>exit</code> 命令返回的值。如果没有主动调用 <code>exit</code> 命令，默认返回为 0。<br>
当执行自定义的 bash 函数时， <code>$?</code> 对应该函数调用 <code>return</code> 命令返回的值。如果没有主动调用 <code>return</code> 命令，默认返回为 0。</p>
<p>下面举例说明 <code>&quot;$*&quot;</code> 和 <code>&quot;$@&quot;</code> 的差异。假设有一个 <code>testparams.sh</code> 脚本，内容如下：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> arg in <span style="color:#e6db74">&#34;</span>$*<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;****:&#34;</span> $arg
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>echo --------------
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> arg in <span style="color:#e6db74">&#34;</span>$@<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;@@@@:&#34;</span> $arg
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>这个脚本分别遍历 <code>&quot;$*&quot;</code> 和 <code>&quot;$@&quot;</code> 扩展后的内容，并打印出来。</p>
<p>执行 <code>./testparams.sh</code> 脚本，结果如下：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>$ ./testparams.sh This is a test
</span></span><span style="display:flex;"><span>****: This is a test
</span></span><span style="display:flex;"><span>--------------
</span></span><span style="display:flex;"><span>@@@@: This
</span></span><span style="display:flex;"><span>@@@@: is
</span></span><span style="display:flex;"><span>@@@@: a
</span></span><span style="display:flex;"><span>@@@@: test</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以看到， <code>&quot;$*&quot;</code> 只产生一个字符串，for 循环只遍历一次。<br>
而 <code>&quot;$@&quot;</code> 产生了多个字符串，for 循环遍历多次，是一个字符串参数数组。</p>
<p><strong>注意</strong> ：如果传入的参数多于 9 个，则不能使用 <code>$10</code> 来引用第 10 个参数，而是要用 <code>${10}</code> 来引用。</p>
<p>即，需要用大括号 <code>{}</code> 把大于 9 的数字括起来。<br>
例如， <code>${10}</code> 表示获取第 10 个参数的值，写为 <code>$10</code> 获取不到第 10 个参数的值。<br>
实际上， <code>$10</code> 相当于 <code>${1}0</code> ，也就是先获取 <code>$1</code> 的值，后面再跟上 0。<br>
如果 <code>$1</code> 的值是 &ldquo;first&rdquo;，则 <code>$10</code> 的值是 &ldquo;first0&rdquo;。</p>
<p>在 bash 中，可以使用 <code>$#</code> 来获取传入的命令行或者传入函数的参数个数。<br>
要注意的是， <code>$#</code> 统计的参数个数不包括脚本自身名称或者函数名称。<br>
例如，执行 <code>./a.sh a b</code> ，则 <code>$#</code> 是 2，而不是 3。</p>
<h2 id="pairs">
  <a class="anchor inpage" href="#pairs">##</a>pairs</h2>
<p><code>{}</code>,<code>[]</code>,<code>()</code>,<code>``</code></p>
<h3 id="-花括号">
  <a class="anchor inpage" href="#-%e8%8a%b1%e6%8b%ac%e5%8f%b7">###</a>{} 花括号</h3>
<h4 id="常规用法">
  <a class="anchor inpage" href="#%e5%b8%b8%e8%a7%84%e7%94%a8%e6%b3%95">####</a>常规用法</h4>
<p>大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中，不允许有空白，除非这个空白被引用或转义。第一种：对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种：对大括号中以点点（..）分割的顺序文件列表起拓展作用，如：touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># ls {ex1,ex2}.sh
ex1.sh  ex2.sh
# ls {ex{1..3},ex4}.sh
ex1.sh  ex2.sh  ex3.sh  ex4.sh
# ls {ex[1-3],ex4}.sh
ex1.sh  ex2.sh  ex3.sh  ex4.sh</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>代码块，又被称为内部组，这个结构事实上创建了一个匿名函数 。与小括号中的命令不同，大括号内的命令不会新开一个子shell运行，即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开，最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。</p>
<h4 id="几种特殊的替换结构">
  <a class="anchor inpage" href="#%e5%87%a0%e7%a7%8d%e7%89%b9%e6%ae%8a%e7%9a%84%e6%9b%bf%e6%8d%a2%e7%bb%93%e6%9e%84">####</a>几种特殊的替换结构</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${var:-string}
${var:&#43;string}
${var:=string}
${var:?string}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ol>
<li>
<p><code>${var:-string}</code>和<code>${var:=string}</code>:若变量var为空，则用在命令行中用string来替换<code>${var:-string}</code>，否则变量var不为空时，则用变量var的值来替换<code>${var:-string}</code>；对于<code>${var:=string}</code>的替换规则和<code>${var:-string}</code>是一样的，所不同之处是<code>${var:=string}</code>若var为空时，用string替换<code>${var:=string}</code>的同时，把string赋给变量var： <code>${var:=string}</code>很常用的一种用法是，判断某个变量是否赋值，没有的话则给它赋上一个默认值。</p>
</li>
<li>
<p><code>${var:+string}</code>的替换规则和上面的相反，即只有当var不是空的时候才替换成string，若var为空时则不替换或者说是替换成变量 var的值，即空值。(因为变量var此时为空，所以这两种说法是等价的)</p>
</li>
<li>
<p><code>${var:?string}</code>替换规则为：若变量var不为空，则用变量var的值来替换<code>${var:?string}</code>；若变量var为空，则把string输出到标准错误中，并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。</p>
</li>
</ol>
<p>在上面这五种替换结构中string不一定是常值的，可用另外一个变量的值或是一种命令的输出。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">default_name=&#34;Guest&#34;
unset name  # 确保 name 未定义

# 如果 name 为空，则使用 default_name 的值
echo &#34;Hello, ${name:-$default_name}&#34;  # 输出: Hello, Guest</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>四种模式匹配替换结构</strong></p>
<p>模式匹配记忆方法：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># 是去掉左边(在键盘上#在$之左边)
% 是去掉右边(在键盘上%在$之右边)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>#</code>和<code>%</code>中的单一符号是最小匹配，两个相同符号是最大匹配。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${var%pattern}
${var%%pattern
${var#pattern}
${var##pattern}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>第一种模式：<code>${variable%pattern}</code>，这种模式时，shell在variable中查找，看它是否一给的模式pattern结尾，如果是，就从命令行把variable中的内容去掉右边最短的匹配模式</li>
<li>第二种模式： <code>${variable%%pattern}</code>，这种模式时，shell在variable中查找，看它是否一给的模式pattern结尾，如果是，就从命令行把variable中的内容去掉右边最长的匹配模式</li>
<li>第三种模式：<code>${variable#pattern}</code> 这种模式时，shell在variable中查找，看它是否一给的模式pattern开始，如果是，就从命令行把variable中的内容去掉左边最短的匹配模式</li>
<li>第四种模式： <code>${variable##pattern}</code> 这种模式时，shell在variable中查找，看它是否一给的模式pattern结尾，如果是，就从命令行把variable中的内容去掉右边最长的匹配模式</li>
<li>这四种模式中都不会改变variable的值，其中，只有在pattern中使用了*匹配符号时，%和%%，#和##才有区别。结构中的pattern支持通配符，*表示零个或多个任意字符，?表示仅与一个任意字符匹配，\[...\]表示匹配中括号里面的字符，\[!...\]表示不匹配中括号里面的字符。</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># var=testcase
# echo $var
testcase
# echo ${var%s*e}
testca
# echo $var
testcase
# echo ${var%%s*e}
te
# echo ${var#?e}
stcase
# echo ${var##?e}
stcase
# echo ${var##*e}

# echo ${var##*s}
e
# echo ${var##test}
case</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="字符串提取和替换">
  <a class="anchor inpage" href="#%e5%ad%97%e7%ac%a6%e4%b8%b2%e6%8f%90%e5%8f%96%e5%92%8c%e6%9b%bf%e6%8d%a2">####</a>字符串提取和替换</h4>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">${var:num}
${var:num1:num2}
${var/pattern/pattern}
${var//pattern/pattern}</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>第一种模式：<code>${var:num}</code>，这种模式时，shell在var中提取第num个字符到末尾的所有字符。若num为正数，从左边0处开始；若num为负数，从右边开始提取字串，但必须使用在冒号后面加空格或一个数字或整个num加上括号，如<code>${var: -2}</code>、<code>${var:1-3}</code>或<code>${var:(-2)}</code>。</li>
<li>第二种模式：<code>${var:num1:num2}</code>，num1是位置，num2是长度。表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。</li>
<li>第三种模式：<code>${var/pattern/pattern}</code>表示将var字符串的第一个匹配的pattern替换为另一个pattern。</li>
<li>第四种模式：<code>${var//pattern/pattern}</code>表示将var字符串中的所有能匹配的pattern替换为另一个pattern。</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">[root@centos ~]# var=/home/centos
[root@centos ~]# echo $var
/home/centos
[root@centos ~]# echo ${var:5}
/centos
[root@centos ~]# echo ${var: -6}
centos
[root@centos ~]# echo ${var:(-6)}
centos
[root@centos ~]# echo ${var:1:4}
home
[root@centos ~]# echo ${var/o/h}
/hhme/centos
[root@centos ~]# echo ${var//o/h}
/hhme/cenths</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>
<p>${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。</p>
</li>
<li>
<p>$(cmd) 命令替换，和`cmd`效果相同，结果为shell命令cmd的输，过某些Shell版本不支持$()形式的命令替换, 如tcsh。</p>
</li>
<li>
<p>$((expression)) 和`exprexpression`效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算。</p>
</li>
<li>
<p>单小括号，(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。</p>
</li>
<li>
<p>单大括号，{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。
对 {} 和 () 而言, 括号中的重定向符只影响该条命令， 而括号外的重定向符影响到括号中的所有命令。</p>
</li>
</ul>
<h3 id="heading">
  <a class="anchor inpage" href="#heading">###</a><code>[]</code></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>type <span style="color:#f92672">[</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> is a shell builtin</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>This means that &lsquo;[&rsquo; is actually a program, just like ls and other programs, so it must be surrounded by spaces.</p>
<ul>
<li>bash 的内部命令，[和test是等同的。如果我们不用绝对路径指明，通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识，右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试，并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号，但是新版的Bash中要求必须这样。</li>
<li>Test和[]中可用的比较运算符只有==和!=，两者都是用于字符串比较的，不可用于整数比较，整数比较只能使用-eq，-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用，对于字符串比较可以使用转义形式，如果比较&quot;ab&quot;和&quot;bc&quot;：\[ ab \\< bc \]，结果为真，也就是返回状态为0。\[ \]中的逻辑与和逻辑或使用-a 和-o 表示。</li>
<li>字符范围。用作正则表达式的一部分，描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。</li>
<li>在一个array 结构的上下文中，中括号用来引用数组中每个元素的编号。</li>
</ul>
<h3 id="heading-1">
  <a class="anchor inpage" href="#heading-1">###</a><code>[[]]</code></h3>
<ul>
<li>\[\[是 bash 程序语言的关键字。并不是一个命令，\[\[ \]] 结构比\[ \]结构更加通用。在\[\[和\]]之间所有的字符都不会发生文件名扩展或者单词分割，但是会发生参数扩展和命令替换。</li>
<li>支持字符串的模式匹配，使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式，而不仅仅是一个字符串，比如\[\[ hello == hell? \]]，结果为真。\[\[ \]] 中匹配字符串或通配符，不需要引号。</li>
<li>使用\[\[... \]]条件判断结构，而不是\[... \]，能够防止脚本中的许多逻辑错误。比如，&amp;&amp;、||、&lt;和&gt; 操作符能够正常存在于\[\[ \]]条件判断结构中，但是如果出现在\[ \]结构中的话，会报错。比如可以直接使用if \[\[ $a!= 1 && $a!= 2 \]], 如果不适用双括号, 则为if \[ $a -ne 1\] &amp;&amp; \[ $a!= 2 \]或者if \[ $a -ne 1 -a $a!= 2 \]。</li>
<li>bash把双中括号中的表达式看作一个单独的元素，并返回一个退出状态码。</li>
</ul>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>$i&lt;5<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $i -lt <span style="color:#ae81ff">5</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $a -ne <span style="color:#ae81ff">1</span> -a $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $a -ne 1<span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">[</span> $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">&amp;&amp;</span> $a !<span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">]]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#66d9ef">$(</span>seq <span style="color:#ae81ff">0</span> 4<span style="color:#66d9ef">)</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#ae81ff">\`</span>seq <span style="color:#ae81ff">0</span> 4<span style="color:#ae81ff">\`</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> <span style="color:#f92672">((</span>i<span style="color:#f92672">=</span>0;i&lt;5;i++<span style="color:#f92672">))</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#f92672">{</span>0..4<span style="color:#f92672">}</span>;<span style="color:#66d9ef">do</span> echo $i;<span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="-和-">
  <a class="anchor inpage" href="#-%e5%92%8c-">###</a><code>[]</code> 和 <code>[[]]</code></h3>
<p>在 <strong>Bash</strong> 脚本中，<code>[ ]</code>（<code>test</code> 命令）和 <code>[[ ]]</code>（关键字）都用于条件判断，但它们在功能、性能和安全性上有显著区别。以下是详细对比：</p>
<h4 id="基本定义">
  <a class="anchor inpage" href="#%e5%9f%ba%e6%9c%ac%e5%ae%9a%e4%b9%89">####</a>基本定义</h4>
<table>
  <thead>
      <tr>
          <th>语法</th>
          <th>类型</th>
          <th>说明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>[ ]</code></td>
          <td><strong>内置命令</strong></td>
          <td>等价于 <code>test</code> 命令，需严格遵循参数规则（如空格和引号）。</td>
      </tr>
      <tr>
          <td><code>[[ ]]</code></td>
          <td><strong>Shell 关键字</strong></td>
          <td>Bash/ksh/zsh 的扩展语法，更灵活，支持额外功能（如模式匹配、逻辑组合）。</td>
      </tr>
  </tbody>
</table>
<h4 id="核心区别">
  <a class="anchor inpage" href="#%e6%a0%b8%e5%bf%83%e5%8c%ba%e5%88%ab">####</a>核心区别</h4>
<p><strong>(1) 字符串比较</strong></p>
<ul>
<li>
<p><strong><code>[ ]</code></strong>：</p>
<ul>
<li>使用 <code>=</code> 和 <code>!=</code> 时，<strong>必须加引号</strong>，否则可能因空格或特殊字符报错。</li>
<li>示例：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$var<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]</span>  <span style="color:#75715e"># 正确</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> $var <span style="color:#f92672">=</span> hello <span style="color:#f92672">]</span>      <span style="color:#75715e"># 若 $var 含空格，会报错</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>[[ ]]</code></strong>：</p>
<ul>
<li>自动处理变量中的空格，无需引号（但仍建议加引号以防未定义变量）。</li>
<li>支持 <code>==</code> 和 <code>!=</code> 的<strong>通配符匹配</strong>（模式匹配）。</li>
<li>示例：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> $var <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]]</span>    <span style="color:#75715e"># 正确，即使 $var 含空格</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $var <span style="color:#f92672">==</span> h* <span style="color:#f92672">]]</span>         <span style="color:#75715e"># 支持通配符匹配（如 &#34;hello&#34; 或 &#34;hi&#34;）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ul>
<p><strong>(2) 数值比较</strong></p>
<ul>
<li>
<p><strong><code>[ ]</code></strong>：</p>
<ul>
<li>必须用 <code>-eq</code>、<code>-lt</code> 等运算符：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$num<span style="color:#e6db74">&#34;</span> -lt <span style="color:#ae81ff">5</span> <span style="color:#f92672">]</span>  <span style="color:#75715e"># 数值比较</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>[[ ]]</code></strong>：</p>
<ul>
<li>仍建议用 <code>-eq</code>、<code>-lt</code>，但支持 <code>&gt;</code> 和 <code>&lt;</code>（需转义或双括号）：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> $num -lt <span style="color:#ae81ff">5</span> <span style="color:#f92672">]]</span>    <span style="color:#75715e"># 标准写法</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $num &lt; <span style="color:#ae81ff">10</span> <span style="color:#f92672">]]</span>     <span style="color:#75715e"># 字符串比较（字典序）！</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">((</span> num &lt; <span style="color:#ae81ff">10</span> <span style="color:#f92672">))</span>      <span style="color:#75715e"># 数值比较的正确写法</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ul>
<p><strong>(3) 逻辑运算符</strong></p>
<ul>
<li>
<p><strong><code>[ ]</code></strong>：</p>
<ul>
<li>用 <code>-a</code>（AND）、<code>-o</code>（OR），需严格分隔：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$a<span style="color:#e6db74">&#34;</span> -gt <span style="color:#ae81ff">1</span> -a <span style="color:#e6db74">&#34;</span>$a<span style="color:#e6db74">&#34;</span> -lt <span style="color:#ae81ff">10</span> <span style="color:#f92672">]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>[[ ]]</code></strong>：</p>
<ul>
<li>用 <code>&amp;&amp;</code> 和 <code>||</code>，更直观：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> $a -gt <span style="color:#ae81ff">1</span> <span style="color:#f92672">&amp;&amp;</span> $a -lt <span style="color:#ae81ff">10</span> <span style="color:#f92672">]]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ul>
<p><strong>(4) 文件测试</strong></p>
<ul>
<li><strong><code>[ ]</code></strong> 和 <code>[[ ]]</code> 均支持，但 <code>[[ ]]</code> 更安全（如未定义变量不会报错）：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span>      <span style="color:#75715e"># 检查文件是否存在</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> -f $file <span style="color:#f92672">]]</span>      <span style="color:#75715e"># 更健壮（即使 $file 未定义也不会语法错误）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p><strong>(5) 正则匹配（仅 <code>[[ ]]</code>）</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">[[</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">=</span>~ ^h <span style="color:#f92672">]]</span>   <span style="color:#75715e"># 正则匹配（返回 true）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="性能与安全性">
  <a class="anchor inpage" href="#%e6%80%a7%e8%83%bd%e4%b8%8e%e5%ae%89%e5%85%a8%e6%80%a7">####</a>性能与安全性</h4>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th><code>[ ]</code></th>
          <th><code>[[ ]]</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>执行速度</strong></td>
          <td>较慢（外部命令或内置命令）</td>
          <td>更快（Bash 关键字）</td>
      </tr>
      <tr>
          <td><strong>安全性</strong></td>
          <td>变量未加引号易报错</td>
          <td>自动处理空格，更健壮</td>
      </tr>
      <tr>
          <td><strong>兼容性</strong></td>
          <td>所有 Shell（sh、dash 等）</td>
          <td>仅 Bash/ksh/zsh</td>
      </tr>
  </tbody>
</table>
<h4 id="何时使用">
  <a class="anchor inpage" href="#%e4%bd%95%e6%97%b6%e4%bd%bf%e7%94%a8">####</a>何时使用？</h4>
<ul>
<li><strong>用 <code>[[ ]]</code></strong>：
<ul>
<li>需要模式匹配、正则表达式、逻辑组合时。</li>
<li>脚本已明确使用 Bash（<code>#!/bin/bash</code>）。</li>
</ul>
</li>
<li><strong>用 <code>[ ]</code></strong>：
<ul>
<li>需兼容 POSIX Shell（如 <code>/bin/sh</code>）。</li>
<li>简单的文件或字符串测试（但务必加引号）。</li>
</ul>
</li>
</ul>
<h4 id="经典示例">
  <a class="anchor inpage" href="#%e7%bb%8f%e5%85%b8%e7%a4%ba%e4%be%8b">####</a>经典示例</h4>
<p><strong>(1) 字符串比较</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># [ ] 必须加引号</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$name<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Alice&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Hello Alice&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># [[ ]] 更灵活</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $name <span style="color:#f92672">==</span> A* <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Name starts with A&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(2) 文件检查</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># [ ] 和 [[ ]] 均可，但后者更安全</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;/path/</span>$file<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;File exists&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> -f /path/$file <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;File exists&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(3) 逻辑组合</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># [ ] 用 -a/-o</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$age<span style="color:#e6db74">&#34;</span> -gt <span style="color:#ae81ff">18</span> -a <span style="color:#e6db74">&#34;</span>$age<span style="color:#e6db74">&#34;</span> -lt <span style="color:#ae81ff">60</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Valid age&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># [[ ]] 用 &amp;&amp;/||</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[[</span> $age -gt <span style="color:#ae81ff">18</span> <span style="color:#f92672">&amp;&amp;</span> $age -lt <span style="color:#ae81ff">60</span> <span style="color:#f92672">]]</span> <span style="color:#f92672">&amp;&amp;</span> echo <span style="color:#e6db74">&#34;Valid age&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="总结">
  <a class="anchor inpage" href="#%e6%80%bb%e7%bb%93">####</a>总结</h4>
<table>
  <thead>
      <tr>
          <th><strong>需求</strong></th>
          <th><strong><code>[ ]</code></strong></th>
          <th><strong><code>[[ ]]</code></strong></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>字符串比较</td>
          <td>需严格加引号</td>
          <td>自动处理空格，支持通配符</td>
      </tr>
      <tr>
          <td>数值比较</td>
          <td>用 <code>-eq</code>、<code>-lt</code></td>
          <td>同 <code>[ ]</code>，但可用 <code>(( ))</code> 替代</td>
      </tr>
      <tr>
          <td>逻辑运算符</td>
          <td><code>-a</code>、<code>-o</code></td>
          <td><code>&amp;&amp;</code>、<code>||</code></td>
      </tr>
      <tr>
          <td>正则匹配</td>
          <td>❌</td>
          <td>✅（<code>=~</code>）</td>
      </tr>
      <tr>
          <td>性能</td>
          <td>较慢</td>
          <td>更快</td>
      </tr>
  </tbody>
</table>
<ul>
<li><strong>优先用 <code>[[ ]]</code></strong>（Bash 脚本中更安全、灵活）。</li>
<li><strong>只有需要兼容 POSIX 时用 <code>[ ]</code></strong>（如 <code>/bin/sh</code> 脚本）。</li>
</ul>
<h3 id="heading-2">
  <a class="anchor inpage" href="#heading-2">###</a><code>()</code></h3>
<ul>
<li><strong>命令组</strong> 。括号中的命令将会新开一个子shell顺序执行，所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开，最后一个命令可以没有分号，各命令和括号之间不必有空格。</li>
<li><strong>命令替换</strong> 。等同于<code>cmd</code>，shell扫描一遍命令行，发现了<code>$(cmd)</code>结构，便将<code>$(cmd)</code>中的<code>cmd</code>执行一次，得到其标准输出，再将此输出放到原来命令。有些shell不支持，如tcsh。</li>
<li><strong>用于初始化数组</strong> 。如：<code>array=(a b c d)</code></li>
</ul>
<h3 id="heading-3">
  <a class="anchor inpage" href="#heading-3">###</a><code>(())</code></h3>
<ul>
<li>整数扩展。这种扩展计算是整数型的计算，不支持浮点型。((exp))结构扩展并计算一个算术表达式的值，如果表达式的结果为0，那么返回的退出状态码为1，或者 是&quot;假&quot;，而一个非零值的表达式所返回的退出状态码将为0，或者是&quot;true&quot;。若是逻辑判断，表达式exp为真则为1,假则为0。</li>
<li>只要括号中的运算符、表达式符合C语言运算规则，都可用在$((exp))中，甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时，输出结果全都自动转化成了十进制。如：echo $((16#5f)) 结果为95 (16进位转十进制)</li>
<li>单纯用 (( )) 也可重定义变量值，比如 a=5; ((a++)) 可将 $a 重定义为6</li>
<li>常用于算术运算比较，双括号中的变量可以不使用<code>$</code>符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用<code>for((i=0;i&lt;5;i++))</code>, 如果不使用双括号, 则为<code>for i in $(seq 0 4)</code>或者<code>for i in {0..4}</code>。再如可以直接使用<code>if (($i&lt;5))</code>, 如果不使用双括号, 则为<code>if \[ $i -lt 5 \]</code>。</li>
</ul>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>var<span style="color:#f92672">=</span><span style="color:#66d9ef">$((</span>expression<span style="color:#66d9ef">))</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="-back-ticks">
  <a class="anchor inpage" href="#-back-ticks">###</a><code>``</code> back ticks</h3>
<p>var= commands</p>
<p><strong>Example</strong>: Suppose we want to get the output of a list of mountpoints with <code>tmpfs</code> in their name. We can craft a statement like this: <code>df -h | grep tmpfs</code>.</p>
<p>To include it in the bash script, we can enclose it in back ticks.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>var<span style="color:#f92672">=</span><span style="color:#ae81ff">\`</span>df -h | grep tmpfs<span style="color:#ae81ff">\`</span>
</span></span><span style="display:flex;"><span>echo $var</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="heading-4">
  <a class="anchor inpage" href="#heading-4">###</a><code>&quot;&quot;</code></h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>repo<span style="color:#f92672">=</span>~<span style="color:#e6db74">&#34;/projects/repo1&#34;</span>  <span style="color:#75715e"># 或直接写 ~/projects/repo1（不加引号）</span>
</span></span><span style="display:flex;"><span>cd <span style="color:#e6db74">&#34;</span>$repo<span style="color:#e6db74">&#34;</span>               <span style="color:#75715e"># 此时 $repo 已是展开后的绝对路径</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 显式展开家目录</span>
</span></span><span style="display:flex;"><span>HOME_DIR<span style="color:#f92672">=</span><span style="color:#66d9ef">$(</span>eval echo <span style="color:#e6db74">&#34;~&#34;</span><span style="color:#66d9ef">)</span>  <span style="color:#75715e"># 或直接写 HOME_DIR=&#34;$HOME&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>repos<span style="color:#f92672">=(</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span>$HOME_DIR<span style="color:#e6db74">/projects/repo1&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;</span>$HOME_DIR<span style="color:#e6db74">/work/repo2&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="-和--1">
  <a class="anchor inpage" href="#-%e5%92%8c--1">###</a><code>&quot;&quot;</code> 和 <code>''</code></h3>
<p>在 <strong>Bash</strong> 脚本中，双引号 <code>&quot;&quot;</code> 和单引号 <code>''</code> 都用于定义字符串，但它们在 <strong>变量扩展</strong>、<strong>命令替换</strong> 和 <strong>特殊字符处理</strong> 上有本质区别。以下是详细对比：</p>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>双引号 <code>&quot;&quot;</code></th>
          <th>单引号 <code>''</code></th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>变量扩展</strong></td>
          <td>✅（如 <code>&quot;$var&quot;</code> 会展开）</td>
          <td>❌（如 <code>'$var'</code> 原样输出）</td>
      </tr>
      <tr>
          <td><strong>命令替换</strong></td>
          <td>✅（如 <code>&quot;$(date)&quot;</code> 会执行）</td>
          <td>❌（如 <code>'$(date)'</code> 原样输出）</td>
      </tr>
      <tr>
          <td><strong>转义字符</strong></td>
          <td>仅 <code>\</code>, <code>$</code>, <code>`</code>, <code>&quot;</code> 生效</td>
          <td>所有字符均按字面处理（无转义）</td>
      </tr>
      <tr>
          <td><strong>用途</strong></td>
          <td>需保留变量或命令结果时使用</td>
          <td>需完全按字面输出时使用</td>
      </tr>
  </tbody>
</table>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>name<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Alice&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Hello, </span>$name<span style="color:#e6db74">&#34;</span>   <span style="color:#75715e"># 输出: Hello, Alice</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Hello, $name&#39;</span>   <span style="color:#75715e"># 输出: Hello, $name</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Today is </span><span style="color:#66d9ef">$(</span>date<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span>  <span style="color:#75715e"># 输出: Today is Mon Jul 1 12:00:00 UTC 2024</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Today is $(date)&#39;</span>  <span style="color:#75715e"># 输出: Today is $(date)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Path is \$HOME&#34;</span>    <span style="color:#75715e"># 输出: Path is $HOME（\$ 被转义）</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Path is \$HOME&#39;</span>    <span style="color:#75715e"># 输出: Path is \$HOME（完全字面）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;She said: &#39;Hello!&#39;&#34;</span>   <span style="color:#75715e"># 输出: She said: &#39;Hello!&#39;</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;He said: &#34;Hi!&#34;&#39;</span>       <span style="color:#75715e"># 输出: He said: &#34;Hi!&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li>
<p>需要<strong>变量或命令替换</strong>时：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Current user: </span>$USER<span style="color:#e6db74">, time: </span><span style="color:#66d9ef">$(</span>date<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p>字符串中包含<strong>空格或特殊字符</strong>（需部分转义）：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Use \&#34;quotes\&#34; inside.&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p>需<strong>完全按字面输出</strong>（如正则表达式、SQL语句）：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>grep -E <span style="color:#e6db74">&#39;^[A-Z]&#39;</span> file.txt  <span style="color:#75715e"># 正则表达式</span>
</span></span><span style="display:flex;"><span>sql<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;SELECT * FROM users;&#39;</span> <span style="color:#75715e"># SQL语句</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p>避免<strong>特殊字符被解析</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;$PATH and $(date)&#39;</span>  <span style="color:#75715e"># 输出: $PATH and $(date)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
<p><strong>特殊情况处理</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>alias rm<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;rm -i&#39;</span>          <span style="color:#75715e"># 单引号内定义别名（避免变量提前展开）</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;It&#39;s a sunny day.&#34;</span>  <span style="color:#75715e"># 双引号内嵌套单引号（无需转义）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;Line 1\nLine 2&#34;</span>     <span style="color:#75715e"># 输出: Line 1\nLine 2（\n 未被转义为换行）</span>
</span></span><span style="display:flex;"><span>echo -e <span style="color:#e6db74">&#34;Line 1\nLine 2&#34;</span>  <span style="color:#75715e"># 输出两行（-e 启用转义）</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#39;Line 1\nLine 2&#39;</span>     <span style="color:#75715e"># 输出: Line 1\nLine 2（完全字面）</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><ul>
<li><strong>单引号稍快</strong>：因为无需解析变量或命令替换。</li>
<li>实际脚本中差异可忽略，优先考虑功能需求。</li>
</ul>
<ol>
<li><strong>默认用双引号</strong>：<br>
保护变量中的空格（如 <code>&quot;$file&quot;</code>），避免路径或文件名错误拆分。
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>cp <span style="color:#e6db74">&#34;</span>$file<span style="color:#e6db74">&#34;</span> <span style="color:#e6db74">&#34;/backup/</span>$file<span style="color:#e6db74">&#34;</span>  <span style="color:#75715e"># 正确处理含空格的文件名</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li><strong>需要纯文本时用单引号</strong>：<br>
如正则表达式、代码生成、避免意外展开。
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>sed -e <span style="color:#e6db74">&#39;s/foo/bar/g&#39;</span> file.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ol>
<h2 id="read-write">
  <a class="anchor inpage" href="#read-write">##</a>read, write</h2>
<h3 id="read">
  <a class="anchor inpage" href="#read">###</a>read</h3>
<h4 id="read-in-console">
  <a class="anchor inpage" href="#read-in-console">####</a>read in console</h4>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;input a&#34;</span>
</span></span><span style="display:flex;"><span>read a
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;input b&#34;</span>
</span></span><span style="display:flex;"><span>read b
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>read -n <span style="color:#ae81ff">3</span> -t <span style="color:#ae81ff">5</span> -s -p <span style="color:#e6db74">&#34;input 3 charater, wait for 5 seconds, silent&#34;</span> c
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;</span>$c<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>printf <span style="color:#e6db74">&#34;a=%s,b=%s,sum is %s&#34;</span> $a $b <span style="color:#66d9ef">$((</span>a <span style="color:#f92672">+</span> b<span style="color:#66d9ef">))</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>It is possible to give arguments to the script on execution.</p>
<p><code>$@</code> is a list of the parameters.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> x in $@
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Entered arg is </span>$x<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Run it like this:</p>
<p><code>./script arg1 arg2</code></p>
<h4 id="read-in-file">
  <a class="anchor inpage" href="#read-in-file">####</a>read in file</h4>
<p>Suppose we have a file <code>sample_file.txt</code>, We can read the file line by line and print the output on the screen.</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>LINE<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> read -r CURRENT_LINE
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;</span>$LINE<span style="color:#e6db74">: </span>$CURRENT_LINE<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">((</span>LINE++<span style="color:#f92672">))</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span> &lt; <span style="color:#e6db74">&#34;sample_file.txt&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="write">
  <a class="anchor inpage" href="#write">###</a>write</h3>
<h2 id="redirection-pipe">
  <a class="anchor inpage" href="#redirection-pipe">##</a>redirection, pipe</h2>
<h3 id="direction">
  <a class="anchor inpage" href="#direction">###</a>direction</h3>
<h4 id="输出重定向">
  <a class="anchor inpage" href="#%e8%be%93%e5%87%ba%e9%87%8d%e5%ae%9a%e5%90%91">####</a>输出重定向</h4>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&gt;</code></td>
          <td>覆盖写入文件（标准输出）</td>
          <td><code>ls &gt; file.txt</code></td>
      </tr>
      <tr>
          <td><code>&gt;&gt;</code></td>
          <td>追加到文件（标准输出）</td>
          <td><code>echo &quot;hi&quot; &gt;&gt; file.txt</code></td>
      </tr>
      <tr>
          <td><code>2&gt;</code></td>
          <td>覆盖写入文件（标准错误）</td>
          <td><code>cmd 2&gt; error.log</code></td>
      </tr>
      <tr>
          <td><code>2&gt;&gt;</code></td>
          <td>追加到文件（标准错误）</td>
          <td><code>cmd 2&gt;&gt; error.log</code></td>
      </tr>
      <tr>
          <td><code>&amp;&gt;</code></td>
          <td>覆盖写入文件（标准输出+标准错误）</td>
          <td><code>cmd &amp;&gt; output.log</code></td>
      </tr>
      <tr>
          <td><code>&amp;&gt;&gt;</code></td>
          <td>追加到文件（标准输出+标准错误）</td>
          <td><code>cmd &amp;&gt;&gt; output.log</code></td>
      </tr>
  </tbody>
</table>
<p><strong>文件描述符操作</strong> Bash 用数字<code>n</code>表示文件描述符（File Descriptor, FD）：</p>
<ul>
<li><code>0</code>：标准输入（stdin）</li>
<li><code>1</code>：标准输出（stdout）</li>
<li><code>2</code>：标准错误（stderr）</li>
</ul>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>n&gt;</code></td>
          <td>覆盖写入到文件描述符 <code>n</code></td>
          <td><code>cmd 3&gt; custom_fd.log</code></td>
      </tr>
      <tr>
          <td><code>n&gt;&gt;</code></td>
          <td>追加到文件描述符 <code>n</code></td>
          <td><code>cmd 3&gt;&gt; custom_fd.log</code></td>
      </tr>
      <tr>
          <td><code>n&gt;&amp;m</code></td>
          <td>将文件描述符 <code>n</code> 重定向到 <code>m</code></td>
          <td><code>cmd 2&gt;&amp;1</code>（错误合并到输出）</td>
      </tr>
      <tr>
          <td><code>n&gt;&amp;-</code></td>
          <td>关闭文件描述符 <code>n</code></td>
          <td><code>exec 3&gt;&amp;-</code></td>
      </tr>
      <tr>
          <td><code>&amp;&gt;file</code> 或 <code>&gt;&amp;file</code></td>
          <td>合并标准输出和错误到文件（兼容性写法）</td>
          <td><code>cmd &amp;&gt; all.log</code></td>
      </tr>
  </tbody>
</table>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将标准错误重定向到文件描述符3，再重定向到文件</span>
</span></span><span style="display:flex;"><span>exec 3&gt;&amp;<span style="color:#ae81ff">1</span>  <span style="color:#75715e"># 备份标准输出到3</span>
</span></span><span style="display:flex;"><span>cmd 2&gt;&amp;<span style="color:#ae81ff">1</span> &gt;output.log | tee -a error.log  <span style="color:#75715e"># 错误流单独处理</span>
</span></span><span style="display:flex;"><span>exec 1&gt;&amp;<span style="color:#ae81ff">3</span>  <span style="color:#75715e"># 恢复标准输出</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>特殊设备重定向</strong></p>
<table>
  <thead>
      <tr>
          <th>目标文件</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>/dev/null</code></td>
          <td>丢弃输出（黑洞设备）</td>
          <td><code>cmd &gt; /dev/null 2&gt;&amp;1</code></td>
      </tr>
      <tr>
          <td><code>/dev/stdout</code></td>
          <td>显式指向标准输出</td>
          <td><code>echo &quot;x&quot; &gt; /dev/stdout</code></td>
      </tr>
      <tr>
          <td><code>/dev/stderr</code></td>
          <td>显式指向标准错误</td>
          <td><code>echo &quot;error&quot; &gt; /dev/stderr</code></td>
      </tr>
      <tr>
          <td><code>/dev/fd/n</code></td>
          <td>重定向到文件描述符 <code>n</code></td>
          <td><code>cmd &gt; /dev/fd/3</code></td>
      </tr>
  </tbody>
</table>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 静默执行命令（忽略所有输出）</span>
</span></span><span style="display:flex;"><span>cmd &gt; /dev/null 2&gt;&amp;<span style="color:#ae81ff">1</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="输入重定向">
  <a class="anchor inpage" href="#%e8%be%93%e5%85%a5%e9%87%8d%e5%ae%9a%e5%90%91">####</a>输入重定向</h4>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;</code></td>
          <td>从文件读取输入（标准输入）</td>
          <td><code>sort &lt; data.txt</code></td>
      </tr>
      <tr>
          <td><code>&lt;&lt;</code></td>
          <td>Here Document（多行输入）</td>
          <td>见前文</td>
      </tr>
      <tr>
          <td><code>&lt;&lt;&lt;</code></td>
          <td>Here String（字符串输入）</td>
          <td><code>grep &quot;x&quot; &lt;&lt;&lt; &quot;abc&quot;</code></td>
      </tr>
  </tbody>
</table>
<p><strong><code>&lt;</code>：标准输入重定向</strong></p>
<p><strong>作用</strong>：将文件内容作为命令的标准输入。<br>
<strong>语法</strong>：<code>command &lt; file</code><br>
<strong>特点</strong>：</p>
<ul>
<li>从文件中读取数据并传递给命令</li>
<li>文件内容会逐行作为命令的输入</li>
</ul>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将 file.txt 的内容作为 wc 命令的输入</span>
</span></span><span style="display:flex;"><span>wc -l &lt; file.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>结果</strong>：统计 <code>file.txt</code> 的行数。</p>
<p><strong><code>&lt;&lt;</code>：Here Document（文档内嵌输入）</strong></p>
<p><strong>作用</strong>：将多行文本（称为 &ldquo;Here Document&rdquo;）作为命令的标准输入，直到遇到指定的结束标记。<br>
<strong>语法</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>command <span style="color:#e6db74">&lt;&lt; DELIMITER
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">多行文本...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">DELIMITER</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>特点</strong>：</p>
<ul>
<li>允许在脚本中直接嵌入多行输入</li>
<li>结束标记（<code>DELIMITER</code>）可以是任意字符串（通常用 <code>EOF</code>）</li>
<li>默认会解析变量和命令替换（除非用引号包围 <code>DELIMITER</code>，如 <code>&lt;&lt;'EOF'</code>）</li>
</ul>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将多行文本传递给 cat 命令</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt; EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">第一行
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">第二行
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">变量值: $HOME
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>结果</strong>：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">第一行
第二行
变量值: /home/username</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong><code>&lt;&lt;&lt;</code>：Here String（字符串内嵌输入）</strong>
<strong>作用</strong>：将单个字符串作为命令的标准输入。<br>
<strong>语法</strong>：<code>command &lt;&lt;&lt; &quot;string&quot;</code><br>
<strong>特点</strong>：</p>
<ul>
<li>直接传递字符串（无需文件或多行文本）</li>
<li>字符串会解析变量和命令替换</li>
<li>比 <code>echo &quot;string&quot; | command</code> 更高效（避免管道和子进程）</li>
</ul>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 将字符串传递给 grep 命令</span>
</span></span><span style="display:flex;"><span>grep <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">&lt;&lt;&lt;</span> <span style="color:#e6db74">&#34;hello world&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>结果</strong>：输出 <code>hello world</code>（因为匹配成功）。</p>
<p><strong>对比总结</strong></p>
<table>
  <thead>
      <tr>
          <th>操作符</th>
          <th>名称</th>
          <th>输入源</th>
          <th>典型用途</th>
          <th>是否解析变量</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;</code></td>
          <td>输入重定向</td>
          <td>文件</td>
          <td>从文件读取数据</td>
          <td>是</td>
      </tr>
      <tr>
          <td><code>&lt;&lt;</code></td>
          <td>Here Document</td>
          <td>多行文本（脚本内嵌）</td>
          <td>传递多行输入（如生成配置文件）</td>
          <td>是（可禁用）</td>
      </tr>
      <tr>
          <td><code>&lt;&lt;&lt;</code></td>
          <td>Here String</td>
          <td>单个字符串</td>
          <td>快速传递变量或简单字符串</td>
          <td>是</td>
      </tr>
  </tbody>
</table>
<p><strong>关键区别</strong></p>
<ol>
<li>
<p><strong>输入来源不同</strong>：</p>
<ul>
<li><code>&lt;</code> 从文件读取</li>
<li><code>&lt;&lt;</code> 从脚本内嵌的多行文本读取</li>
<li><code>&lt;&lt;&lt;</code> 从单个字符串读取</li>
</ul>
</li>
<li>
<p><strong>性能差异</strong>：</p>
<ul>
<li><code>&lt;&lt;&lt;</code> 比 <code>echo &quot;str&quot; | command</code> 更高效（避免管道）</li>
<li><code>&lt;</code> 适合处理大文件（逐行读取，不占用内存）</li>
</ul>
</li>
<li>
<p><strong>变量解析</strong>：</p>
<ul>
<li><code>&lt;&lt;</code> 和 <code>&lt;&lt;&lt;</code> 默认解析变量，但 <code>&lt;&lt;</code> 可通过 <code>&lt;&lt;'DELIMITER'</code> 禁用解析</li>
<li><code>&lt;</code> 由命令决定是否解析（如 <code>cat</code> 不解析，<code>eval</code> 会解析）</li>
</ul>
</li>
</ol>
<hr>
<p><strong>使用场景示例</strong>
<strong><code>&lt;</code> 的典型用途</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 从配置文件读取输入</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> read line; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;配置行: </span>$line<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span> &lt; config.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong><code>&lt;&lt;</code> 的典型用途</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 生成多行配置文件</span>
</span></span><span style="display:flex;"><span>cat &gt; app.conf <span style="color:#e6db74">&lt;&lt; EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">server_ip=192.168.1.1
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">port=8080
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong><code>&lt;&lt;&lt;</code> 的典型用途</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 快速检查字符串是否包含子串</span>
</span></span><span style="display:flex;"><span>grep <span style="color:#e6db74">&#34;error&#34;</span> <span style="color:#f92672">&lt;&lt;&lt;</span> <span style="color:#e6db74">&#34;</span>$log_content<span style="color:#e6db74">&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>注意事项</strong></p>
<ol>
<li>
<p><strong><code>&lt;&lt;</code> 的结束标记</strong>：</p>
<ul>
<li>结束标记必须单独一行且顶格书写（不能有缩进）：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 错误示例（缩进会导致语法错误）</span>
</span></span><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt; EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">内容...
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  EOF</span>  <span style="color:#75715e"># 缩进了，无法识别为结束标记</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong><code>&lt;&lt;&lt;</code> 的字符串引用</strong>：</p>
<ul>
<li>如果字符串包含空格或特殊字符，需用引号包围：
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 安全写法</span>
</span></span><span style="display:flex;"><span>wc -w <span style="color:#f92672">&lt;&lt;&lt;</span> <span style="color:#e6db74">&#34;hello world&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
<li>
<p><strong>性能选择</strong>：</p>
<ul>
<li>处理大量数据时优先用 <code>&lt;</code>（文件）或 <code>&lt;&lt;</code>（多行文本）</li>
<li>简单字符串操作用 <code>&lt;&lt;&lt;</code> 更高效</li>
</ul>
</li>
</ol>
<h4 id="重定向组合">
  <a class="anchor inpage" href="#%e9%87%8d%e5%ae%9a%e5%90%91%e7%bb%84%e5%90%88">####</a>重定向组合</h4>
<p><strong>(1) 同时重定向输入和输出</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 从input.txt读取，结果写入output.txt</span>
</span></span><span style="display:flex;"><span>command &lt; input.txt &gt; output.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(2) 分离标准输出和错误</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 标准输出到out.log，错误到err.log</span>
</span></span><span style="display:flex;"><span>command &gt; out.log 2&gt; err.log</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>(3) 合并输出和错误到同一文件</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 方式1（推荐）</span>
</span></span><span style="display:flex;"><span>command &amp;&gt; combined.log
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 方式2（传统写法）</span>
</span></span><span style="display:flex;"><span>command &gt; combined.log 2&gt;&amp;<span style="color:#ae81ff">1</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="进程替换process-substitution">
  <a class="anchor inpage" href="#%e8%bf%9b%e7%a8%8b%e6%9b%bf%e6%8d%a2process-substitution">####</a>进程替换（Process Substitution）</h4>
<p>用 <code>&gt;(...)</code> 和 <code>&lt;(...)</code> 将命令输出/输入视为临时文件：</p>
<table>
  <thead>
      <tr>
          <th>符号</th>
          <th>作用</th>
          <th>示例</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>&lt;(cmd)</code></td>
          <td>将命令输出作为文件输入</td>
          <td><code>diff &lt;(ls dir1) &lt;(ls dir2)</code></td>
      </tr>
      <tr>
          <td><code>&gt;(cmd)</code></td>
          <td>将命令输入作为文件输出</td>
          <td><code>tee &gt;(gzip &gt; out.gz)</code></td>
      </tr>
  </tbody>
</table>
<p><strong>示例</strong>：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 比较两个目录的文件列表差异</span>
</span></span><span style="display:flex;"><span>diff &lt;<span style="color:#f92672">(</span>ls /path/to/dir1<span style="color:#f92672">)</span> &lt;<span style="color:#f92672">(</span>ls /path/to/dir2<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 将输出同时写入文件和压缩</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;data&#34;</span> | tee &gt;<span style="color:#f92672">(</span>gzip &gt; output.gz<span style="color:#f92672">)</span> &gt; original.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="综合示例">
  <a class="anchor inpage" href="#%e7%bb%bc%e5%90%88%e7%a4%ba%e4%be%8b">####</a>综合示例</h4>
<p>** 日志记录脚本**</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>exec 3&gt;&amp;<span style="color:#ae81ff">1</span>  <span style="color:#75715e"># 备份标准输出到描述符3</span>
</span></span><span style="display:flex;"><span>exec &gt; &gt;<span style="color:#f92672">(</span>tee -a stdout.log<span style="color:#f92672">)</span> 2&gt; &gt;<span style="color:#f92672">(</span>tee -a stderr.log &gt;&amp;2<span style="color:#f92672">)</span>  <span style="color:#75715e"># 分离输出和错误</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;正常消息&#34;</span>  <span style="color:#75715e"># 写入stdout.log</span>
</span></span><span style="display:flex;"><span>ls /nonexistent  <span style="color:#75715e"># 错误写入stderr.log</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>exec 1&gt;&amp;<span style="color:#ae81ff">3</span>  <span style="color:#75715e"># 恢复标准输出</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;回到终端显示&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>复杂重定向</strong></p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准输出1&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准错误1&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准输出2&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;标准错误2&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span> &gt; &gt;<span style="color:#f92672">(</span>grep <span style="color:#e6db74">&#34;标准输出&#34;</span> &gt; out.txt<span style="color:#f92672">)</span> 2&gt; &gt;<span style="color:#f92672">(</span>grep <span style="color:#e6db74">&#34;标准错误&#34;</span> &gt; err.txt<span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><strong>注意事项</strong></p>
<ol>
<li>
<p><strong>顺序敏感</strong>：<br>
<code>2&gt;&amp;1 &gt;file</code> 和 <code>&gt;file 2&gt;&amp;1</code> 完全不同！后者才是合并输出到文件。</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 错误：错误流不会进入文件</span>
</span></span><span style="display:flex;"><span>cmd 2&gt;&amp;<span style="color:#ae81ff">1</span> &gt; file
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 正确：合并输出和错误到文件</span>
</span></span><span style="display:flex;"><span>cmd &gt; file 2&gt;&amp;<span style="color:#ae81ff">1</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>文件描述符范围</strong>：<br>
Bash 默认支持 <code>0-9</code>，更高数值需用 <code>exec</code> 显式分配。</p>
</li>
<li>
<p><strong>管道与重定向优先级</strong>：<br>
管道 <code>|</code> 优先级高于重定向，必要时用 <code>{ }</code> 分组：</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#f92672">{</span> cmd1 | cmd2; <span style="color:#f92672">}</span> &gt; output.txt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
<li>
<p><strong>Here Document 的变体</strong>：</p>
<ul>
<li><code>&lt;&lt;-</code>：忽略结束标记前的制表符（Tab）
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>cat <span style="color:#e6db74">&lt;&lt;- EOF
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Indented text
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">EOF</span>  <span style="color:#75715e"># 可以用Tab缩进</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></li>
</ul>
</li>
</ol>
<h3 id="pipe">
  <a class="anchor inpage" href="#pipe">###</a>pipe</h3>
<h2 id="control">
  <a class="anchor inpage" href="#control">##</a>control</h2>
<h3 id="if">
  <a class="anchor inpage" href="#if">###</a>if</h3>
<ul>
<li><code>if...then...fi</code> statements</li>
<li><code>if...then...else...fi</code> statements</li>
<li><code>if..elif..else..fi</code></li>
<li><code>if..then..else..if..then..fi..fi..</code> (Nested Conditionals)</li>
</ul>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ... <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># if-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># else-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>or</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ... <span style="color:#f92672">]</span> ; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># if-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># else-code</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>conditions:</p>
<p>examples:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -lt <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;X is less than zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -gt <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;X is more than zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -le <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is less than or equal to  zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -ge <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is more than or equal to zero&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is the string or number \&#34;0\&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X matches the string \&#34;hello\&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> !<span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;hello&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is not the string \&#34;hello\&#34;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -n <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is of nonzero length&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -f <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is the path of a real file&#34;</span> <span style="color:#f92672">||</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;No such file: </span>$X<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> -x <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is the path of an executable file&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span> <span style="color:#e6db74">&#34;</span>$X<span style="color:#e6db74">&#34;</span> -nt <span style="color:#e6db74">&#34;/etc/passwd&#34;</span> <span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>      echo <span style="color:#e6db74">&#34;X is a file which is newer than /etc/passwd&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>read a
</span></span><span style="display:flex;"><span>read b
</span></span><span style="display:flex;"><span>read c
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $a <span style="color:#f92672">==</span> $b -a $b <span style="color:#f92672">==</span> $c -a $a <span style="color:#f92672">==</span> $c <span style="color:#f92672">]</span> <span style="color:#75715e"># -a means</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>echo EQUILATERAL
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">elif</span> <span style="color:#f92672">[</span> $a <span style="color:#f92672">==</span> $b -o $b <span style="color:#f92672">==</span> $c -o $a <span style="color:#f92672">==</span> $c <span style="color:#f92672">]</span> <span style="color:#75715e"># -o means or</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>echo ISOSCELES
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>echo SCALENE
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="loop">
  <a class="anchor inpage" href="#loop">###</a>loop</h3>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#f92672">{</span>1..5<span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo $i
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> X in cyan magenta yellow
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo $X
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span>i<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> <span style="color:#f92672">[[</span> $i -le <span style="color:#ae81ff">10</span> <span style="color:#f92672">]]</span> ; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>   echo <span style="color:#e6db74">&#34;</span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">((</span> i <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">))</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 定义数组（空格分隔元素，可含特殊字符）</span>
</span></span><span style="display:flex;"><span>fruits<span style="color:#f92672">=(</span><span style="color:#e6db74">&#34;Apple&#34;</span> <span style="color:#e6db74">&#34;Banana&#34;</span> <span style="color:#e6db74">&#34;Orange&#34;</span> <span style="color:#e6db74">&#34;Grape&#34;</span> <span style="color:#e6db74">&#34;Watermelon&#34;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> fruit in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>fruits[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Fruit: </span>$fruit<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>!fruits[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Index </span>$i<span style="color:#e6db74">: </span><span style="color:#e6db74">${</span>fruits[i]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># 定义仓库目录列表（支持绝对路径或相对路径）</span>
</span></span><span style="display:flex;"><span>repos<span style="color:#f92672">=(</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo1&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo2&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo3&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;/path/to/repo4&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 遍历所有仓库</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> i in <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">${</span>repos[@]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Updating repo: </span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    cd <span style="color:#e6db74">&#34;</span>$i<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">||</span> <span style="color:#f92672">{</span> echo <span style="color:#e6db74">&#34;Failed to enter </span>$i<span style="color:#e6db74">&#34;</span>; <span style="color:#66d9ef">continue</span>; <span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 执行 git pull</span>
</span></span><span style="display:flex;"><span>    git pull origin main  <span style="color:#75715e"># 假设分支是 main，根据实际情况修改</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 检查 git pull 是否成功</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $? -eq <span style="color:#ae81ff">0</span> <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;Successfully updated: </span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;Failed to update: </span>$i<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;----------------------------------&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;All repositories updated!&#34;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="function">
  <a class="anchor inpage" href="#function">##</a>function</h2>
<blockquote class="alert alert-warning">
      <p class="alert-heading"><br></p><p><strong>fork boom!</strong></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">:(){:|:;};:</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></blockquote><h2 id="advance">
  <a class="anchor inpage" href="#advance">##</a>Advance</h2>
<h3 id="get-opts">
  <a class="anchor inpage" href="#get-opts">###</a>get-opts</h3>
<p>example:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>docs<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Usage: \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\tbash </span>$0<span style="color:#e6db74"> [options] \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\nOptions: \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t-N NAME: your name, required\
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t-a AGE: your age, required\
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t-v: verbose mode, optional\
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\nExample: \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">\n\t bash </span>$0<span style="color:#e6db74"> -N balabala -a 24 &#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>usage<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    echo -e $docs &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $# -eq <span style="color:#ae81ff">0</span> <span style="color:#f92672">]</span> <span style="color:#f92672">||</span> <span style="color:#f92672">[</span> $1 <span style="color:#f92672">==</span> -h <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span> usage; <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 设置变量的默认值</span>
</span></span><span style="display:flex;"><span>verbose<span style="color:#f92672">=</span>n
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 检查变量参数是否缺失</span>
</span></span><span style="display:flex;"><span>check<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>    opt<span style="color:#f92672">=</span>$1
</span></span><span style="display:flex;"><span>    arg<span style="color:#f92672">=</span>$2
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> $arg <span style="color:#f92672">=</span>~ ^- <span style="color:#f92672">]]</span> <span style="color:#f92672">||</span> <span style="color:#f92672">[</span> ! $arg <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;ERROR: -</span>$opt<span style="color:#e6db74"> expects an corresponding argument&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>        usage
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 循环解析脚本的所有positional parameters</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> getopts :vN:a: opt
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">do</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">case</span> $opt in
</span></span><span style="display:flex;"><span>    v<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        verbose<span style="color:#f92672">=</span>y
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    N<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        check N $OPTARG
</span></span><span style="display:flex;"><span>        name<span style="color:#f92672">=</span>$OPTARG
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    a<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        check a $OPTARG
</span></span><span style="display:flex;"><span>        age<span style="color:#f92672">=</span>$OPTARG
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    :<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;ERROR: -</span>$OPTARG<span style="color:#e6db74"> expects an corresponding argument&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>        usage
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">\?</span><span style="color:#f92672">)</span> <span style="color:#75715e"># shell里&#39;?&#39;具有匹配一位任意字符的作用，因此需要转义为普通字符</span>
</span></span><span style="display:flex;"><span>        echo <span style="color:#e6db74">&#34;ERROR: unkown option -</span>$OPTARG<span style="color:#e6db74">&#34;</span> &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>        usage
</span></span><span style="display:flex;"><span>        ;;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">esac</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">done</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 如果用户没有提供-N选项</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ! $name <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo ERROR: option -N is required &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    usage
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">## 如果用户没有提供-a选项</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ! $age <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo ERROR: option -a is required &gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>    usage
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> $verbose <span style="color:#f92672">==</span> n <span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Merry Christmas! </span>$name<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Hello, your name is </span>$name<span style="color:#e6db74">, you are </span>$age<span style="color:#e6db74"> years old!&#34;</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Merry Christmas!!&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>在 <code>:vN:a:</code>中，第一个<code>:</code> 表示静默错误模式（silent error mode）。如果没有这个<code>:</code>，当遇到无效选项时，getopts 会打印错误消息。<br>
选项后的 <code>:</code>（如 N:）表示该选项需要一个参数。<br>
如果没有 <code>:</code>，则表示该选项不需要参数。</p>
<h3 id="cron">
  <a class="anchor inpage" href="#cron">###</a>cron</h3>
<p>Cron is a job scheduling utility present in Unix like systems. You can schedule jobs to execute daily, weekly, monthly or in a specific time of the day. Automation in Linux heavily relies on cron jobs.</p>
<p>Below is the syntax to schedule crons:</p>
<details open>
    <summary>bash</summary><pre
        class="chroma codeblock"
      ><code class="language-bash" data-lang="bash"
          ><span style="display:flex;"><span><span style="color:#75715e"># Cron job example</span>
</span></span><span style="display:flex;"><span>* * * * * sh /path/to/script.sh</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Here, <code>*</code> represents minute(s) hour(s) day(s) month(s) weekday(s), respectively.</p>
<p>Below are some examples of scheduling cron jobs.</p>
<table>
  <thead>
      <tr>
          <th>SCHEDULE</th>
          <th>SCHEDULED VALUE</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>5 0 * 8 *</td>
          <td>At 00:05 in August.</td>
      </tr>
      <tr>
          <td>5 4 * * 6</td>
          <td>At 04:05 on Saturday.</td>
      </tr>
      <tr>
          <td>0 22 * * 1-5</td>
          <td>At 22:00 on every day-of-week from Monday through Friday.</td>
      </tr>
  </tbody>
</table>
<p><code>crontab -l</code> lists the already scheduled scripts for a particular user.</p>
]]></content:encoded></item><item><title>从键盘到字符</title><link>https://hiraethecho.github.io/docs/linux/keysym/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/keysym/</guid><description>linux下从键盘收到信号后到屏幕上显示字符的过程</description><content:encoded><![CDATA[<h1 id="从键盘到字符">
  <a class="anchor inpage" href="#%e4%bb%8e%e9%94%ae%e7%9b%98%e5%88%b0%e5%ad%97%e7%ac%a6">#</a>从键盘到字符</h1>
<h2 id="前置知识">
  <a class="anchor inpage" href="#%e5%89%8d%e7%bd%ae%e7%9f%a5%e8%af%86">##</a>前置知识</h2>
<p>参考
</p>
<ul>
<li>硬件，即键盘本身，发出扫描码（scancode），发送给内核；</li>
<li>内核并将其转换为键码（keycode）。键码是操作系统用来识别按键的数字表示。</li>
<li>受到键码后，X服务器或Wayland合成器将其转换为键符（keysym）。键符是一个更高级别的表示，表示按键的实际字符或功能。</li>
</ul>
<p>在xorg下，有
来使用keycode</p>
<h2 id="识别">
  <a class="anchor inpage" href="#%e8%af%86%e5%88%ab">##</a>识别</h2>
<p>xorg下管理接入的输入设备，例如 find id of touchpad:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">xinput list | grep -i &#34;Touchpad&#34; | awk &#39;{print $6}&#39; | sed &#39;s/[^0-9]//g&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>似乎需要添加文件 <code>/usr/share/X11/xorg.conf.d/30-touchpad.conf</code></p>
<details open>
    <summary>conf</summary><pre
        class="codeblock"
      ><code class="language-conf" data-lang="conf">Section &#34;InputClass&#34;
        Identifier &#34;MyTouchpad&#34;
        MatchIsTouchpad &#34;on&#34;
        Driver &#34;libinput&#34;
        Option &#34;Tapping&#34; &#34;on&#34;
EndSection</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>之后才能正常识别<code>touchpad</code>：</p>
<details open>
    <summary>xinput</summary><pre
        class="codeblock"
      ><code class="language-xinput" data-lang="xinput">
⎡ Virtual core pointer                    	id=2	[master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer              	id=4	[slave  pointer  (2)]
⎜   ↳ GXTP7863:00 27C6:01E0 Mouse             	id=11	[slave  pointer  (2)]
⎜   ↳ GXTP7863:00 27C6:01E0 Touchpad          	id=12	[slave  pointer  (2)]
⎜   ↳ HS6209 2.4G Wireless Receiver Keyboard  	id=9	[slave  pointer  (2)]
⎜   ↳ HS6209 2.4G Wireless Receiver Mouse     	id=10	[slave  pointer  (2)]
⎣ Virtual core keyboard                   	id=3	[master keyboard (2)]
    ↳ Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
    ↳ Video Bus                               	id=6	[slave  keyboard (3)]
    ↳ Power Button                            	id=7	[slave  keyboard (3)]
    ↳ Huawei WMI hotkeys                      	id=13	[slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard            	id=14	[slave  keyboard (3)]</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>否则只会识别两个设备，没有 <code>Mouse</code> <code>Touchpad</code></p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>$ xinput list
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>⎡ Virtual core pointer                    	id<span style="color:#f92672">=</span>2	<span style="color:#f92672">[</span>master pointer  <span style="color:#f92672">(</span>3<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>⎜   ↳ Virtual core XTEST pointer              	id<span style="color:#f92672">=</span>4	<span style="color:#f92672">[</span>slave  pointer  <span style="color:#f92672">(</span>2<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>⎜   ↳ GXTP7863:00 27C6:01E0                   	id<span style="color:#f92672">=</span>10	<span style="color:#f92672">[</span>slave  pointer  <span style="color:#f92672">(</span>2<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>⎜   ↳ GXTP7863:00 27C6:01E0                   	id<span style="color:#f92672">=</span>11	<span style="color:#f92672">[</span>slave  pointer  <span style="color:#f92672">(</span>2<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>⎣ Virtual core keyboard                   	id<span style="color:#f92672">=</span>3	<span style="color:#f92672">[</span>master keyboard <span style="color:#f92672">(</span>2<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>    ↳ Virtual core XTEST keyboard             	id<span style="color:#f92672">=</span>5	<span style="color:#f92672">[</span>slave  keyboard <span style="color:#f92672">(</span>3<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>    ↳ Video Bus                               	id<span style="color:#f92672">=</span>6	<span style="color:#f92672">[</span>slave  keyboard <span style="color:#f92672">(</span>3<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>    ↳ Power Button                            	id<span style="color:#f92672">=</span>7	<span style="color:#f92672">[</span>slave  keyboard <span style="color:#f92672">(</span>3<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>    ↳ Huawei WMI hotkeys                      	id<span style="color:#f92672">=</span>12	<span style="color:#f92672">[</span>slave  keyboard <span style="color:#f92672">(</span>3<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>    ↳ AT Translated Set <span style="color:#ae81ff">2</span> keyboard            	id<span style="color:#f92672">=</span>13	<span style="color:#f92672">[</span>slave  keyboard <span style="color:#f92672">(</span>3<span style="color:#f92672">)]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>xev</code>: find keycode;</p>
<h2 id="修改">
  <a class="anchor inpage" href="#%e4%bf%ae%e6%94%b9">##</a>修改</h2>
<h3 id="xorg">
  <a class="anchor inpage" href="#xorg">###</a>xorg</h3>
<p>支持的修改可以参考 <code>/usr/share/X11/xkb/rules/base.lst</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">  caps                 Caps Lock behavior
  caps:internal        Caps Lock uses internal capitalization; Shift &#34;pauses&#34; Caps Lock
  caps:internal_nocancel Caps Lock uses internal capitalization; Shift does not affect Caps Lock
  caps:shift           Caps Lock acts as Shift with locking; Shift &#34;pauses&#34; Caps Lock
  caps:shift_nocancel  Caps Lock acts as Shift with locking; Shift does not affect Caps Lock
  caps:capslock        Caps Lock toggles normal capitalization of alphabetic characters
  caps:shiftlock       Caps Lock toggles Shift Lock (affects all keys)
  caps:swapescape      Swap Esc and Caps Lock
  caps:escape          Make Caps Lock an additional Esc
  caps:escape_shifted_capslock Make Caps Lock an additional Esc, but Shift &#43; Caps Lock is the regular Caps Lock
  caps:backspace       Make Caps Lock an additional Backspace
  caps:return          Make Caps Lock an additional Return key
  caps:super           Make Caps Lock an additional Super
  caps:hyper           Make Caps Lock an additional Hyper
  caps:menu            Make Caps Lock an additional Menu key
  caps:numlock         Make Caps Lock an additional Num Lock
  caps:ctrl_shifted_capslock Make Caps Lock an additional Ctrl and Shift &#43; Caps Lock the regular Caps Lock
  caps:ctrl_modifier   Make Caps Lock act as an additional Ctrl modifier, but keep identifying as Caps Lock
  caps:digits_row      Caps Lock gives digits on the digits row (Azerty layouts)
  caps:digits_row_independent_lock Shift &#43; Caps locks the digits on the digits row, Caps Lock alone behaves as usual (Azerty layouts)
  caps:none            Caps Lock is disabled

  ctrl                 Ctrl position
  ctrl:nocaps          Caps Lock as Ctrl
  ctrl:lctrl_meta      Left Ctrl as Meta
  ctrl:swapcaps        Swap Ctrl and Caps Lock
  ctrl:grouptoggle_capscontrol Caps Lock as Ctrl,  Left Control switches to another layout
  ctrl:hyper_capscontrol Caps Lock as Ctrl, Ctrl as Hyper
  ctrl:ac_ctrl         To the left of &#34;A&#34;
  ctrl:aa_ctrl         At the bottom left
  ctrl:rctrl_ralt      Right Ctrl as Right Alt
  ctrl:ralt_rctrl      Right Alt as Right Control
  ctrl:menu_rctrl      Menu as Right Ctrl
  ctrl:swap_lalt_lctl  Swap Left Alt with Left Ctrl
  ctrl:swap_ralt_rctl  Swap Right Alt with Right Ctrl
  ctrl:swap_lwin_lctl  Swap Left Win with Left Ctrl
  ctrl:swap_rwin_rctl  Swap Right Win with Right Ctrl
  ctrl:swap_lalt_lctl_lwin Left Alt as Ctrl, Left Ctrl as Win, Left Win as Left Alt</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="xmodmap">
  <a class="anchor inpage" href="#xmodmap">####</a>xmodmap</h4>
<details open>
    <summary>man</summary><pre
        class="chroma codeblock"
      ><code class="language-man" data-lang="man"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>XMODMAP(1)                  General Commands Manual                  XMODMAP(1)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>       xmodmap - utility for modifying keymaps and pointer button mappings in X
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>       xmodmap [-options ...] [filename]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DESCRIPTION
</span></span><span style="display:flex;"><span>       The  xmodmap  program  is used to edit and display the keyboard modifier
</span></span><span style="display:flex;"><span>       map and keymap table that are used by  client  applications  to  convert
</span></span><span style="display:flex;"><span>       event  keycodes into keysyms.  It is usually run from the user&#39;s session
</span></span><span style="display:flex;"><span>       startup script to configure the keyboard according to personal tastes.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>OPTIONS
</span></span><span style="display:flex;"><span>       The following options may be used with xmodmap:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -display display
</span></span><span style="display:flex;"><span>               This option specifies the host and display to use.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -help   This option indicates that a brief description  of  the  command
</span></span><span style="display:flex;"><span>               line  arguments should be printed on the standard error channel.
</span></span><span style="display:flex;"><span>               This will be done whenever an unhandled  argument  is  given  to
</span></span><span style="display:flex;"><span>               xmodmap.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -grammar
</span></span><span style="display:flex;"><span>               This option indicates that a help message describing the expres‐
</span></span><span style="display:flex;"><span>               sion  grammar  used  in  files and with -e expressions should be
</span></span><span style="display:flex;"><span>               printed on the standard error.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -version
</span></span><span style="display:flex;"><span>               This option indicates that xmodmap should print its version  in‐
</span></span><span style="display:flex;"><span>               formation and exit.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -verbose
</span></span><span style="display:flex;"><span>               This option indicates that xmodmap should print logging informa‐
</span></span><span style="display:flex;"><span>               tion as it parses its input.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -quiet  This option turns off the verbose logging.  This is the default.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -n      This  option  indicates  that xmodmap should not change the map‐
</span></span><span style="display:flex;"><span>               pings, but should display what it would do,  like  make(1)  does
</span></span><span style="display:flex;"><span>               when given this option.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -e expression
</span></span><span style="display:flex;"><span>               This  option specifies an expression to be executed.  Any number
</span></span><span style="display:flex;"><span>               of expressions may be specified from the command line.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -pm     This option indicates that the current modifier  map  should  be
</span></span><span style="display:flex;"><span>               printed  on  the  standard output.   This is the default mode of
</span></span><span style="display:flex;"><span>               operation if no other mode options are specified.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -pk     This option indicates that the current keymap  table  should  be
</span></span><span style="display:flex;"><span>               printed on the standard output.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -pke    This  option  indicates  that the current keymap table should be
</span></span><span style="display:flex;"><span>               printed on the standard output in the form of  expressions  that
</span></span><span style="display:flex;"><span>               can be fed back to xmodmap.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -pp     This  option  indicates  that  the current pointer map should be
</span></span><span style="display:flex;"><span>               printed on the standard output.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -       A lone dash means that the standard input should be used as  the
</span></span><span style="display:flex;"><span>               input file.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       The  filename specifies a file containing xmodmap expressions to be exe‐
</span></span><span style="display:flex;"><span>       cuted.  This file is usually kept in the user&#39;s home  directory  with  a
</span></span><span style="display:flex;"><span>       name like .xmodmaprc.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXPRESSION GRAMMAR
</span></span><span style="display:flex;"><span>       The  xmodmap program reads a list of expressions and parses them all be‐
</span></span><span style="display:flex;"><span>       fore attempting to execute any of them.  This makes it possible to refer
</span></span><span style="display:flex;"><span>       to keysyms that are being redefined in a natural way without  having  to
</span></span><span style="display:flex;"><span>       worry as much about name conflicts.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       The   list   of   keysym   names   may  be  found  in  the  header  file
</span></span><span style="display:flex;"><span>       &lt;X11/keysymdef.h&gt; (without the XK_ prefix).   Keysyms  matching  Unicode
</span></span><span style="display:flex;"><span>       characters  may  be  specified  as  &#34;U0020&#34;  to  &#34;U007E&#34;  and &#34;U00A0&#34; to
</span></span><span style="display:flex;"><span>       &#34;U10FFFF&#34; for all possible Unicode characters.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       keycode NUMBER = KEYSYMNAME ...
</span></span><span style="display:flex;"><span>               The list of keysyms is assigned to the indicated keycode  (which
</span></span><span style="display:flex;"><span>               may  be specified in decimal, hex or octal and can be determined
</span></span><span style="display:flex;"><span>               by running the xev program).  Up to eight  keysyms  may  be  at‐
</span></span><span style="display:flex;"><span>               tached to a key, however the last four are not used in any major
</span></span><span style="display:flex;"><span>               X server implementation.  The first keysym is used when no modi‐
</span></span><span style="display:flex;"><span>               fier  key  is  pressed  in conjunction with this key, the second
</span></span><span style="display:flex;"><span>               with Shift, the third when the Mode_switch key is used with this
</span></span><span style="display:flex;"><span>               key and the fourth when both the Mode_switch and Shift keys  are
</span></span><span style="display:flex;"><span>               used.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       keycode any = KEYSYMNAME ...
</span></span><span style="display:flex;"><span>               If no existing key has the specified list of keysyms assigned to
</span></span><span style="display:flex;"><span>               it,  a spare key on the keyboard is selected and the keysyms are
</span></span><span style="display:flex;"><span>               assigned to it.  The list of keysyms may be specified  in  deci‐
</span></span><span style="display:flex;"><span>               mal, hex or octal.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       keysym KEYSYMNAME = KEYSYMNAME ...
</span></span><span style="display:flex;"><span>               The KEYSYMNAME on the left hand side is translated into matching
</span></span><span style="display:flex;"><span>               keycodes  used  to  perform the corresponding set of keycode ex‐
</span></span><span style="display:flex;"><span>               pressions.  Note that if the same keysym is  bound  to  multiple
</span></span><span style="display:flex;"><span>               keys, the expression is executed for each matching keycode.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       clear MODIFIERNAME
</span></span><span style="display:flex;"><span>               This removes all entries in the modifier map for the given modi‐
</span></span><span style="display:flex;"><span>               fier,  where  valid  name are: Shift, Lock, Control, Mod1, Mod2,
</span></span><span style="display:flex;"><span>               Mod3, Mod4, and Mod5 (case does not matter  in  modifier  names,
</span></span><span style="display:flex;"><span>               although  it  does  matter  for  all other names).  For example,
</span></span><span style="display:flex;"><span>               ‘‘clear Lock&#39;&#39; will remove all any keys that were bound  to  the
</span></span><span style="display:flex;"><span>               shift lock modifier.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       add MODIFIERNAME = KEYSYMNAME ...
</span></span><span style="display:flex;"><span>               This adds all keys containing the given keysyms to the indicated
</span></span><span style="display:flex;"><span>               modifier  map.   The  keysym names are evaluated after all input
</span></span><span style="display:flex;"><span>               expressions are read to make it easy  to  write  expressions  to
</span></span><span style="display:flex;"><span>               swap keys (see the EXAMPLES section).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       remove MODIFIERNAME = KEYSYMNAME ...
</span></span><span style="display:flex;"><span>               This  removes all keys containing the given keysyms from the in‐
</span></span><span style="display:flex;"><span>               dicated modifier map.  Unlike add, the keysym names  are  evalu‐
</span></span><span style="display:flex;"><span>               ated  as  the  line  is read in.  This allows you to remove keys
</span></span><span style="display:flex;"><span>               from a modifier without having to worry  about  whether  or  not
</span></span><span style="display:flex;"><span>               they have been reassigned.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       pointer = default
</span></span><span style="display:flex;"><span>               This sets the pointer map back to its default settings (button 1
</span></span><span style="display:flex;"><span>               generates a code of 1, button 2 generates a 2, etc.).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       pointer = NUMBER ...
</span></span><span style="display:flex;"><span>               This sets the pointer map to contain the indicated button codes.
</span></span><span style="display:flex;"><span>               The  list always starts with the first physical button.  Setting
</span></span><span style="display:flex;"><span>               a button code to 0 disables events from that button.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Lines that begin with an exclamation point (!) are taken as comments.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       If you want to change the binding of a modifier key, you must  also  re‐
</span></span><span style="display:flex;"><span>       move it from the appropriate modifier map.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXAMPLES
</span></span><span style="display:flex;"><span>       Many  pointers  are designed such that the first button is pressed using
</span></span><span style="display:flex;"><span>       the index finger of the right hand.  People  who  are  left-handed  fre‐
</span></span><span style="display:flex;"><span>       quently  find  that  it  is more comfortable to reverse the button codes
</span></span><span style="display:flex;"><span>       that get generated so that the primary button is pressed using the index
</span></span><span style="display:flex;"><span>       finger of the left hand.  This could be done on a 3  button  pointer  as
</span></span><span style="display:flex;"><span>       follows:
</span></span><span style="display:flex;"><span>       %  xmodmap -e &#34;pointer = 3 2 1&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Many  applications  support  the notion of Meta keys (similar to Control
</span></span><span style="display:flex;"><span>       keys except that Meta is held down instead of Control).   However,  some
</span></span><span style="display:flex;"><span>       servers  do  not  have a Meta keysym in the default keymap table, so one
</span></span><span style="display:flex;"><span>       needs to be added by hand.  The following command will  attach  Meta  to
</span></span><span style="display:flex;"><span>       the  Multi-language  key (sometimes labeled Compose Character).  It also
</span></span><span style="display:flex;"><span>       takes advantage of the fact that applications that need a Meta key  sim‐
</span></span><span style="display:flex;"><span>       ply  need  to  get the keycode and don&#39;t require the keysym to be in the
</span></span><span style="display:flex;"><span>       first column of the keymap table.  This means that applications that are
</span></span><span style="display:flex;"><span>       looking for a Multi_key (including the default modifier map)  won&#39;t  no‐
</span></span><span style="display:flex;"><span>       tice any change.
</span></span><span style="display:flex;"><span>       %  xmodmap -e &#34;keysym Multi_key = Multi_key Meta_L&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Similarly, some keyboards have an Alt key but no Meta key.  In that case
</span></span><span style="display:flex;"><span>       the following may be useful:
</span></span><span style="display:flex;"><span>       %  xmodmap -e &#34;keysym Alt_L = Meta_L Alt_L&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       One  of  the  more simple, yet convenient, uses of xmodmap is to set the
</span></span><span style="display:flex;"><span>       keyboard&#39;s &#34;rubout&#34; key to generate  an  alternate  keysym.   This  fre‐
</span></span><span style="display:flex;"><span>       quently involves exchanging Backspace with Delete to be more comfortable
</span></span><span style="display:flex;"><span>       to the user.  If the ttyModes resource in xterm is set as well, all ter‐
</span></span><span style="display:flex;"><span>       minal emulator windows will use the same key for erasing characters:
</span></span><span style="display:flex;"><span>       %  xmodmap -e &#34;keysym BackSpace = Delete&#34;
</span></span><span style="display:flex;"><span>       %  echo &#34;XTerm*ttyModes:  erase ^?&#34; | xrdb -merge
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Some  keyboards do not automatically generate less than and greater than
</span></span><span style="display:flex;"><span>       characters when the comma and period keys  are  shifted.   This  can  be
</span></span><span style="display:flex;"><span>       remedied with xmodmap by resetting the bindings for the comma and period
</span></span><span style="display:flex;"><span>       with the following scripts:
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       ! make shift-, be &lt; and shift-. be &gt;
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       keysym comma = comma less
</span></span><span style="display:flex;"><span>       keysym period = period greater
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       One of the more irritating differences between keyboards is the location
</span></span><span style="display:flex;"><span>       of  the  Control  and CapsLock keys.  A common use of xmodmap is to swap
</span></span><span style="display:flex;"><span>       these two keys as follows:
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       ! Swap Caps_Lock and Control_L
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       remove Lock = Caps_Lock
</span></span><span style="display:flex;"><span>       remove Control = Control_L
</span></span><span style="display:flex;"><span>       keysym Control_L = Caps_Lock
</span></span><span style="display:flex;"><span>       keysym Caps_Lock = Control_L
</span></span><span style="display:flex;"><span>       add Lock = Caps_Lock
</span></span><span style="display:flex;"><span>       add Control = Control_L
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       This example can be run again to swap the keys back  to  their  previous
</span></span><span style="display:flex;"><span>       assignments.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       The  keycode command is useful for assigning the same keysym to multiple
</span></span><span style="display:flex;"><span>       keycodes.  Although unportable, it  also  makes  it  possible  to  write
</span></span><span style="display:flex;"><span>       scripts  that  can  reset  the keyboard to a known state.  The following
</span></span><span style="display:flex;"><span>       script sets the backspace key  to  generate  Delete  (as  shown  above),
</span></span><span style="display:flex;"><span>       flushes  all  existing  caps  lock bindings, makes the CapsLock key be a
</span></span><span style="display:flex;"><span>       control key, make F5 generate Escape, and makes Break/Reset be  a  shift
</span></span><span style="display:flex;"><span>       lock.
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       ! On the HP, the following keycodes have key caps as listed:
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       !     101  Backspace
</span></span><span style="display:flex;"><span>       !      55  Caps
</span></span><span style="display:flex;"><span>       !      14  Ctrl
</span></span><span style="display:flex;"><span>       !      15  Break/Reset
</span></span><span style="display:flex;"><span>       !      86  Stop
</span></span><span style="display:flex;"><span>       !      89  F5
</span></span><span style="display:flex;"><span>       !
</span></span><span style="display:flex;"><span>       keycode 101 = Delete
</span></span><span style="display:flex;"><span>       keycode 55 = Control_R
</span></span><span style="display:flex;"><span>       clear Lock
</span></span><span style="display:flex;"><span>       add Control = Control_R
</span></span><span style="display:flex;"><span>       keycode 89 = Escape
</span></span><span style="display:flex;"><span>       keycode 15 = Caps_Lock
</span></span><span style="display:flex;"><span>       add Lock = Caps_Lock
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ENVIRONMENT
</span></span><span style="display:flex;"><span>       DISPLAY to get default host and display number.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>X Version 11                     xmodmap 1.0.11                      XMODMAP(1)</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>xmodmap 修改键码到键符的映射 (<code>xkeycaps</code> gui);</p>
<p>usage of <code>xmodmap</code>:</p>
<p>modifier for X Window. mod1: left Alt, mod2: Num_Lock，mod3: no，mod4: Left Super (windows)，mod5: Shift</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>$ xmodmap -pm
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>xmodmap:  up to <span style="color:#ae81ff">4</span> keys per modifier, <span style="color:#f92672">(</span>keycodes in parentheses<span style="color:#f92672">)</span>:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>shift       Shift_L <span style="color:#f92672">(</span>0x32<span style="color:#f92672">)</span>,  Shift_R <span style="color:#f92672">(</span>0x3e<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>lock        Caps_Lock <span style="color:#f92672">(</span>0x42<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>control     Control_L <span style="color:#f92672">(</span>0x25<span style="color:#f92672">)</span>,  Control_R <span style="color:#f92672">(</span>0x69<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>mod1        Alt_L <span style="color:#f92672">(</span>0x40<span style="color:#f92672">)</span>,  Alt_R <span style="color:#f92672">(</span>0x6c<span style="color:#f92672">)</span>,  Alt_L <span style="color:#f92672">(</span>0xcc<span style="color:#f92672">)</span>,  Meta_L <span style="color:#f92672">(</span>0xcd<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>mod2        Num_Lock <span style="color:#f92672">(</span>0x4d<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>mod3        ISO_Level5_Shift <span style="color:#f92672">(</span>0xcb<span style="color:#f92672">)</span>,  Hyper_L <span style="color:#f92672">(</span>0xcf<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>mod4        Super_L <span style="color:#f92672">(</span>0x85<span style="color:#f92672">)</span>,  Super_R <span style="color:#f92672">(</span>0x86<span style="color:#f92672">)</span>,  Super_L <span style="color:#f92672">(</span>0xce<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>mod5        ISO_Level3_Shift <span style="color:#f92672">(</span>0x5c<span style="color:#f92672">)</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Keycode is what the kernal get, and keysym is what it gives. Each keysym column in the table corresponds to a particular combination of modifier keys:</p>
<ol>
<li>Key</li>
<li>Shift+Key</li>
<li>Mode_switch+Key</li>
<li>Mode_switch+Shift+Key</li>
<li>ISO_Level3_Shift+Key</li>
<li>ISO_Level3_Shift+Shift+Key</li>
</ol>
<p>check current keycode map:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">$ xmodmap -pke

keycode   8 =
keycode   9 = Escape NoSymbol Escape
keycode  10 = 1 exclam 1 exclam
keycode  11 = 2 at 2 at
keycode  12 = 3 numbersign 3 numbersign
keycode  13 = 4 dollar 4 dollar
keycode  14 = 5 percent 5 percent
keycode  15 = 6 asciicircum 6 asciicircum
keycode  16 = 7 ampersand 7 ampersand
keycode  17 = 8 asterisk 8 asterisk
keycode  18 = 9 parenleft 9 parenleft
keycode  19 = 0 parenright 0 parenright
...
keycode  34 = bracketleft braceleft bracketleft braceleft
keycode  35 = bracketright braceright bracketright braceright
keycode  36 = Return NoSymbol Return
keycode  37 = Control_L NoSymbol Control_L
keycode  38 = a A a A
keycode  39 = s S s S
keycode  40 = d D d D
keycode  41 = f F f F
keycode  42 = g G g G
keycode  43 = h H h H
keycode  67 = F1 F1 F1 F1 F1 F1 XF86Switch_VT_1
keycode  68 = F2 F2 F2 F2 F2 F2 XF86Switch_VT_2
...</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><blockquote class="alert alert-warning">
      <p class="alert-heading">WARNING</p><p>xmodmap设置会被setxkbmap重置，它不仅将字母数字键改变为映射表中的值，还将所有其他键重置为启动时的默认值。
由于Xorg的限制，xmodmap设置不会自动应用到热插拔设备上。如果在应用了自定义映射表后，系统中添加了一个新的键盘，则必须重新应用自定义映射表</p></blockquote><h4 id="setxkbmap">
  <a class="anchor inpage" href="#setxkbmap">####</a>setxkbmap</h4>
<p><code>setxkbmap</code>: set keyboard layout;</p>
<details open>
    <summary>man</summary><pre
        class="chroma codeblock"
      ><code class="language-man" data-lang="man"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SETXKBMAP(1)                General Commands Manual                SETXKBMAP(1)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>       setxkbmap - set the keyboard using the X Keyboard Extension
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>       setxkbmap [ args ] [ layout [ variant [ option ...  ] ] ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DESCRIPTION
</span></span><span style="display:flex;"><span>       The  setxkbmap command maps the keyboard to use the layout determined by
</span></span><span style="display:flex;"><span>       the options specified on the command line.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       An XKB keymap is constructed from a number of components which are  com‐
</span></span><span style="display:flex;"><span>       piled only as needed.  The source for all of the components can be found
</span></span><span style="display:flex;"><span>       in /usr/share/X11/xkb.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>OPTIONS
</span></span><span style="display:flex;"><span>       -compat name
</span></span><span style="display:flex;"><span>               Specifies  the  name  of the compatibility map component used to
</span></span><span style="display:flex;"><span>               construct a keyboard layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -config file
</span></span><span style="display:flex;"><span>               Specifies the name of an XKB configuration file which  describes
</span></span><span style="display:flex;"><span>               the keyboard to be used.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -device device
</span></span><span style="display:flex;"><span>               Specifies  the  numeric  device id of the input device to be up‐
</span></span><span style="display:flex;"><span>               dated with the new keyboard layout. If not specified,  the  core
</span></span><span style="display:flex;"><span>               keyboard device of the X server is updated.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -display display
</span></span><span style="display:flex;"><span>               Specifies  the  display to be updated with the new keyboard lay‐
</span></span><span style="display:flex;"><span>               out.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -geometry name
</span></span><span style="display:flex;"><span>               Specifies the name of the geometry component used to construct a
</span></span><span style="display:flex;"><span>               keyboard layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -help   Prints a message describing the valid input to setxkbmap.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -I directory
</span></span><span style="display:flex;"><span>               Adds a directory to the list of directories to be used to search
</span></span><span style="display:flex;"><span>               for specified layout or rules files.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -keycodes name
</span></span><span style="display:flex;"><span>               Specifies the name of the keycodes component used to construct a
</span></span><span style="display:flex;"><span>               keyboard layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -keymap name
</span></span><span style="display:flex;"><span>               Specifies the name of the keymap description used to construct a
</span></span><span style="display:flex;"><span>               keyboard layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -layout name
</span></span><span style="display:flex;"><span>               Specifies the name of the layout used to  determine  the  compo‐
</span></span><span style="display:flex;"><span>               nents which make up the keyboard description. The -layout option
</span></span><span style="display:flex;"><span>               may  only  be  used once. Multiple layouts can be specified as a
</span></span><span style="display:flex;"><span>               comma-separated list.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -model name
</span></span><span style="display:flex;"><span>               Specifies the name of the keyboard model used to  determine  the
</span></span><span style="display:flex;"><span>               components  which  make  up  the keyboard description.  Only one
</span></span><span style="display:flex;"><span>               model may be specified on the command line.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -option name
</span></span><span style="display:flex;"><span>               Specifies the name of an  option  to  determine  the  components
</span></span><span style="display:flex;"><span>               which make up the keyboard description;  multiple options may be
</span></span><span style="display:flex;"><span>               specified,  one  per  -option flag. Note that setxkbmap adds op‐
</span></span><span style="display:flex;"><span>               tions specified in the command line to the options that were set
</span></span><span style="display:flex;"><span>               before (as saved in root window properties). If you want to  re‐
</span></span><span style="display:flex;"><span>               place  all  previously  specified  options, use the -option flag
</span></span><span style="display:flex;"><span>               with an empty argument first.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -print  With this option setxkbmap just prints component names in a for‐
</span></span><span style="display:flex;"><span>               mat acceptable by xkbcomp (an XKB keymap  compiler)  and  exits.
</span></span><span style="display:flex;"><span>               The option can be used for tests instead of a verbose option and
</span></span><span style="display:flex;"><span>               in  cases  when one needs to run both the setxkbmap and the xkb‐
</span></span><span style="display:flex;"><span>               comp in chain (see below).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -query  With this option setxkbmap just prints the current rules, model,
</span></span><span style="display:flex;"><span>               layout, variant, and options, then exits.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -rules file
</span></span><span style="display:flex;"><span>               Specifies the name of the rules file used  to  resolve  the  re‐
</span></span><span style="display:flex;"><span>               quested layout and model to a set of component names.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -symbols name
</span></span><span style="display:flex;"><span>               Specifies  the name of the symbols component used to construct a
</span></span><span style="display:flex;"><span>               keyboard layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -synch  Force synchronization for X requests.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -types name
</span></span><span style="display:flex;"><span>               Specifies the name of the types component used  to  construct  a
</span></span><span style="display:flex;"><span>               keyboard layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -variant name
</span></span><span style="display:flex;"><span>               Specifies which variant of the keyboard layout should be used to
</span></span><span style="display:flex;"><span>               determine the components which make up the keyboard description.
</span></span><span style="display:flex;"><span>               The -variant option may only be used once. Multiple variants can
</span></span><span style="display:flex;"><span>               be  specified as a comma-separated list and will be matched with
</span></span><span style="display:flex;"><span>               the layouts specified with -layout.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -verbose|-v [level]
</span></span><span style="display:flex;"><span>               Specifies level of verbosity in output messages.   Valid  levels
</span></span><span style="display:flex;"><span>               range  from 0 (least verbose) to 10 (most verbose).  The default
</span></span><span style="display:flex;"><span>               verbosity level is 5.  If no level  is  specified,  each  -v  or
</span></span><span style="display:flex;"><span>               -verbose flag raises the level by 1.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -version
</span></span><span style="display:flex;"><span>               Prints the program&#39;s version number.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>USING WITH xkbcomp
</span></span><span style="display:flex;"><span>       If you have an Xserver and a client shell running on different computers
</span></span><span style="display:flex;"><span>       and  some  XKB  configuration files on those machines are different, you
</span></span><span style="display:flex;"><span>       can get problems specifying a keyboard map by model, layout, and options
</span></span><span style="display:flex;"><span>       names.  This is because setxkbmap converts its arguments to names of XKB
</span></span><span style="display:flex;"><span>       configuration files according to files that are on the client-side  com‐
</span></span><span style="display:flex;"><span>       puter,  then  sends  these file names to the server where xkbcomp has to
</span></span><span style="display:flex;"><span>       compose a complete keyboard map using files which the server has.   Thus
</span></span><span style="display:flex;"><span>       if the sets of files differ in some way, the names that setxkbmap gener‐
</span></span><span style="display:flex;"><span>       ates can be unacceptable on the server side.  You can solve this problem
</span></span><span style="display:flex;"><span>       by  running  the xkbcomp on the client side too.  With the -print option
</span></span><span style="display:flex;"><span>       setxkbmap just prints the file names in an  appropriate  format  to  its
</span></span><span style="display:flex;"><span>       stdout  and this output can be piped directly to the xkbcomp input.  For
</span></span><span style="display:flex;"><span>       example, the command
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       setxkbmap us -print | xkbcomp - $DISPLAY
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       makes both steps run on the same (client) machine and loads  a  keyboard
</span></span><span style="display:flex;"><span>       map into the server.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>XWAYLAND
</span></span><span style="display:flex;"><span>       Xwayland  is  an  X  server  that  uses a Wayland Compositor as backend.
</span></span><span style="display:flex;"><span>       Xwayland acts as translation layer between the X protocol and  the  Way‐
</span></span><span style="display:flex;"><span>       land protocol but does not manage the keymaps - these are handled by the
</span></span><span style="display:flex;"><span>       Wayland Compositor.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Changing  the  keymap  with  setxkbmap is not supported by Xwayland.  In
</span></span><span style="display:flex;"><span>       most instances, using setxkbmap on Xwayland is indicative of a bug in  a
</span></span><span style="display:flex;"><span>       shell script and setxkbmap will print a warning. Use the Wayland Compos‐
</span></span><span style="display:flex;"><span>       itor&#39;s native XKB configuration methods instead.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SEE ALSO
</span></span><span style="display:flex;"><span>       xkbcomp(1), xkeyboard-config(7)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>FILES
</span></span><span style="display:flex;"><span>       /usr/share/X11/xkb
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>X Version 11                    setxkbmap 1.3.4                    SETXKBMAP(1)</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>simple examples</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>setxkbmap -option ctrl:swapcaps <span style="color:#75715e"># swap ctrl and caps</span>
</span></span><span style="display:flex;"><span>setxkbmap -option ctrl:nocaps</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="xcape">
  <a class="anchor inpage" href="#xcape">####</a>xcape</h4>
<p><code>xcape</code>: use a modifier as another key.</p>
<details open>
    <summary>man</summary><pre
        class="chroma codeblock"
      ><code class="language-man" data-lang="man"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>XCAPE(1)                          xcape Manual                         XCAPE(1)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>       xcape - use a modifier key as another key
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>       xcape [-d] [-t timeout] [-e map-expression]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DESCRIPTION
</span></span><span style="display:flex;"><span>       xcape allows a modifier key to be used as another key when it is pressed
</span></span><span style="display:flex;"><span>       and released on its own. The default behaviour is to generate the Escape
</span></span><span style="display:flex;"><span>       key in place of Control_L (Left Control).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>OPTIONS
</span></span><span style="display:flex;"><span>       -d     Debug mode.  Will run as a foreground process.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -t timeout
</span></span><span style="display:flex;"><span>              Give  a  timeout  in milliseconds.  If you hold a key longer than
</span></span><span style="display:flex;"><span>              timeout a key event will not be generated.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -e map-expression
</span></span><span style="display:flex;"><span>              Use map-expression as the expression(s).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXPRESSION SYNTAX
</span></span><span style="display:flex;"><span>       Expression syntax is ´ModKey=Key[|OtherKey]´.  Multiple expressions  can
</span></span><span style="display:flex;"><span>       be passed, delimited by semi-colons (;).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       A  list  of  keysyms  can  be found in the header file &lt;X11/keysymdef.h&gt;
</span></span><span style="display:flex;"><span>       (without the XK_ prefix).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Note that shifted keys must be specified as a shift key followed by  the
</span></span><span style="display:flex;"><span>       key  to be pressed rather than the actual name of the character. For ex‐
</span></span><span style="display:flex;"><span>       ample to generate &#34;{&#34; the expression ´ModKey=Shift_L|bracketleft´  could
</span></span><span style="display:flex;"><span>       be used (assuming that you have a key with ´{´ above ´[´).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       You  can also specify ModKey in decimal (prefix #), octal (#0), or hexa‐
</span></span><span style="display:flex;"><span>       decimal (#0x). It will be interpreted as a keycode unless no correspond‐
</span></span><span style="display:flex;"><span>       ing key name is found.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXAMPLES
</span></span><span style="display:flex;"><span>       Make Left Shift generate Escape when pressed and released on  it&#39;s  own,
</span></span><span style="display:flex;"><span>       and  Left  Control generate Ctrl-O combination when pressed and released
</span></span><span style="display:flex;"><span>       on it&#39;s own:
</span></span><span style="display:flex;"><span>              xcape -e &#39;Shift_L=Escape;Control_L=Control_L|O&#39;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       In conjugation with xmodmap it is possible to make an ordinary  key  act
</span></span><span style="display:flex;"><span>       as an extra modifier. First map the key to the modifier with xmodmap and
</span></span><span style="display:flex;"><span>       then the modifier back to the key with xcape. As an example, we can make
</span></span><span style="display:flex;"><span>       the  space bar work as an additional ctrl key when held with the follow‐
</span></span><span style="display:flex;"><span>       ing sequence of commands:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       First, map an unused modifier&#39;s keysym to  the  spacebar&#39;s  keycode  and
</span></span><span style="display:flex;"><span>       make it a control modifier. It needs to be an existing key so that emacs
</span></span><span style="display:flex;"><span>       won&#39;t spazz out when you press it. Hyper_L is a good candidate.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>              spare_modifier=&#34;Hyper_L&#34;
</span></span><span style="display:flex;"><span>              xmodmap -e &#34;keycode 65 = $spare_modifier&#34;
</span></span><span style="display:flex;"><span>              xmodmap -e &#34;remove mod4 = $spare_modifier&#34;
</span></span><span style="display:flex;"><span>              # hyper_l is mod4 by default
</span></span><span style="display:flex;"><span>              xmodmap -e &#34;add Control = $spare_modifier&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Next,  map  space  to  an unused keycode (to keep it around for xcape to
</span></span><span style="display:flex;"><span>       use).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>              xmodmap -e &#34;keycode any = space&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Finally use xcape to cause the  space  bar  to  generate  a  space  when
</span></span><span style="display:flex;"><span>       tapped.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>              xcape -e &#34;$spare_modifier=space&#34;</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>example</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>xcape -e <span style="color:#e6db74">&#39;Alt_L=Escape&#39;</span> <span style="color:#75715e"># Escape when tap, ALt when hold</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h4 id="example">
  <a class="anchor inpage" href="#example">####</a>example</h4>
<p>for example, <kbd>caps</kbd> as <kbd>escape</kbd> and <kbd>ctrl</kbd></p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span><span style="color:#75715e"># I usually use following</span>
</span></span><span style="display:flex;"><span>setxkbmap -option <span style="color:#e6db74">&#39;caps:ctrl_modifier&#39;</span> <span style="color:#75715e"># caps become ctrl</span>
</span></span><span style="display:flex;"><span>xcape -e <span style="color:#e6db74">&#39;Caps_Lock=Escape&#39;</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="wayland">
  <a class="anchor inpage" href="#wayland">###</a>wayland</h3>
<p>似乎暂时只有KDE Gnome的环境里还有改的方法</p>
<h3 id="console">
  <a class="anchor inpage" href="#console">###</a>console</h3>
<p>
</p>
<h3 id="keyd">
  <a class="anchor inpage" href="#keyd">###</a>keyd</h3>
<p>
， inspired by via</p>
<p>这个厉害，tty, X11, wayland都能用，而且能实现很强的配置效果。</p>
<details open>
    <summary>tldr</summary><pre
        class="codeblock"
      ><code class="language-tldr" data-lang="tldr">
  Remap keys.
  More information: &lt;https://manned.org/keyd&gt;.

  Start and enable the `keyd` service:

      systemctl enable keyd --now

  Display keypress information:

      sudo keyd monitor

  Reset bindings and reload the configuration files in `/etc/keyd`:

      sudo keyd reload

  List all valid key names:

      keyd list-keys

  Create a temporary binding:

      sudo keyd bind &#34;pressed_key = output_key&#34;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>Other software:</p>
<ul>
<li>interception-tools with plugins
<ul>
<li>dual-function-keys (like Mod-Tap feature of zmk and qmk)</li>
<li>caps2esc</li>
<li>space2meta</li>
</ul>
</li>
</ul>
<h2 id="ref">
  <a class="anchor inpage" href="#ref">##</a>ref</h2>
<p>
</p>
]]></content:encoded></item><item><title>安装后的建议配置</title><link>https://hiraethecho.github.io/docs/linux/archpostinstall/</link><pubDate>Mon, 18 Nov 2024 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/archpostinstall/</guid><description>archlinux安装后的建议配置，新建用户，软件等</description><content:encoded><![CDATA[<h1 id="安装后的建议配置">
  <a class="anchor inpage" href="#%e5%ae%89%e8%a3%85%e5%90%8e%e7%9a%84%e5%bb%ba%e8%ae%ae%e9%85%8d%e7%bd%ae">#</a>安装后的建议配置</h1>
<blockquote class="alert alert-important">
      <p class="alert-heading">IMPORTANT</p><p></p></blockquote><h2 id="add-user">
  <a class="anchor inpage" href="#add-user">##</a>add user</h2>
<p>添加用户并设置密码</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>useradd -m USERNAME
</span></span><span style="display:flex;"><span>passwd USERNAME</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以将用户家目录设置成btrfs的子卷，这样可以更好的管理快照。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">useradd -m --btrfs-subvolume-home USERNAME</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>添加用户到wheel组：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">usermod -aG wheel USERNAME</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>或者在创建用户时用</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">useradd -m -G wheel USERNAME</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>让<code>wheel</code>组的用户可以使用<code>sudo</code>，需要编辑<code>/etc/sudoers</code>文件，可以使用<code>visudo</code>命令，如果环境变量没有指定默认编辑器，会提示选择，选择一个之后会进入文件编辑界面。或者使用</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">EDITOR=nvim visudo</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>取消下面的注释</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># %wheel ALL=(ALL:ALL)</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="package-managerment">
  <a class="anchor inpage" href="#package-managerment">##</a>Package managerment</h2>
<p>换源：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># /etc/pacman.d/mirrorlist
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>添加<code>archlinuxcn</code>仓库。在 <code>/etc/pacman.conf</code>中添加</p>
<details open>
    <summary>text</summary><pre
        class="chroma codeblock"
      ><code class="language-text" data-lang="text"
          ><span style="display:flex;"><span>[archlinuxcn]
</span></span><span style="display:flex;"><span>Server = https://mirrors.tuna.tsinghua.edu.cn/archlinuxcn/$arch</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>更新keyring</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">pacman -Sy archlinux-keyring
pacman -Sy archlinuxcn-keyring</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>然后建议滚到最新</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">pacman -Syyu</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>在<code>archlinuxcn</code>中有aur-helper，比如</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">pacman -S paru</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>clean pacman:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>paccache -r <span style="color:#75715e"># 清理缓存,仅包含最近的三个版本</span>
</span></span><span style="display:flex;"><span>paccache -rk1 <span style="color:#75715e"># 清理缓存,仅包含最近的1个版本</span>
</span></span><span style="display:flex;"><span>pacman -Sc <span style="color:#75715e"># 清理未安装软件包</span>
</span></span><span style="display:flex;"><span>pacman -Scc <span style="color:#75715e"># 清理缓存中所有内容</span>
</span></span><span style="display:flex;"><span>sudo pacman -Rcsn <span style="color:#66d9ef">$(</span>pacman -Qdtq -<span style="color:#66d9ef">)</span>
</span></span><span style="display:flex;"><span>journalctl --vacuum-size<span style="color:#f92672">=</span>50M <span style="color:#75715e">#限制日志</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="基础功能">
  <a class="anchor inpage" href="#%e5%9f%ba%e7%a1%80%e5%8a%9f%e8%83%bd">##</a>基础功能</h2>
<h3 id="网络">
  <a class="anchor inpage" href="#%e7%bd%91%e7%bb%9c">###</a>网络</h3>
<p>启动服务，<code>iwd</code>是连接网络的，自带域名解析。需要</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># /etc/iwd/main.conf
[General]
EnableNetworkConfiguration=true</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>也可以用<code>dhcpcd</code>解析</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">systemctl enable dhcpcd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>tui: <code>impala</code></p>
<p>或者用<code>networkmanager</code></p>
<p>Using iwd as backend of NetworkManager, <code>/etc/NetworkManager/NetworkManager.conf</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">[device]
wifi.backend=iwd</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>then</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>systemctl mask wpa_supplicant
</span></span><span style="display:flex;"><span>systemctl enable iwd</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="sound">
  <a class="anchor inpage" href="#sound">###</a>sound</h3>
<ul>
<li>ALSA: is a set of built-in Linux kernel modules.</li>
<li>PulseAudio: is a general purpose sound server intended to run as a middleware between your applications and your hardware devices, either using ALSA or OSS.</li>
<li>pamixer: cli mixer of PulseAudio</li>
<li>pavucontrol: gui of PulseAudio</li>
</ul>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">sudo pacman -S alsa-ultis pulseaudio pavucontrol
pulseaudio --check
pulseaudio -D</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="light">
  <a class="anchor inpage" href="#light">###</a>light</h3>
<p><code>video</code>组的用户可以控制亮度</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo pacman -S acpilight
</span></span><span style="display:flex;"><span>sudo gpasswd video -a _username_ <span style="color:#75715e"># 或者</span>
</span></span><span style="display:flex;"><span>sudo usermod -aG video _username_</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="bluetooth">
  <a class="anchor inpage" href="#bluetooth">###</a>bluetooth</h3>
<p>蓝牙耳机需要<code>pulseaudio-bluetooth</code>和<code>bluez-utils</code>。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">sudo systemctl enable bluetooth.service --now</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>tui: <code>bluetui</code></p>
<h3 id="input">
  <a class="anchor inpage" href="#input">###</a>input</h3>
<p>在<code>X11</code>中需要安装<code>xf86-input-libinput</code>等</p>
<p>To find id of touchpad</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">xinput list | grep -i &#34;Touchpad&#34; | awk &#39;{print $6}&#39; | sed &#39;s/[^0-9]//g&#39;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>keys:</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>setxkbmap -option ctrl:nocaps &amp;
</span></span><span style="display:flex;"><span>xcape -e <span style="color:#e6db74">&#39;Control_L=Return&#39;</span> &amp;
</span></span><span style="display:flex;"><span>xcape -e <span style="color:#e6db74">&#39;Alt_L=Escape&#39;</span> &amp;</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="battery">
  <a class="anchor inpage" href="#battery">###</a>battery</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">upower -e

/org/freedesktop/UPower/devices/line_power_ACAD
/org/freedesktop/UPower/devices/battery_BAT1
/org/freedesktop/UPower/devices/DisplayDevice</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>check battery <code>sudo upower -i /org/freedesktop/UPower/devices/battery_BAT1 </code></p>
<h3 id="driver">
  <a class="anchor inpage" href="#driver">###</a>driver</h3>
<p>for amd integrated, open source driver:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">sudo pacman -S mesa lib32-mesa xf86-video-amdgpu vulkan-radeon lib32-vulkan-radeon</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="desktop-environment">
  <a class="anchor inpage" href="#desktop-environment">##</a>Desktop Environment</h2>
<p>
</p>
<h3 id="成品桌面环境">
  <a class="anchor inpage" href="#%e6%88%90%e5%93%81%e6%a1%8c%e9%9d%a2%e7%8e%af%e5%a2%83">###</a>成品桌面环境</h3>
<ul>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
<h3 id="components">
  <a class="anchor inpage" href="#components">###</a>components</h3>
<p>At least one need</p>
<ul>
<li>window manager or 
</li>
<li>
</li>
</ul>
<p>Usually also need:</p>
<ul>
<li>
</li>
<li>
).</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
<p>Other components usually provided by desktop environments are:</p>
<ul>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
<h3 id="utils">
  <a class="anchor inpage" href="#utils">###</a>utils</h3>
<p><code>filedialog</code> 是其他应用需要选择文件时的弹窗。通常需要一些<code>xdg-desktop-portal</code>，不同的包有不同的
。</p>
<h3 id="x11">
  <a class="anchor inpage" href="#x11">###</a>X11</h3>
<p><code>Xlibre</code> <code>wayback</code></p>
<h3 id="wayland">
  <a class="anchor inpage" href="#wayland">###</a>wayland</h3>
<p>gnome, kde</p>
<p>niri, hyprland, sway, river, wayfire,</p>
<h2 id="applications">
  <a class="anchor inpage" href="#applications">##</a>Applications</h2>
<h3 id="shell-and-terminal">
  <a class="anchor inpage" href="#shell-and-terminal">###</a>shell and terminal</h3>
<h3 id="steam">
  <a class="anchor inpage" href="#steam">###</a>steam:</h3>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">id -u
id -g</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>mount:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">sudo mkdir /media/gamedisk</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># /etc/fstab
UUID=38CE9483CE943AD8 /media/gamedisk lowntfs-3g uid=1000,gid=1000,rw,user,exec,umask=000 0 0</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>debug:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">mkdir -p ~/.steam/steam/steamapps/compatdata
ln -s ~/.steam/steam/steamapps/compatdata /media/gamedisk/Steam/steamapps/</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="wechat">
  <a class="anchor inpage" href="#wechat">###</a>wechat</h3>
<p>微信使用fcitx输入法会有一些问题，似乎是不能正常读取环境变量。修改<code>/usr/share/applications/wechat.desktop</code>来设定变量。有可能在更新后被覆盖，或许可以放在<code>~/.local/share/applications/wechat.desktop</code>中。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">[Desktop Entry]
Name=wechat
Name[zh_CN]=微信
Exec=env XMODIFIERS=&#34;@im=fcitx&#34; GTK_IM_MODULE=&#34;fcitx&#34; QT_IM_MODULE=&#34;fcitx&#34; /usr/bin/wechat %U
StartupNotify=true
Terminal=false
Icon=/opt/wechat/icons/wechat.png
Type=Application
Categories=Utility;
Comment=Wechat Desktop
Comment[zh_CN]=微信桌面版</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script>]]></content:encoded></item><item><title>双系统安装archlinux</title><link>https://hiraethecho.github.io/docs/linux/archinstall/</link><pubDate>Mon, 09 Oct 2023 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/archinstall/</guid><description>双系统安装archlinux，btrfs分区、grub启动项</description><content:encoded><![CDATA[<h1 id="basic-installation-of-arch-linux">
  <a class="anchor inpage" href="#basic-installation-of-arch-linux">#</a>Basic installation of arch linux</h1>
<blockquote class="alert alert-important">
      <p class="alert-heading">有能力者建议看</p><p></p></blockquote><p>双系统安装archlinux，使用btrfs文件系统。重装系统的参考。</p>
<blockquote class="alert alert-tip">
      <p class="alert-heading">windows部分</p><p>由于windows安装和更新可能会改动efi分区，建议先安装windows，然后再安装archlinux。<br>
如果需要干净的windows，可以参考
。</p></blockquote><h2 id="启动盘">
  <a class="anchor inpage" href="#%e5%90%af%e5%8a%a8%e7%9b%98">##</a>启动盘</h2>
<p>下载archlinux的iso文件。找一个U盘，用 <code>ventoy</code>安装，然后把iso放进去。</p>
<p>可以先在win下用 <kbd>win</kbd>+<kbd>x</kbd>、<kbd>k</kbd> 打开磁盘管理，然后手动分区，用win的GUI代替之后的命令行分区。可以使用<code>diskgenuis</code>软件做更多操作。</p>
<p>插上U盘，重起电脑，在开机时按 <kbd>F11</kbd> <kbd>F12</kbd> <kbd>F2</kbd> 之类能进入选择启动位置的界面，选择从U盘启动。之后应该会启动U盘里的<code>ventoy</code>，选择arch的iso。这样就进入<code>arch live</code> 的系统，这个系统是用来安装arch的。</p>
<h2 id="处理磁盘">
  <a class="anchor inpage" href="#%e5%a4%84%e7%90%86%e7%a3%81%e7%9b%98">##</a>处理磁盘</h2>
<blockquote class="alert alert-tip">
      <p class="alert-heading">TIP</p><p>此时进入的是<code>arch live</code>环境，其实这个时候已经可以拔掉U盘了。在这个环境中做的修改不会保存。</p></blockquote><p>接下来要预处理实际电脑上的磁盘，也就是系统安装位置。</p>
<h3 id="network-and-time">
  <a class="anchor inpage" href="#network-and-time">###</a>network and time</h3>
<p>首先是把<code>arch live</code>系统联网，设置时间，配置软件源。使用 <code>iwctl</code> 连接网络。</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>iwctl <span style="color:#75715e"># 进入iwctl</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>iwd<span style="color:#f92672">]</span> help <span style="color:#75715e"># 查看使用方法</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>iwd<span style="color:#f92672">]</span> station wlan0 connect **SSID** <span style="color:#75715e"># example</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>iwd<span style="color:#f92672">]</span> exit <span style="color:#75715e"># 退出iwctl</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>同步时间</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>timedatectl set-ntp true
</span></span><span style="display:flex;"><span>timedatectl status</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>在 <code>/etc/pacman.d/mirrorlist</code>中添加pacman的源，推荐清华源。否则可能下载速度慢。</p>
<details open>
    <summary>text</summary><pre
        class="chroma codeblock"
      ><code class="language-text" data-lang="text"
          ><span style="display:flex;"><span>Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="分区">
  <a class="anchor inpage" href="#%e5%88%86%e5%8c%ba">###</a>分区</h3>
<blockquote class="alert alert-warning">
      <p class="alert-heading">WARNING</p><p>这一步是操作实际电脑的磁盘，会删除数据。请小心操作。
将预留空间格式化为btrfs文件系统，并分区。</p></blockquote><p>首先查看分区：</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>fdisk -l</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>看清楚各个分区，以下以<code>nvme0n1p5</code>为例作为linux分区。</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>mkfs.btrfs  -L btrfs-arch /dev/nvme0n1p5 <span style="color:#75715e"># -L means label, can be omitted</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>先挂载这个分区，根据需要创建其子卷。</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>mount -o /dev/nvme0n1p3 /mnt <span style="color:#75715e"># 这条命令将分区挂载到btrfs的顶级子卷，即 / 子卷， id=5</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 通常这些子卷</span>
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@   <span style="color:#75715e"># 创建顶级子卷下的 @ 子卷，将作为新linux的 / 目录</span>
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@home <span style="color:#75715e"># 创建顶级子卷下的 /@home 子卷，将作为新linux的 用户家目录，即 /home</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 以下可选</span>
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@log
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@cache
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@opt
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@tmp
</span></span><span style="display:flex;"><span>btrfs subvolume create /mnt/@root</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>检查一下，应该有以下输出：</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>btrfs subvolume list /mnt
</span></span><span style="display:flex;"><span>ID <span style="color:#ae81ff">256</span> gen <span style="color:#ae81ff">405</span> parent <span style="color:#ae81ff">5</span> top level <span style="color:#ae81ff">5</span> path @
</span></span><span style="display:flex;"><span>ID <span style="color:#ae81ff">257</span> gen <span style="color:#ae81ff">409</span> parent <span style="color:#ae81ff">5</span> top level <span style="color:#ae81ff">5</span> path @home</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><blockquote class="alert alert-note">
      <p class="alert-heading">NOTE</p><p>ID 是子卷的 id，gen 是子卷的代数，parent 是父卷的 id，top level 是顶级子卷的 id，path 是子卷的路径<br>
应该还有其他子卷的输出，这里没有列出。</p></blockquote><p>接下来先取消挂载顶级子卷，再挂载子卷到对应的目录：</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>umount /mnt
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@ /dev/nvme0n1p5 /mnt <span style="color:#75715e">#挂载 @ 子卷到新系统的 / 目录</span>
</span></span><span style="display:flex;"><span>mkdir -p /mnt/<span style="color:#f92672">{</span>boot/efi,home,var/<span style="color:#f92672">{</span>log,cache<span style="color:#f92672">}}</span> <span style="color:#75715e">#创建新系统的 /boot/efi、/home、/var/log、/var/cache</span>
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@home -m /dev/nvme0n1p5 /mnt/home <span style="color:#75715e"># -m 创建挂载的文件夹</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 如果创建了对应子卷，那么</span>
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@log -m /dev/nvme0n1p5 /mnt/var/log
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@cache -m /dev/nvme0n1p5 /mnt/var/cache
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@tmp -m /dev/nvme0n1p5 /mnt/tmp
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@opt -m /dev/nvme0n1p5 /mnt/opt
</span></span><span style="display:flex;"><span>mount -o noatime,nodiratime,compress<span style="color:#f92672">=</span>zstd,subvol<span style="color:#f92672">=</span>@root -m /dev/nvme0n1p5 /mnt/root</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>查看挂载情况</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>findmnt -nt btrfs</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>挂载efi分区。因为单硬盘安装双系统，所以使用windows系统原有的efi分区。</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>mount /dev/nvme0n1p1 /mnt/boot/efi</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><blockquote class="alert alert-tip">
      <p class="alert-heading">TIP</p><p>win初始的efi分区大小可能不够 <code>/boot</code> ，所以可以只挂载 <code>/boot/efi</code>。也可以创建<code>/efi</code><br>
在win下可以用 <code>diskgenuis</code> 查看efi分区。</p></blockquote><blockquote class="alert alert-note">
      <p class="alert-heading">update 2025-07-27</p><p>ESP分区的挂载，现在推荐直接挂载到<code>/efi</code>而不是<code>/boot/efi</code></p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>mount /dev/nvme0n1p1 /mnt/efi</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>除此之外，<code>btrfs</code>格式的<code>/boot</code>会导致一些奇怪的报错，比如稀疏文件的问题等，以及<code>grub</code>无法设置为从上次启动的选项启动。所以也可以单开一个分区来挂载<code>/boot</code>.
参见
</p></blockquote><details open>
    <summary>shell</summary><pre
        class="chroma codeblock"
      ><code class="language-shell" data-lang="shell"
          ><span style="display:flex;"><span>mkdir -p /mnt/efi
</span></span><span style="display:flex;"><span>mount /dev/nvme0n1p1 /mnt/boot/efi</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以把这些子卷关闭写时复制</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">chattr &#43;C /mnt/tmp
chattr &#43;C /mnt/var/cache
chattr &#43;C /mnt/var/log</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="安装系统">
  <a class="anchor inpage" href="#%e5%ae%89%e8%a3%85%e7%b3%bb%e7%bb%9f">##</a>安装系统</h2>
<p>这一步是实际安装系统到电脑上。
install and genfstab 安装系统并生成分区表</p>
<p>安装系统到新分区，这里使用 <code>pacstrap</code> 命令，安装一些必要组件和后续使用的基础软件，包括linux内核、linux固件、btrfs-progs管理btrfs文件系统、dhcpcd、iwd、networkmanager管理网络、neovim编辑器、git、sudo、grub、os-prober (查找硬盘上其他系统，在grub界面启动windows系统)、efibootmgr</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>pacstrap -K -M /mnt base base-devel linux linux-headers btrfs-progs iwd neovim git
</span></span><span style="display:flex;"><span>sudo grub os-prober efibootmgr amd-ucode dhcpcd</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><blockquote class="alert alert-note">
      <p class="alert-heading">NOTE</p><p>根据cpu安装 <code>amd-ucode</code> 或 <code>intel-ucode</code></p></blockquote><p>接下来生成分区表，记录这个磁盘分区是如何使用的。</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">genfstab -U /mnt &gt;&gt; /mnt/etc/fstab</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="配置grub启动">
  <a class="anchor inpage" href="#%e9%85%8d%e7%bd%aegrub%e5%90%af%e5%8a%a8">##</a>配置grub启动</h2>
<p>配置grub，使得电脑启动时能找到这个系统。这一步需要进入新安装的系统中：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">arch-chroot /mnt</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>这个命令之后就进入了刚刚安装的archlinux系统，之后的命令都是在这个系统中执行的。</p>
<blockquote class="alert alert-note">
      <p class="alert-heading">NOTE</p><p>对于双系统安装，要让grub发现其他系统。在<code>/etc/default/grub</code>中取消注释</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># GRUB_DISABLE_OS_PROBER=false</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>对于btrfs，似乎需要一些操作才能使<code>os-prober</code>起效。<br>
在<code>/etc/mkinitcpio.conf</code> 添加 btrfs 到 MODULES=(&hellip;)行 找到 HOOKS=(&hellip;)行，更换fsck为btrfs 最终你看到的/etc/mkinitcpio.conf文件格式为</p>
<details open>
    <summary>text</summary><pre
        class="chroma codeblock"
      ><code class="language-text" data-lang="text"
          ><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>MODULES=(btrfs)
</span></span><span style="display:flex;"><span>HOOKS=(base udev autodetect modconf block filesystems keyboard btrfs)
</span></span><span style="display:flex;"><span>...</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>然后重新生成 initramfs</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>mkinitcpio -P</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></blockquote><p>安装启动器<code>grub</code>到efi分区，并生成grub文件：</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>grub-install --target<span style="color:#f92672">=</span>x86_64-efi --efi-directory<span style="color:#f92672">=</span>/boot/efi --bootloader-id<span style="color:#f92672">=</span>arch --recheck</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">grub-mkconfig -o /boot/grub/grub.cfg</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><blockquote class="alert alert-tip">
      <p class="alert-heading">TIP</p><p>可以先对grub做一些配置，也可以后续执行。<br>
去掉 quiet 参数，调整 loglevel 值为 5 ，加入 nowatchdog 参数</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sed -i <span style="color:#e6db74">&#34;s|GRUB_CMDLINE_LINUX_DEFAULT.*|GRUB_CMDLINE_LINUX_DEFAULT=\&#34;loglevel=5 nowatchdog\&#34;|&#34;</span> /etc/default/grub</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script></blockquote><p>理论上现在可以重启电脑，选择从硬盘启动，就可以看到grub界面，选择archlinux启动。但最好先做一些基本配置。</p>
<h2 id="基本配置">
  <a class="anchor inpage" href="#%e5%9f%ba%e6%9c%ac%e9%85%8d%e7%bd%ae">##</a>基本配置</h2>
<p>首先设置root密码</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">passwd root</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>设置密码是静默输入，不会显示密码，输入两次即可。</p>
<p>配置locale、hostname、网络等</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>ln -sf /usr/share/zoneinfo/Region/City /etc/localtime <span style="color:#75715e">#替换Region/City为你所在区域，例如Asia/Shanghai</span>
</span></span><span style="display:flex;"><span>hwclock --systohc <span style="color:#75715e"># 同步硬件时钟</span>
</span></span><span style="display:flex;"><span>timedatectl set-ntp true
</span></span><span style="display:flex;"><span>timedatectl set-local-rtc true <span style="color:#75715e">#同步双系统时间</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;en_US.UTF-8 UTF-8&#34;</span> &gt;&gt; /etc/locale.gen
</span></span><span style="display:flex;"><span>locale-gen
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;LANG=en_US.UTF-8&#34;</span> &gt; /etc/locale.conf <span style="color:#75715e">#或者编辑文件，取消注释</span>
</span></span><span style="display:flex;"><span>systemctl enable NetworkManager.service <span style="color:#75715e"># 启动网络服务</span>
</span></span><span style="display:flex;"><span>hostnamectl set-hostname &lt;yourhostname&gt; <span style="color:#75715e"># 设置主机名</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>时间格式也可以设置</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;LC_TIME=C.UTF-8&#34;</span> &gt;&gt; /etc/locale.conf <span style="color:#75715e"># &gt;&gt; 表示追加。</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>hosts:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># /etc/hosts
127.0.0.1   localhost
::1         localhost
127.0.1.1   &lt;yourhostname&gt;.localdomain    &lt;yourhostname&gt;</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="quit-and-reboot">
  <a class="anchor inpage" href="#quit-and-reboot">##</a>quit and reboot</h2>
<p>退出新系统，取消挂载，重启</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">exit #退出chroot
umount /mnt/boot/efi
umount /mnt/home
umount /mnt
reboot</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>之后有一些
。</p>
]]></content:encoded></item><item><title>用btrfs做linux的快照备份</title><link>https://hiraethecho.github.io/docs/linux/btrfs/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/linux/btrfs/</guid><description>&lt;h1 id="linux下的-btrfs"&gt;
&lt;a class="anchor inpage" href="#linux%e4%b8%8b%e7%9a%84-btrfs"&gt;#&lt;/a&gt;linux下的 btrfs&lt;/h1&gt;
&lt;h2 id="btrfs的功能"&gt;
&lt;a class="anchor inpage" href="#btrfs%e7%9a%84%e5%8a%9f%e8%83%bd"&gt;##&lt;/a&gt;btrfs的功能&lt;/h2&gt;
&lt;p&gt;写时复制 &lt;code&gt;copy on right&lt;/code&gt;功能使得非常时候做快照。&lt;/p&gt;
&lt;p&gt;子卷功能可以更方便的分区。以及添加新设备。&lt;/p&gt;
&lt;h2 id="官方手册"&gt;
&lt;a class="anchor inpage" href="#%e5%ae%98%e6%96%b9%e6%89%8b%e5%86%8c"&gt;##&lt;/a&gt;官方手册&lt;/h2&gt;
&lt;details open&gt;
&lt;summary&gt;man&lt;/summary&gt;&lt;pre
class="chroma codeblock"
&gt;&lt;code class="language-man" data-lang="man"
&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;BTRFS(8) BTRFS BTRFS(8)
&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;NAME
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs - a toolbox to manage btrfs filesystems
&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;SYNOPSIS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs [global options] &amp;lt;group&amp;gt; [&amp;lt;group&amp;gt;...] &amp;lt;command&amp;gt; [options] [&amp;lt;args&amp;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;DESCRIPTION
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; The btrfs utility is a toolbox for managing btrfs filesystems. There
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; are command groups to work with subvolumes, devices, for whole filesys‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tem or other specific actions. See section COMMANDS.
&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; There are also standalone tools for some tasks like btrfs-convert(8) or
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfstune(8) that were separate historically and/or haven&amp;#39;t been merged
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; to the main utility. See section STANDALONE TOOLS for more details.
&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; For other topics (mount options, etc) please refer to the separate man‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ual page btrfs(5).
&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;COMMAND SYNTAX
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Any command name can be shortened so long as the shortened form is unam‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; biguous, however, it is recommended to use full command names in
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; scripts. All command groups have their manual page named btrfs-&amp;lt;group&amp;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; For example: it is possible to run btrfs sub snaps instead of btrfs sub‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; volume snapshot. But btrfs file s is not allowed, because file s may be
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; interpreted both as filesystem show and as filesystem sync.
&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; If the command name is ambiguous, the list of conflicting options is
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; printed.
&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; Sizes, both upon input and output, can be expressed in either SI or
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IEC-I units (see numfmt(1)) with the suffix B appended. All numbers
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; will be formatted according to the rules of the C locale (ignoring the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; shell locale, see locale(7)).
&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; For an overview of a given command use btrfs command --help or btrfs
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; [command...] help --full to print all available options for all com‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mands.
&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; There are global options that are passed between btrfs and the group
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; name and affect behaviour not specific to the command, e.g. verbosity or
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; the type of the output:
&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; btrfs -q subvolume create ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs --dry-run subvolume create ...
&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; --format &amp;lt;format&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; if supported by the command, print subcommand output in that for‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; mat (text, json)
&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; -v|--verbose
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; increase verbosity of the subcommand
&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; -q|--quiet
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print only errors
&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; --log &amp;lt;level&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; set log level (default, info, verbose, debug, quiet)
&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; The remaining options are relevant only for the main tool:
&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; --help print condensed help for all subcommands
&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; --version
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; print version string
&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;COMMANDS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; balance
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Balance btrfs filesystem chunks across single or several devices.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; See btrfs-balance(8) for details.
&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; check Do off-line check on a btrfs filesystem. See btrfs-check(8) for
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; details.
&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; device Manage devices managed by btrfs, including add/delete/scan and so
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; on. See btrfs-device(8) for details.
&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; filesystem
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Manage a btrfs filesystem, including label setting/sync and so
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; on. See btrfs-filesystem(8) for details.
&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; inspect-internal
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Debug tools for developers/hackers. See
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-inspect-internal(8) for details.
&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; property
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Get/set a property from/to a btrfs object. See btrfs-property(8)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; for details.
&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; qgroup Manage quota group(qgroup) for btrfs filesystem. See
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-qgroup(8) for details.
&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; quota Manage quota on btrfs filesystem like enabling/rescan and etc.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; See btrfs-quota(8) and btrfs-qgroup(8) for details.
&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; receive
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Receive subvolume data from stdin/file for restore and etc. See
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-receive(8) for details.
&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; replace
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Replace btrfs devices. See btrfs-replace(8) for details.
&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; rescue Try to rescue damaged btrfs filesystem. See btrfs-rescue(8) for
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; details.
&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; restore
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Try to restore files from a damaged btrfs filesystem. See
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-restore(8) for details.
&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; scrub Scrub a btrfs filesystem. See btrfs-scrub(8) for details.
&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; send Send subvolume data to stdout/file for backup and etc. See
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-send(8) for details.
&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; subvolume
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Create/delete/list/manage btrfs subvolume. See
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-subvolume(8) for details.
&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;STANDALONE TOOLS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; New functionality could be provided using a standalone tool. If the
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; functionality proves to be useful, then the standalone tool is declared
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; obsolete and its functionality is copied to the main tool. Obsolete
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tools are removed after a long (years) depreciation period.
&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; Tools that are still in active use without an equivalent in btrfs:
&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; btrfs-convert
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; in-place conversion from ext2/3/4 filesystems to btrfs
&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; btrfstune
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tweak some filesystem properties on a unmounted filesystem
&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; btrfs-select-super
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rescue tool to overwrite primary superblock from a spare copy
&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; btrfs-find-root
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; rescue helper to find tree roots in a filesystem
&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; For space-constrained environments, it&amp;#39;s possible to build a single bi‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nary with functionality of several standalone tools. This is following
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; the concept of busybox where the file name selects the functionality.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; This works for symlinks or hardlinks. The full list can be obtained by
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs help --box.
&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;EXIT STATUS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs returns a zero exit status if it succeeds. Non zero is returned in
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; case of failure.
&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;AVAILABILITY
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs is part of btrfs-progs. Please refer to the documentation at ‐
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; https://btrfs.readthedocs.io.
&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;SEE ALSO
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs(5), btrfs-balance(8), btrfs-check(8), btrfs-convert(8),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-device(8), btrfs-filesystem(8), btrfs-inspect-internal(8),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-property(8), btrfs-qgroup(8), btrfs-quota(8), btrfs-receive(8),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-replace(8), btrfs-rescue(8), btrfs-restore(8), btrfs-scrub(8),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; btrfs-send(8), btrfs-subvolume(8), btrfstune(8), mkfs.btrfs(8)
&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;6.14 Mar 27, 2025 BTRFS(8)&lt;/span&gt;&lt;/span&gt;&lt;/code
&gt;&lt;button onclick="copyCode(this)" class="copybtn"&gt;copy&lt;/button&gt;&lt;/pre&gt;&lt;/details&gt;
&lt;script&gt;
function copyCode(btn) {
const code = btn.previousElementSibling.textContent.trim();
navigator.clipboard.writeText(code).then(() =&gt; {
btn.innerText = "copied";
setTimeout(() =&gt; (btn.innerText = "copy"), 2000);
});
}
&lt;/script&gt;&lt;h2 id="快照"&gt;
&lt;a class="anchor inpage" href="#%e5%bf%ab%e7%85%a7"&gt;##&lt;/a&gt;快照&lt;/h2&gt;
&lt;p&gt;用timeshift和snapper做快照。子卷布局&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="linux下的-btrfs">
  <a class="anchor inpage" href="#linux%e4%b8%8b%e7%9a%84-btrfs">#</a>linux下的 btrfs</h1>
<h2 id="btrfs的功能">
  <a class="anchor inpage" href="#btrfs%e7%9a%84%e5%8a%9f%e8%83%bd">##</a>btrfs的功能</h2>
<p>写时复制 <code>copy on right</code>功能使得非常时候做快照。</p>
<p>子卷功能可以更方便的分区。以及添加新设备。</p>
<h2 id="官方手册">
  <a class="anchor inpage" href="#%e5%ae%98%e6%96%b9%e6%89%8b%e5%86%8c">##</a>官方手册</h2>
<details open>
    <summary>man</summary><pre
        class="chroma codeblock"
      ><code class="language-man" data-lang="man"
          ><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>BTRFS(8)                             BTRFS                             BTRFS(8)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>       btrfs - a toolbox to manage btrfs filesystems
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>       btrfs [global options] &lt;group&gt; [&lt;group&gt;...] &lt;command&gt; [options] [&lt;args&gt;]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DESCRIPTION
</span></span><span style="display:flex;"><span>       The  btrfs  utility  is a toolbox for managing btrfs filesystems.  There
</span></span><span style="display:flex;"><span>       are command groups to work with subvolumes, devices, for whole  filesys‐
</span></span><span style="display:flex;"><span>       tem or other specific actions. See section COMMANDS.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       There  are also standalone tools for some tasks like btrfs-convert(8) or
</span></span><span style="display:flex;"><span>       btrfstune(8) that were separate historically and/or haven&#39;t been  merged
</span></span><span style="display:flex;"><span>       to the main utility. See section STANDALONE TOOLS for more details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       For  other topics (mount options, etc) please refer to the separate man‐
</span></span><span style="display:flex;"><span>       ual page btrfs(5).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>COMMAND SYNTAX
</span></span><span style="display:flex;"><span>       Any command name can be shortened so long as the shortened form is unam‐
</span></span><span style="display:flex;"><span>       biguous, however, it  is  recommended  to  use  full  command  names  in
</span></span><span style="display:flex;"><span>       scripts.  All command groups have their manual page named btrfs-&lt;group&gt;.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       For example: it is possible to run btrfs sub snaps instead of btrfs sub‐
</span></span><span style="display:flex;"><span>       volume snapshot.  But btrfs file s is not allowed, because file s may be
</span></span><span style="display:flex;"><span>       interpreted both as filesystem show and as filesystem sync.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       If  the  command  name  is ambiguous, the list of conflicting options is
</span></span><span style="display:flex;"><span>       printed.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Sizes, both upon input and output, can be  expressed  in  either  SI  or
</span></span><span style="display:flex;"><span>       IEC-I  units  (see  numfmt(1))  with the suffix B appended.  All numbers
</span></span><span style="display:flex;"><span>       will be formatted according to the rules of the C locale  (ignoring  the
</span></span><span style="display:flex;"><span>       shell locale, see locale(7)).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       For  an  overview  of  a given command use btrfs command --help or btrfs
</span></span><span style="display:flex;"><span>       [command...] help --full to print all available  options  for  all  com‐
</span></span><span style="display:flex;"><span>       mands.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       There  are  global  options  that are passed between btrfs and the group
</span></span><span style="display:flex;"><span>       name and affect behaviour not specific to the command, e.g. verbosity or
</span></span><span style="display:flex;"><span>       the type of the output:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          btrfs -q subvolume create ...
</span></span><span style="display:flex;"><span>          btrfs --dry-run subvolume create ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       --format &lt;format&gt;
</span></span><span style="display:flex;"><span>              if supported by the command, print subcommand output in that for‐
</span></span><span style="display:flex;"><span>              mat (text, json)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -v|--verbose
</span></span><span style="display:flex;"><span>              increase verbosity of the subcommand
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       -q|--quiet
</span></span><span style="display:flex;"><span>              print only errors
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       --log &lt;level&gt;
</span></span><span style="display:flex;"><span>              set log level (default, info, verbose, debug, quiet)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       The remaining options are relevant only for the main tool:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       --help print condensed help for all subcommands
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       --version
</span></span><span style="display:flex;"><span>              print version string
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>COMMANDS
</span></span><span style="display:flex;"><span>       balance
</span></span><span style="display:flex;"><span>              Balance btrfs filesystem chunks across single or several devices.
</span></span><span style="display:flex;"><span>              See btrfs-balance(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       check  Do off-line check on a btrfs filesystem.  See btrfs-check(8)  for
</span></span><span style="display:flex;"><span>              details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       device Manage devices managed by btrfs, including add/delete/scan and so
</span></span><span style="display:flex;"><span>              on.  See btrfs-device(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       filesystem
</span></span><span style="display:flex;"><span>              Manage  a  btrfs  filesystem, including label setting/sync and so
</span></span><span style="display:flex;"><span>              on.  See btrfs-filesystem(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       inspect-internal
</span></span><span style="display:flex;"><span>              Debug       tools       for       developers/hackers.         See
</span></span><span style="display:flex;"><span>              btrfs-inspect-internal(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       property
</span></span><span style="display:flex;"><span>              Get/set a property from/to a btrfs object.  See btrfs-property(8)
</span></span><span style="display:flex;"><span>              for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       qgroup Manage   quota   group(qgroup)   for   btrfs   filesystem.    See
</span></span><span style="display:flex;"><span>              btrfs-qgroup(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       quota  Manage quota on btrfs filesystem like  enabling/rescan  and  etc.
</span></span><span style="display:flex;"><span>              See btrfs-quota(8) and btrfs-qgroup(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       receive
</span></span><span style="display:flex;"><span>              Receive  subvolume data from stdin/file for restore and etc.  See
</span></span><span style="display:flex;"><span>              btrfs-receive(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       replace
</span></span><span style="display:flex;"><span>              Replace btrfs devices.  See btrfs-replace(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       rescue Try to rescue damaged btrfs filesystem.  See btrfs-rescue(8)  for
</span></span><span style="display:flex;"><span>              details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       restore
</span></span><span style="display:flex;"><span>              Try  to  restore  files  from  a  damaged  btrfs filesystem.  See
</span></span><span style="display:flex;"><span>              btrfs-restore(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       scrub  Scrub a btrfs filesystem.  See btrfs-scrub(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       send   Send subvolume data to  stdout/file  for  backup  and  etc.   See
</span></span><span style="display:flex;"><span>              btrfs-send(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       subvolume
</span></span><span style="display:flex;"><span>              Create/delete/list/manage       btrfs       subvolume.        See
</span></span><span style="display:flex;"><span>              btrfs-subvolume(8) for details.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>STANDALONE TOOLS
</span></span><span style="display:flex;"><span>       New functionality could be provided using  a  standalone  tool.  If  the
</span></span><span style="display:flex;"><span>       functionality  proves to be useful, then the standalone tool is declared
</span></span><span style="display:flex;"><span>       obsolete and its functionality is copied  to  the  main  tool.  Obsolete
</span></span><span style="display:flex;"><span>       tools are removed after a long (years) depreciation period.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       Tools that are still in active use without an equivalent in btrfs:
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       btrfs-convert
</span></span><span style="display:flex;"><span>              in-place conversion from ext2/3/4 filesystems to btrfs
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       btrfstune
</span></span><span style="display:flex;"><span>              tweak some filesystem properties on a unmounted filesystem
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       btrfs-select-super
</span></span><span style="display:flex;"><span>              rescue tool to overwrite primary superblock from a spare copy
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       btrfs-find-root
</span></span><span style="display:flex;"><span>              rescue helper to find tree roots in a filesystem
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>       For  space-constrained environments, it&#39;s possible to build a single bi‐
</span></span><span style="display:flex;"><span>       nary with functionality of several standalone tools. This  is  following
</span></span><span style="display:flex;"><span>       the  concept  of  busybox where the file name selects the functionality.
</span></span><span style="display:flex;"><span>       This works for symlinks or hardlinks. The full list can be  obtained  by
</span></span><span style="display:flex;"><span>       btrfs help --box.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>EXIT STATUS
</span></span><span style="display:flex;"><span>       btrfs returns a zero exit status if it succeeds. Non zero is returned in
</span></span><span style="display:flex;"><span>       case of failure.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>AVAILABILITY
</span></span><span style="display:flex;"><span>       btrfs  is  part  of btrfs-progs.  Please refer to the documentation at ‐
</span></span><span style="display:flex;"><span>       https://btrfs.readthedocs.io.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SEE ALSO
</span></span><span style="display:flex;"><span>       btrfs(5),    btrfs-balance(8),     btrfs-check(8),     btrfs-convert(8),
</span></span><span style="display:flex;"><span>       btrfs-device(8),     btrfs-filesystem(8),     btrfs-inspect-internal(8),
</span></span><span style="display:flex;"><span>       btrfs-property(8),  btrfs-qgroup(8),  btrfs-quota(8),  btrfs-receive(8),
</span></span><span style="display:flex;"><span>       btrfs-replace(8),   btrfs-rescue(8),  btrfs-restore(8),  btrfs-scrub(8),
</span></span><span style="display:flex;"><span>       btrfs-send(8), btrfs-subvolume(8), btrfstune(8), mkfs.btrfs(8)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>6.14                              Mar 27, 2025                         BTRFS(8)</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="快照">
  <a class="anchor inpage" href="#%e5%bf%ab%e7%85%a7">##</a>快照</h2>
<p>用timeshift和snapper做快照。子卷布局</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">ID 257 gen 96108 top level 5 path @home
ID 318 gen 105959 top level 257 path @home/username
ID 268 gen 96108 top level 318 path @home/username/.snapshots
ID 269 gen 96108 top level 268 path @home/username/.snapshots/1/snapshot
ID 258 gen 105883 top level 5 path @root
ID 259 gen 105850 top level 5 path @cache
ID 260 gen 105959 top level 5 path @log
ID 261 gen 105942 top level 5 path @tmp
ID 262 gen 98722 top level 5 path @opt
ID 273 gen 96108 top level 262 path @opt/.snapshots
ID 274 gen 96108 top level 258 path @root/.snapshots
ID 285 gen 96433 top level 274 path @root/.snapshots/1/snapshot
ID 290 gen 105959 top level 5 path @
ID 519 gen 96445 top level 268 path @home/username/.snapshots/2/snapshot
ID 536 gen 103272 top level 5 path timeshift-btrfs/snapshots/2025-04-21_12-54-20/@
ID 537 gen 104133 top level 5 path timeshift-btrfs/snapshots/2025-04-21_20-12-43/@</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>即根目录用<code>timeshift</code>备份，并且回滚过一次（从@的ID可以看出来，不是安装时创建的256），而<code>/home/username</code>,<code>/home/root</code>,<code>/home/opt</code>用<code>snapper</code>做了几个快照</p>
<h3 id="timeshift-备份根目录">
  <a class="anchor inpage" href="#timeshift-%e5%a4%87%e4%bb%bd%e6%a0%b9%e7%9b%ae%e5%bd%95">###</a>timeshift 备份根目录</h3>
<p>注意<code>btrfs</code>的子卷布局，根目录必须是<code>@</code>，例如</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">ID 257 gen 96108 top level 5 path @home
ID 258 gen 105883 top level 5 path @root
ID 259 gen 105850 top level 5 path @cache
ID 260 gen 105930 top level 5 path @log
ID 261 gen 105928 top level 5 path @tmp
ID 262 gen 98722 top level 5 path @opt
ID 290 gen 105929 top level 5 path @</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h3 id="snapper-备份子卷">
  <a class="anchor inpage" href="#snapper-%e5%a4%87%e4%bb%bd%e5%ad%90%e5%8d%b7">###</a>snapper 备份子卷</h3>
<p>参考：</p>
<ul>
<li>
</li>
<li>
</li>
</ul>
<p>snapper更加灵活。首先创建一个snapper的配置文件</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo snapper -c <span style="color:#f92672">[</span>name of config<span style="color:#f92672">]</span> create-config <span style="color:#f92672">[</span>path-to-subvol<span style="color:#f92672">]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>例如对根目录的备份配置，<code>snapper</code>默认配置名是<code>root</code></p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo snapper -c root create-config /</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p><code>snapper</code>默认会创建子卷<code>/.snapshots</code>，似乎是<code>opensuse</code>风格的，把它调整成一般的布局</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">sudo umount /.snapshots
sudo rm -r /.snapshots
sudo btrfs subvolume delete /.snapshots
sudo mkdir /.snapshots
sudo mount -o subvol=/ /dev/nvme0n1p1 /mnt
sudo btrfs subvolume create /mnt/@snapshots</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以对其他子卷做同样的操作，比如对<code>/opt (@opt)</code>,<code>/root (@root)</code>。</p>
<p>对用户目录，首先有<code>@home</code>子卷挂载<code>/home</code>，然后用</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>useradd
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Usage: useradd <span style="color:#f92672">[</span>options<span style="color:#f92672">]</span> LOGIN
</span></span><span style="display:flex;"><span>       useradd -D
</span></span><span style="display:flex;"><span>       useradd -D <span style="color:#f92672">[</span>options<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>Options:
</span></span><span style="display:flex;"><span>      --btrfs-subvolume-home    use BTRFS subvolume <span style="color:#66d9ef">for</span> home directory</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>选项创建<code>@home/user_name</code>子卷挂载用户家目录<code>/home/user_name</code>。这样再用上述方法可以对特定用户的家目录做快照。子卷会像</p>
<h3 id="从快照中恢复">
  <a class="anchor inpage" href="#%e4%bb%8e%e5%bf%ab%e7%85%a7%e4%b8%ad%e6%81%a2%e5%a4%8d">###</a>从快照中恢复</h3>
<p>对snapper创建的<code>/</code>的快照，复杂的手动方法，要从live
USB开始，就是安装<code>arch</code>时的live系统</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo mount /dev/nvme0n1p6 /mnt
</span></span><span style="display:flex;"><span>cd /mnt
</span></span><span style="display:flex;"><span>sudo mv /mnt/@ /mnt/@.broken
</span></span><span style="display:flex;"><span>sudo btrfs subvolume snapshot /mnt/@snapshots/<span style="color:#f92672">{</span>number<span style="color:#f92672">}</span>/snapshot /mnt/@
</span></span><span style="display:flex;"><span>sudo btrfs subvolume delete /mnt/@.broken</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>不进入live系统的方法，看上去很危险，最好回滚后立刻重启</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>sudo mount -o subvol<span style="color:#f92672">=</span>/ /dev/nvme0n1p1 /mnt
</span></span><span style="display:flex;"><span>sudo btrfs subvolume snapshot /mnt/@ /mnt/@bad
</span></span><span style="display:flex;"><span>sudo btrfs subvolume delete /mnt/@
</span></span><span style="display:flex;"><span>sudo btrfs subvolume snapshot /mnt/@snapshots/要恢复的快照号/snapshot /mnt/@</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>可以用脚本完成回滚（来自
）</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>set -e
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> x<span style="color:#e6db74">&#34;</span>$1<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> x <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;No snapshot number given.&#34;</span> 1&gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Usage: rollback [snapshot to rollback]&#34;</span> 1&gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>  exit <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>root_dev<span style="color:#f92672">=</span><span style="color:#e6db74">`</span>findmnt -n -o SOURCE / | sed <span style="color:#e6db74">&#39;s/\[.*\]//g&#39;</span><span style="color:#e6db74">`</span>
</span></span><span style="display:flex;"><span>root_subvol<span style="color:#f92672">=</span><span style="color:#e6db74">`</span>findmnt -n -o SOURCE / | sed <span style="color:#e6db74">&#39;s/.*\[\(.*\)\].*/\1/&#39;</span><span style="color:#e6db74">`</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;&gt;= Rollback to #</span>$1<span style="color:#e6db74"> on device </span>$root_dev<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># create snapshot before</span>
</span></span><span style="display:flex;"><span>sudo snapper create --read-only --type single -d <span style="color:#e6db74">&#34;Before rollback to #</span>$1<span style="color:#e6db74">&#34;</span> --userdata important<span style="color:#f92672">=</span>yes
</span></span><span style="display:flex;"><span>sudo mount -o subvol<span style="color:#f92672">=</span>/ $root_dev /mnt
</span></span><span style="display:flex;"><span><span style="color:#75715e"># check enviornment</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> x<span style="color:#e6db74">&#34;</span>$root_subvol<span style="color:#e6db74">&#34;</span> <span style="color:#f92672">==</span> x/@ <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>  echo <span style="color:#e6db74">&#34;Warning: Not run in a snapshot, a subvolume @old will be created. You should consider remove it after reboot.&#34;</span> 1&gt;&amp;<span style="color:#ae81ff">2</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> <span style="color:#f92672">[[</span> -d /mnt/@old <span style="color:#f92672">]]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Found last @old, remove it.&#34;</span>
</span></span><span style="display:flex;"><span>    sudo btrfs subvolume delete /mnt/@old &gt;/dev/null
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>  sudo mv /mnt/@ /mnt/@old
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>  sudo btrfs subvolume delete /mnt/@ &gt;/dev/null
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span><span style="display:flex;"><span>sudo btrfs subvolume snapshot /mnt/@snapshots/$1/snapshot /mnt/@ &gt;/dev/null
</span></span><span style="display:flex;"><span>sudo umount /mnt</span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>其他子卷的<code>snapper</code>快照，直接用</p>
<details open>
    <summary>sh</summary><pre
        class="chroma codeblock"
      ><code class="language-sh" data-lang="sh"
          ><span style="display:flex;"><span>snapper -c <span style="color:#f92672">[</span>config<span style="color:#f92672">]</span> rollback <span style="color:#f92672">[</span>number<span style="color:#f92672">]</span></span></span></code
        ><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><p>对于<code>timeshift</code>，直接gui操作就行。</p>
<p>回滚后最好立刻重启。</p>
<h2 id="技巧">
  <a class="anchor inpage" href="#%e6%8a%80%e5%b7%a7">##</a>技巧</h2>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">btrfs filesystem du -s /path/to/subvolume</code><button onclick="copyCode(this)" class="copybtn">copy</button></pre></details>

  <script>
    function copyCode(btn) {
      const code = btn.previousElementSibling.textContent.trim();
      navigator.clipboard.writeText(code).then(() => {
        btn.innerText = "copied";
        setTimeout(() => (btn.innerText = "copy"), 2000);
      });
    }
  </script><h2 id="reference">
  <a class="anchor inpage" href="#reference">##</a>Reference</h2>
<ol>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ol>
]]></content:encoded></item></channel></rss>