<?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>ArchlinuxonDocs</title><link>https://hiraethecho.github.io/docs/tags/archlinux/</link><description>Recent contentinArchlinuxonDocs</description><generator>Hugo --0.152.2</generator><language>en</language><managingEditor>wyz2016zxc@outlook.com(Hiraeth)</managingEditor><webMaster>wyz2016zxc@outlook.com(Hiraeth)</webMaster><lastBuildDate>Mon, 16 Mar 2026 15:39:39 +0800</lastBuildDate><atom:link href="https://hiraethecho.github.io/docs/tags/archlinux/index.xml" rel="self" type="application/rss+xml"/><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>pake打包web应用</title><link>https://hiraethecho.github.io/docs/dev/pake/</link><pubDate>Sun, 08 Jun 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/dev/pake/</guid><description>&lt;h1 id="pake打包web应用"&gt;
&lt;a class="anchor inpage" href="#pake%e6%89%93%e5%8c%85web%e5%ba%94%e7%94%a8"&gt;#&lt;/a&gt;pake打包web应用&lt;/h1&gt;
&lt;p&gt;
可以将web转化为桌面应用，比&lt;code&gt;electron&lt;/code&gt;更轻量。&lt;/p&gt;
&lt;h2 id="安装pake"&gt;
&lt;a class="anchor inpage" href="#%e5%ae%89%e8%a3%85pake"&gt;##&lt;/a&gt;安装pake&lt;/h2&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;npm -g install pake-cli&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;p&gt;需要&lt;code&gt;rust&lt;/code&gt;等工具链&lt;/p&gt;</description><content:encoded><![CDATA[<h1 id="pake打包web应用">
  <a class="anchor inpage" href="#pake%e6%89%93%e5%8c%85web%e5%ba%94%e7%94%a8">#</a>pake打包web应用</h1>
<p>
可以将web转化为桌面应用，比<code>electron</code>更轻量。</p>
<h2 id="安装pake">
  <a class="anchor inpage" href="#%e5%ae%89%e8%a3%85pake">##</a>安装pake</h2>
<p>用户级安装：</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">npm -g install pake-cli</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>rust</code>等工具链</p>
<h2 id="打包web应用">
  <a class="anchor inpage" href="#%e6%89%93%e5%8c%85web%e5%ba%94%e7%94%a8">##</a>打包web应用</h2>
<p>例如</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">pake chat.deepseek.com --name deepseek --width 1080 --height 1920 --show-system-tray --icon 512x512-RGBA.png</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>要注意的是分辨率设置，以及icon格式为512x512的png，似乎必须是<code>RGBA</code></p>
<p>会得到<code>deepseek.deb</code>，内部结构为</p>
<details open>
    <summary>deb</summary><pre
        class="codeblock"
      ><code class="language-deb" data-lang="deb">control.tar.gz
data.tar.gz
debian-binary</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>data.tar.gz</code>里面，用<code>tar -xvf data.tar.gz</code>得到</p>
<details open>
    <summary>usr</summary><pre
        class="codeblock"
      ><code class="language-usr" data-lang="usr"> usr
├──  bin
│   └──  pake
├──  lib
│   └──  deepseek
│       └──  png
│           └──  deepseek_512.png
└──  share
    ├──  applications
    │   └──  deepseek.desktop
    └──  icons
        └──  hicolor
            └──  512x512
                └──  apps
                    └──  pake.png</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/bin/pake</code>是单二进制文件，可以直接运行<code>./usr/bin/pake</code>。其他的是快捷方式<code>usr/share/application/deepseek.desktop</code>和图标等。</p>
<h2 id="on-arch">
  <a class="anchor inpage" href="#on-arch">##</a>On Arch</h2>
<p>在<code>archlinux</code>上可以将其做成<code>.zst</code>格式的包，用<code>pacman</code>管理。</p>
<p>把下面内容写入<code>PKGBUILD</code>文件</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang=""># Maintainer: hiraethecho &lt;wyz2016zxc at outlook dot com&gt;
pkgname=&#34;${_appname}-pake&#34;
pkgver=1.0.0
pkgrel=1
pkgdesc=&#34;${_appname} pake&#34;
arch=(&#39;x86_64&#39;)
license=(&#39;MIT&#39;)
conflicts=(&#34;${_appname}-pake&#34;)
depends=(
    &#39;gtk3&#39;
    &#39;webkit2gtk-4.1&#39;
)
source=(
  ${_appname}.deb
)
sha256sums=(&#39;SKIP&#39;)
prepare() {
    bsdtar -xf &#34;${srcdir}/data.&#34;*
    sed -e &#34;
        s/Exec=pake/Exec=${_appname}/g
        s|Icon=pake|Icon=${_appname}|g
    &#34; -i &#34;${srcdir}/usr/share/applications/${_appname}.desktop&#34;
    mv ${srcdir}/usr/share/icons/hicolor/*/apps/pake.png ${srcdir}/usr/share/icons/pake.png
}
package() {
    install -Dm755 &#34;${srcdir}/usr/bin/pake&#34; &#34;${pkgdir}/usr/bin/${_appname}&#34;
    install -Dm644 &#34;${srcdir}/usr/share/applications/${_appname}.desktop&#34; &#34;${pkgdir}/usr/share/applications/${_appname}.desktop&#34;
    install -Dm644 &#34;${srcdir}/usr/share/icons/pake.png&#34; &#34;${pkgdir}/usr/share/pixmaps/${_appname}.png&#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>然后执行这个shell脚本，注意<code>-i</code> <code>-w</code> <code>-n</code>选项</p>
<details open>
    <summary>pake2zst</summary><pre
        class="codeblock"
      ><code class="language-pake2zst" data-lang="pake2zst">#!/usr/bin/bash
# generate a zst from pake
url=&#34;&#34;
icon=&#34;&#34;
name=&#34;&#34;
while getopts &#34;:n:i:w:&#34; opt; do
  case $opt in
  n) name=&#34;$OPTARG&#34; ;;
  i) icon=&#34;$OPTARG&#34; ;;
  w) url=&#34;$OPTARG&#34; ;;
  \?)
    echo &#34;无效选项: -$OPTARG&#34; &gt;&amp;2
    ;;
  esac
done

echo -e &#34;$url $icon $name&#34;
# pake $url --icon $icon --height=1080 --width=1920 --show-system-tray --name $appname
sed -i &#34;/pkgdesc/a\\url=${url}&#34; PKGBUILD
sed -i &#34;/pkgname/i\\_appname=${name}&#34; PKGBUILD
makepkg</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>.zst</code>包，用<code>pacman -U name-pake-1.0.0-1-x86_64.pkg.tar.zst</code>即可。</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>安装后的建议配置</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>折腾的linux+X11+dwm</title><link>https://hiraethecho.github.io/docs/project/dwm/</link><pubDate>Mon, 29 Jul 2024 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/project/dwm/</guid><description>关于linux C dwm等</description><content:encoded><![CDATA[<h1 id="近期折腾的archlinux">
  <a class="anchor inpage" href="#%e8%bf%91%e6%9c%9f%e6%8a%98%e8%85%be%e7%9a%84archlinux">#</a>近期折腾的archlinux</h1>
<p>也算是一些业余学习吧。先叠个甲，业余学习所以可能有错误，只是个人理解。</p>
<h2 id="linux">
  <a class="anchor inpage" href="#linux">##</a>linux</h2>
<p>linux内核的功能是调用硬件，为程序分配使用<br>
GNU is not unix. 在斯托曼的组织下，为了取代unix开发了一系列自由软件，但是没有内核，用了linus的内核。<br>
shell是包裹在内核外面的外壳，用来和内核沟通。并且有POSIX的shell标准，来规范shell的语言。常见的shell有<code>bash</code> <code>zsh</code>等。而另一个常见的<code>fish</code>不符合POSIX.<br>
Terminal是使用shell的界面。最基础的terminal就是tty，是过去计算机的一个物理部件（console控制台是另一个过去的物理部件，直接控制机器。tty是<em>远程</em>的控制方式。）常见的terminal有alacritty、kitty和各大桌面环境配套的。</p>
<p>linux的哲学之一在于，每一个程序只做一件事，并努力做到最好。像word这样的windows应用，常被认为是臃肿的，“每个人只用到了全部功能的1%
”。但这是因为“每个人用的都是不同的1%”。然而在linux的世界里，为了自己需要的那1%，通常只需要安装对应的那1%。当然，困难之处在于在广大社区中找到对应的程序，并且使自己所需要的各种程序和谐共存互相协调。</p>
<p>GNU/linux有各种发行版，虽然个人感到主要区别在包管理器和预装软件。包管理器的其中一个功能就是尽量保证各个程序可以互相协调，自动解决程序的依赖等问题。至于预装软件可能是发行版制作者的个人倾向。<br>
BTW，I use arch.</p>
<p>Arch发行版是一个Geek风格的linux发行版，目的在于用户尽可能自由配置自己的linux（当然似乎比不上Gentoo甚至lfs）。它有两个特点，其一是滚动更新，即没有稳定版本，总可以获得最新的软件版本。好处是获得最新功能，第一时间获得已知bug的修复；坏处是，也可以第一时间获得bug，以及面临软件之间版本不兼容的问题（这也是linux哲学的负面影响）。第二个特点是AUR，既用户仓库。每个发行版的包管理器通常有对应的软件源，而arch除了官方软件源外还有用户仓库，即每个用户都可以把应用按照规范打包供他人使用。优点在于AUR里什么都有，缺点在于很多应用无人负责或没有充分维护。</p>
<h2 id="图形化界面x11">
  <a class="anchor inpage" href="#%e5%9b%be%e5%bd%a2%e5%8c%96%e7%95%8c%e9%9d%a2x11">##</a>图形化界面X11</h2>
<p>为了在tty外情景使用linux，需要图形化界面。</p>
<p>X11是linux的一个图形化界面的协议，每个图形化程序并不是靠它自己显示画面，而是通过协议用Xorg来创建图形的。除此之外还有混成器（例如picom）来提供一些画面特效等。wayland是另一套图形化方案，本身替代了Xorg和混成器的功能。</p>
<p>linux下的桌面环境（Desktop Environment），如KDE GNOME Xfce等，提供了一整套日常使用的基本功能，例如窗口管理，应用启动器，托盘，设置，蓝牙，网络等。但事实上如果追求极简，那么仅仅使用窗口管理器（Windows Manager）也是可行的。</p>
<p>Windows Manager，通俗的解释，就是显示应用程序的窗口，并且拖动、调整大小、最大化等功能的部分，不包括壁纸、声音网络蓝牙键盘触摸板等设置、应用启动器和托盘。<br>
常见的独立窗口管理器包括i3，openbox，awesome等。而我选择的是dwm，属于suckless系列，用C语言编写，代码仅2000余行，更改配置需要修改源码重新编译，添加功能是通过.diff文件打补丁实现。</p>
<h2 id="dwm和c">
  <a class="anchor inpage" href="#dwm%e5%92%8cc">##</a>dwm和C</h2>
<p>这几周时间一直在加强的我dwm，被迫学习了C语言的使用，以及基于lazygit的自娱自乐式历史管理。</p>
<p>C语言是面向过程的，以函数为中心的。但实际写dwm代码的时候，则主要用“面向对象”的思路在写。对象里的函数和变量是用指针或者全局变量，实现地很曲折。</p>
<p>C语言算是很底层的编程语言了，指针可能是其最重要的特性。指针直接指向变量的存储地址，非常有趣。在函数调用时，传参传指针进去，可以直接在物理存贮的意义上理解程序是如何使用和修改变量的值的。另外还有位运算，也很有趣。</p>
<p>C语言同时还是非常省内存（这里应该指的是内存吗？）的语言，每次写一个新变量都小心翼翼地。遥想大一学C语言的时候，还要注意变量要在代码块之前先声明，开个动态数组都麻烦的一匹，用完还要free掉。后来看见其他语言随便新建变量，太难接受了。不过这种节省也导致一些逆天的feature.例如一个结构体</p>
<details open>
    <summary>C</summary><pre
        class="chroma codeblock"
      ><code class="language-C" data-lang="C"
          ><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> i;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">float</span> f;
</span></span><span style="display:flex;"><span>} Arg1;</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>那么一个Arg就会有两个成员。但是还有一种操作</p>
<details open>
    <summary>C</summary><pre
        class="chroma codeblock"
      ><code class="language-C" data-lang="C"
          ><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">union</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> i;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">float</span> f;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>v;
</span></span><span style="display:flex;"><span>} Arg2;</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>union</code>的意思是，<code>Arg2</code>只能有一个类型。当创建一个<code>Arg1 a1</code>时，会给 <code>a1.i</code>和<code>a1.f</code>都分配地址。但是<code>Arg2 a2</code>就只有一个地址，当用了<code>a2.i=1</code>之后就不能再赋值<code>a2.f</code>了。这样如果不同函数的输入一个是<code>int</code>另一个是<code>float</code>，那就可以都写成<code>Arg2</code>，十分优雅。但是需要复杂功能是就很难用。<br>
除此之外，这个<code>void *v</code>也是个奇妙的用法，只要用上强制类型转换<code>Client *c=(Client *)v</code>就可以很灵活的使用各种类型的变量了。</p>
<h2 id="">
  <a class="anchor inpage" href="#">##</a></h2>
<p>最后，可以在我的
找到我的dotfiles和dwm。还没有整理，也没文档，以后有时间心情再说吧。</p>
<h2 id="tabbed-scratchpad">
  <a class="anchor inpage" href="#tabbed-scratchpad">##</a>tabbed scratchpad</h2>
<p><code>st -c class -n name</code> with <code>precmd () {print -Pn &quot;\e]0;%~\a&quot;}</code> in <code>.zshrc</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">_NET_WM_ICON_NAME(UTF8_STRING) = &#34;~&#34;
WM_ICON_NAME(UTF8_STRING) = &#34;~&#34;
WM_CLASS(STRING) = &#34;name&#34;, &#34;class&#34;
_NET_WM_NAME(UTF8_STRING) = &#34;~&#34;
WM_NAME(UTF8_STRING) = &#34;~&#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><code>tabbed -n &quot;scratchpad&quot; -c -r 2 st -w '' -g 150x40 -c class -n name</code> with <code>precmd () {print -Pn &quot;\e]0;%~\a&quot;}</code> in <code>.zshrc</code></p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">WM_NAME(UTF8_STRING) = &#34;~&#34;
_NET_WM_NAME(UTF8_STRING) = &#34;~&#34;
WM_CLASS(STRING) = &#34;scratchpad&#34;, &#34;tabbed&#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><strong>summary</strong>: In <code>WM_CLASS(STRING)=&quot;name&quot;,&quot;class&quot;</code>, <code>&quot;name&quot;</code> is for <code>st -n name</code> and <code>tabbed -n name</code>, and is also <code>instance</code> in <code>rules</code>; <code>class</code> is for <code>st -c class</code>, and class of <code>tabbed</code> is always <code>tabbed</code>.</p>
<p>origin <code>manage()</code>:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">  selmon-&gt;tagset[selmon-&gt;seltags] &amp;= ~scratchtag;
  if (!strcmp(c-&gt;name, scratchpadname)) {
    c-&gt;mon-&gt;tagset[c-&gt;mon-&gt;seltags] |= c-&gt;tags = scratchtag;
    c-&gt;isfloating = 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>we can modify to</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">void manage(Window w, XWindowAttributes *wa) {
  Client *c, *t = NULL;
&#43; XClassHint ch = {NULL, NULL};
&#43; const char *class, *instance;
    ...
&#43; XGetClassHint(dpy, c-&gt;win, &amp;ch);
&#43;  instance = ch.res_name ? ch.res_name : broken;
  selmon-&gt;tagset[selmon-&gt;seltags] &amp;= ~scratchtag;
~ if (!strcmp(instance, scratchpadname)) {
    c-&gt;mon-&gt;tagset[c-&gt;mon-&gt;seltags] |= c-&gt;tags = scratchtag;
    c-&gt;isfloating = 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>btw, <code>apply_rules</code>:</p>
<details open>
    <summary>TEXT</summary><pre
        class="codeblock"
      ><code class="language-" data-lang="">  XGetClassHint(dpy, c-&gt;win, &amp;ch);
  class = ch.res_class ? ch.res_class : broken;
  instance = ch.res_name ? ch.res_name : broken;

  for (i = 0; i &lt; LENGTH(rules); i&#43;&#43;) {
    r = &amp;rules[i];
    if ((!r-&gt;title || strstr(c-&gt;name, r-&gt;title)) &amp;&amp;
        (!r-&gt;class || strstr(class, r-&gt;class)) &amp;&amp;
        (!r-&gt;instance || strstr(instance, r-&gt;instance))) {
      c-&gt;isfloating = r-&gt;isfloating;
      c-&gt;tags |= r-&gt;tags;
      c-&gt;opacity = r-&gt;opacity;
      c-&gt;unfocusopacity = r-&gt;unfocusopacity;
      for (m = mons; m &amp;&amp; m-&gt;num != r-&gt;monitor; m = m-&gt;next) ;
      if (m)
        c-&gt;mon = m;
    }
  }</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>