<?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>模組七：桌面環境維護與故障排除 on Tarragon</title><link>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/</link><description>Recent content in 模組七：桌面環境維護與故障排除 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 30 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/index.xml" rel="self" type="application/rss+xml"/><item><title>Linux 桌面的故障隔離模型</title><link>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/fault-isolation-model/</link><pubDate>Tue, 30 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/fault-isolation-model/</guid><description>&lt;p>Linux 桌面環境的故障隔離建立在一個結構性的設計決策上：&lt;strong>顯示合成器（compositor）是 userspace process，不是 kernel 的一部分&lt;/strong>。這意味著 Hyprland 掛了只是桌面消失，作業系統核心還在正常運作。&lt;/p>
&lt;p>本文用「桌面環境」泛指使用者看到的圖形介面整體。技術上，Hyprland 是 Wayland compositor——負責視窗合成和輸入管理，不含完整桌面環境（DE）的套件管理、設定面板等元件。GNOME、KDE Plasma 才是完整的 DE。但在故障隔離的討論中，關鍵區分是 kernel space vs userspace，compositor 和 DE 都在 userspace 這一側。&lt;/p>
&lt;h2 id="kernel-與-userspace-的隔離邊界">Kernel 與 Userspace 的隔離邊界&lt;/h2>
&lt;p>作業系統分成兩個執行空間。Kernel space 負責硬體驅動、記憶體管理、process 排程這些基礎設施。Userspace 跑所有應用程式，包括桌面環境本身。&lt;/p>
&lt;p>兩個空間之間有硬體層級的隔離——CPU 的保護環機制（ring 0 是核心層級、ring 3 是應用程式層級，硬體強制限制 ring 3 的程式碼存取 ring 0 的記憶體）。Userspace 的 process 不管怎麼崩潰，都不會直接影響 kernel。Kernel 會清理掉崩潰的 process、回收它佔用的記憶體，然後繼續運作。&lt;/p>
&lt;p>這個隔離機制解釋了一個關鍵差異：為什麼 Linux 上一個 app crash 通常只是那個視窗消失，而不會拖垮整台機器。&lt;/p>
&lt;h2 id="為什麼-windows-會藍屏">為什麼 Windows 會藍屏&lt;/h2>
&lt;p>Windows 的藍屏（Blue Screen of Death, BSOD）是 kernel panic 的表現——作業系統核心本身遇到無法恢復的錯誤，只能停機。&lt;/p>
&lt;p>Windows 藍屏頻率較高的結構性原因在於&lt;strong>顯示驅動的執行位置&lt;/strong>。Windows 把 GPU 驅動放在 kernel mode（WDDM 架構），NVIDIA 或 AMD 的驅動程式碼直接跑在核心空間。驅動有 bug 時，錯誤發生在 kernel space，清理掉再繼續的選項不存在——繼續執行可能造成資料損壞，只能停機。&lt;/p>
&lt;p>藍屏頻率高是架構選擇的代價。把驅動放在 kernel mode 可以減少 context switch 的效能開銷，GPU 效能更好。代價是驅動 bug 的爆炸半徑從「app crash」升級成「整台停機」。Windows 10/11 已加入 TDR（Timeout Detection and Recovery）機制——GPU driver hang 時系統嘗試 reset driver 而非直接藍屏，大幅降低了 GPU 導致的 BSOD 頻率。但架構上 driver 仍在 kernel mode，藍屏的可能性仍然存在。&lt;/p>
&lt;h2 id="linux-桌面的架構差異">Linux 桌面的架構差異&lt;/h2>
&lt;p>Linux 桌面環境的顯示合成器（Hyprland、Sway、KDE Plasma 的 KWin）跑在 userspace。它們透過 DRM/KMS（Direct Rendering Manager / Kernel Mode Setting，Linux 的顯示子系統介面）跟 kernel 的 GPU 驅動溝通，但合成器本身的程式碼不在 kernel space 裡。&lt;/p>
&lt;p>這個架構選擇的效果：&lt;/p>
&lt;p>&lt;strong>Compositor crash&lt;/strong>。Hyprland 如果遇到 segfault 或其他 fatal error，kernel 終止這個 userspace process。所有由它管理的視窗消失，螢幕回到 TTY 登入畫面或黑屏。但 kernel 還在跑——其他 TTY 可以登入，SSH 可以連線，背景的 service 繼續運作。&lt;/p>
&lt;p>&lt;strong>GPU driver bug&lt;/strong>。Linux 的 GPU 驅動分兩層：kernel module（可動態載入的核心擴充模組，如 &lt;code>nvidia.ko&lt;/code>、&lt;code>amdgpu.ko&lt;/code>）負責硬體操作，userspace 的 Mesa / NVIDIA userspace driver 負責 OpenGL/Vulkan 實作。Kernel module 出問題理論上可以 kernel panic，但實際行為取決於驅動。AMD 的開源 &lt;code>amdgpu&lt;/code> 通常會嘗試 reset GPU 而非直接 panic，常見的表現是畫面凍結幾秒後恢復。NVIDIA 的閉源 &lt;code>nvidia.ko&lt;/code> 是隔離模型的主要例外——kernel 社群無法審查或修復其程式碼，hang 時恢復能力遠弱於 amdgpu，經常拖垮整個 session 且 TTY 切換也受影響。這是後續&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">故障場景&lt;/a>中 NVIDIA 相關 caveat 的根源。&lt;/p></description><content:encoded><![CDATA[<p>Linux 桌面環境的故障隔離建立在一個結構性的設計決策上：<strong>顯示合成器（compositor）是 userspace process，不是 kernel 的一部分</strong>。這意味著 Hyprland 掛了只是桌面消失，作業系統核心還在正常運作。</p>
<p>本文用「桌面環境」泛指使用者看到的圖形介面整體。技術上，Hyprland 是 Wayland compositor——負責視窗合成和輸入管理，不含完整桌面環境（DE）的套件管理、設定面板等元件。GNOME、KDE Plasma 才是完整的 DE。但在故障隔離的討論中，關鍵區分是 kernel space vs userspace，compositor 和 DE 都在 userspace 這一側。</p>
<h2 id="kernel-與-userspace-的隔離邊界">Kernel 與 Userspace 的隔離邊界</h2>
<p>作業系統分成兩個執行空間。Kernel space 負責硬體驅動、記憶體管理、process 排程這些基礎設施。Userspace 跑所有應用程式，包括桌面環境本身。</p>
<p>兩個空間之間有硬體層級的隔離——CPU 的保護環機制（ring 0 是核心層級、ring 3 是應用程式層級，硬體強制限制 ring 3 的程式碼存取 ring 0 的記憶體）。Userspace 的 process 不管怎麼崩潰，都不會直接影響 kernel。Kernel 會清理掉崩潰的 process、回收它佔用的記憶體，然後繼續運作。</p>
<p>這個隔離機制解釋了一個關鍵差異：為什麼 Linux 上一個 app crash 通常只是那個視窗消失，而不會拖垮整台機器。</p>
<h2 id="為什麼-windows-會藍屏">為什麼 Windows 會藍屏</h2>
<p>Windows 的藍屏（Blue Screen of Death, BSOD）是 kernel panic 的表現——作業系統核心本身遇到無法恢復的錯誤，只能停機。</p>
<p>Windows 藍屏頻率較高的結構性原因在於<strong>顯示驅動的執行位置</strong>。Windows 把 GPU 驅動放在 kernel mode（WDDM 架構），NVIDIA 或 AMD 的驅動程式碼直接跑在核心空間。驅動有 bug 時，錯誤發生在 kernel space，清理掉再繼續的選項不存在——繼續執行可能造成資料損壞，只能停機。</p>
<p>藍屏頻率高是架構選擇的代價。把驅動放在 kernel mode 可以減少 context switch 的效能開銷，GPU 效能更好。代價是驅動 bug 的爆炸半徑從「app crash」升級成「整台停機」。Windows 10/11 已加入 TDR（Timeout Detection and Recovery）機制——GPU driver hang 時系統嘗試 reset driver 而非直接藍屏，大幅降低了 GPU 導致的 BSOD 頻率。但架構上 driver 仍在 kernel mode，藍屏的可能性仍然存在。</p>
<h2 id="linux-桌面的架構差異">Linux 桌面的架構差異</h2>
<p>Linux 桌面環境的顯示合成器（Hyprland、Sway、KDE Plasma 的 KWin）跑在 userspace。它們透過 DRM/KMS（Direct Rendering Manager / Kernel Mode Setting，Linux 的顯示子系統介面）跟 kernel 的 GPU 驅動溝通，但合成器本身的程式碼不在 kernel space 裡。</p>
<p>這個架構選擇的效果：</p>
<p><strong>Compositor crash</strong>。Hyprland 如果遇到 segfault 或其他 fatal error，kernel 終止這個 userspace process。所有由它管理的視窗消失，螢幕回到 TTY 登入畫面或黑屏。但 kernel 還在跑——其他 TTY 可以登入，SSH 可以連線，背景的 service 繼續運作。</p>
<p><strong>GPU driver bug</strong>。Linux 的 GPU 驅動分兩層：kernel module（可動態載入的核心擴充模組，如 <code>nvidia.ko</code>、<code>amdgpu.ko</code>）負責硬體操作，userspace 的 Mesa / NVIDIA userspace driver 負責 OpenGL/Vulkan 實作。Kernel module 出問題理論上可以 kernel panic，但實際行為取決於驅動。AMD 的開源 <code>amdgpu</code> 通常會嘗試 reset GPU 而非直接 panic，常見的表現是畫面凍結幾秒後恢復。NVIDIA 的閉源 <code>nvidia.ko</code> 是隔離模型的主要例外——kernel 社群無法審查或修復其程式碼，hang 時恢復能力遠弱於 amdgpu，經常拖垮整個 session 且 TTY 切換也受影響。這是後續<a href="/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">故障場景</a>中 NVIDIA 相關 caveat 的根源。</p>
<p><strong>應用程式 crash</strong>。Firefox、VS Code、任何 GUI 程式崩潰，只有那個視窗消失。Compositor 繼續管理剩下的視窗，桌面環境不受影響。</p>
<h2 id="ttykernel-存活時的首選救生通道">TTY：kernel 存活時的首選救生通道</h2>
<p>TTY（TeleTYpewriter）是 Linux 核心直接提供的純文字終端機介面，獨立於任何桌面環境。systemd 預設配置下有 6 個 virtual console（TTY1-TTY6）。Wayland compositor（如 Hyprland）通常佔用 TTY1，其餘可用。</p>
<p>切換方式：<code>Ctrl+Alt+F2</code>（切到 TTY2）到 <code>Ctrl+Alt+F6</code>（切到 TTY6）。</p>
<p>TTY 的重要性在於它<strong>不依賴 compositor</strong>。Hyprland 掛了、compositor crash 導致桌面消失——只要 kernel 還活著、GPU driver 仍能處理 VT switch，TTY 就能切過去登入操作：</p>
<ul>
<li>用 <code>htop</code> 或 <code>ps</code> 查看哪個 process 出問題</li>
<li><code>kill</code> 有問題的 process</li>
<li>用 <code>vim</code> 或 <code>nano</code> 修改配置檔</li>
<li>重新啟動 Hyprland（<code>Hyprland</code> 指令）</li>
<li>如果需要，正常 <code>reboot</code></li>
</ul>
<p>TTY 切換失效的情境有兩種：kernel panic（極罕見）和 GPU 完全 hang 導致 VT switch 本身卡住（NVIDIA 閉源驅動在 Wayland 上較常見，需確保 <code>nvidia_drm.modeset=1</code>）。後者的替代手段是 SSH 遠端登入或 Magic SysRq 鍵（見<a href="/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">常見故障場景</a>的場景三）。</p>
<h2 id="記憶體耗盡oom的處理機制">記憶體耗盡（OOM）的處理機制</h2>
<p>Linux kernel 有 OOM Killer（Out of Memory Killer）機制——當記憶體和 swap 都用完、kernel 無法再分配新頁面時，自動挑選佔用記憶體最多、重要性最低的 process 強制終止，釋放記憶體讓系統繼續運作。</p>
<p>OOM Killer 的行為有時超出使用者的預期——它可能直接終止 Hyprland（因為 compositor 通常佔用不少記憶體），導致桌面突然消失。但關鍵是：<strong>系統沒有崩潰</strong>。Kernel 還在、TTY 還在、SSH 還在。</p>
<p>預防 OOM 的常見做法：</p>
<ul>
<li>設定 swap（即使用 SSD，2-4GB 的 swap 也能在記憶體壓力大時提供緩衝）</li>
<li>啟用 <code>systemd-oomd</code>（userspace 的 OOM 管理，比 kernel OOM Killer 更早介入、更可控）</li>
<li>監控記憶體用量（<code>btop</code> 或 <code>htop</code> 可以看即時狀態）</li>
</ul>
<h2 id="故障層級速查">故障層級速查</h2>
<table>
  <thead>
      <tr>
          <th>故障層級</th>
          <th>症狀</th>
          <th>系統影響</th>
          <th>恢復手段</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>應用程式 crash</td>
          <td>單一視窗消失</td>
          <td>無</td>
          <td>重開該程式</td>
      </tr>
      <tr>
          <td>工具 crash（waybar 等）</td>
          <td>狀態列 / 通知 / 啟動器消失</td>
          <td>無</td>
          <td>重啟該工具</td>
      </tr>
      <tr>
          <td>Compositor crash</td>
          <td>所有視窗消失、黑屏</td>
          <td>桌面環境不可用</td>
          <td>TTY 登入、重啟 compositor</td>
      </tr>
      <tr>
          <td>GPU driver hang</td>
          <td>畫面凍結</td>
          <td>桌面環境不可用</td>
          <td>TTY 或 SSH、kill compositor</td>
      </tr>
      <tr>
          <td>OOM</td>
          <td>系統極慢或桌面被殺</td>
          <td>部分 process 被終止</td>
          <td>TTY 登入、清理 process</td>
      </tr>
      <tr>
          <td>Kernel panic</td>
          <td>完全停機</td>
          <td>全機不可用</td>
          <td>只能重開機</td>
      </tr>
  </tbody>
</table>
<p>前五個層級都有恢復手段，只有 kernel panic 需要重開機。日常使用中遇到的故障多數落在前三層。</p>
]]></content:encoded></item><item><title>常見故障場景與恢復操作</title><link>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/</link><pubDate>Tue, 30 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/</guid><description>&lt;p>這篇按故障場景組織，每個場景列出症狀、原因、恢復步驟和預防措施。出問題時按症狀找到對應場景，照步驟操作。&lt;/p>
&lt;h2 id="場景一hyprland-compositor-crash">場景一：Hyprland compositor crash&lt;/h2>
&lt;p>&lt;strong>症狀&lt;/strong>：所有視窗同時消失，螢幕變黑或回到 TTY 登入畫面。滑鼠鍵盤有反應（可以切 TTY），但沒有桌面。&lt;/p>
&lt;p>&lt;strong>原因&lt;/strong>：Compositor process 遇到 fatal error 被 kernel 終止。常見觸發條件包括 plugin 相容性問題、特定 Wayland 協議操作觸發的 bug、GPU driver 回傳異常狀態。&lt;/p>
&lt;p>&lt;strong>恢復步驟&lt;/strong>：&lt;/p>
&lt;p>注意：以下步驟中 &lt;code>killall Hyprland&lt;/code> 或重啟 Hyprland 會終止所有由 compositor 管理的視窗，未存檔的工作會遺失。如果可能，先透過 TTY 或 SSH 嘗試存檔（如 &lt;code>kill -USR1 &amp;lt;pid&amp;gt;&lt;/code> 對支援的應用程式觸發存檔）。&lt;/p>
&lt;ol>
&lt;li>&lt;code>Ctrl+Alt+F2&lt;/code> 切到 TTY2&lt;/li>
&lt;li>用你的帳號登入&lt;/li>
&lt;li>檢查 Hyprland 的最後錯誤訊息：&lt;/li>
&lt;/ol>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 通用方式（不管 Hyprland 怎麼啟動都有效）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">journalctl -b &lt;span class="p">|&lt;/span> grep -i hypr &lt;span class="p">|&lt;/span> tail -30
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 如果 Hyprland 是 systemd user unit，可以更精準地查：&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">journalctl --user -u hyprland -n &lt;span class="m">50&lt;/span> --no-pager&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="4">
&lt;li>重新啟動 Hyprland：&lt;/li>
&lt;/ol>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Hyprland&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol start="5">
&lt;li>如果反覆 crash，檢查最近改過的 config：&lt;/li>
&lt;/ol>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="nb">cd&lt;/span> ~/.config/hypr
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">git diff &lt;span class="c1"># 如果 dotfile 有版控&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>預防&lt;/strong>：config 改動後用 &lt;code>hyprctl reload&lt;/code> 測試，不要直接重啟。啟用 plugin 前確認版本跟 Hyprland 版本相容。&lt;/p>
&lt;h2 id="場景二單一桌面工具掛了">場景二：單一桌面工具掛了&lt;/h2>
&lt;p>&lt;strong>症狀&lt;/strong>：狀態列（waybar）消失、啟動器（wofi/rofi）叫不出來、通知（mako/dunst）不跳了。桌面其他功能正常，視窗可以操作。&lt;/p>
&lt;p>&lt;strong>原因&lt;/strong>：這些工具各自是獨立的 process。掛了只影響自己的功能，不影響 compositor 或其他工具。常見原因是 config 語法錯誤（改完 config 後觸發）、記憶體洩漏（長時間運作後）、或外部服務連線異常（如 waybar 的某個 module 連不到系統匯流排）。&lt;/p>
&lt;p>&lt;strong>恢復步驟&lt;/strong>：&lt;/p>
&lt;p>判斷啟動方式：如果工具是在 Hyprland config 裡用 &lt;code>exec-once&lt;/code>（Hyprland 的自動啟動指令，compositor 啟動時執行一次）啟動的，用 &lt;code>killall&lt;/code> + 手動重啟；如果是 systemd user unit，用 &lt;code>systemctl --user&lt;/code>。&lt;/p>
&lt;p>&lt;code>exec-once&lt;/code> 啟動方式（多數 Hyprland 安裝的預設做法）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># waybar 掛了&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">killall waybar&lt;span class="p">;&lt;/span> waybar &lt;span class="p">&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># wofi 掛了&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">killall wofi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1"># wofi 只在需要時啟動，不用常駐&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c1"># mako 掛了&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">killall mako&lt;span class="p">;&lt;/span> mako &lt;span class="p">&amp;amp;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>systemd user unit 啟動方式：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">systemctl --user restart waybar
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">systemctl --user restart mako&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>確認工具是否在跑&lt;/strong>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">pgrep waybar &lt;span class="c1"># 有輸出 = 在跑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">pgrep mako &lt;span class="c1"># 沒輸出 = 沒在跑&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>預防&lt;/strong>：改 config 後重啟對應的工具確認語法正確。Waybar 的 config 是 JSON 格式，語法錯誤會導致它無法啟動——改完後先用 &lt;code>waybar&lt;/code> 前台跑一次看有沒有錯誤訊息。&lt;/p>
&lt;h2 id="場景二點五鎖屏卡死hyprlock-異常結束">場景二點五：鎖屏卡死（hyprlock 異常結束）&lt;/h2>
&lt;p>&lt;strong>症狀&lt;/strong>：鎖屏畫面消失但桌面沒回來，螢幕顯示 Hyprland 的失效保護訊息（「it looks like you locked your screen but the lockscreen app died」），或畫面全黑但系統有回應（SSH 能連、TTY 可能切得到也可能切不到）。&lt;/p>
&lt;p>&lt;strong>原因&lt;/strong>：鎖屏工具（Hyprlock、Swaylock）透過 Wayland 的 ext-session-lock 協議向 compositor 請求鎖定。鎖定狀態由 compositor 持有，唯一正常解鎖動作是鎖屏 client 通過認證後呼叫 unlock_and_destroy。如果鎖屏 client 在持鎖狀態下被殺（&lt;code>pkill&lt;/code>、crash），compositor 沒收到認證信號，會維持鎖定並顯示失效保護畫面。這跟殺 waybar/mako 不同——那些是普通 process，殺了重啟就好；鎖屏 client 持有安全狀態，殺了反而卡住。&lt;/p></description><content:encoded><![CDATA[<p>這篇按故障場景組織，每個場景列出症狀、原因、恢復步驟和預防措施。出問題時按症狀找到對應場景，照步驟操作。</p>
<h2 id="場景一hyprland-compositor-crash">場景一：Hyprland compositor crash</h2>
<p><strong>症狀</strong>：所有視窗同時消失，螢幕變黑或回到 TTY 登入畫面。滑鼠鍵盤有反應（可以切 TTY），但沒有桌面。</p>
<p><strong>原因</strong>：Compositor process 遇到 fatal error 被 kernel 終止。常見觸發條件包括 plugin 相容性問題、特定 Wayland 協議操作觸發的 bug、GPU driver 回傳異常狀態。</p>
<p><strong>恢復步驟</strong>：</p>
<p>注意：以下步驟中 <code>killall Hyprland</code> 或重啟 Hyprland 會終止所有由 compositor 管理的視窗，未存檔的工作會遺失。如果可能，先透過 TTY 或 SSH 嘗試存檔（如 <code>kill -USR1 &lt;pid&gt;</code> 對支援的應用程式觸發存檔）。</p>
<ol>
<li><code>Ctrl+Alt+F2</code> 切到 TTY2</li>
<li>用你的帳號登入</li>
<li>檢查 Hyprland 的最後錯誤訊息：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 通用方式（不管 Hyprland 怎麼啟動都有效）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">journalctl -b <span class="p">|</span> grep -i hypr <span class="p">|</span> tail -30
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 如果 Hyprland 是 systemd user unit，可以更精準地查：</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">journalctl --user -u hyprland -n <span class="m">50</span> --no-pager</span></span></code></pre></div><ol start="4">
<li>重新啟動 Hyprland：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">Hyprland</span></span></code></pre></div><ol start="5">
<li>如果反覆 crash，檢查最近改過的 config：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">cd</span> ~/.config/hypr
</span></span><span class="line"><span class="ln">2</span><span class="cl">git diff  <span class="c1"># 如果 dotfile 有版控</span></span></span></code></pre></div><p><strong>預防</strong>：config 改動後用 <code>hyprctl reload</code> 測試，不要直接重啟。啟用 plugin 前確認版本跟 Hyprland 版本相容。</p>
<h2 id="場景二單一桌面工具掛了">場景二：單一桌面工具掛了</h2>
<p><strong>症狀</strong>：狀態列（waybar）消失、啟動器（wofi/rofi）叫不出來、通知（mako/dunst）不跳了。桌面其他功能正常，視窗可以操作。</p>
<p><strong>原因</strong>：這些工具各自是獨立的 process。掛了只影響自己的功能，不影響 compositor 或其他工具。常見原因是 config 語法錯誤（改完 config 後觸發）、記憶體洩漏（長時間運作後）、或外部服務連線異常（如 waybar 的某個 module 連不到系統匯流排）。</p>
<p><strong>恢復步驟</strong>：</p>
<p>判斷啟動方式：如果工具是在 Hyprland config 裡用 <code>exec-once</code>（Hyprland 的自動啟動指令，compositor 啟動時執行一次）啟動的，用 <code>killall</code> + 手動重啟；如果是 systemd user unit，用 <code>systemctl --user</code>。</p>
<p><code>exec-once</code> 啟動方式（多數 Hyprland 安裝的預設做法）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># waybar 掛了</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">killall waybar<span class="p">;</span> waybar <span class="p">&amp;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># wofi 掛了</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">killall wofi
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># wofi 只在需要時啟動，不用常駐</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># mako 掛了</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">killall mako<span class="p">;</span> mako <span class="p">&amp;</span></span></span></code></pre></div><p>systemd user unit 啟動方式：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">systemctl --user restart waybar
</span></span><span class="line"><span class="ln">2</span><span class="cl">systemctl --user restart mako</span></span></code></pre></div><p><strong>確認工具是否在跑</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">pgrep waybar  <span class="c1"># 有輸出 = 在跑</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">pgrep mako    <span class="c1"># 沒輸出 = 沒在跑</span></span></span></code></pre></div><p><strong>預防</strong>：改 config 後重啟對應的工具確認語法正確。Waybar 的 config 是 JSON 格式，語法錯誤會導致它無法啟動——改完後先用 <code>waybar</code> 前台跑一次看有沒有錯誤訊息。</p>
<h2 id="場景二點五鎖屏卡死hyprlock-異常結束">場景二點五：鎖屏卡死（hyprlock 異常結束）</h2>
<p><strong>症狀</strong>：鎖屏畫面消失但桌面沒回來，螢幕顯示 Hyprland 的失效保護訊息（「it looks like you locked your screen but the lockscreen app died」），或畫面全黑但系統有回應（SSH 能連、TTY 可能切得到也可能切不到）。</p>
<p><strong>原因</strong>：鎖屏工具（Hyprlock、Swaylock）透過 Wayland 的 ext-session-lock 協議向 compositor 請求鎖定。鎖定狀態由 compositor 持有，唯一正常解鎖動作是鎖屏 client 通過認證後呼叫 unlock_and_destroy。如果鎖屏 client 在持鎖狀態下被殺（<code>pkill</code>、crash），compositor 沒收到認證信號，會維持鎖定並顯示失效保護畫面。這跟殺 waybar/mako 不同——那些是普通 process，殺了重啟就好；鎖屏 client 持有安全狀態，殺了反而卡住。</p>
<p><strong>恢復步驟</strong>：</p>
<ol>
<li>嘗試切到另一個 TTY（<code>Ctrl+Alt+F2</code>）。注意：ext-session-lock 的安全語意允許 compositor 攔截 VT 切換快捷鍵，此時 TTY 切不過去，改用 SSH 從另一台機器連入</li>
<li>允許新的鎖屏 client 接管既有的鎖：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hyprctl --instance <span class="m">0</span> <span class="s1">&#39;keyword misc:allow_session_lock_restore 1&#39;</span></span></span></code></pre></div><ol start="3">
<li>重新拉一個鎖屏 client：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">hyprctl --instance <span class="m">0</span> <span class="s1">&#39;dispatch exec hyprlock&#39;</span></span></span></code></pre></div><ol start="4">
<li>回到鎖屏畫面，用密碼正常解鎖</li>
</ol>
<p><strong>判讀</strong>：<code>loginctl show-session &lt;id&gt; -p LockedHint</code> 可能顯示 <code>LockedHint=no</code>（logind 層認為沒鎖），但畫面仍進不去——因為擋住畫面的是 compositor 的 ext-session-lock，跟 logind 的提示是獨立的兩層。判斷畫面鎖定狀態看 compositor 層，不看 logind。</p>
<p><strong>預防</strong>：測試鎖屏時備好恢復路徑（知道密碼、或預先開 SSH）。不要用殺 process 的方式結束鎖屏——要結束就走認證解鎖。自動化流程若會啟動鎖屏，把「需要人工解鎖」算進代價。鎖屏安全模型的完整說明見 <a href="/blog/linux/dotfile/knowledge-cards/session-lock/" data-link-title="Wayland Session Lock（鎖屏安全狀態）" data-link-desc="hyprlock / swaylock 畫面卡住、pkill 後進不了桌面、或要在 VM / 自動化環境測試鎖屏時回來讀">Session Lock</a>。</p>
<h2 id="場景二點六桌面-shell-畫得出來但互動死掉進程活著卻-wedged">場景二點六：桌面 shell 畫得出來但互動死掉（進程活著卻 wedged）</h2>
<p><strong>症狀</strong>：bar / 狀態列還在螢幕上、看起來一切正常，但點它的按鈕（工作區切換、系統匣圖示）沒反應，keybind 叫不出啟動器（wofi / 內建 launcher）。同時焦點視窗（例如終端機）打字完全正常——鍵盤到得了應用程式，只是桌面 shell 的互動死了。</p>
<p><strong>原因</strong>：這是跟場景二（工具掛了）不同的一類故障，關鍵差別在<strong>進程還活著</strong>。場景二是 process 崩潰退出（<code>pgrep</code> 沒輸出），殺了重啟就好；這裡的桌面 shell（如 caelestia / Quickshell）進程還在跑（<code>pgrep</code> 找得到、STAT 是正常的 <code>S</code>、在 <code>poll</code> 等事件、CPU 不高），但它內部的某個子系統初始化失敗了——常見是 QML scene 的某個物件因為上游錯誤沒建起來、變成 null，於是負責「keybind → 開抽屜」「bar 按鈕互動」的模組對 null 讀屬性、整條互動接線死掉。bar 之所以還畫得出來，是它還停在初始化失敗前那一幀的畫面：<strong>畫得出來不等於還活著</strong>，跟鎖屏那課（畫面有密碼框不等於真的在鎖）是同一個陷阱。</p>
<p>上游觸發常是渲染層。實測案例：VM 的 GPU 只提供到 GLSL 1.20，而 shell 的 shader 需要 GLES 100/300/330，pipeline 建不起來（log 狂噴 <code>Failed to build graphics pipeline state</code>），這次渲染失敗把 scene 初始化打斷，drawers 狀態物件變 null。</p>
<p><strong>診斷（別看 pgrep，讀 shell 自己的 log）</strong>：</p>
<p><code>pgrep</code> 在這裡會騙你——它回報「在跑」，但那不等於「在運作」。權威來源是 shell 自己的 log，而且這種 log 常常<strong>不在 journalctl、也不在你猜的路徑</strong>，要用該 shell 專屬的 log 指令：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># caelestia 的例子：用它自己的 CLI 印 shell log</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">caelestia shell -l 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span> tail -40
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 看的是 QML 的 TypeError：對 null 讀屬性 = 那個子系統死了</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1">#   scene: @modules/Shortcuts.qml: TypeError: Cannot read property &#39;launcher&#39; of null</span></span></span></code></pre></div><p>另一個活性探針是 shell 的 <strong>IPC 回不回真實狀態</strong>：正常時查抽屜列表會回傳名字，子系統死掉時回空——這比「進程在不在」精準得多：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 子系統活著 → 列出 bar/launcher/session…；死掉 → 回空</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">caelestia shell ipc call drawers list</span></span></code></pre></div><p><strong>恢復步驟</strong>：重啟 shell 讓 scene 重建。以 caelestia 為例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">caelestia shell -k     <span class="c1"># 殺掉卡住的 shell</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">caelestia shell -d     <span class="c1"># 重新啟動（detached）</span></span></span></code></pre></div><p><strong>驗證修好了，看子系統回來、不是看 pgrep</strong>：重啟後 process 一定在（<code>pgrep</code> 本來就會有），要確認的是接線恢復——<code>caelestia shell ipc call drawers list</code> 從「回空」變成列出真實抽屜名、log 不再噴 null 的 TypeError。這對應「重啟成功要驗子系統狀態、不是驗 process 存在」的通用紀律。</p>
<p><strong>判讀與其他場景的界線</strong>：<code>pgrep</code> 有輸出 + bar 畫得出來 → 別急著判「正常」；點不動 / keybind 死掉就是 wedged 的訊號，往 shell 自己的 log 查。這跟場景二（process 真的沒了、<code>pgrep</code> 空）、場景三（compositor 整個凍結、連終端機打字都不行）都不同——這裡 compositor 正常、焦點視窗鍵盤正常，只有 shell 的互動接線死。判「進程活著到底有沒有在運作」的通用招式，見 <a href="/blog/linux/debug/process-service-state-diagnosis/" data-link-title="程序、服務與狀態怎麼判" data-link-desc="要判斷一個程式活著沒、某個系統服務現在由誰提供、桌面 session 有沒有被鎖、或終端機多工器的 session 還在不在時，用對的權威來源而不是靠畫面或猜的名字">程序、服務與狀態怎麼判</a>。</p>
<p><strong>預防</strong>：留意 shell log 裡持續出現的 shader / 渲染 pipeline 錯誤——在 VM 或 GL 支援不足的環境，這類錯誤可能非致命地存在（shell 大致能用），但一次渲染失敗就可能打斷 scene 初始化、把互動接線弄死。VM 環境要確認 GPU 提供的 GL / GLSL 版本足夠（virtio-gpu 走 mesa/zink 提供 GL 3.3+），或在 shell 設定關掉需要高階 shader 的效果。</p>
<h2 id="場景三gpu-driver-hang畫面凍結">場景三：GPU driver hang（畫面凍結）</h2>
<p><strong>症狀</strong>：桌面畫面完全凍結——滑鼠不動、鍵盤不回應、<code>Ctrl+Alt+F2</code> 切 TTY 也沒反應或延遲很久才回應。但如果從另一台機器 SSH 進來，系統是活的，process 都在跑。</p>
<p><strong>原因</strong>：GPU driver 進入異常狀態。NVIDIA 閉源驅動在 Linux 上的穩定性不如 AMD 開源驅動（amdgpu），特別是在 Wayland 環境下。常見觸發條件包括 suspend/resume 之後 GPU 沒正確恢復、某些 OpenGL/Vulkan 操作觸發 driver bug、顯示輸出切換（接上或拔掉外接螢幕）。</p>
<p><strong>恢復步驟</strong>：</p>
<p>方法 A — 如果 TTY 能切過去：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 切到 TTY2</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">Ctrl+Alt+F2
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 殺掉 Hyprland（它會帶走所有視窗）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">killall Hyprland
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 重新啟動</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">Hyprland</span></span></code></pre></div><p>方法 B — 如果 TTY 也凍結、但 SSH 能連：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 從另一台機器 SSH 進來（需事先知道 IP，見下方預防段）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">ssh user@machine-ip
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 殺掉 compositor</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">killall Hyprland
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 如果需要 reset GPU（NVIDIA，且 driver 仍回應）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 前提：所有使用 GPU 的 process 已停止（compositor 已 kill）</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">sudo nvidia-smi --gpu-reset
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 切回機器前面重啟 Hyprland</span></span></span></code></pre></div><p>方法 C — 如果完全無回應，先嘗試 Magic SysRq：</p>
<p>Magic SysRq 是 kernel 層級的緊急操作介面，即使 userspace 完全卡死也能回應。按住 <code>Alt+SysRq</code>（筆電通常是 <code>Alt+Fn+SysRq</code>），然後依序按 <code>R E I S U B</code>（每個鍵間隔幾秒）：</p>
<ul>
<li><code>R</code> — 把鍵盤從 raw mode 搶回來</li>
<li><code>E</code> — 對所有 process 送 SIGTERM</li>
<li><code>I</code> — 對所有 process 送 SIGKILL</li>
<li><code>S</code> — sync 所有檔案系統</li>
<li><code>U</code> — remount 所有檔案系統為 read-only</li>
<li><code>B</code> — 立即 reboot</li>
</ul>
<p>這比直接斷電安全——sync + unmount 步驟會盡量保護磁碟上的資料。Arch Linux 預設可能停用 SysRq，需在 <code>/etc/sysctl.d/</code> 設定 <code>kernel.sysrq=1</code> 啟用。</p>
<p>方法 D — 如果 SysRq 也無效，按住電源鍵強制關機：</p>
<p>這是最後手段。Linux 的 ext4/btrfs 檔案系統有 journal 保護，強制關機通常不會損壞<strong>檔案系統結構</strong>。但 journal 保護的是 metadata 一致性，正在寫入的使用者資料（未存檔的文件、正在下載的檔案）仍然可能遺失或損壞。重開機後正常登入 TTY、啟動 Hyprland 即可。如果開機過程有異常，用 <code>journalctl -b -1 -p err</code> 查看上次開機的錯誤訊息，確認是否有檔案系統修復紀錄。</p>
<p><strong>預防</strong>：</p>
<ul>
<li>NVIDIA 用戶：關注 driver 版本的 release notes，已知有 Wayland 問題的版本避開</li>
<li>配置 suspend 後的 GPU 恢復：在 Hyprland config 或 systemd sleep hook 裡加入 GPU reset 操作</li>
<li>事先記錄機器的 IP 位址（<code>ip addr show</code>）或設定固定 hostname（如 mDNS 的 <code>machine.local</code>），桌面凍結時才有辦法從另一台機器 SSH 進來</li>
<li>考慮開啟 SSH server，出問題時可以遠端救援。開啟後應配置 key-based authentication 並停用密碼登入（<code>PasswordAuthentication no</code>），避免在網路上暴露密碼登入通道：</li>
</ul>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo systemctl <span class="nb">enable</span> sshd
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo systemctl start sshd
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 安全配置：停用密碼登入（確保已設好 SSH key 再改）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 編輯 /etc/ssh/sshd_config，設定 PasswordAuthentication no</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># 然後 sudo systemctl restart sshd</span></span></span></code></pre></div><h2 id="場景四記憶體耗盡oom">場景四：記憶體耗盡（OOM）</h2>
<p><strong>症狀</strong>：系統變得極慢，操作有明顯延遲（幾秒到幾十秒）。隨後可能某些 process 突然被殺掉——瀏覽器分頁消失、IDE 視窗關閉，嚴重時 Hyprland 本身被 OOM Killer 終止導致桌面消失。</p>
<p><strong>原因</strong>：實體記憶體和 swap 都用完了。常見觸發者是瀏覽器（Chrome/Firefox 的分頁越開越多）、IDE（大型專案的 language server）、Docker container、或應用程式的記憶體洩漏。</p>
<p><strong>恢復步驟</strong>：</p>
<p>如果還能操作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 找出誰在吃記憶體</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">top -o %MEM
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 或用 htop/btop 的互動介面</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 殺掉佔最多記憶體的 process</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nb">kill</span> &lt;PID&gt;</span></span></code></pre></div><p>如果桌面已經被殺、在 TTY 裡：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 看 OOM Killer 殺了誰</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">journalctl -b <span class="p">|</span> grep -i <span class="s2">&#34;out of memory&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">journalctl -b <span class="p">|</span> grep -i <span class="s2">&#34;oom&#34;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 清理完後重啟桌面</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">Hyprland</span></span></code></pre></div><p><strong>預防</strong>：</p>
<p>設定 swap（即使 RAM 夠大，swap 提供 OOM 前的緩衝時間讓你有機會手動清理 process）。RAM 16GB 以上的機器，2-4GB swap 作緩衝通常足夠：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 查看是否有 swap</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">swapon --show
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 如果沒有，建立一個 4GB 的 swap file（ext4 檔案系統）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">sudo fallocate -l 4G /swapfile
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">sudo chmod <span class="m">600</span> /swapfile
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">sudo mkswap /swapfile
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">sudo swapon /swapfile
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 永久生效：加入 /etc/fstab</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">echo</span> <span class="s1">&#39;/swapfile none swap defaults 0 0&#39;</span> <span class="p">|</span> sudo tee -a /etc/fstab</span></span></code></pre></div><p>Btrfs 檔案系統不支援 <code>fallocate</code> 建立 swap file。Btrfs 用戶需改用 <code>btrfs filesystem mkswapfile</code> 或建立專屬的 swap subvolume，具體做法參考 Arch Wiki 的 Btrfs swap 段落。</p>
<p>啟用 systemd-oomd（比 kernel OOM Killer 更早介入、更可控）。systemd-oomd 在 cgroup 的記憶體壓力達到閾值時就開始清理，預設配置對多數桌面場景足夠。進階調整可透過 <code>/etc/systemd/oomd.conf</code> 設定：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo systemctl <span class="nb">enable</span> systemd-oomd
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo systemctl start systemd-oomd</span></span></code></pre></div><h2 id="場景五config-寫錯導致-hyprland-啟動失敗">場景五：Config 寫錯導致 Hyprland 啟動失敗</h2>
<p><strong>症狀</strong>：從 display manager（圖形登入畫面，如 SDDM、GDM）登入後立刻黑屏又回到登入畫面，或直接回到 TTY。如果從 TTY 手動執行 <code>Hyprland</code>，看到錯誤訊息後立即退出。</p>
<p><strong>原因</strong>：Hyprland config 有語法錯誤或引用了不存在的資源。常見錯誤包括 <code>source</code> 指定的檔案不存在、keybind 語法寫錯、monitor 設定格式錯誤。</p>
<p><strong>恢復步驟</strong>：</p>
<ol>
<li>切到 TTY（<code>Ctrl+Alt+F2</code>）</li>
<li>登入後直接跑 Hyprland 看錯誤訊息：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 看 Hyprland 的啟動錯誤（也可用 journalctl -b | grep -i hypr）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">Hyprland
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># Hyprland 如果因 config 錯誤無法啟動，會直接印出錯誤訊息後退出</span></span></span></code></pre></div><ol start="3">
<li>根據錯誤訊息修改 config：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Hyprland 的主 config</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">vim ~/.config/hypr/hyprland.conf
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 如果用了 source 拆分，錯誤訊息會指出是哪個檔案</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">vim ~/.config/hypr/keybinds.conf</span></span></code></pre></div><ol start="4">
<li>修完後重新啟動：</li>
</ol>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">Hyprland</span></span></code></pre></div><p><strong>常見 config 錯誤</strong>：</p>
<p><code>source</code> 路徑錯誤——檔案不存在或路徑拼錯：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 確認 source 指定的檔案都存在</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">grep <span class="s2">&#34;^source&#34;</span> ~/.config/hypr/hyprland.conf
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 逐一檢查每個路徑</span></span></span></code></pre></div><p>Monitor 設定錯誤——指定了不存在的螢幕名稱：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 查看系統實際的螢幕名稱</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># 在能進桌面時記下來，或用 wlr-randr</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">wlr-randr</span></span></code></pre></div><p>Keybind 語法錯誤——dispatcher 名稱拼錯或參數格式不對。Hyprland 的 keybind 格式是 <code>bind = MOD, key, dispatcher, params</code>，少一個欄位或 dispatcher 拼錯就會報錯。</p>
<p><strong>預防</strong>：config 改動時用 <code>hyprctl reload</code> 即時測試，不要改完 config 就直接重啟 Hyprland。如果 dotfile 用 Git 管理，改壞了可以 <code>git checkout</code> 回退。</p>
<h2 id="場景六suspendresume-後桌面異常">場景六：Suspend/resume 後桌面異常</h2>
<p><strong>症狀</strong>：筆電蓋上或手動 suspend 後喚醒，出現以下任一情況——螢幕黑屏但系統有反應（鍵盤背光亮）、解析度跑掉、多螢幕配置丟失（所有視窗擠到一個螢幕）、compositor 直接 crash 回到 TTY。</p>
<p><strong>原因</strong>：GPU driver 在 suspend/resume 過程中需要保存和恢復 GPU 狀態。NVIDIA 閉源驅動在 Wayland 上的 suspend/resume 支援不如 AMD 開源驅動穩定，特別是多螢幕配置和高刷新率模式下容易出問題。</p>
<p><strong>恢復步驟</strong>：</p>
<p>如果螢幕黑屏但系統有反應：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 切到 TTY</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">Ctrl+Alt+F2
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 檢查 Hyprland 是否還在跑</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">pgrep Hyprland
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 如果在跑但沒畫面，kill 再重啟</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">killall Hyprland
</span></span><span class="line"><span class="ln">9</span><span class="cl">Hyprland</span></span></code></pre></div><p>如果解析度或螢幕配置跑掉：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 在 Hyprland 內重新套用 monitor 設定</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">hyprctl reload</span></span></code></pre></div><p>如果 compositor 已經 crash：按場景一的步驟從 TTY 重啟。</p>
<p><strong>預防</strong>：</p>
<ul>
<li>NVIDIA 用戶：在 <code>/etc/modprobe.d/nvidia.conf</code> 啟用 preserve video memory allocations：</li>
</ul>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># /etc/modprobe.d/nvidia.conf</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">options nvidia <span class="nv">NVreg_PreserveVideoMemoryAllocations</span><span class="o">=</span><span class="m">1</span></span></span></code></pre></div><p>同時啟用 NVIDIA 的 suspend/resume systemd service：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">sudo systemctl <span class="nb">enable</span> nvidia-suspend
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo systemctl <span class="nb">enable</span> nvidia-resume
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo systemctl <span class="nb">enable</span> nvidia-hibernate</span></span></code></pre></div><ul>
<li>AMD 用戶：amdgpu driver 的 suspend/resume 通常開箱即用，遇到問題先更新 kernel（<code>pacman -Syu linux</code>）。</li>
</ul>
]]></content:encoded></item><item><title>日誌判讀與診斷工具</title><link>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/log-reading-diagnostic-tools/</link><pubDate>Tue, 30 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/07-desktop-maintenance/log-reading-diagnostic-tools/</guid><description>&lt;p>恢復操作解決的是「怎麼讓桌面回來」，日誌判讀解決的是「為什麼會壞掉」。前者是急救，後者是找病因。如果同一個問題反覆出現，只做急救不找根因會一直繞圈。&lt;/p>
&lt;h2 id="journalctl系統日誌的主要入口">journalctl：系統日誌的主要入口&lt;/h2>
&lt;p>systemd 的日誌系統（journal）集中收錄所有 service、kernel、user session 的 log。&lt;code>journalctl&lt;/code> 是查詢這些日誌的指令。&lt;/p>
&lt;h3 id="基本用法">基本用法&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 本次開機的所有日誌&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">journalctl -b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 本次開機的錯誤以上等級（err + crit + alert + emerg）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">journalctl -b -p err
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 本次開機，只看最後 50 行&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">journalctl -b -n &lt;span class="m">50&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># 上一次開機的日誌（如果問題發生在上次開機、這次重開後想查）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">journalctl -b -1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="c1"># 即時跟蹤新 log（類似 tail -f）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">journalctl -f&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="過濾特定來源">過濾特定來源&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 只看 Hyprland 相關&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">journalctl -b &lt;span class="p">|&lt;/span> grep -i hypr
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 只看特定 systemd user unit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">journalctl --user -u waybar -b
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 只看 kernel 訊息（等同 dmesg）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">journalctl -b -k
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># 只看某個 process 的 log（用 PID）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">journalctl &lt;span class="nv">_PID&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">12345&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="時間範圍過濾">時間範圍過濾&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 最近 10 分鐘的 log&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">journalctl --since &lt;span class="s2">&amp;#34;10 min ago&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 指定時間區間&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">journalctl --since &lt;span class="s2">&amp;#34;2026-06-30 14:00&amp;#34;&lt;/span> --until &lt;span class="s2">&amp;#34;2026-06-30 14:30&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="dmesgkernel-層訊息">dmesg：Kernel 層訊息&lt;/h2>
&lt;p>&lt;code>dmesg&lt;/code> 顯示 kernel ring buffer 的內容——硬體偵測、driver 載入、硬體錯誤這些 kernel 層面的事件。排查 GPU driver 問題、USB 裝置問題、磁碟錯誤時需要看這裡。&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 所有 kernel 訊息（帶時間戳記）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">dmesg -T
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 只看錯誤和警告&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">dmesg -T --level&lt;span class="o">=&lt;/span>err,warn
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># GPU 相關（NVIDIA）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">dmesg -T &lt;span class="p">|&lt;/span> grep -i nvidia
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># GPU 相關（AMD）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">dmesg -T &lt;span class="p">|&lt;/span> grep -i amdgpu
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="c1"># USB 相關（鍵盤滑鼠突然不回應時看這裡）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">dmesg -T &lt;span class="p">|&lt;/span> grep -i usb&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>GPU driver 問題在 dmesg 裡的嚴重度差異很大：&lt;/p>
&lt;p>一般 GPU hang（driver 嘗試自動恢復）：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">[ 123.456] nvidia-modeset: ERROR: ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">[ 123.789] NVRM: Xid (PCI:0000:01:00): 79, pid=1234, ...
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">[ 124.000] amdgpu: GPU reset begin!
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">[ 124.500] amdgpu: GPU reset succeeded&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>NVIDIA 的 &lt;code>Xid&lt;/code> 錯誤代碼表示不同類型的 GPU 錯誤。常見的 &lt;code>Xid 79&lt;/code> 是 GPU fallback，&lt;code>Xid 31&lt;/code> 是 GPU setup failure。完整代碼表可在 NVIDIA 官方文件搜尋「Xid Errors」。&lt;/p></description><content:encoded><![CDATA[<p>恢復操作解決的是「怎麼讓桌面回來」，日誌判讀解決的是「為什麼會壞掉」。前者是急救，後者是找病因。如果同一個問題反覆出現，只做急救不找根因會一直繞圈。</p>
<h2 id="journalctl系統日誌的主要入口">journalctl：系統日誌的主要入口</h2>
<p>systemd 的日誌系統（journal）集中收錄所有 service、kernel、user session 的 log。<code>journalctl</code> 是查詢這些日誌的指令。</p>
<h3 id="基本用法">基本用法</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 本次開機的所有日誌</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">journalctl -b
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 本次開機的錯誤以上等級（err + crit + alert + emerg）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">journalctl -b -p err
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 本次開機，只看最後 50 行</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">journalctl -b -n <span class="m">50</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 上一次開機的日誌（如果問題發生在上次開機、這次重開後想查）</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">journalctl -b -1
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 即時跟蹤新 log（類似 tail -f）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">journalctl -f</span></span></code></pre></div><h3 id="過濾特定來源">過濾特定來源</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 只看 Hyprland 相關</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">journalctl -b <span class="p">|</span> grep -i hypr
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 只看特定 systemd user unit</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">journalctl --user -u waybar -b
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 只看 kernel 訊息（等同 dmesg）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">journalctl -b -k
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 只看某個 process 的 log（用 PID）</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">journalctl <span class="nv">_PID</span><span class="o">=</span><span class="m">12345</span></span></span></code></pre></div><h3 id="時間範圍過濾">時間範圍過濾</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 最近 10 分鐘的 log</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">journalctl --since <span class="s2">&#34;10 min ago&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 指定時間區間</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">journalctl --since <span class="s2">&#34;2026-06-30 14:00&#34;</span> --until <span class="s2">&#34;2026-06-30 14:30&#34;</span></span></span></code></pre></div><h2 id="dmesgkernel-層訊息">dmesg：Kernel 層訊息</h2>
<p><code>dmesg</code> 顯示 kernel ring buffer 的內容——硬體偵測、driver 載入、硬體錯誤這些 kernel 層面的事件。排查 GPU driver 問題、USB 裝置問題、磁碟錯誤時需要看這裡。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 所有 kernel 訊息（帶時間戳記）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">dmesg -T
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 只看錯誤和警告</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">dmesg -T --level<span class="o">=</span>err,warn
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># GPU 相關（NVIDIA）</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">dmesg -T <span class="p">|</span> grep -i nvidia
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># GPU 相關（AMD）</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">dmesg -T <span class="p">|</span> grep -i amdgpu
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># USB 相關（鍵盤滑鼠突然不回應時看這裡）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">dmesg -T <span class="p">|</span> grep -i usb</span></span></code></pre></div><p>GPU driver 問題在 dmesg 裡的嚴重度差異很大：</p>
<p>一般 GPU hang（driver 嘗試自動恢復）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[  123.456] nvidia-modeset: ERROR: ...
</span></span><span class="line"><span class="ln">2</span><span class="cl">[  123.789] NVRM: Xid (PCI:0000:01:00): 79, pid=1234, ...
</span></span><span class="line"><span class="ln">3</span><span class="cl">[  124.000] amdgpu: GPU reset begin!
</span></span><span class="line"><span class="ln">4</span><span class="cl">[  124.500] amdgpu: GPU reset succeeded</span></span></code></pre></div><p>NVIDIA 的 <code>Xid</code> 錯誤代碼表示不同類型的 GPU 錯誤。常見的 <code>Xid 79</code> 是 GPU fallback，<code>Xid 31</code> 是 GPU setup failure。完整代碼表可在 NVIDIA 官方文件搜尋「Xid Errors」。</p>
<p>硬體層級故障（嚴重，可能需要檢查硬體）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">[  123.789] NVRM: Xid (PCI:0000:01:00): 79, pid=1234, GPU has fallen off the bus</span></span></code></pre></div><p><code>GPU has fallen off the bus</code> 表示 GPU 跟主機板的 PCIe 連線完全中斷。偶發一次可能是 driver 問題，反覆出現通常是硬體故障（PCIe 供電不足、顯卡接觸不良、過熱）。</p>
<h2 id="hyprctlhyprland-的-runtime-狀態查詢">hyprctl：Hyprland 的 Runtime 狀態查詢</h2>
<p><code>hyprctl</code> 是 Hyprland 提供的命令列控制工具，可以在 compositor 運行中查詢狀態和執行操作。只有在 Hyprland 正在跑的時候才能使用。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 目前所有視窗的資訊</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">hyprctl clients
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 目前的 monitor 設定</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">hyprctl monitors
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 目前的 workspace 資訊</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">hyprctl workspaces
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># Hyprland 版本和 build 資訊</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">hyprctl version
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 重新載入 config（不重啟 compositor）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">hyprctl reload
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 查看上一次 config reload 是否有錯誤</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">hyprctl systeminfo</span></span></code></pre></div><p><code>hyprctl reload</code> 是測試 config 變更的安全方式。如果 config 有語法錯誤，reload 會報錯但 compositor 繼續用舊 config 跑，不會崩潰。</p>
<h2 id="systemctlservice-狀態管理">systemctl：Service 狀態管理</h2>
<p>桌面環境的工具（waybar、mako 等）如果用 systemd user unit 管理，可以用 <code>systemctl --user</code> 查看狀態和重啟。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 查看某個 user service 的狀態</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">systemctl --user status waybar
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 輸出範例：</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># waybar.service - Highly customizable Wayland bar</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">#    Loaded: loaded (/usr/lib/systemd/user/waybar.service; enabled)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1">#    Active: active (running) since Mon 2026-06-30 10:00:00 CST</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1">#    Main PID: 1234 (waybar)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 重啟</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">systemctl --user restart waybar
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 看最近的 log</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">systemctl --user status waybar -n <span class="m">20</span></span></span></code></pre></div><p>如果這些工具不是 systemd unit（在 Hyprland config 裡用 <code>exec-once</code> 啟動的），就不能用 <code>systemctl</code> 管理。改用 <code>pgrep</code> 和 <code>kill</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">pgrep waybar      <span class="c1"># 查看是否在跑</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">killall waybar    <span class="c1"># 停止</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">waybar <span class="p">&amp;</span>          <span class="c1"># 背景啟動</span></span></span></code></pre></div><h2 id="即時資源監控">即時資源監控</h2>
<p>排查效能問題和記憶體耗盡時，需要看即時的系統資源使用情況。</p>
<p><strong>htop</strong>：互動式 process 監控。按 <code>M</code> 可以按記憶體用量排序，按 <code>P</code> 按 CPU 排序。找到佔用異常的 process 後按 <code>F9</code> 可以直接 kill。</p>
<p><strong>btop</strong>：功能更豐富的替代品，顯示 CPU、記憶體、磁碟、網路的即時使用情況，圖形化介面比 htop 直觀。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 安裝</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo pacman -S btop    <span class="c1"># Arch</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo apt install btop  <span class="c1"># Debian/Ubuntu</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 執行</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">btop</span></span></code></pre></div><p><strong>nvidia-smi</strong>：NVIDIA GPU 的專屬監控工具。顯示 GPU 使用率、記憶體、溫度、跑在上面的 process。</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 一次性查看</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">nvidia-smi
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 持續監控（每 2 秒更新）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">nvidia-smi -l <span class="m">2</span></span></span></code></pre></div><h2 id="常見-log-pattern-速查">常見 Log Pattern 速查</h2>
<table>
  <thead>
      <tr>
          <th>Pattern</th>
          <th>出處</th>
          <th>代表什麼</th>
          <th>下一步</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>Out of memory: Killed process</code></td>
          <td>journalctl / dmesg</td>
          <td>OOM Killer 殺了某個 process</td>
          <td>檢查被殺的 process 名稱、設定 swap 或 systemd-oomd</td>
      </tr>
      <tr>
          <td><code>GPU has fallen off the bus</code></td>
          <td>dmesg</td>
          <td>NVIDIA GPU 完全失聯</td>
          <td>檢查 PCIe 供電、更新 driver、檢查硬體</td>
      </tr>
      <tr>
          <td><code>Xid ... pid=</code></td>
          <td>dmesg</td>
          <td>NVIDIA GPU 錯誤（Xid 編號對應不同類型的錯誤）</td>
          <td>查 NVIDIA 的 Xid 錯誤代碼表</td>
      </tr>
      <tr>
          <td><code>GPU reset begin</code></td>
          <td>dmesg</td>
          <td>AMD GPU driver 嘗試 reset GPU</td>
          <td>通常會自動恢復，頻繁出現代表 driver 或硬體問題</td>
      </tr>
      <tr>
          <td><code>segfault at</code></td>
          <td>journalctl</td>
          <td>某個 process segfault（記憶體存取違規）</td>
          <td>記下 process 名稱，搜尋該軟體的已知 bug</td>
      </tr>
      <tr>
          <td><code>Failed to start</code></td>
          <td>systemctl status</td>
          <td>systemd unit 啟動失敗</td>
          <td>看完整的 status 輸出和 journalctl log 找原因</td>
      </tr>
      <tr>
          <td><code>config error</code> / <code>parse error</code></td>
          <td>各工具自身的 log</td>
          <td>Config 檔語法錯誤</td>
          <td>檢查最近改過的 config 檔</td>
      </tr>
  </tbody>
</table>
<h2 id="排查流程">排查流程</h2>
<p>這篇是 Hyprland 桌面的具體日誌工具；背後「先讀權威狀態、不靠肉眼猜」的通用診斷心法（每種問題的權威來源、四步流程），見 <a href="/blog/linux/debug/diagnosis-read-authoritative-state/" data-link-title="診斷心法：讀權威狀態，不靠肉眼猜表象" data-link-desc="Linux 上一個現象看起來像 A 卻可能是 B、想建立一套先讀權威狀態再下判斷的除錯紀律、避免看畫面就猜而猜錯時回來讀">Linux 除錯與診斷：診斷心法</a>。遇到桌面環境問題時的判讀順序：</p>
<ol>
<li>
<p><strong>判斷影響範圍</strong>：只有一個視窗壞了、某個工具壞了、整個桌面壞了、還是系統完全不回應？影響範圍決定要看哪一層的 log。</p>
</li>
<li>
<p><strong>看 journalctl</strong>：<code>journalctl -b -p err</code> 先看本次開機有沒有錯誤等級的訊息。大部分 userspace 的問題（compositor crash、工具 crash）會出現在這裡。</p>
</li>
<li>
<p><strong>看 dmesg</strong>：如果 journalctl 沒有明顯線索、或症狀跟硬體有關（畫面凍結、USB 不回應），<code>dmesg -T --level=err,warn</code> 看 kernel 層有沒有硬體或 driver 錯誤。</p>
</li>
<li>
<p><strong>查特定工具的狀態</strong>：<code>systemctl --user status &lt;tool&gt;</code> 或 <code>pgrep &lt;tool&gt;</code> 確認工具是否還活著。如果死了，看它最後的 log 訊息。</p>
</li>
<li>
<p><strong>即時監控</strong>：如果問題是漸進式的（越來越慢、偶爾卡頓），開 <code>btop</code> 或 <code>htop</code> 觀察 CPU 和記憶體的即時趨勢，找出佔用異常的 process。</p>
</li>
</ol>
<h2 id="找到問題後的下一步">找到問題後的下一步</h2>
<p>判讀完 log 確認問題類型後，行動路徑依問題性質分流：</p>
<ul>
<li><strong>Config 錯誤</strong>：直接修 config，用 <code>hyprctl reload</code> 或重啟工具驗證。操作步驟見<a href="/blog/linux/dotfile/07-desktop-maintenance/common-failures-recovery/" data-link-title="常見故障場景與恢復操作" data-link-desc="Hyprland 黑屏、waybar 消失、畫面凍結、記憶體爆掉或 config 寫錯導致進不了桌面時，按症狀查恢復操作">常見故障場景與恢復操作</a>。</li>
<li><strong>軟體 bug</strong>（segfault、特定操作觸發 crash）：到該軟體的 issue tracker（通常在 GitHub）搜尋錯誤訊息。Hyprland 的 issue tracker 在 <code>github.com/hyprwm/Hyprland</code>。回報 bug 時附上 <code>hyprctl systeminfo</code> 的輸出和相關的 journalctl log。</li>
<li><strong>GPU driver 問題</strong>：NVIDIA 用戶檢查是否有更新的 driver 版本（<code>pacman -Syu nvidia</code>）。AMD 用戶的 driver 跟 kernel 綁定，更新 kernel 就更新 driver（<code>pacman -Syu linux</code>）。</li>
<li><strong>硬體故障</strong>（<code>GPU has fallen off the bus</code> 反覆出現）：軟體層面無法解決，需要檢查硬體（PCIe 插槽接觸、供電、溫度）。</li>
</ul>
]]></content:encoded></item></channel></rss>