<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Clover Tree</title>
  
  <subtitle>Clover Yan的博客</subtitle>
  <link href="https://blog.khyan.top/atom.xml" rel="self"/>
  
  <link href="https://blog.khyan.top/"/>
  <updated>2026-01-25T10:19:17.225Z</updated>
  <id>https://blog.khyan.top/</id>
  
  <author>
    <name>Clover Yan</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>LUKS全盘加密实战</title>
    <link href="https://blog.khyan.top/2026/01/luks/"/>
    <id>https://blog.khyan.top/2026/01/luks/</id>
    <published>2026-01-21T13:31:22.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<p>在日常使用Linux系统时，大家总会遇到需要保护数据安全的场景。LUKS（Linux Unified Key Setup）作为Linux系统中常用的全盘加密解决方案，能够有效地保护磁盘上的数据。本文将详细介绍如何在Linux系统中使用LUKS进行全盘加密。</p><p>LUKS的配置非常灵活，能够进行对已有数据的加密。下面我将介绍如何在已经安装了Linux系统的机器中使用LUKS进行全盘加密。</p><div class="panel panel-info">    <div class="panel-title"><i class="fa fa-info"></i>笔者的系统环境配置</div>    <div class="panel-body">        <ul><li>发行版：Arch Linux</li><li>使用systemd来管理系统服务</li><li>硬盘：NVMe QLC SSD</li><li>采用GRUB作为引导加载程序</li><li>根分区<code>/dev/nvme0n1p8</code>使用ext4文件系统</li><li>ESP分区<code>/dev/nvme0n1p6</code>用于存放引导文件</li></ul>    </div>    </div><h2 id="准备工作">准备工作</h2><p>在开始之前，我们需要准备好<code>cryptsetup</code>工具。Arch Linux Live环境中已经预装了该工具。</p><h3 id="评估加解密性能">评估加解密性能</h3><p>首先，我们将测试系统的加解密性能。如果你的电脑的加解密速度还不如硬盘读写速度，应该考虑不要使用LUKS加密。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cryptsetup benchmark</span><br></pre></td></tr></table></figure><p>确认要进行LUKS加密后，启动到Arch Linux Live环境。不要挂载分区，以便进行后续操作。</p><p>LUKS2加密推荐保留32 MB的未分配空间来存储加密头信息。准确地说，是LUKS2最小头信息大小的两倍。</p><p>在Linux中，分区与文件系统是不同的概念，我们将要缩小文件系统来为LUKS加密腾出空间。这一步可以先缩得小一些，后续可以再扩大。</p><h3 id="缩小文件系统，为加密预留空间">缩小文件系统，为加密预留空间</h3><p>例如，我们将ext4格式的根分区<code>/dev/nvme0n1p8</code>缩小<strong>到</strong>99G，以腾出空间用于存储LUKS加密头信息。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">e2fsck -f /dev/nvme0n1p8</span><br><span class="line">resize2fs /dev/nvme0n1p8 99G</span><br></pre></td></tr></table></figure><p>完成文件系统的缩小后，应尝试启动系统，确保一切正常。</p><h3 id="分离-boot与根分区">分离<code>/boot</code>与根分区</h3><p>让GRUB解密磁盘是一件很麻烦的事情。为了使GRUB能够正常启动Linux，我们需要让<code>/boot</code>和<code>/</code>不在同一分区上。</p><p>笔者原先只是把ESP分区挂载在<code>/efi</code>，但ESP分区足够大，有1 GB。现在我们可以把<code>/boot</code>中的内容移动到ESP分区，再把<code>/efi</code>所在的分区挂载为<code>/boot</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">mount /dev/nvme0n1p8 /mnt</span><br><span class="line">mount /dev/nvme0n1p6 /mnt/efi</span><br><span class="line"><span class="built_in">mv</span> /mnt/boot/* /mnt/efi/</span><br><span class="line">umount /mnt/efi</span><br><span class="line"><span class="built_in">rm</span> -r /mnt/boot</span><br><span class="line"><span class="built_in">rm</span> -r /mnt/efi</span><br><span class="line"><span class="built_in">mkdir</span> /mnt/boot</span><br><span class="line">mount /dev/nvme0n1p6 /mnt/boot</span><br><span class="line">arch-chroot /mnt</span><br><span class="line">grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB</span><br><span class="line">grub-mkconfig -o /boot/grub/grub.cfg</span><br><span class="line"><span class="built_in">exit</span></span><br><span class="line">umount -R /mnt</span><br></pre></td></tr></table></figure><h3 id="启动验证与文件系统检查">启动验证与文件系统检查</h3><p>完成上述步骤后，应再次尝试启动系统，确保一切正常。为保险起见，应再次执行<code>e2fsck</code>检查文件系统。</p><h2 id="开始加密">开始加密</h2><p>接下来，我们将开始对根分区进行LUKS加密。</p><div class="alert alert-warning">  <div class="icon"><i class="fa fa-warning"></i></div>  <div class="text">  <p>务必确保电脑连接稳定的电源。在加密过程中断电可能会导致数据丢失！</p>  </div>  </div><h3 id="执行原地加密">执行原地加密</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cryptsetup reencrypt --encrypt --reduce-device-size=32m /dev/nvme0n1p8</span><br></pre></td></tr></table></figure><p>这意味着我们将在分区开头留出32 MB的空间用于存储LUKS加密头信息，加密后的数据将从偏移32 MB处开始存储，整个可用空间减少32 MB。因为我们已经预先缩小了文件系统，所以数据不会超出可用范围，不会丢失。</p><p>系统会询问你是否进行加密。因为我们完成了文件系统的缩小，所以不会有内容被抹去，可以输入<code>YES</code>继续。接下来请输入并确认加密密码。</p><p>接下来就是漫长的等待时间。笔者在一块使用QLC闪存的硬盘上加密了750 GB的数据，花费了大约3小时2分钟。</p><h3 id="打开加密分区并扩展文件系统">打开加密分区并扩展文件系统</h3><p>完成加密后，应尝试解密分区。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cryptsetup open /dev/nvme0n1p8 crypt_data</span><br></pre></td></tr></table></figure><p>输入密码后，分区将被解密并映射到<code>/dev/mapper/crypt_data</code>。若一切正常，我们可以扩大文件系统以恢复剩余的空间。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">resize2fs /dev/mapper/crypt_data</span><br></pre></td></tr></table></figure><h3 id="挂载检查数据完整性">挂载检查数据完整性</h3><p>接下来，挂载分区并检查数据是否完好无损。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mount /dev/mapper/crypt_data /mnt</span><br><span class="line"><span class="built_in">ls</span> /mnt</span><br></pre></td></tr></table></figure><p>完成检查后，先不要退出Live环境，接下来我们将进行必要的配置以确保系统能够正常启动。</p><h2 id="配置系统">配置系统</h2><p>为了使系统能够在启动时解密LUKS分区，我们需要在初始化内存盘中包含系统解密的支持。首先挂载<code>/boot</code>分区，并切换到已安装的系统环境中。</p><h3 id="挂载-boot并进入chroot环境">挂载<code>/boot</code>并进入chroot环境</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mount /dev/nvme0n1p6 /mnt/boot</span><br><span class="line">arch-chroot /mnt</span><br></pre></td></tr></table></figure><p>为了使用FIDO2安全密钥进行解密，我们需要使用<code>sd-encrypt</code>钩子，而不是传统的<code>encrypt</code>钩子，即添加<code>sd-encrypt</code>钩子到<code>/etc/mkinitcpio.conf</code>的<code>HOOKS</code>数组中。</p><h3 id="更新mkinitcpio钩子">更新mkinitcpio钩子</h3><p>打开<code>/etc/mkinitcpio.conf</code>文件，找到<code>HOOKS</code>行，将原有的<code>udev</code>替换为<code>systemd</code>，再将<code>sd-encrypt</code>添加到<code>filesystems</code>之前的位置，类似下面：</p><figure class="highlight bash"><figcaption><span>/etc/mkinitcpio.conf</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">HOOKS=(base systemd autodetect microcode modconf kms keyboard keymap consolefont block sd-encrypt resume filesystems fsck)</span><br></pre></td></tr></table></figure><div class="panel panel-info">    <div class="panel-title"><i class="fa fa-info"></i>提示</div>    <div class="panel-body">        <p>为了在输入口令时启动小键盘数字锁定，可以安装<a href="https://aur.archlinux.org/packages/mkinitcpio-sd-numlock"><code>mkinitcpio-sd-numlock</code></a><sup>AUR</sup>包，并将<code>sd-numlock</code>钩子添加到<code>sd-encrypt</code>之前。</p>    </div>    </div><p>保存并退出后，重新生成初始化内存盘：</p><h3 id="重新生成initramfs">重新生成initramfs</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkinitcpio -P</span><br></pre></td></tr></table></figure><p>接下来，我们要配置分区的自动挂载。请注意，因为我们加密的是根分区，所以<strong>不应</strong>在<code>/etc/crypttab</code>中配置，而是要更新GRUB配置。编辑<code>/etc/default/grub</code>文件：</p><h3 id="配置GRUB内核参数">配置GRUB内核参数</h3><p>编辑<code>/etc/default/grub</code>文件，找到<code>GRUB_CMDLINE_LINUX</code>行，添加<code>rd.luks.name=</code>参数，指定加密分区的UUID和映射名称。可以使用<code>blkid</code>命令获取分区的UUID。</p><p>为了方便起见，可以在vim中使用<code>:r !blkid /dev/nvme0n1p8</code>命令来把命令输出插入到文件中，再把光标移到合适的位置，用<code>36x</code>和<code>p</code>命令剪切和粘贴UUID。完成后记得删除插入的行。</p><p>增加内核参数，将LUKS分区映射到<code>/dev/mapper/root</code>，并设为根分区。记得把UUID替换为实际的内容，如下所示：</p><figure class="highlight ini"><figcaption><span>/etc/default/grub</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">GRUB_CMDLINE_LINUX</span>=<span class="string">&quot;... rd.luks.name=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx=root root=/dev/mapper/root ...&quot;</span></span><br></pre></td></tr></table></figure><p>保存并退出。</p><h3 id="更新fstab指向映射设备">更新fstab指向映射设备</h3><p>需要进一步更新<code>/etc/fstab</code>文件，确保根分区指向解密后的映射设备。应将原有的根分区行中的UUID替换为<code>/dev/mapper/root</code>，例如：</p><figure class="highlight bash"><figcaption><span>/etc/fstab</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/dev/mapper/root        /               ext4            rw,relatime     0 1</span><br></pre></td></tr></table></figure><h3 id="生成GRUB配置并重启">生成GRUB配置并重启</h3><p>重新生成GRUB配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grub-mkconfig -o /boot/grub/grub.cfg</span><br></pre></td></tr></table></figure><p>完成后，退出chroot环境并重启系统：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">exit</span></span><br><span class="line">umount -R /mnt</span><br><span class="line">reboot</span><br></pre></td></tr></table></figure><p>在系统启动时，应该会提示输入LUKS加密的密码。输入正确的密码后，系统将继续启动并挂载根分区。</p><h2 id="进阶配置">进阶配置</h2><p>完成加密后，就可以在线使用LUKS分区并进行管理操作了。</p><h3 id="更新加密口令">更新加密口令</h3><p>要更新LUKS分区的密码，我们应先添加新密码，再删除旧密码。可以使用以下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> cryptsetup luksAddKey /dev/nvme0n1p8</span><br><span class="line"><span class="comment"># 输入新密码</span></span><br><span class="line"><span class="built_in">sudo</span> cryptsetup luksRemoveKey /dev/nvme0n1p8</span><br><span class="line"><span class="comment"># 输入旧密码</span></span><br></pre></td></tr></table></figure><h3 id="注册FIDO2安全密钥">注册FIDO2安全密钥</h3><p>要使用FIDO2安全密钥进行解密，可以使用以下命令将硬件密钥添加到LUKS分区：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> systemd-cryptenroll --fido2-device=auto /dev/nvme0n1p8</span><br></pre></td></tr></table></figure><p>这样，我们就完成了LUKS全盘加密的配置。</p><p>至于TPM2.0自动解密，由于涉及到安全启动的配置，笔者因使用NVIDIA硬件难以配置安全启动，故无法测试该功能。</p><h3 id="开启TRIM支持">开启TRIM支持</h3><p>默认情况下，LUKS会阻止TRIM命令传递到底层存储设备，这是为了安全考虑（<a href="https://wiki.archlinuxcn.org/wiki/Dm-crypt/%E7%89%B9%E6%AE%8A%E5%BA%94%E7%94%A8#%E5%9B%BA%E6%80%81%E7%A1%AC%E7%9B%98%E7%9A%84Discard/TRIM%E6%94%AF%E6%8C%81">dm-crypt/特殊应用 § 固态硬盘的Discard/TRIM支持 — Arch Linux 中文维基</a>）。</p><p>如果使用的是SSD，开启TRIM支持可以提升性能和延长寿命，还有利于保护对LUKS头的修改。执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> cryptsetup --allow-discards --persistent refresh root</span><br></pre></td></tr></table></figure><p>请记得启用<code>fstrim.timer</code> systemd服务，以在后台定期运行TRIM操作。</p><h3 id="配置交换分区">配置交换分区</h3><p>在使用LUKS时，需要搭配加密交换分区以保护交换数据。此处演示如何将已有的交换分区加密。</p><div class="alert alert-info">  <div class="icon"><i class="fa fa-info"></i></div>  <div class="text">  <p>您可参阅<a href="https://wiki.archlinuxcn.org/wiki/Dm-crypt/%E4%BA%A4%E6%8D%A2%E5%88%86%E5%8C%BA%E5%8A%A0%E5%AF%86#%E9%9C%80%E8%A6%81%E4%BC%91%E7%9C%A0%E6%94%AF%E6%8C%81">dm-crypt/交换分区加密 § 需要休眠支持 — Arch Linux 中文维基</a>。</p>  </div>  </div><h4 id="创建加密交换分区">创建加密交换分区</h4><p>首先，卸载已有的交换分区：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> swapoff /dev/nvme0n1p7</span><br></pre></td></tr></table></figure><p>然后，清空并使用LUKS加密交换分区：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> cryptsetup luksFormat --label=swap /dev/nvme0n1p7</span><br></pre></td></tr></table></figure><p>打开该容器，并映射到/dev/mapper/swap：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> cryptsetup open /dev/disk/by-label/swap swap</span><br></pre></td></tr></table></figure><p>在映射设备上创建swap文件系统：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> mkswap /dev/mapper/swap</span><br></pre></td></tr></table></figure><p>这样我们就完成了加密交换分区的创建。</p><h4 id="配置系统使用加密交换分区">配置系统使用加密交换分区</h4><p>编辑<code>/etc/fstab</code>文件，将映射设备添加为交换分区：</p><figure class="highlight bash"><figcaption><span>/etc/fstab</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/dev/mapper/swap        none            swap            defaults        0 0</span><br></pre></td></tr></table></figure><p>最后，编辑<code>/etc/default/grub</code>文件，增加一组<code>rd.luks.name=</code>参数，并更改交换分区的<code>resume</code>参数。加密分区的UUID可以通过<code>blkid /dev/nvme0n1p7</code>命令获取。</p><p>编辑后的参数类似：</p><figure class="highlight ini"><figcaption><span>/etc/default/grub</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">GRUB_CMDLINE_LINUX</span>=<span class="string">&quot;... rd.luks.name=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx=swap resume=/dev/mapper/swap ...&quot;</span></span><br></pre></td></tr></table></figure><p>重新生成GRUB配置：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> grub-mkconfig -o /boot/grub/grub.cfg</span><br></pre></td></tr></table></figure><p>这样就完成了加密交换分区的配置。</p><p>接下来可以为交换分区更改验证方式，例如添加TPM2.0自动解密，方法与根分区类似。</p><h2 id="未雨绸缪">未雨绸缪</h2><p>建议创建一个恢复密钥，以便在忘记密码时使用。此外，为了防止加密头信息损坏导致数据无法访问，建议备份LUKS加密头信息。</p><h3 id="创建恢复密钥">创建恢复密钥</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> systemd-cryptenroll --recovery-key /dev/nvme0n1p8</span><br></pre></td></tr></table></figure><p>请把恢复密钥妥善保管在安全的地方。</p><h3 id="备份加密头信息">备份加密头信息</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> cryptsetup luksHeaderBackup /dev/nvme0n1p8 --header-backup-file luks_header_backup.img</span><br></pre></td></tr></table></figure><h2 id="结语">结语</h2><blockquote><p>数据无价，谨慎操作。</p></blockquote><p>LUKS全盘加密为Linux用户提供了强大的数据保护手段，但在实施过程中务必小心谨慎，确保数据安全。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;在日常使用Linux系统时，大家总会遇到需要保护数据安全的场景。LUKS（Linux Unified Key Setup）作为Linux系统中常用的全盘加密解决方案，能够有效地保护磁盘上的数据。本文将详细介绍如何在Linux系统中使用LUKS进行全盘加密。&lt;/p&gt;
&lt;p&gt;L</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Linux" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/Linux/"/>
    
    
    <category term="Linux实战" scheme="https://blog.khyan.top/tags/Linux%E5%AE%9E%E6%88%98/"/>
    
    <category term="安全" scheme="https://blog.khyan.top/tags/%E5%AE%89%E5%85%A8/"/>
    
    <category term="加密" scheme="https://blog.khyan.top/tags/%E5%8A%A0%E5%AF%86/"/>
    
  </entry>
  
  <entry>
    <title>警惕地面推广，请收好这份指南</title>
    <link href="https://blog.khyan.top/2025/11/fuck-you/"/>
    <id>https://blog.khyan.top/2025/11/fuck-you/</id>
    <published>2025-11-29T04:10:36.000Z</published>
    <updated>2026-01-25T10:19:17.224Z</updated>
    
    <content type="html"><![CDATA[<ol><li>不要理睬在路边和你搭话的人。</li><li>如果已经理睬了，不要相信他说的自己的动人故事。</li><li>如果相信了他说的动人故事，也不要拿他给你的东西，不然一会儿你还不回去。</li><li>如果拿了他给你的东西，也不要买他的东西，尽量尽快脱身。</li><li>如果实在傻而想买他的东西，要明确买的是什么东西。</li><li>即使明确了买的是什么东西，也要明确单价和总价。不要相信他的报价，无论是市场价还是所谓的优惠价，无论是用什么介质展示的。</li><li>即使明确了价格，也不要用出示付款码的方式付款。微信现在支持用手机扫描他人的付款码来转走任意金额。</li><li>如果可能，录音或拍摄视频。</li><li>如果在校园内看到地推人员，请报告给保卫处。</li><li><strong>在你给他钱之前，你随时都可以要求离开。</strong></li></ol><h2 id="延伸阅读">延伸阅读</h2><p><a href="https://www.zhihu.com/question/292201734/answer/915351752">优露清的即擦净真的有推销员说的那么好吗？ - 生知安行的回答 - 知乎</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;ol&gt;
&lt;li&gt;不要理睬在路边和你搭话的人。&lt;/li&gt;
&lt;li&gt;如果已经理睬了，不要相信他说的自己的动人故事。&lt;/li&gt;
&lt;li&gt;如果相信了他说的动人故事，也不要拿他给你的东西，不然一会儿你还不回去。&lt;/li&gt;
&lt;li&gt;如果拿了他给你的东西，也不要买他的东西，尽量尽快脱身。&lt;/</summary>
      
    
    
    
    <category term="生活" scheme="https://blog.khyan.top/categories/%E7%94%9F%E6%B4%BB/"/>
    
    
    <category term="地面推广" scheme="https://blog.khyan.top/tags/%E5%9C%B0%E9%9D%A2%E6%8E%A8%E5%B9%BF/"/>
    
    <category term="诈骗" scheme="https://blog.khyan.top/tags/%E8%AF%88%E9%AA%97/"/>
    
    <category term="优露清" scheme="https://blog.khyan.top/tags/%E4%BC%98%E9%9C%B2%E6%B8%85/"/>
    
  </entry>
  
  <entry>
    <title>在你的Arch Linux笔记本上畅快使用NVIDIA显卡，包括Vulkan</title>
    <link href="https://blog.khyan.top/2025/11/nvidia-on-arch-laptop-vulkan/"/>
    <id>https://blog.khyan.top/2025/11/nvidia-on-arch-laptop-vulkan/</id>
    <published>2025-11-23T04:39:56.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<p>上回（《<a href="/2025/07/nvidia-on-arch-laptop/" title="在你的 Arch Linux 笔记本上畅快使用 NVIDIA 显卡">在你的 Arch Linux 笔记本上畅快使用 NVIDIA 显卡</a>》）说到如何在Arch Linux上配置NVIDIA和Intel双显卡，但还留有一个问题未解决，就是Vulkan应用会唤醒独显，导致启动和退出一些应用时因需要唤醒独显而卡顿。</p><p>而且，部分GTK4应用，如Ptyxis，即使使用了GL作为渲染后端，也会调用Vulkan而唤醒独显。</p><p>本文将介绍如何解决这个问题。</p><h2 id="禁止Vulkan使用独显">禁止Vulkan使用独显</h2><p>设置环境变量 <code>VK_LOADER_DRIVERS_DISABLE=nvidia_icd.json</code>，可以禁止Vulkan加载NVIDIA的驱动，从而避免唤醒独显。</p><p>把它加入 <code>/etc/environment</code> 文件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;VK_LOADER_DRIVERS_DISABLE=nvidia_icd.json&#x27;</span> | <span class="built_in">sudo</span> <span class="built_in">tee</span> -a /etc/environment</span><br></pre></td></tr></table></figure><h2 id="让prime-run能调用独显">让<code>prime-run</code>能调用独显</h2><p><code>nvidia-prime</code>包提供的原版<code>/usr/bin/prime-run</code>脚本不会取消设置<code>VK_LOADER_DRIVERS_DISABLE</code>：</p><p><code>/usr/bin/prime-run</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line">__NV_PRIME_RENDER_OFFLOAD=1 __VK_LAYER_NV_optimus=NVIDIA_only __GLX_VENDOR_LIBRARY_NAME=nvidia <span class="string">&quot;<span class="variable">$@</span>&quot;</span></span><br></pre></td></tr></table></figure><p>我们需要自定义一个<code>prime-run</code>脚本。通过创建<code>/usr/local/bin/prime-run</code>文件，我们可以覆盖掉原版的<code>prime-run</code>脚本。脚本如下，也可在<a href="https://github.com/Kimiblock/moeOS.config/blob/master/usr/share/moeOS-Docs/bin/prime-run">https://github.com/Kimiblock/moeOS.config/blob/master/usr/share/moeOS-Docs/bin/prime-run</a>下载：</p><p><code>/usr/local/bin/prime-run</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> [ -d /proc/driver/nvidia/gpus ]; <span class="keyword">then</span></span><br><span class="line"><span class="built_in">env</span> \</span><br><span class="line">-u VK_LOADER_DRIVERS_DISABLE \</span><br><span class="line">__NV_PRIME_RENDER_OFFLOAD=1 \</span><br><span class="line">__VK_LAYER_NV_optimus=NVIDIA_only \</span><br><span class="line">__GLX_VENDOR_LIBRARY_NAME=nvidia \</span><br><span class="line">VK_LOADER_DRIVERS_SELECT=nvidia_icd.json \</span><br><span class="line">__EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/10_nvidia.json \</span><br><span class="line"><span class="string">&quot;<span class="variable">$@</span>&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="built_in">env</span> \</span><br><span class="line">-u VK_LOADER_DRIVERS_DISABLE \</span><br><span class="line">DRI_PRIME=1 \</span><br><span class="line"><span class="string">&quot;<span class="variable">$@</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br></pre></td></tr></table></figure><p>记得设置执行位。</p><p>这样，当你需要使用独显运行Vulkan应用时，只需使用<code>prime-run &lt;command&gt;</code>即可。</p><p>美中不足的是，<code>switcheroo-control</code>集成的「使用独立显卡启动」选项并不是直接调用<code>prime-run</code>，所以Vulkan应用不能通过GNOME的右键菜单选项来方便地使用独显运行了。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;上回（《&lt;a href=&quot;/2025/07/nvidia-on-arch-laptop/&quot; title=&quot;在你的 Arch Linux 笔记本上畅快使用 NVIDIA 显卡&quot;&gt;在你的 Arch Linux 笔记本上畅快使用 NVIDIA 显卡&lt;/a&gt;》）说到如何在Arch </summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Linux" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/Linux/"/>
    
    
    <category term="Linux实战" scheme="https://blog.khyan.top/tags/Linux%E5%AE%9E%E6%88%98/"/>
    
    <category term="Arch Linux" scheme="https://blog.khyan.top/tags/Arch-Linux/"/>
    
    <category term="NVIDIA" scheme="https://blog.khyan.top/tags/NVIDIA/"/>
    
  </entry>
  
  <entry>
    <title>分析一种利用腾讯文档传播的新型诈骗</title>
    <link href="https://blog.khyan.top/2025/11/scam-via-qq-docs/"/>
    <id>https://blog.khyan.top/2025/11/scam-via-qq-docs/</id>
    <published>2025-11-19T03:08:15.000Z</published>
    <updated>2026-01-25T10:19:17.226Z</updated>
    
    <content type="html"><![CDATA[<p>近日我频繁收到通过QQ私信分享的腾讯文档链接，不法分子利用<strong>马化腾的妈</strong>和<strong>腾讯的客服</strong>的<strong>存在状态必定相同</strong>的特点，以腾讯文档为跳板进行钓鱼。遇到这种情况时，大家务必提高警惕。本文将粗浅地分析一下这种诈骗的技术手段。</p><p><a href="#%E9%98%B2%E8%8C%83%E5%BB%BA%E8%AE%AE">快速跳转到防范建议</a></p><h2 id="诈骗文档的传播">诈骗文档的传播</h2><p>诈骗分子首先通过盗号获取QQ账号，以该账号的名义创建腾讯文档，并通过群内临时会话发送文档链接。由于是同学、熟人发送，受害者更容易信任并点击链接：</p><p><img src="/assets/pic/scam-via-qq-docs/4def7a9d7729b4066190a8877528e0e03ccf2b78ca1ff8b6a762769ce8512e92.webp" alt="QQ私信"></p><p>点击链接后，受害者会看到一个腾讯文档，所述内容贴近真实通知的情境，而且通常包含一些诱导性的信息，如「收到邮件的同学请立即打开查询登记」等：</p><p><img src="/assets/pic/scam-via-qq-docs/aaec3c20549999702b4776c22020e2d2fa1492a97f401e0c849cabc53b48774a.webp" alt="诈骗文档截图"></p><p>文档中故意插入模糊的图片，并故意写入相关提示，诱导用户打开链接：</p><blockquote><p>如文件过大导致图片模糊打不开，请复制上方链接地址到手机浏览器上打开[登录个人腾讯文档信息版面自行查看认证]</p></blockquote><p>导航到文档中提供的诈骗网站后，受害者会被引导至一个伪装成正规登录页面的钓鱼网站，开始诈骗流程。</p><p><strong>从这一步开始，你不再在腾讯所控制的页面中操作，而是进入了由第三方控制的伪造页面。</strong></p><h2 id="对诈骗网站的分析">对诈骗网站的分析</h2><p>诈骗网站的设计非常粗糙，骗的就是不仔细看、觉得事情很重要哗哗哗连底裤都给出去了的笨蛋！</p><h3 id="落地页：">落地页：<code>/</code></h3><p>首先看到的是一个虚假的贴图页面，贴图都不好好贴，用的是CSS <code>background: url('./images/School.png') no-repeat center;</code>。贴图比较宽，如果你眼尖，在手机上应该也能发现画面拉伸、字体不对等问题了。</p><p>点击图片的任意位置就能看到弹窗，提示你进入登录页面：</p><p><img src="/assets/pic/scam-via-qq-docs/f18776e02d094f251cd5da8a9cc80060cb64c5b8c6e6395f55b477c08bcb2def.webp" alt="诈骗网站落地页截图"></p><p>点击确定按钮后，用户进入伪造的登录页面。</p><h3 id="登录页：-step-in">登录页：<code>/step_in/</code></h3><p><img src="/assets/pic/scam-via-qq-docs/1e79acfac8241d05fa19d13dc76294cb278db9b9c3d4e7ae5830355e19106f5d.webp" alt="诈骗网站登录页截图"></p><p>值得一提的是，这玩意儿的键盘是照着旧版iOS的键盘自己搓的，如果你在电脑上打开就会看到很惊悚的画风：</p><p><img src="/assets/pic/scam-via-qq-docs/a2ddc27459241aa06e2c79e7bab5b8971e5e6965af6d6ab7130bc47eea030d0d.webp" alt="诈骗网站登录页键盘截图"></p><p>自己搓键盘有一个好处，就是在微信、QQ里打开时，不会弹出「非腾讯官方页面」的警告。缺点么……如果你走点心，可能就发现这键盘和你手机上的不一样了。</p><p>下面的代码是登录页的核心验证逻辑：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">sameChar</span>(<span class="params">str</span>) &#123;</span><br><span class="line"><span class="keyword">var</span> result = <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">var</span> c = str.<span class="title function_">charAt</span>(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; str.<span class="property">length</span>; i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (c != str.<span class="title function_">charAt</span>(i)) &#123;</span><br><span class="line">result = <span class="literal">false</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">error</span>(<span class="params">msg</span>) &#123;</span><br><span class="line">$(<span class="string">&quot;#error_message&quot;</span>).<span class="title function_">html</span>(msg);</span><br><span class="line">$(<span class="string">&quot;#error_tips&quot;</span>).<span class="title function_">show</span>().<span class="title function_">delay</span>(<span class="number">3000</span>).<span class="title function_">hide</span>(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">var</span> err = <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Login</span>(<span class="params"></span>) &#123;</span><br><span class="line"><span class="keyword">var</span> p = $(<span class="string">&quot;#p&quot;</span>).<span class="title function_">val</span>();</span><br><span class="line"><span class="keyword">var</span> u = $(<span class="string">&quot;#u&quot;</span>).<span class="title function_">val</span>();</span><br><span class="line"><span class="keyword">if</span> (u == <span class="string">&#x27;&#x27;</span>) &#123;</span><br><span class="line"><span class="title function_">error</span>(<span class="string">&#x27;&amp;#24744;&amp;#36824;&amp;#27809;&amp;#26377;&amp;#36755;&amp;#20837;&amp;#24080;&amp;#21495;！&#x27;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (p == <span class="string">&#x27;&#x27;</span>) &#123;</span><br><span class="line"><span class="title function_">error</span>(<span class="string">&#x27;&amp;#24744;&amp;#36824;&amp;#27809;&amp;#26377;&amp;#36755;&amp;#20837;&amp;#23494;&amp;#30721;！&#x27;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (u.<span class="property">length</span> &lt; <span class="number">6</span> || u.<span class="property">length</span> &gt; <span class="number">11</span>) &#123;</span><br><span class="line"><span class="title function_">error</span>(<span class="string">&quot;&amp;#24744;&amp;#36755;&amp;#20837;&amp;#30340;&amp;#24080;&amp;#21495;&amp;#26684;&amp;#24335;&amp;#19981;&amp;#27491;&amp;#30830;&amp;#65292;&amp;#35831;&amp;#37325;&amp;#26032;&amp;#36755;&amp;#20837;。&quot;</span>);</span><br><span class="line">$(<span class="string">&quot;#u&quot;</span>).<span class="title function_">val</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (p.<span class="property">length</span> &lt; <span class="number">6</span> || p.<span class="property">length</span> &gt; <span class="number">16</span>) &#123;</span><br><span class="line"><span class="title function_">error</span>(<span class="string">&#x27;&amp;#24744;&amp;#36755;&amp;#20837;&amp;#30340;&amp;#23494;&amp;#30721;&amp;#26684;&amp;#24335;&amp;#19981;&amp;#27491;&amp;#30830;&amp;#65292;&amp;#35831;&amp;#37325;&amp;#26032;&amp;#36755;&amp;#20837;。&#x27;</span>);</span><br><span class="line">$(<span class="string">&quot;#p&quot;</span>).<span class="title function_">val</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="title function_">sameChar</span>(u)) &#123;</span><br><span class="line"><span class="title function_">error</span>(<span class="string">&quot;&amp;#24744;&amp;#36755;&amp;#20837;&amp;#30340;&amp;#24080;&amp;#21495;&amp;#26684;&amp;#24335;&amp;#19981;&amp;#27491;&amp;#30830;&amp;#65292;&amp;#35831;&amp;#37325;&amp;#26032;&amp;#36755;&amp;#20837;。&quot;</span>);</span><br><span class="line">$(<span class="string">&quot;#u&quot;</span>).<span class="title function_">val</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="title function_">sameChar</span>(p)) &#123;</span><br><span class="line"><span class="title function_">error</span>(<span class="string">&quot;&amp;#24744;&amp;#36755;&amp;#20837;&amp;#30340;&amp;#23494;&amp;#30721;&amp;#26684;&amp;#24335;&amp;#19981;&amp;#27491;&amp;#30830;&amp;#65292;&amp;#35831;&amp;#37325;&amp;#26032;&amp;#36755;&amp;#20837;。&quot;</span>);</span><br><span class="line">$(<span class="string">&quot;#p&quot;</span>).<span class="title function_">val</span>(<span class="string">&#x27;&#x27;</span>);</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">ds</span>(<span class="string">&#x27;sv&#x27;</span>, &#123;</span><br><span class="line"><span class="attr">user</span>: u,</span><br><span class="line"><span class="attr">pass</span>: p</span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">cess</span>) cess.<span class="title function_">init</span>(<span class="string">&#x27;登记&#x27;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>对用户输入的限制还挺严格，在前端就排除了乱填的那些人。通过验证后调用的<code>ds</code>函数是这样的：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">ds</span>(<span class="params">act,data</span>)&#123;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(data);</span><br><span class="line">$.<span class="title function_">get</span>(<span class="string">&#x27;../app/data.php&#x27;</span>,<span class="string">&#x27;sv=&#x27;</span>+<span class="built_in">encodeURIComponent</span>(<span class="title function_">b6</span>(<span class="title function_">b6</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(&#123;<span class="attr">act</span>:act||<span class="string">&#x27;sv&#x27;</span>,<span class="attr">data</span>:data&#125;)))),<span class="keyword">function</span>(<span class="params">d</span>)&#123;</span><br><span class="line">d = <span class="title function_">dejson</span>(d);</span><br><span class="line">&#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>输入账号密码并点击登录按钮后，数据会被双重Base64编码，并通过GET请求发送到服务端：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/app/data.php?sv=ZXlKaFkzUWlPaUp6ZGlJc0ltUmhkR0VpT25zaWRYTmxjaUk2SWpFeE5EVXhOQ0lzSW5CaGMzTWlPaUp4ZDJWeWRIbDFhVzl3SW4xOQ==</span><br></pre></td></tr></table></figure><p>解码后：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;act&quot;</span><span class="punctuation">:</span><span class="string">&quot;sv&quot;</span><span class="punctuation">,</span><span class="attr">&quot;data&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span><span class="attr">&quot;user&quot;</span><span class="punctuation">:</span><span class="string">&quot;114514&quot;</span><span class="punctuation">,</span><span class="attr">&quot;pass&quot;</span><span class="punctuation">:</span><span class="string">&quot;qwertyuiop&quot;</span><span class="punctuation">&#125;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="手机号输入页：-step-phone">手机号输入页：<code>/step_phone/</code></h3><p><img src="/assets/pic/scam-via-qq-docs/c270bba596300ad5b1f605eae9f127e819459554d105cb604e6c774ef35ba6ba.webp" alt="诈骗网站手机号输入页截图"></p><p>在这一页，网站欺骗用户需要验证，并要求输入手机号。提交手机号时，数据经过双重Base64编码通过GET请求发送到服务端：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/app/data.php?sv=ZXlKaFkzUWlPaUp6ZGlJc0ltUmhkR0VpT25zaWNHaHZibVVpT2lJeE1UUTFNVFF4T1RFNU9DSjlmUT09</span><br></pre></td></tr></table></figure><p>解码后：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;act&quot;</span><span class="punctuation">:</span><span class="string">&quot;sv&quot;</span><span class="punctuation">,</span><span class="attr">&quot;data&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span><span class="attr">&quot;phone&quot;</span><span class="punctuation">:</span><span class="string">&quot;11451419198&quot;</span><span class="punctuation">&#125;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="验证码输入页：-step-code">验证码输入页：<code>/step_code/</code></h3><p><img src="/assets/pic/scam-via-qq-docs/d6505aa1beb1e970e6e948426250998d0ed14102a45a7916bede056e4f144e59.webp" alt="诈骗网站验证码输入页截图"></p><p>这一步，网站会在后台轮询后端。总之，验证码提交后，数据依然是经过双重Base64编码通过GET请求发送到服务端：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/app/data.php?sv=ZXlKaFkzUWlPaUp6ZGlJc0ltUmhkR0VpT25zaVkyOWtaU0k2SWpFeE1UUTFNU0o5ZlE9PQ==</span><br></pre></td></tr></table></figure><p>解码后：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span><span class="attr">&quot;act&quot;</span><span class="punctuation">:</span><span class="string">&quot;sv&quot;</span><span class="punctuation">,</span><span class="attr">&quot;data&quot;</span><span class="punctuation">:</span><span class="punctuation">&#123;</span><span class="attr">&quot;code&quot;</span><span class="punctuation">:</span><span class="string">&quot;111451&quot;</span><span class="punctuation">&#125;</span><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="完成页：-step-done">完成页：<code>/step_done/</code></h3><p>恭喜，你被骗了！🎉</p><p><img src="/assets/pic/scam-via-qq-docs/51785e1dec0c1ef3a79c26bc82214949682b8e48a0a9591fa0f9b9e84869288b.webp" alt="诈骗网站完成页截图"></p><p>上面这个腾讯的图标是会转的，其实就是一张GIF，让你以为页面在加载。尽管网站提示「请勿操作！文档加载中…」，但是你永远也看不到文档了；一同变得永远也看不到的还有你的QQ，它马上就要变成下一个用于钓鱼的账户了……</p><h2 id="多提一句">多提一句</h2><p>如果你成功找回了QQ号，记得看一下自己是不是被学校的很多群踢掉了。记得加回来哦！</p><h2 id="防范建议">防范建议</h2><ol><li><strong>提高警惕</strong>：不要轻易点击陌生人发送的链接，哪怕是腾讯文档的连接。腾讯他妈的哪有客服，就算有人举报，我看一周之内都未必能下掉。问我咋知道的？问就是我真的还收到过一次……<br><img src="/assets/pic/scam-via-qq-docs/236821bf189c217ddd36660c153de0ea1e1ca9f32f6a55b2d2a5e41e54f6e856.webp" alt="钓鱼邮件截图"></li><li><strong>验证来源</strong>：学校发的通知肯定是学校的域名，收集表也不可能私聊发给你，登录QQ的时候肯定也是在<code>qq.com</code>域名下。</li><li><strong>换个花哨的键盘皮肤和手机字体</strong>：在钓鱼网站模仿你的操作系统元素（如键盘）时，你能够及时发现问题。同时，你也可以及时发现使用简单的贴图完成的伪装。需要注意的是，这种方法在对界面和字体不太敏感的人身上可能防范力度不大，延伸阅读中的文章谈到了这个问题，我节选一段小故事放在这里：<blockquote><p>Back in 2007 as the IE team was launching Extended Validation (EV) certificates, Microsoft Research was publishing a paper calling into question their effectiveness. A Fortune 500 financial company came to visit the IE team as they evaluated whether they wanted to go into the EV Certificate Authority business. They were excited about the prospect (as were we, since they were a well-known-name with natural synergies) but they noted that they thought the picture-in-picture problem was a fatal flaw.</p><p>I was defensive– “It’s interesting,” I conceded, “but I don’t think it’s a very plausible attack.“</p><p>They retorted “Well, we passed this screenshot around our entire information security department, and nobody could tell it’s a picture-in-picture attack. Can you?” they slid an 8.5×11 color print across the table.</p><p>“Of course!” I said, immediately relieved. I quickly grew gravely depressed as I realized the implications of the fact that they couldn’t tell the difference.</p><p>“How?” they demanded.</p><p>“It’s a picture of an IE7 browser running on Windows Vista in the transparent Aero Glass theme with a page containing a JPEG of an IE7 browser running on Windows XP in the Luna-aka-Fisher Price theme?” I pointed out.</p><p>“Oh. Huh.” they remarked as they squinted and reexamined the picture.</p><p>My thoughts of using browser personalization as an effective mitigation died that day.</p></blockquote></li></ol><h2 id="延伸阅读">延伸阅读</h2><ul><li><a href="https://textslashplain.com/2017/01/14/the-line-of-death/">The Line of Death</a></li></ul><h2 id="外部链接">外部链接</h2><ul><li><a href="https://web.archive.org/web/20251119014759/https://ed19zd.mobper.com/">本例中的诈骗网站在Wayback Machine的快照</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;近日我频繁收到通过QQ私信分享的腾讯文档链接，不法分子利用&lt;strong&gt;马化腾的妈&lt;/strong&gt;和&lt;strong&gt;腾讯的客服&lt;/strong&gt;的&lt;strong&gt;存在状态必定相同&lt;/strong&gt;的特点，以腾讯文档为跳板进行钓鱼。遇到这种情况时，大家务必提高警惕。本文将</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="安全" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/%E5%AE%89%E5%85%A8/"/>
    
    
    <category term="诈骗" scheme="https://blog.khyan.top/tags/%E8%AF%88%E9%AA%97/"/>
    
    <category term="Web" scheme="https://blog.khyan.top/tags/Web/"/>
    
    <category term="QQ" scheme="https://blog.khyan.top/tags/QQ/"/>
    
  </entry>
  
  <entry>
    <title>为什么 Unicode 有「私用区字符不会在无此字体其他电脑上显示」的规定？</title>
    <link href="https://blog.khyan.top/2025/11/unicode-pua/"/>
    <id>https://blog.khyan.top/2025/11/unicode-pua/</id>
    <published>2025-11-11T13:12:00.000Z</published>
    <updated>2026-01-25T10:19:17.226Z</updated>
    
    <content type="html"><![CDATA[<p>题目描述：</p><blockquote><p>也就是说，例如私用区的生造汉字、符号等，仅自己电脑能显示，其他电脑如果不装载此私用区就无法显示，是技术不足，还是另有隐情?</p></blockquote><p>原文链接：<a href="https://www.zhihu.com/question/12008172105/answer/1971686708467728921">https://www.zhihu.com/question/12008172105/answer/1971686708467728921</a></p><hr><p>从题主的问法可以看出来，题主对 Unicode 只是略有了解。我企图通过这个回答，来简述一些计算机字符渲染原理的基础知识。</p><p>要回答这个问题，首先要明确一点，就是「私用区字符不会在无此字体其他电脑上显示」这个问题，Unicode 不背锅。</p><p>要理解这一点，先要理解电脑是怎么渲染字符的。</p><h2 id="电脑是怎么渲染字符的">电脑是怎么渲染字符的</h2><h3 id="存储：Unicode">存储：Unicode</h3><p>高中信息技术课老师一定强调过，在计算机内部，所有数据都是以二进制存储的，所以你在知乎上看到的每个字，在计算机内部都是 0 和 1 的排列。</p><p>例如，题主昵称中的「稻」在以 UTF-8 编码的情况下就表示为 1110 <strong>0111</strong> 10<strong>10 1000</strong> 10<strong>11 1011</strong>。8 位二进制是 1 个字节，「稻」字占用了 3 个字节。</p><p>实际上，UTF-8 编码中有些部分是填充格式用的，计算机读到这种格式就知道这是一个 Unicode 字符。这里不展开讲，总之有用的部分我已经加粗标出，它是 0111 1010 0011 1011。</p><p>因为 4 位二进制恰好是 1 位 16 进制，人们常常也用 16 进制来表示二进制内容。再加上前缀「U+」表明这是一个 Unicode 码位，就是通行的表示 Unicode 码位的方式：U+7A3B。</p><h3 id="显示：字体渲染引擎">显示：字体渲染引擎</h3><p>电脑的操作系统得到 7A3B 这个码位之后，并不能直接把码位给你，因为你并不认识这个码位对应的是什么字，更别说目测二进制了。</p><p>操作系统中的字体渲染引擎会在用户指定的或系统安装的所有字体中找到提供这个码位的合适的字体，从中提取出字形数据。字形数据储存了一个字符「应该长什么样」，如果字体中有这个字形，字体渲染引擎会把它渲染在屏幕上，你才能看到对应的字。</p><hr><p>总之，Unicode 只规定码位应当是什么，例如 U+7A3B 是「稻」字；而字体文件才负责规定「稻」字长什么样。对于私用区字符，因为 Unicode 里面根本没有规定具体的实现，自然就是各个字体随意发挥。事实上，如果有哪款不符合规范的字体把「稻」做成别的字形，或者根本不做「稻」字，题主的昵称就会得到私用区字符的待遇。</p><h2 id="理解私用区">理解私用区</h2><blockquote><p>在 Unicode 中，私人使用区（英语：Private Use Areas，PUA）指其解释未在 Unicode 标准中指定，而是由合作用户之间的私人协议决定其用途的一系列码位。目前定义了三个私人使用区：一个在基本多语言平面（U+E000-U+F8FF）中，另外两个几乎包含了整个第 15 和第 16 平面（分别为 U+F0000-U+FFFFD，U+100000-U+10FFFD）。</p><p>（摘自 <a href="https://zh.wikipedia.org/wiki/%E7%A7%81%E4%BA%BA%E4%BD%BF%E7%94%A8%E5%8C%BA">https://zh.wikipedia.org/wiki/私人使用区</a>）</p></blockquote><p>总之，私用区就是一块预留的区域，字体制作者可以按喜好去使用，在不同的字体中自由分配，Unicode 也不管辖它具体是什么用途。</p><p>根据我推测的题主的喜好，我做如下不太恰当的比喻：如果把每套字体当作不同玩家的原神世界，各国（平面）的地图（字符集）已经被米哈游（Unicode 协会）安排好了用处，但留出了尘歌壶（私用区）。而每个玩家可以自由安排尘歌壶世界，并不受到米哈游的制约。因为每个玩家的尘歌壶世界（不同字体的私用区）各有千秋，所以尘歌壶中每个坐标（码位）放置的东西也不同。当不同的玩家在各自不同的尘歌壶世界中位于同一坐标（不同字体调用同一码位），所看到的东西（字符）也不能保证是一样的。</p><p>考虑到私用区很大，而且和字体绑定，所以它被使用得不多，一般字体中私用区码位的内容都是空的，才有了题主所见的「私用区字符不会在无此字体其他电脑上显示」这一情况。如果恰好两款字体都使用的私用区的同一码位，也是被允许的情况，此时用户就会看到张冠李戴的效果了。</p><p>这是 Unicode 刻意留出的自由，允许组织在不申请官方编号的前提下进行内部编码。而代价就是私用区字符的字形必须随字体文件一起分发和安装，否则就没法正常显示了。</p><h2 id="私用区的应用">私用区的应用</h2><p>使用私用区字符大都是为了在不干扰标准编码的前提下，插入自定义符号或图形。</p><p>因为不知道题主是在哪里看到这句话的，我不能针对性地解释，所以我在下面举出其他例子，供后来者参考。</p><h3 id="Apple-标志">Apple 标志</h3><p>在 Apple 设备上，「」（U+F8FF）会显示成苹果标志。如果 Apple 产品的用户在文档中输入这个字符，并发送给一个没有安装 Apple 系统的用户时，接收方电脑的字体文件没有 U+F8FF 这个码位，就无法显示，在一些较老的设备上似乎会显示为藏文字符。</p><h3 id="Fira-Code-字体">Fira Code 字体</h3><p>在广受欢迎的编程字体 Fira Code 中，就有私用区字符：</p><blockquote><p>Fira Code is the first programming font to offer dedicated glyphs to render progress bars:</p><p>Fira Code 是首款提供专用字形来渲染进度条的编程字体：</p><p><img src="https://github.com/tonsky/FiraCode/raw/master/extras/progress.png" alt="Fira Code progress bar"></p><p>In action:</p><p><img src="https://github.com/tonsky/FiraCode/raw/master/extras/progress.gif" alt="Fira Code progress bar animated"></p><p>We hope more programming fonts will adopt this convention and ship their own versions.</p><p>我们希望更多编程字体能够采用这种规范，并发布自己的版本。</p><p>（摘自 <a href="https://github.com/tonsky/FiraCode">https://github.com/tonsky/FiraCode</a>）</p></blockquote><p>可以看到，Fira Code 漂亮的进度条就是通过在私用区的 U+EE00-U+EE0B 码位放置符号来达成的。</p><h3 id="Twitter-的-Chirp-字体">Twitter 的 Chirp 字体</h3><p>又如，字符「」（U+EA00）位于私用区，在 Twitter 上会显示成漂亮的推特小鸟标志，这是因为它被包括在 Twitter 官方客户端所使用的 Chirp 字体中。如果通过一些不带 Chirp 字体的第三方客户端去查看，就看不到了，这是因为系统默认字体往往在 U+EA00 处没有对应的字形。顺便一提，Chirp 字体可以支持显示 Apple 标志，这也是私用区字符与字体相关的好处，安装了相应的字体就能显示。</p><hr><h2 id="题外话">题外话</h2><p>知乎推给我这个题，我其实是不想答的，因为显然其他答主能回答得更好，我算是鲁班门前弄大斧。但我翻了一下回答，看到多数回答都在阴阳怪气，终究还是忍不住了。浅答一下，也算整理整理自己关于 Unicode 的知识，还请其他答主海涵，友好交流，有问题请指出。</p><p>从本题的其他回答也能看出，知乎的环境正在变得越来越差。这其实是很好的一道题，其他回答不懂装懂还乱比喻，不知道在阴阳怪气什么。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;题目描述：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;也就是说，例如私用区的生造汉字、符号等，仅自己电脑能显示，其他电脑如果不装载此私用区就无法显示，是技术不足，还是另有隐情?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;原文链接：&lt;a href=&quot;https://www.zh</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="知乎回答" scheme="https://blog.khyan.top/categories/%E7%9F%A5%E4%B9%8E%E5%9B%9E%E7%AD%94/"/>
    
    
    <category term="Unicode" scheme="https://blog.khyan.top/tags/Unicode/"/>
    
    <category term="字体" scheme="https://blog.khyan.top/tags/%E5%AD%97%E4%BD%93/"/>
    
  </entry>
  
  <entry>
    <title>在华为手表上听音乐吧——FLAC 到 MP3 带标签转换教程</title>
    <link href="https://blog.khyan.top/2025/09/i-hate-id3/"/>
    <id>https://blog.khyan.top/2025/09/i-hate-id3/</id>
    <published>2025-09-17T07:27:00.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<p>华为手表支持通过手机同步音乐文件进行离线播放，而且支持 FLAC 格式。但是，你真的想在手表那么小的存储空间里放大量的 FLAC 文件吗……本文将教你如何将 FLAC 文件转换为 MP3，并保留原有的标签信息供「华为运动健康」App 使用。</p><blockquote><p>FFmpeg 本身是支持转换标签的（利用 <code>-map_metadata</code> 选项，可自行问 LLM 了解），但它的标签支持并不是很好，会丢掉一些信息，比如封面图和歌词。给手表用是够了，但是如果要用于其他场景就不太合适了。同时，本文的主要目的是教学和记录，所以接下来会通过一个 Python 脚本来实现更完整的标签复制。</p></blockquote><h2 id="转换音乐">转换音乐</h2><p>FFmpeg 走起。保存下面的脚本为 <code>flac2mp3.sh</code>，然后通过命令行运行它，传入源文件夹和目标文件夹作为参数即可。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">SOURCE_DIR=<span class="string">&quot;<span class="variable">$1</span>&quot;</span></span><br><span class="line">DEST_DIR=<span class="string">&quot;<span class="variable">$2</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> -p <span class="string">&quot;<span class="variable">$DEST_DIR</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> file <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$SOURCE_DIR</span>&quot;</span>/*.flac; <span class="keyword">do</span></span><br><span class="line">filename=$(<span class="built_in">basename</span> -- <span class="string">&quot;<span class="variable">$file</span>&quot;</span> .flac)</span><br><span class="line">output_file=<span class="string">&quot;<span class="variable">$DEST_DIR</span>/<span class="variable">$filename</span>.mp3&quot;</span></span><br><span class="line"><span class="keyword">if</span> [ -f <span class="string">&quot;<span class="variable">$output_file</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;跳过转换: <span class="variable">$file</span> -&gt; <span class="variable">$output_file</span>（文件已存在）&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">ffmpeg -i <span class="string">&quot;<span class="variable">$file</span>&quot;</span> -b:a 320k <span class="string">&quot;<span class="variable">$output_file</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;转换完成: <span class="variable">$file</span> -&gt; <span class="variable">$output_file</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;所有文件转换完成！&quot;</span></span><br></pre></td></tr></table></figure><p>上面的脚本会将指定文件夹中的所有 FLAC 文件转换为 320 kbps 的 MP3 文件。</p><h2 id="复制标签">复制标签</h2><p>接下来，保存下面的 Python 脚本为 <code>vorbis2id3.py</code>，并确保你已经安装了 <code>mutagen</code> Python 库。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> mutagen.flac <span class="keyword">import</span> FLAC</span><br><span class="line"><span class="keyword">from</span> mutagen.id3 <span class="keyword">import</span> ID3, TIT2, TPE1, TALB, TPE2, TCOM, TDRC, TCON, TRCK, TPOS, COMM, USLT, APIC</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">copy_vorbis_to_id3</span>(<span class="params">flac_path, mp3_path</span>):</span><br><span class="line">flac_tags = FLAC(flac_path)</span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line">audio = ID3(mp3_path)</span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line">audio = ID3()</span><br><span class="line">audio.delete()</span><br><span class="line">tag_map = &#123;</span><br><span class="line"><span class="string">&#x27;title&#x27;</span>: TIT2,</span><br><span class="line"><span class="string">&#x27;artist&#x27;</span>: TPE1,</span><br><span class="line"><span class="string">&#x27;album&#x27;</span>: TALB,</span><br><span class="line"><span class="string">&#x27;albumartist&#x27;</span>: TPE2,</span><br><span class="line"><span class="string">&#x27;composer&#x27;</span>: TCOM,</span><br><span class="line"><span class="string">&#x27;date&#x27;</span>: TDRC,</span><br><span class="line"><span class="string">&#x27;genre&#x27;</span>: TCON,</span><br><span class="line"><span class="string">&#x27;tracknumber&#x27;</span>: TRCK,</span><br><span class="line"><span class="string">&#x27;discnumber&#x27;</span>: TPOS,</span><br><span class="line"><span class="string">&#x27;comment&#x27;</span>: COMM,</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> key, frame_class <span class="keyword">in</span> tag_map.items():</span><br><span class="line"><span class="keyword">if</span> key <span class="keyword">in</span> flac_tags:</span><br><span class="line">value = flac_tags[key][<span class="number">0</span>]</span><br><span class="line">audio.add(frame_class(encoding=<span class="number">3</span>, text=value))</span><br><span class="line"><span class="keyword">if</span> <span class="string">&#x27;lyrics&#x27;</span> <span class="keyword">in</span> flac_tags:</span><br><span class="line">lyrics_text = flac_tags[<span class="string">&#x27;lyrics&#x27;</span>][<span class="number">0</span>]</span><br><span class="line">audio.add(USLT(encoding=<span class="number">3</span>, lang=<span class="string">&#x27;eng&#x27;</span>, desc=<span class="string">&#x27;Lyrics&#x27;</span>, text=lyrics_text))</span><br><span class="line"><span class="keyword">if</span> flac_tags.pictures:</span><br><span class="line">flac_cover = flac_tags.pictures[<span class="number">0</span>]</span><br><span class="line">mime_type = flac_cover.mime</span><br><span class="line">image_data = flac_cover.data</span><br><span class="line">audio.add(</span><br><span class="line">APIC(</span><br><span class="line">encoding=<span class="number">3</span>,</span><br><span class="line">mime=mime_type,</span><br><span class="line"><span class="built_in">type</span>=<span class="number">3</span>,</span><br><span class="line">desc=<span class="string">&#x27;Cover&#x27;</span>,</span><br><span class="line">data=image_data</span><br><span class="line">)</span><br><span class="line">)</span><br><span class="line">audio.save(mp3_path, v2_version=<span class="number">3</span>)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">f&quot;Copied tags for <span class="subst">&#123;os.path.basename(flac_path)&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">process_music_folders</span>(<span class="params">flac_dir, mp3_dir</span>):</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> os.path.exists(mp3_dir):</span><br><span class="line">os.makedirs(mp3_dir)</span><br><span class="line"><span class="keyword">for</span> root, dirs, files <span class="keyword">in</span> os.walk(flac_dir):</span><br><span class="line"><span class="keyword">for</span> flac_file <span class="keyword">in</span> files:</span><br><span class="line"><span class="keyword">if</span> flac_file.endswith(<span class="string">&#x27;.flac&#x27;</span>):</span><br><span class="line">flac_path = os.path.join(root, flac_file)</span><br><span class="line">relative_path = os.path.relpath(flac_path, flac_dir)</span><br><span class="line">mp3_file = os.path.splitext(os.path.basename(flac_file))[<span class="number">0</span>] + <span class="string">&#x27;.mp3&#x27;</span></span><br><span class="line">mp3_path = os.path.join(mp3_dir, os.path.dirname(relative_path), mp3_file)</span><br><span class="line">mp3_sub_dir = os.path.dirname(mp3_path)</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> os.path.exists(mp3_sub_dir):</span><br><span class="line">os.makedirs(mp3_sub_dir)</span><br><span class="line"><span class="keyword">if</span> os.path.exists(mp3_path):</span><br><span class="line"><span class="built_in">print</span>(<span class="string">f&quot;Processing <span class="subst">&#123;flac_file&#125;</span>...&quot;</span>)</span><br><span class="line">copy_vorbis_to_id3(flac_path, mp3_path)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">flac_folder = <span class="built_in">input</span>(<span class="string">&quot;请输入 FLAC 文件夹路径: &quot;</span>).strip()</span><br><span class="line">mp3_folder = <span class="built_in">input</span>(<span class="string">&quot;请输入 MP3 输出文件夹路径: &quot;</span>).strip()</span><br><span class="line">process_music_folders(flac_folder, mp3_folder)</span><br></pre></td></tr></table></figure><p>哇，好多代码。<s>都是 LLM 写的。</s></p><p>上面的脚本会递归地处理指定文件夹中的所有 FLAC 文件，并将它们的标签复制到对应的 MP3 文件中。</p><h2 id="导入文件">导入文件</h2><p>自己复制到手机上导入，这个不用我说。</p><p>需要注意几点：</p><ol><li>「华为运动健康」App 对于手机上标题重复的音乐文件会忽略掉某一个，机制不明……不要把打标签前后的文件都放在手机上。</li><li>「华为运动健康」App 对于「标题」标签里面有 <code>-</code> 的文件，无论有没有歌手信息，都会把它拆开当作标题和歌手，例如 <code>太陽系デスコ-初音ミク「マジカルミライ 2020」Live- (feat. 初音ミク)</code>……最好改一下。</li><li>代码里指定了 ID3 版本为 ID3v2.3。它的兼容性比较好，如果你导入其他地方的文件有问题，不妨试试把标签转换成 ID3v2.3。</li></ol><h2 id="结语">结语</h2><p>MP3 草案在 1991 年发布，直到 5 年后才有了 ID3v1。如果当时的人就能想到标签这回事，大概也没这么多事情吧。</p><h2 id="后记">后记</h2><ol><li>群友推荐用 Kid3 处理和转换 ID3 标签。</li><li>群友推荐用 qaac 处理 AAC 格式，比 MP3 更好。</li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;华为手表支持通过手机同步音乐文件进行离线播放，而且支持 FLAC 格式。但是，你真的想在手表那么小的存储空间里放大量的 FLAC 文件吗……本文将教你如何将 FLAC 文件转换为 MP3，并保留原有的标签信息供「华为运动健康」App 使用。&lt;/p&gt;
&lt;blockquote&gt;</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
    <category term="华为" scheme="https://blog.khyan.top/tags/%E5%8D%8E%E4%B8%BA/"/>
    
    <category term="穿戴设备" scheme="https://blog.khyan.top/tags/%E7%A9%BF%E6%88%B4%E8%AE%BE%E5%A4%87/"/>
    
    <category term="手表" scheme="https://blog.khyan.top/tags/%E6%89%8B%E8%A1%A8/"/>
    
    <category term="音频" scheme="https://blog.khyan.top/tags/%E9%9F%B3%E9%A2%91/"/>
    
  </entry>
  
  <entry>
    <title>在你的 Arch Linux 笔记本上畅快使用 NVIDIA 显卡</title>
    <link href="https://blog.khyan.top/2025/07/nvidia-on-arch-laptop/"/>
    <id>https://blog.khyan.top/2025/07/nvidia-on-arch-laptop/</id>
    <published>2025-07-21T14:57:22.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<p>新购机械革命旷世 X Pro 游戏笔记本电脑一台，搭载 NVIDIA GeForce RTX 5070 Ti Laptop 显卡，到手后便安装了 Arch Linux。此乃我初次安装 Arch Linux，亦是初次使用带有独立显卡的电脑（😭️）。</p><p>为达到效率与性能的最佳平衡，意欲采用混合模式，NVIDIA 独立显卡按需启动。折腾过程中遇到不少问题，通过查阅 Arch Wiki 和其他资料，最终配置成功。现将过程记录为本文，以供自己和后人参考。</p><h2 id="环境">环境</h2><ul><li>CPU: Intel Core i9-13900HX（不要缩缸！🙏）</li><li>GPU: NVIDIA GeForce RTX 5070 Ti Laptop</li><li>操作系统: Arch Linux</li><li>桌面环境: GNOME on Wayland</li></ul><h2 id="安装-NVIDIA-驱动">安装 NVIDIA 驱动</h2><p>这部分很快，<code>pacman</code> 一把梭会帮你把要配置的都配置好，而且网上教程很多，也可参考 <a href="https://wiki.archlinuxcn.org/title/NVIDIA">Arch Wiki</a>，该部分不赘述。需要注意的是，似乎 50 系 GPU 需要安装 <code>nvidia-open</code> 驱动，而非 <code>nvidia</code> 驱动。如果不确定，可先安装一个，然后用 <code>sudo dmesg</code> 查看。</p><p>安装之后，建议再安装 <code>nvidia-utils</code> 和 <code>lib32-nvidia-utils</code> <sup>multilib</sup>。</p><h2 id="配置和测试-PRIME">配置和测试 PRIME</h2><blockquote><p>本段的内容在 Arch Wiki 中均有涉及。</p></blockquote><p><a href="https://wiki.archlinuxcn.org/wiki/PRIME">PRIME</a>（<code>nvidia-prime</code>）是在 Linux 上使用 NVIDIA Optimus 技术的绝佳工具。本例中，我们将配置 <strong>PRIME GPU 分载</strong>，使得在通过 Intel 核芯显卡输出画面的同时能够使用 NVIDIA 独立显卡进行图形处理。</p><p>首先，安装 PRIME：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> pacman -S nvidia-prime</span><br></pre></td></tr></table></figure><p>接下来，配置 udev 和模块参数。</p><p>你可以选择安装 <code>nvidia-prime-rtd3pm</code> <sup>AUR</sup> 包，它会自动创建所需的 udev 规则和模块参数文件。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yay -S nvidia-prime-rtd3pm</span><br></pre></td></tr></table></figure><p>如果你不想从 AUR 装包，那么请根据 <a href="https://wiki.archlinuxcn.org/wiki/PRIME#NVIDIA">Arch Wiki</a> 创建以下两个文件：</p><ul><li><code>/etc/udev/rules.d/80-nvidia-pm.rules</code></li><li><code>/etc/modprobe.d/nvidia-pm.conf</code></li></ul><blockquote><p>有必要解释一下我们设置的模块参数：<code>options nvidia &quot;NVreg_DynamicPowerManagement=0x02&quot;</code>。</p><p>根据 <a href="https://download.nvidia.com/XFree86/Linux-x86_64/435.17/README/dynamicpowermanagement.html#DriverSettingsfe624">NVIDIA 官方文档</a>，该选项为 <code>0x00</code> 时表示禁用动态电源管理，<code>0x01</code> 时表示启用动态电源管理，<code>0x02</code> 时表示启用动态电源管理并允许系统在空闲时将 GPU 关机。</p></blockquote><p>装完包或者创建好所需的文件之后，请重启电脑。</p><p>重启后，你可以使用以下命令来检查 NVIDIA GPU 是否已关闭。首先获取 NVIDIA GPU 的 PCI 设备 ID：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lspci | grep -i nvidia</span><br></pre></td></tr></table></figure><p>笔者的输出如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">02:00.0 VGA compatible controller: NVIDIA Corporation GB205M [GeForce RTX 5070 Ti Mobile] (rev a1)</span><br><span class="line">02:00.1 Audio device: NVIDIA Corporation Device 2f80 (rev a1)</span><br></pre></td></tr></table></figure><p>这证明笔者的 NVIDIA GPU 的 PCI 设备 ID 是 <code>02:00.0</code>。下面请你把命令中的 <code>&lt;pci_device_id&gt;</code> 替换为你的 NVIDIA GPU 的 PCI 设备 ID。执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> /sys/bus/pci/devices/0000:&lt;pci_device_id&gt;/power/runtime_status</span><br></pre></td></tr></table></figure><p>输出有如下可能：</p><ul><li><code>suspended</code>：表示 NVIDIA GPU 已被挂起。</li><li><code>resuming</code>：表示 NVIDIA GPU 正在恢复运行。</li><li><code>active</code>：表示 NVIDIA GPU 正在运行。</li><li><code>suspending</code>：表示 NVIDIA GPU 正在挂起。</li></ul><p>如果输出是 <code>suspended</code>，那么恭喜你，你的 NVIDIA GPU 已经成功启用了动态电源管理，并且在不使用时会自动挂起断电。如果输出非预期，请继续参考 <a href="https://wiki.archlinuxcn.org/wiki/PRIME#NVIDIA">Arch Wiki</a>。</p><p>还需要启用 <code>nvidia-persistenced.service</code> 服务，以避免内核在 NVIDIA 设备资源不再使用时清空设备状态：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> nvidia-persistenced.service</span><br><span class="line"><span class="built_in">sudo</span> systemctl start nvidia-persistenced.service</span><br></pre></td></tr></table></figure><p>测试无误后，可以安装 <code>switcheroo-control</code> 包并启用 <code>switcheroo-control.service</code> 以使用 GNOME 集成，这样就可以右击应用程序文件夹里的图标，快速地选择「使用独立显卡启动」选项，用独显运行应用程序。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> pacman -S switcheroo-control</span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> switcheroo-control.service</span><br></pre></td></tr></table></figure><p>然后重启电脑。</p><h2 id="问题排除：独显莫名其妙就被唤醒了？">问题排除：独显莫名其妙就被唤醒了？</h2><p>通过使用 <code>watch</code> 命令，你可以实时监视独显的状态：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">watch -n 1 <span class="built_in">cat</span> /sys/bus/pci/devices/0000:&lt;pci_device_id&gt;/power/runtime_status</span><br></pre></td></tr></table></figure><p>当你打开 GTK4 应用，或者打开基于 Electron 的应用时，可能会听到强劲的风扇声，并注意到独显的状态变为 <code>active</code>。</p><p>这是因为 GTK4 应用默认会使用 Vulkan 进行渲染，而 Vulkan 在启动时会导致独显被唤醒。你可以使用下面的方法来解决 GTK4 应用唤醒独显的问题。</p><p><strong>此章节的剩余内容已经过时。请参考《<a href="/2025/11/nvidia-on-arch-laptop-vulkan/" title="在你的Arch Linux笔记本上畅快使用NVIDIA显卡，包括Vulkan">在你的Arch Linux笔记本上畅快使用NVIDIA显卡，包括Vulkan</a>》以获取最新的解决方案。</strong></p><p>Electron 应用只会唤醒独显几秒钟，不影响使用，用掩耳盗铃的方法解决。（如果你知道怎么解决，请告知。）</p><p>下面着重解决 GTK4 应用唤醒独显的问题。</p><p>参考 <a href="https://wiki.archlinux.org/title/GTK#GTK4_applications_using_the_dGPU_on_NVIDIA_Optimus_setups">Arch Wiki - GTK#GTK4 applications using the dGPU on NVIDIA Optimus setups</a>，我们知道 GTK 在枚举设备时会选择第一个可用的 GPU，而 NVIDIA 通常将独显显示为第一个，因此现在将默认使用 Vulkan 渲染器，即调用 NVIDIA 独显。</p><p>解决方案就是让 Vulkan 优先调用 Intel 核芯显卡（参考下面的 Arch Linux BBS 帖子），或者采取我选择的方式，把 GTK4 的渲染后端换回 <code>ngl</code>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p ~/.config/environment.d &amp;&amp; <span class="built_in">echo</span> GSK_RENDERER=ngl &gt; ~/.config/environment.d/gsk.conf</span><br></pre></td></tr></table></figure><p>然后重启电脑。</p><p>对于 Flatpak 应用，请参考 <a href="https://bbs.archlinux.org/viewtopic.php?id=284426">Arch Linux BBS - NVIDIA Discrete GPU/DGPU powers on on every program that opens.</a> 中的解决方案。</p><h2 id="延伸：实时监视独显状态">延伸：实时监视独显状态</h2><p><code>watch</code> 命令只能在终端使用，不太方便。通过使用一个简单的 GNOME 扩展，你可以把独显的状态集成到 GNOME 顶部栏中。</p><p>安装扩展 <a href="https://extensions.gnome.org/extension/2932/executor/">Executor</a> 后，可以监视命令的输出。我写了一个简单的命令，你可以将其添加到 Executor 中：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">s=$(<span class="built_in">cat</span> /sys/bus/pci/devices/0000:&lt;pci_device_id&gt;/power/runtime_status); <span class="built_in">echo</span> <span class="string">&quot;独显<span class="subst">$(if [ <span class="string">&quot;<span class="variable">$s</span>&quot;</span> = <span class="string">&quot;active&quot;</span> ]; then echo <span class="string">&quot;活动&quot;</span>; elif [ <span class="string">&quot;<span class="variable">$s</span>&quot;</span> = <span class="string">&quot;suspended&quot;</span> ]; then echo <span class="string">&quot;挂起&quot;</span>; elif [ <span class="string">&quot;<span class="variable">$s</span>&quot;</span> = <span class="string">&quot;resuming&quot;</span> ]; then echo <span class="string">&quot;恢复中&quot;</span>; elif [ <span class="string">&quot;<span class="variable">$s</span>&quot;</span> = <span class="string">&quot;suspending&quot;</span> ]; then echo <span class="string">&quot;挂起中&quot;</span>; else echo <span class="string">&quot; <span class="variable">$s</span>&quot;</span>; fi)</span>&quot;</span></span><br></pre></td></tr></table></figure><p>注意把命令中的 <code>&lt;pci_device_id&gt;</code> 替换为你的 NVIDIA GPU 的 PCI 设备 ID。</p><h2 id="结语">结语</h2><p>通过以上步骤，你应该能够在 Arch Linux 笔记本上成功配置并使用 NVIDIA 独立显卡。希望这篇文章能对你有所帮助，祝你在 Linux 的世界里畅游无阻！</p><p>如有任何问题或建议，请不吝赐教！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;新购机械革命旷世 X Pro 游戏笔记本电脑一台，搭载 NVIDIA GeForce RTX 5070 Ti Laptop 显卡，到手后便安装了 Arch Linux。此乃我初次安装 Arch Linux，亦是初次使用带有独立显卡的电脑（😭️）。&lt;/p&gt;
&lt;p&gt;为达到效率</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Linux" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/Linux/"/>
    
    
    <category term="Linux实战" scheme="https://blog.khyan.top/tags/Linux%E5%AE%9E%E6%88%98/"/>
    
    <category term="Arch Linux" scheme="https://blog.khyan.top/tags/Arch-Linux/"/>
    
    <category term="NVIDIA" scheme="https://blog.khyan.top/tags/NVIDIA/"/>
    
  </entry>
  
  <entry>
    <title>纸飞机在雨中飞——对 Telegram 的一些思考</title>
    <link href="https://blog.khyan.top/2024/09/paper-plane-in-the-rain/"/>
    <id>https://blog.khyan.top/2024/09/paper-plane-in-the-rain/</id>
    <published>2024-09-06T12:23:00.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>以下内容整理自我在网上聊天室中的发言。</p></blockquote><p>距离 Telegram CEO Pavel Du Rove 最初被法国政府提出指控已有数周。<a href="https://blog.yitianshijie.net/2024/09/06/5062/">有文章</a>因 Telegram 不默认启用端到端加密而对其隐私性提出质疑。以下是我的观点。</p><p>Telegram 是主流聊天软件中唯一支持在众多设备上同时登录的。要么作出取舍，要么像 Matrix 一样在其他设备上干瞪眼看无法解密的提示。</p><p>当然，这些暗示着 Telegram 是个弱隐私的平台，但他们的宣传显然与实际不符。我宁愿在隐私和便利中选择后者，当然我知道有人不愿。</p><p>说实在的，我觉得追求极度隐私的人一开始便不该选择 Telegram。对于普遍隐私来说，Telegram 其实也差点火候。我倒是怀疑 Telegram 在拿用户隐私当作审查不力的挡箭牌。一个弱隐私的平台本该能很好地对付诈骗和儿童色情内容的。更何况，Telegram 上大部分的违法活动都植根频道和群组之中，没有经过端到端加密的保护。</p><p>所以，谁也不知道杜叔叔葫芦里卖的什么药。纸飞机在雨中飞，带着被淋湿的机翼。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;以下内容整理自我在网上聊天室中的发言。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;距离 Telegram CEO Pavel Du Rove 最初被法国政府提出指控已有数周。&lt;a href=&quot;https://blog.yitianshijie.ne</summary>
      
    
    
    
    <category term="时评" scheme="https://blog.khyan.top/categories/%E6%97%B6%E8%AF%84/"/>
    
    
    <category term="Telegram" scheme="https://blog.khyan.top/tags/Telegram/"/>
    
  </entry>
  
  <entry>
    <title>震惊！早起不叠被子有这么多好处！</title>
    <link href="https://blog.khyan.top/2024/08/stop-folding-the-quilt/"/>
    <id>https://blog.khyan.top/2024/08/stop-folding-the-quilt/</id>
    <published>2024-08-31T08:54:00.000Z</published>
    <updated>2026-01-25T10:19:17.226Z</updated>
    
    <content type="html"><![CDATA[<p>你还在每天早上费劲地叠被子吗？快停下！现在，一项震惊世人的研究表明，<strong>早起不叠被子竟然有许多意想不到的好处</strong>！ </p><p><strong>1.  告别尘螨，呼吸更自由！</strong></p><p>我们都知道，被子是尘螨的乐园。而每天叠被子，就如同将它们关在一个温暖潮湿的密闭空间里，让它们繁衍生息。不叠被子，让被子充分通风，尘螨无处藏身，自然也就减少了过敏和哮喘的风险。</p><p><strong>2.  提高免疫力，远离疾病！</strong></p><p>研究发现，人体皮肤上的益生菌对维持免疫力至关重要，而叠被子会导致益生菌数量减少。不叠被子，让被子保持自然状态，有助于益生菌的生长，提升免疫力，减少患病风险。</p><p><strong>3.  节省时间，多睡一会儿！</strong></p><p>你是否经常因为叠被子而迟到？不叠被子，就能节省宝贵的时间，多睡一会儿，迎接美好的一天。</p><p><strong>4.  减轻压力，放松身心！</strong></p><p>叠被子是一个重复性的动作，容易让人感到烦躁和压力。不叠被子，可以减少这种压力，让你更加放松，拥有一个愉悦的心情。</p><p><strong>5.  保持被子蓬松，舒适度UP！</strong></p><p>叠被子会导致被子变得紧实，影响舒适度。不叠被子，让被子保持蓬松状态，更加柔软舒适。</p><p>总之，早起不叠被子，不仅是时尚，更是一种健康的生活方式。快行动起来，尝试一下吧！你一定会爱上这种轻松自在的感觉！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;你还在每天早上费劲地叠被子吗？快停下！现在，一项震惊世人的研究表明，&lt;strong&gt;早起不叠被子竟然有许多意想不到的好处&lt;/strong&gt;！ &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.  告别尘螨，呼吸更自由！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们都知道，被子是尘螨的乐园。而每天</summary>
      
    
    
    
    <category term="生活" scheme="https://blog.khyan.top/categories/%E7%94%9F%E6%B4%BB/"/>
    
    <category term="由生成式人工智能辅助创作" scheme="https://blog.khyan.top/categories/%E7%94%B1%E7%94%9F%E6%88%90%E5%BC%8F%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E8%BE%85%E5%8A%A9%E5%88%9B%E4%BD%9C/"/>
    
    
    <category term="健康" scheme="https://blog.khyan.top/tags/%E5%81%A5%E5%BA%B7/"/>
    
    <category term="被子" scheme="https://blog.khyan.top/tags/%E8%A2%AB%E5%AD%90/"/>
    
  </entry>
  
  <entry>
    <title>“反转”不是进步，真相需要维护</title>
    <link href="https://blog.khyan.top/2024/04/truth-need-maintenance/"/>
    <id>https://blog.khyan.top/2024/04/truth-need-maintenance/</id>
    <published>2024-04-04T08:27:00.000Z</published>
    <updated>2026-01-25T10:19:17.226Z</updated>
    
    <content type="html"><![CDATA[<p>本文是考场作文，得分 50 分。我自以为颇有意义，现将原文如实呈现，整理如下，供大家参考阅读，望不吝赐教。</p><hr><p>阅读下面材料，根据要求写作。（60 分）</p><p>近些年在互联网传播场域中，“反转”式新闻连番上演。在这个时代，对同一事件的报道常常出现一次或多次显著变化，有时甚至出现反向变化。网民们也已被教育得习惯“蹲一个反转”“让子弹飞”。</p><p>有人称其为“污染井效应”，即流传的虚假言论污染了公众舆论之井。美国智库兰德公司也用“真相衰退”这个词来概括人们在公共生活中事实和基于事实的分析所占比重越来越少的现象。</p><p>对此，你有怎样的体验与思考？写一篇文章，谈谈自己的看法。</p><p>要求：① 角度自选，立意自定，题目自拟；② 明确文体，不得写成诗歌；③ 不得少于 800 字；④ 不得抄袭、套作。</p><hr><h1>“反转”不是进步，真相需要维护</h1><p>随着互联网的高速发展，自媒体、短视频成为了新媒体新闻传播的关键领域。新闻传播的快速化趋势引发了“反转”的屡屡上演，更是点燃了网民们对网络信息真实性的思考。笔者认为，“反转”式新闻是事实被掩盖的危险信号，必须由多方共同努力，杜绝真相被掩盖。</p><p>“反转”式新闻的出现，在于新兴媒介一味追求“快”的共性，却忽略了准确性。时下流行的短视频便是典型的样板。短视频内容门槛低、质量低、传播速度快，用户生成内容的模式注定了其内容良莠不齐。如此的特点使它成为虚假“真相”的主要来源而为澄清事实，相关的权威部门又不得不反复采取措施，其中更是难免产生误传，导致信息需要多次修正，进而产生反转。由此观之，短视频等新媒体是“反转”式新闻的祸根。</p><p>“反转”式新闻决不是真相逐步得到修正的进步体现，而是虚假信息肆虐的预警信号。短视频出现之前，新闻的主要来源是报纸和权威性互联网媒体。其时因信息来源权威而纯粹，虚假信息较少。短视频使人人都能成为网络的中心，空洞无物的“新黄色新闻”更是佐证了短视频的短视。“污染井效应”的理论在这里得到了生动而又可悲的诠释：动动手指便能发布一条虚假内容堆积成的短视频信息，公众舆论之井被大量虚假言论污染。而作为舆论之井井底之蛙的公众在浏览短视频的被动接收过程中受大量或真或假信息以及多次、多级的“反转”影响，只能接收到扭曲和破碎的事实。</p><p>“反转”式新闻的杜绝，是势在必行、迫在眉睫的任务。互联网平台必须加强内容审核，对屡次发表相应虚假内容的用户进行处罚，立法者也应修订相应的法规，增加造谣成本。唯有杜绝虚假“真相”的产生，才能将“反转”的负面影响扼杂在摇篮之中。</p><p>诚然，“反转”式新闻的产生主要由虚假信息驱使，事实调查的不清楚也是另一种可能的原因。随着技术的进步，调查真相的手段更多，有时初步结论并非事实真相。这种情况下，“反转”则是必要而必不可少的，但也要警惕其成为滥用的理由。</p><p>“反转”式新闻不是进步的体现，真相本当一次查明。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本文是考场作文，得分 50 分。我自以为颇有意义，现将原文如实呈现，整理如下，供大家参考阅读，望不吝赐教。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;阅读下面材料，根据要求写作。（60 分）&lt;/p&gt;
&lt;p&gt;近些年在互联网传播场域中，“反转”式新闻连番上演。在这个时代，对同一事件的报道常常出现</summary>
      
    
    
    
    <category term="时评" scheme="https://blog.khyan.top/categories/%E6%97%B6%E8%AF%84/"/>
    
    <category term="考场作文" scheme="https://blog.khyan.top/categories/%E8%80%83%E5%9C%BA%E4%BD%9C%E6%96%87/"/>
    
    
    <category term="反转" scheme="https://blog.khyan.top/tags/%E5%8F%8D%E8%BD%AC/"/>
    
    <category term="真相" scheme="https://blog.khyan.top/tags/%E7%9C%9F%E7%9B%B8/"/>
    
    <category term="新闻学" scheme="https://blog.khyan.top/tags/%E6%96%B0%E9%97%BB%E5%AD%A6/"/>
    
  </entry>
  
  <entry>
    <title>记一次有惊无险的 Linux 下根分区大小调整经历</title>
    <link href="https://blog.khyan.top/2024/02/linux-resize-root-partition/"/>
    <id>https://blog.khyan.top/2024/02/linux-resize-root-partition/</id>
    <published>2024-02-13T11:41:00.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<p><strong>你将在本文中读到以下内容</strong>：使用 fdisk 工具恢复分区顺序、删除交换分区后需要的修复工作</p><p>如果你只是想了解如何扩容磁盘，请看文章最后的<strong>结论</strong>部分。</p><p><em>请注意</em>，请<em>不要</em>效仿本文中的错误操作。<em>只有</em>你遇到了相似的问题，<em>才</em>可以运用文章中的补救措施。由于作者并不精通 Linux，不保证文章内容准确，采用文章中的方法，<em>后果自负</em>。本文没有配屏幕截图。</p><h2 id="前情提要">前情提要</h2><p>由于 Windows 系统过于卡顿，因此最近开始使用 Linux 操作系统，选用的是 Ubuntu 22.04 LTS 发行版。使用过程中逐渐感到磁盘空间不足，遂打算扩充磁盘空间以供使用。</p><h3 id="当前系统环境">当前系统环境</h3><p>我已有的磁盘情况如下（按照在磁盘上的顺序排列）：</p><ul><li><code>/dev/sda</code>：机械硬盘，容量为 1 TB。<ul><li><code>sda2</code>：逻辑分区。<ul><li><code>sda5</code>：交换分区（swap），容量 16 GB。</li><li><code>sda6</code>：Linux 根目录，容量 64 GB。</li></ul></li><li><code>sda1</code>：位于磁盘最后的 NTFS 分区，容量约 800 GB。</li></ul></li><li><code>/dev/sdb</code>：SSD。<code>sdb1</code> 上装有 Windows 11 操作系统。</li></ul><h3 id="预期结果">预期结果</h3><p>由于交换分区过大，完全用不完，计划将交换分区缩小至 4 GB，并将 <code>sda6</code> 向前扩展 12 GB。</p><hr><p><strong>附注</strong>：后续使用证明，4 GB 交换分区有些捉襟见肘，一般来说将近吃满，长时间不关机会完全吃满导致电脑卡顿，后续又调整为 8 GB。我的电脑内存是 8 GB，供参考。</p><h2 id="摸索过程">摸索过程</h2><h3 id="在-Ubuntu-主系统上的操作">在 Ubuntu 主系统上的操作</h3><p>我打开了 GNOME「磁盘」工具，解除挂载之后企图调节 swap 分区大小，发现不能调节，遂打算删除后重建。（<strong>请不要效仿，后果自负。</strong>）</p><p>删除 swap 之后，系统提示内核无法响应分区序号的更改，<code>/dev/sda6</code> 变为 <code>/dev/sda5</code>，让我重新启动操作系统。</p><p>我瞬间慌了，立刻找到闲置的优盘，开始烧写 Ventoy，制作启动盘。烧写完成之后，重启进入 Live CD。</p><h3 id="在-Live-CD-中的抢救工作">在 Live CD 中的抢救工作</h3><p>进入 Live CD 之后直接启动 <strong>GParted</strong> 图形界面（Ubuntu Live CD 预装）查看分区情况。创建新的 swap 分区，调节主分区大小（时间会很长），然后重启。</p><p>调节之后的分区情况如下：</p><ul><li><code>sda2</code>：逻辑分区。<ul><li><code>sda6</code>：swap 分区，容量 4 GB。</li><li><code>sda5</code>：Linux 根目录，容量 76 GB。</li></ul></li><li><code>sda1</code>：位于磁盘最后的 NTFS 分区，容量约 800 GB。</li></ul><hr><p><strong>附注</strong>：如果硬盘上有 swap 分区，Live CD 会使用它。GParted 会用「🔑」标记挂载的分区，你需要右键点击取消挂载。</p><h3 id="引导失败-—-修复分区序号">引导失败 — 修复分区序号</h3><p>重启之后无法进入操作系统。屏幕上显示的内容如下：</p><pre><code>error: unknown filesystem.Entering rescue mode...grub rescue&gt; _</code></pre><p>这个画面显然使我不安。我用电源键关机重新进入 Live CD。通过搜索，我知道是分区序号改变的缘故。<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>经过摸索，总结修复过程如下：</p><ol><li>执行 <code>sudo fdisk /dev/sda</code>；</li><li>用 <code>x</code> 进入高级模式，<code>f</code> 执行分区序号调整。</li></ol><p>调整之后，分区序号会重新排列，变成了这样：</p><ul><li><code>sda1</code>：逻辑分区。<ul><li><code>sda5</code>：swap 分区，容量 4 GB。</li><li><code>sda6</code>：Linux 根目录，容量 76 GB。</li></ul></li><li><code>sda2</code>：位于磁盘最后的 NTFS 分区，容量约 800 GB。</li></ul><p><code>sda1</code> 和 <code>sda2</code> 交换了，但不影响使用<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>。</p><h3 id="后续收尾-—-关于交换分区">后续收尾 — 关于交换分区</h3><p>经过一番摸索和修复，系统终于可以正常启动了，但仍然会遇到下面两个问题。</p><p><strong>问题 1</strong> 启动时控制台界面会一直跳光标，一分钟后显示：</p><pre><code>Gave up waiting for suspend/resume device</code></pre><p>之后才会出现 GUI 启动界面。这是交换分区被重新创建，UUID 不同造成的。</p><p><strong>解决方法</strong>：删除 <code>/etc/initramfs-tools/conf.d/resume</code>，并执行 <code>update-initramfs -u</code>。<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup></p><p><strong>问题 2</strong> 重启之后，系统也不会使用这个新的交换分区。</p><p><strong>解决方法</strong>：运行 <code>sudo blkid</code>，获得新建的交换分区的 UUID，输出如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/dev/sda5: UUID=&quot;********-****-****-****-************&quot; TYPE=&quot;swap&quot; PARTUUID=&quot;********-**&quot;</span><br></pre></td></tr></table></figure><p>编辑 <code>/etc/fstab</code>，如下：</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># /etc/fstab: static file system information.</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Use &#x27;blkid&#x27; to print the universally unique identifier for a</span></span><br><span class="line"><span class="comment"># device; this may be used with UUID= as a more robust way to name devices</span></span><br><span class="line"><span class="comment"># that works even if disks are added and removed. See fstab(5).</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># &lt;file system&gt; &lt;mount point&gt;   &lt;type&gt;  &lt;options&gt;       &lt;dump&gt;  &lt;pass&gt;</span></span><br><span class="line"><span class="comment"># / was on /dev/sda6 during installation</span></span><br><span class="line"><span class="attr">UUID</span>=********-****-****-****-************ /               ext4    errors=remount-ro <span class="number">0</span>       <span class="number">1</span></span><br><span class="line"><span class="comment"># swap was on /dev/sda5 during installation</span></span><br><span class="line"><span class="attr">UUID</span>=********-****-****-****-************ none            swap    sw                <span class="number">0</span>       <span class="number">0</span> <span class="comment"># 修改此处的 UUID</span></span><br></pre></td></tr></table></figure><p>重启系统，终于正常了。</p><h2 id="结论">结论</h2><p>本文主要焦点在误操作之后的恢复。一般来说，只要不贪图方便，正常操作，不会出现问题。正常的磁盘扩充过程：重启进入 Live CD，直接通过 GParted 工具调整分区大小。</p><p>以及，谨记名言：</p><blockquote><p>早晚别刷机！</p></blockquote><hr class="footnotes-sep"><section class="footnotes"><ol class="footnotes-list"><li id="fn1" class="footnote-item"><p>电脑引导用的是分区 UUID，发生此情况的原因尚不明确。欢迎留言分享。 <a href="#fnref1" class="footnote-backref">↩︎</a></p></li><li id="fn2" class="footnote-item"><p>后续挂载时系统莫名其妙提示需要到 Windows 中执行 <code>chkdsk /f</code> 修复，不知原因，故记录于此。 <a href="#fnref2" class="footnote-backref">↩︎</a></p></li><li id="fn3" class="footnote-item"><p>如果你继续遇到错误，请参考 <a href="https://unix.stackexchange.com/questions/590518/boot-blocks-with-gave-up-waiting-for-suspend-resume-device">ubuntu - Boot blocks with “Gave up waiting for suspend/resume device” - Unix &amp; Linux Stack Exchange</a>。 <a href="#fnref3" class="footnote-backref">↩︎</a></p></li></ol></section>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;strong&gt;你将在本文中读到以下内容&lt;/strong&gt;：使用 fdisk 工具恢复分区顺序、删除交换分区后需要的修复工作&lt;/p&gt;
&lt;p&gt;如果你只是想了解如何扩容磁盘，请看文章最后的&lt;strong&gt;结论&lt;/strong&gt;部分。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;请注意&lt;/em&gt;，请&lt;</summary>
      
    
    
    
    <category term="技术" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/"/>
    
    <category term="Linux" scheme="https://blog.khyan.top/categories/%E6%8A%80%E6%9C%AF/Linux/"/>
    
    
    <category term="Linux实战" scheme="https://blog.khyan.top/tags/Linux%E5%AE%9E%E6%88%98/"/>
    
  </entry>
  
  <entry>
    <title>你好，世界！</title>
    <link href="https://blog.khyan.top/2018/05/hello-world/"/>
    <id>https://blog.khyan.top/2018/05/hello-world/</id>
    <published>2018-05-06T09:03:12.000Z</published>
    <updated>2026-01-25T10:19:17.225Z</updated>
    
    <content type="html"><![CDATA[<p>欢迎使用 <code>Kratos : Rebirth</code> 这个我们精心打造的 Hexo 主题！希望能在接下来的旅途中与您相伴，共同创造出更多难以忘怀的美好体验。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;欢迎使用 &lt;code&gt;Kratos : Rebirth&lt;/code&gt; 这个我们精心打造的 Hexo 主题！希望能在接下来的旅途中与您相伴，共同创造出更多难以忘怀的美好体验。&lt;/p&gt;
</summary>
      
    
    
    
    <category term="全新体验" scheme="https://blog.khyan.top/categories/%E5%85%A8%E6%96%B0%E4%BD%93%E9%AA%8C/"/>
    
    
    <category term="欢迎" scheme="https://blog.khyan.top/tags/%E6%AC%A2%E8%BF%8E/"/>
    
  </entry>
  
</feed>
