<?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>Onfailure on Tarragon</title><link>https://tarrragon.github.io/blog/tags/onfailure/</link><description>Recent content in Onfailure on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 03 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/onfailure/index.xml" rel="self" type="application/rss+xml"/><item><title>systemd OnFailure（失敗觸發鉤子）</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/systemd-onfailure/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/systemd-onfailure/</guid><description>&lt;p>&lt;code>OnFailure=&lt;/code> 是 systemd unit 的一個指令：當這個 unit 進入 failed 狀態時，自動啟動它指定的另一個 unit。它承擔的語意是「失敗時的鉤子」——把「某個服務掛了」這個事件，接到一段你自己定義的處理（送告警、跑修復腳本）。告警邏輯因此不必是額外的 daemon，寫成一個普通的 oneshot service 掛在 &lt;code>OnFailure=&lt;/code> 上就成，零額外常駐依賴。這是 systemd 環境裡最正統的服務失效告警起點；沒有 systemd 的容器或被 orchestrator 管的服務用不上這套，改走外部探針或平台的健康檢查。&lt;/p>
&lt;p>它最反直覺、也最容易踩的一點是觸發時機：&lt;code>OnFailure&lt;/code> 不是「放棄才觸發」，而是&lt;strong>每一次失敗都觸發&lt;/strong>——包含搭配 &lt;code>Restart=on-failure&lt;/code> 時每次 auto-restart 中途的那些失敗。&lt;a href="https://tarrragon.github.io/blog/linux/debug/service-failure-monitoring/" data-link-title="服務掛了怎麼自動知道：從肉眼盯到主動告警" data-link-desc="不想每次都手動 systemctl 檢查服務死活、想讓機器在 service 掛掉時主動推播通知、或擔心整台機器當掉沒人知道時回來讀">服務掛了怎麼自動知道&lt;/a> 實測一個重試 3 次後放棄的服務，&lt;code>OnFailure&lt;/code> 觸發了 4 次（3 次 auto-restart 加 1 次最終 &lt;code>start-limit-hit&lt;/code>）。所以只掛 &lt;code>OnFailure=&lt;/code> 加 &lt;code>Restart=&lt;/code>，每次瞬斷都會發一則告警、把信箱洗爆。（這個觸發次數是特定 systemd 版本的實測、跨版本調整過，機制本身「每次失敗都觸發」則跨版本成立。）&lt;/p>
&lt;p>真正做到「只在放棄才告警」，靠的是在處理器腳本裡加一道狀態閘門：auto-restart 中途服務的 &lt;code>ActiveState&lt;/code> 是 &lt;code>activating&lt;/code>、撞上限進 failed 才是 &lt;code>failed&lt;/code>，腳本只在 &lt;code>failed&lt;/code> 才送。&lt;code>OnFailure=&lt;/code> 負責「失敗就觸發」、config 的 &lt;code>Restart=&lt;/code> / &lt;code>StartLimitBurst=&lt;/code> 負責「重試幾次」、handler 的閘門負責「只在終局告警」——三者合起來才是「先自動重啟、放棄才吵」。&lt;/p>
&lt;p>要一次把 &lt;code>OnFailure=&lt;/code> 套到所有 service，用 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/systemd-drop-in/" data-link-title="systemd drop-in（不改原檔的設定疊加）" data-link-desc="想覆寫套件裝的 systemd unit 又不被升級蓋掉、一次對所有 service 套一條設定、或搞不清 systemctl edit 改了哪個檔時讀">drop-in&lt;/a>：放一個 &lt;code>service.d/&lt;/code> 的 top-level drop-in，設定就套用到每個 &lt;code>.service&lt;/code>。這會帶出一個遞迴陷阱——全域 drop-in 也套到告警處理器自己，它失敗會觸發自己；用 &lt;code>systemctl edit&lt;/code> 開 override、在 &lt;code>[Unit]&lt;/code> 段寫一行空的 &lt;code>OnFailure=&lt;/code> 清掉繼承值擋掉。完整的鉤子鏈（處理器 unit、送出腳本、遞迴陷阱、canary 驗證）在 &lt;a href="https://tarrragon.github.io/blog/linux/debug/service-failure-monitoring/" data-link-title="服務掛了怎麼自動知道：從肉眼盯到主動告警" data-link-desc="不想每次都手動 systemctl 檢查服務死活、想讓機器在 service 掛掉時主動推播通知、或擔心整台機器當掉沒人知道時回來讀">服務掛了怎麼自動知道&lt;/a>。&lt;/p>
&lt;p>相關概念：&lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/systemd-drop-in/" data-link-title="systemd drop-in（不改原檔的設定疊加）" data-link-desc="想覆寫套件裝的 systemd unit 又不被升級蓋掉、一次對所有 service 套一條設定、或搞不清 systemctl edit 改了哪個檔時讀">systemd drop-in&lt;/a>（全域套用 &lt;code>OnFailure=&lt;/code> 的機制、以及清空繼承值的空賦值）、&lt;a href="https://tarrragon.github.io/blog/linux/debug/service-failure-monitoring/" data-link-title="服務掛了怎麼自動知道：從肉眼盯到主動告警" data-link-desc="不想每次都手動 systemctl 檢查服務死活、想讓機器在 service 掛掉時主動推播通知、或擔心整台機器當掉沒人知道時回來讀">服務掛了怎麼自動知道&lt;/a>（&lt;code>OnFailure&lt;/code> 告警鏈的完整單機實作）。從單機告警往上到概念層的探活、liveness 與自動重啟見 &lt;a href="https://tarrragon.github.io/blog/devops/04-service-health/systemd-watchdog-restart/" data-link-title="systemd watchdog 與自動重啟" data-link-desc="在單機 systemd 上做服務自動恢復時，釐清 watchdog 主動報活與 restart policy 被動拉起是兩套機制、以及為什麼要先重啟幾次才放棄">DevOps：systemd watchdog 與自動重啟&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p><code>OnFailure=</code> 是 systemd unit 的一個指令：當這個 unit 進入 failed 狀態時，自動啟動它指定的另一個 unit。它承擔的語意是「失敗時的鉤子」——把「某個服務掛了」這個事件，接到一段你自己定義的處理（送告警、跑修復腳本）。告警邏輯因此不必是額外的 daemon，寫成一個普通的 oneshot service 掛在 <code>OnFailure=</code> 上就成，零額外常駐依賴。這是 systemd 環境裡最正統的服務失效告警起點；沒有 systemd 的容器或被 orchestrator 管的服務用不上這套，改走外部探針或平台的健康檢查。</p>
<p>它最反直覺、也最容易踩的一點是觸發時機：<code>OnFailure</code> 不是「放棄才觸發」，而是<strong>每一次失敗都觸發</strong>——包含搭配 <code>Restart=on-failure</code> 時每次 auto-restart 中途的那些失敗。<a href="/blog/linux/debug/service-failure-monitoring/" data-link-title="服務掛了怎麼自動知道：從肉眼盯到主動告警" data-link-desc="不想每次都手動 systemctl 檢查服務死活、想讓機器在 service 掛掉時主動推播通知、或擔心整台機器當掉沒人知道時回來讀">服務掛了怎麼自動知道</a> 實測一個重試 3 次後放棄的服務，<code>OnFailure</code> 觸發了 4 次（3 次 auto-restart 加 1 次最終 <code>start-limit-hit</code>）。所以只掛 <code>OnFailure=</code> 加 <code>Restart=</code>，每次瞬斷都會發一則告警、把信箱洗爆。（這個觸發次數是特定 systemd 版本的實測、跨版本調整過，機制本身「每次失敗都觸發」則跨版本成立。）</p>
<p>真正做到「只在放棄才告警」，靠的是在處理器腳本裡加一道狀態閘門：auto-restart 中途服務的 <code>ActiveState</code> 是 <code>activating</code>、撞上限進 failed 才是 <code>failed</code>，腳本只在 <code>failed</code> 才送。<code>OnFailure=</code> 負責「失敗就觸發」、config 的 <code>Restart=</code> / <code>StartLimitBurst=</code> 負責「重試幾次」、handler 的閘門負責「只在終局告警」——三者合起來才是「先自動重啟、放棄才吵」。</p>
<p>要一次把 <code>OnFailure=</code> 套到所有 service，用 <a href="/blog/linux/dotfile/knowledge-cards/systemd-drop-in/" data-link-title="systemd drop-in（不改原檔的設定疊加）" data-link-desc="想覆寫套件裝的 systemd unit 又不被升級蓋掉、一次對所有 service 套一條設定、或搞不清 systemctl edit 改了哪個檔時讀">drop-in</a>：放一個 <code>service.d/</code> 的 top-level drop-in，設定就套用到每個 <code>.service</code>。這會帶出一個遞迴陷阱——全域 drop-in 也套到告警處理器自己，它失敗會觸發自己；用 <code>systemctl edit</code> 開 override、在 <code>[Unit]</code> 段寫一行空的 <code>OnFailure=</code> 清掉繼承值擋掉。完整的鉤子鏈（處理器 unit、送出腳本、遞迴陷阱、canary 驗證）在 <a href="/blog/linux/debug/service-failure-monitoring/" data-link-title="服務掛了怎麼自動知道：從肉眼盯到主動告警" data-link-desc="不想每次都手動 systemctl 檢查服務死活、想讓機器在 service 掛掉時主動推播通知、或擔心整台機器當掉沒人知道時回來讀">服務掛了怎麼自動知道</a>。</p>
<p>相關概念：<a href="/blog/linux/dotfile/knowledge-cards/systemd-drop-in/" data-link-title="systemd drop-in（不改原檔的設定疊加）" data-link-desc="想覆寫套件裝的 systemd unit 又不被升級蓋掉、一次對所有 service 套一條設定、或搞不清 systemctl edit 改了哪個檔時讀">systemd drop-in</a>（全域套用 <code>OnFailure=</code> 的機制、以及清空繼承值的空賦值）、<a href="/blog/linux/debug/service-failure-monitoring/" data-link-title="服務掛了怎麼自動知道：從肉眼盯到主動告警" data-link-desc="不想每次都手動 systemctl 檢查服務死活、想讓機器在 service 掛掉時主動推播通知、或擔心整台機器當掉沒人知道時回來讀">服務掛了怎麼自動知道</a>（<code>OnFailure</code> 告警鏈的完整單機實作）。從單機告警往上到概念層的探活、liveness 與自動重啟見 <a href="/blog/devops/04-service-health/systemd-watchdog-restart/" data-link-title="systemd watchdog 與自動重啟" data-link-desc="在單機 systemd 上做服務自動恢復時，釐清 watchdog 主動報活與 restart policy 被動拉起是兩套機制、以及為什麼要先重啟幾次才放棄">DevOps：systemd watchdog 與自動重啟</a>。</p>
]]></content:encoded></item></channel></rss>