鳥哥 Daemon ====== # 什麼是 Daemon? 在背景常駐的行程叫做 service,成為 service 的程式稱作 daemon。 通常來說,行程的名稱結尾都會有個 "d",用以區分普通程式的行程。 - 舉例:`syslogd`、`crond`、 `sshd` 實際上,service 跟 daemon 這兩個詞不會分的那麼清楚,畢竟兩個是生命共同體。 冷知識:此命名由來是[馬克士威的思想實驗](https://en.wikipedia.org/wiki/Maxwell%27s_demon) ## Daemon 的啟動方式 1. 直接由 init 啟動 - 通常在開機期間系統會啟動一些 daemon 來處理網路請求、硬體活動、其他程式需求。 - 做這些事情的初始化程式會是 SysVinit 或 Upstart 或 Systemd 2. 由一支行程 fork 出子行程後,父行程立即結束,因此子行程會被 init 接管 - 通常經由 [daemon(3)](https://man7.org/linux/man-pages/man3/daemon.3.html) 來脫離 terminal (tty) 控制,成為背景行程 # 系統初始化程式 在開機過程中,kernel 會指派自己的 PID 為 0,初始化程式的 PID 為 1,這是因為它是核心建立的第一個行程。 以下為基本開機流程: ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/62f20d13-bbb7-41f4-adf0-36f7f29c065b/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/62f20d13-bbb7-41f4-adf0-36f7f29c065b/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130304Z&X-Amz-Expires=86400&X-Amz-Signature=ea6bae95951be05e674af1368904b316cfebe4f06ee81546617b774876af4297&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) 根據時代演進,大多數 Linux 發行版的初始化程式,從 SysVinit → Upstart → Systemd,這些進步帶來了更快的速度、更多的彈性與功能。 ## 先談談元老級的 init ### 服務啟動、關閉、查看 - 啟動: `/etc/init.d/{daemon} start` - 關閉: `/etc/init.d/{daemon} stop` - 重新啟動: `/etc/init.d/{daemon} restart` - 狀態觀察: `/etc/init.d/{daemon} status` ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/59453e6c-cd46-4050-9ef1-33d2ccdb0417/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/59453e6c-cd46-4050-9ef1-33d2ccdb0417/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130323Z&X-Amz-Expires=86400&X-Amz-Signature=48ef46d2f95a1485104184821fe7af204c8c5efd1a34e77c49c2857573da26b1&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) ### 服務分類 - 獨立啟動模式 (stand alone):服務獨立啟動,該服務直接常駐於記憶體中,提供本機或用戶的服務行為,反應速度快 - 總管程式 (super daemon):由特殊的 xinetd 或 inetd 這兩個總管程式(super daemon)提供 socket 對應或 port 對應的管理。當沒有用戶要求某 socket 或 port 時, 所需要的服務是不會被啟動的,唯有在需要時才對啟動相對應的 daemon,因此可以省下不少系統資源。 ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b20f8be4-615c-497a-a85b-6bdc5942d9d7/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/b20f8be4-615c-497a-a85b-6bdc5942d9d7/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130339Z&X-Amz-Expires=86400&X-Amz-Signature=140825b389eddbd492beab00a1253b42fdd875314c287f2c60afc2a4d3519fef&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) ### 服務的相依性問題 如果系統需要收信,網路服務卻沒有啟動,這時肯定是無法收到來自網際網路的新信件。 init 不具有相依性檢查功能,也就是需要自己手動排除上述問題... ### 執行級別(runlevel)分類 init 是系統的第一個行程,可以根據使用者自訂的 runlevel 來決定要喚醒哪些不同的服務。 因應不同需求,runlevel 可以分成幾類: ![](https://i.imgur.com/tw1RLez.png) 如果要修改 runlevel 可以到 `/etc/inittab` 修改(現在 systemd 系統已經沒有了)。 或是透過 `init 0`、 `init 6` 等指令來切換不同 run level,前兩個指令分別代表 `shutdown -h`、`reboot` 。 關於不同 run level 需要做的事情,可以到 `/etc/rc.d/rcx.d` 設定。 ### 設定開機自動執行 - 預設啟動: `chkconfig {daemon} on`、`chkconfig --level 35 {daemon} on` (指定在 run level 3 跟 5) - 預設不啟動: `chkconfig {daemon} off` - 檢查預設行為: `chkconfig --list {daemon}` ### 歷史資訊 - Ubuntu 6.10 以後改用 Upstart,13.04 改用 Systemd - CentOS 7 以後改用 Systemd ## Systemd 介紹 目前主流初始化程式,可相容舊有 init 的腳本。 ### 優點 - 平行處理所有服務,加速開機流程 - init 是每項任務依序啟動,systemd 可以讓不相依的程式同時啟動(善用多核心、減少各種等待時間) - 整合處理 - 只需要 systemd 服務搭配 `systemctl` 指令 - 不像 init 依據功能分成許多不同的指令: `init`、`chkconfig`、`service`。 - 服務相依性的自我檢查 - 如果 B 服務是架構在 A 服務上面啟動的,那當你在沒有啟動 A 服務的情況下僅手動啟動 B 服務時, systemd 會自動幫你啟動 A 服務 - 依 daemon 功能分類 - 定義所有的服務為一個服務單位 (unit),並將該 unit 歸類到不同的服務類型 (type) - 服務單位 (unit) 區分為 service, socket, target, path, snapshot, timer 等多種不同的類型(type) - 舊的 init 僅分為 stand alone 與 super daemon - 將多個 daemons 集合成為一個群組 - 如同 systemV 的 init 裡頭有個 runlevel 的特色,systemd 亦將許多的功能集合成為一個所謂的 **target** 項目 - 亦即是執行某個 target 就是執行好多個 daemon ### 缺點 - 在 runlevel 的對應上,約僅有 runlevel 1, 3, 5 有對應到 systemd 的某些 target 類型而已,沒有全部對應 - 全部的 systemd 都用 systemctl 這個管理程式管理,而 systemctl 支援的語法有限制,不像 /etc/init.d/daemon 就是純腳本可以自訂參數,systemctl 不可自訂參數 - 如果某個服務啟動是管理員自己手動執行啟動,而不是使用 systemctl 去啟動的 (例如你自己手動輸入 crond 以啟動 crond 服務),那麼 systemd 將無法偵測到該服務,而無法進一步管理 - systemd 啟動過程中,無法與管理員透過 standard input 傳入訊息!因此,自行撰寫 systemd 的啟動設定時,務必要取消互動機制~(連透過啟動時傳進的標準輸入訊息也要避免!) ### 設定檔放置目錄 不同發行版大同小異,下圖為 Ubuntu 20.04 LTS:(`man systemd.unit`) ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7e9b0964-2507-4633-b70a-32e6e435d984/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/7e9b0964-2507-4633-b70a-32e6e435d984/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130400Z&X-Amz-Expires=86400&X-Amz-Signature=5d917b605751b93b44d8e8a564eab322dc4580ce2a2580c5167656e5053a5b0d&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) 開機是否會執行哪些服務主要看 `/etc/systemd/system`,裡面有些會軟連結到 `/usr/lib/systemd/system`。 ### systemd 的 unit 類型分類說明 ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2ee6ebe4-8e98-4b86-b65a-eaf3786177bc/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/2ee6ebe4-8e98-4b86-b65a-eaf3786177bc/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130402Z&X-Amz-Expires=86400&X-Amz-Signature=f81ed1a24c6b2c0beb767a1e4c93c14bb63da2cbc5200a276e9d1a3876286018&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) 根據**副檔名**可以知道腳本屬於哪個 type,而常見 type 如下: - service(最常見) - 一般服務類型,主要是系統服務 - 包括伺服器本身所需要的本機服務以及網路服務都是 - socket - 內部程序資料交換的插槽服務 - 主要是 IPC (Inter-process communication) 的傳輸訊息插槽檔 (socket file) 功能。 這種類型的服務通常在監控訊息傳遞的插槽檔,當有透過此插槽檔傳遞訊息來說要連結服務時,就依據當時的狀態將該用戶的要求傳送到對應的 daemon, 若 daemon 尚未啟動,則啟動該 daemon 後再傳送用戶的要求 - target - 執行環境類型,其實是一群 unit 的集合 - 執行 xxx.target 就是執行一堆其他 .service 或/及 .socket 之類的服務就是了 - mount / automount / swap - 控制掛載點 - timer - 循環執行 unit - 預設會執行相同檔名(除了副檔名)之服務 - path - 偵測特定檔案或目錄類型 - 例如最常見的列印服務,就是透過偵測列印佇列目錄來啟動列印功能 - slice - 藉由 cgroups 階層式管理多個行程資源 上述詳細資料可以透過 `man systemd` 查詢 # 使用 systemctl 管理服務 ## 管理單一服務 ```bash systemd [command] [unit] ``` command 主要有: ``` start :立刻啟動後面接的 unit stop :立刻關閉後面接的 unit restart :立刻關閉後啟動後面接的 unit,亦即執行 stop 再 start 的意思 reload :不關閉後面接的 unit 的情況下,重新載入設定檔,讓設定生效 enable :設定下次開機時,後面接的 unit 會被啟動 disable :設定下次開機時,後面接的 unit 不會被啟動 status :目前後面接的這個 unit 的狀態,會列出有沒有正在執行、開機預設執行否、登錄等資訊等! is-active :目前有沒有正在運作中 is-enabled:開機時有沒有預設要啟用這個 unit ``` 實際執行結果: - 可以看到 Loaded 最後面有 **enabled**,代表開機時會自動啟動 ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/17057231-4dbb-4c09-b28c-578575619906/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/17057231-4dbb-4c09-b28c-578575619906/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130406Z&X-Amz-Expires=86400&X-Amz-Signature=3e67a5d0bbb87b9847d4cd866cc4db76af336bdd1e0631026a370949d78a39f5&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) **可能的 status:** - active (running) - 正有一隻或多隻程序正在系統中執行 - active (exited) - 僅執行一次就正常結束的服務,目前並沒有任何程序在系統中執行 - active (waiting) - 正在執行當中,不過還再等待其他的事件才能繼續處理 - 例如:列印佇列服務需有有列印工作進來,才會繼續工作 - inactive - 這個服務目前沒有在運作 小技巧:可以使用 `systemctl status --all` 查看所有服務狀態 **daemon 預設狀態:** - enabled:這個 daemon 將在開機時被執行 - disabled:這個 daemon 在開機時不會被執行 - static:這個 daemon 不可以自己啟動 (enable 不可),不過可能會被其他的 enabled 的服務來喚醒 (相依屬性的服務) - mask:這個 daemon 無論如何都無法被啟動,因為已經被強制註銷 (非刪除),可以避免被相依服務啟動。可透過 systemctl unmask 方式改回原本狀態。 ### 補充 有些人可能會覺得 `systemctl` 在一些情況下不好用: ```bash systemctl "status" xxx systemctl "restart" xxx systemctl "status" xxx ``` 如果要連續下這三條指令,勢必得按下 ⬆️ 鍵,並移動游標到中間修改 command,太麻煩。 `service` 指令是一個 wrapper,可對 `init` 與 `systemctl` 腳本做出簡單的操作,也就是通吃。 ```bash service xxx status service xxx restart service xxx status ``` ## 觀察系統上所有的服務 ```bash systemctl [command] [--type=TYPE] [--all] ``` command 說明 ```bash list-units :依據 unit 列出目前有啟動的 unit。若加上 --all 才會列出沒啟動的。 list-unit-files :依據 /usr/lib/systemd/system/ 內的檔案,將所有檔案列表說明。 --type=TYPE:就是之前提到的 unit type,主要有 service, socket, target 等 ``` ## 管理不同的操作環境 ### 基本概念 查看 type 為 target 的 unit: ```bash systemctl list-units --type=target --all ``` 上面包含了跟操作介面比較相關的 target: - graphical.target: - 文字加上圖形界面,這個項目已經包含了底下的 multi-user.target 項目 - multi-user.target: - 純文字模式 - rescue.target: - 在無法使用 root 登入的情況下,systemd 在開機時會多加一個額外的暫時系統,與原本的系統無關 - 這時可以取得 root 的權限來維護系統,但是這是額外系統,因此可能需要動到 chroot 的方式來取得你原有的系統 - emergency.target: - 緊急處理系統的錯誤,還是需要使用 root 登入的情況,在無法使用 rescue.target 時,可以嘗試使用這種模式 - shutdown.target: - 就是關機的流程 - getty.target: - 可以設定你需要幾個 tty 之類的 正常的模式是 multi-user.target 以及 graphical.target 兩個,救援方面的模式主要是 rescue.target 以及更嚴重的 emergency.target。 ### 操作方式 透過 target unit: ```bash systemctl get-default # 取得目前開機會載入的 target(可以想像成 runlevel) # --> graphical.target systemctl set-default multi-user.target # 純設定,需重開機生效 systemctl isolate multi-user.target # 立即切換成 multi-user.target ``` 透過簡化指令: ```bash systemctl poweroff # 系統關機 systemctl reboot # 重新開機 systemctl suspend # 進入暫停模式 systemctl hibernate # 進入休眠模式 systemctl rescue # 強制進入救援模式 systemctl emergency # 強制進入緊急救援模式 ``` - suspend:暫停模式會將系統的狀態資料保存到記憶體中,然後關閉掉大部分的系統硬體,並沒有實際關機,喚醒的速度較快。 - hibernate:休眠模式則是將系統狀態保存到硬碟當中,保存完畢後,將電腦關機 ## 分析服務相依性 ```bash systemctl list-dependencies [unit] [--reverse 反向追蹤] ``` ## 列出 socket ```bash systemctl list-sockets ``` ![https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4815b855-0fe3-4946-a7d0-3e81cea466b5/Untitled.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/4815b855-0fe3-4946-a7d0-3e81cea466b5/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210206%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210206T130411Z&X-Amz-Expires=86400&X-Amz-Signature=df2e410a4f53187eb720a049e6cc79fd39281d98aa41fe7f3f66628995088702&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22) ## 設定檔目錄簡介 - `/lib/systemd/system/xxxx.service` - 官方釋出的預設設定檔 - `/etc/systemd/system/xxxx.service.d/custom.conf` - 在 `/etc/systemd/system` 底下建立與設定檔相同檔名的目錄,但是要加上 `.d` 的副檔名 - 在該目錄下建立設定檔即可。另外,設定檔最好附檔名取名為 .conf 較佳! 在這個目錄下的檔案會「累加其他設定」進入 `/lib/systemd/system/xxxx.service` 內 - `/etc/systemd/system/xxxx.service.wants/*` - 此目錄內的檔案為連結檔,設定相依服務的連結 - 意思是啟動了 vsftpd.service 之後,最好再加上這目錄底下建議的服務 - `/etc/systemd/system/xxxx.service.requires/*` - 此目錄內的檔案為連結檔,設定相依服務的連結。意思是在啟動 `xxxx.service` 之前,需要事先啟動哪些服務的意思 ## 設定項目簡介 ```bash ➜ systemctl cat sshd [Unit] # 這個項目與此 unit 的解釋、執行服務相依性有關 Description=OpenSSH server daemon After=network.target sshd-keygen.service Wants=sshd-keygen.service [Service] # 這個項目與實際執行的指令參數有關 EnvironmentFile=/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s [Install] # 這個項目說明此 unit 要掛載哪個 target 底下 WantedBy=multi-user.target ``` - `[Unit]` - unit 本身的說明,以及與其他相依 daemon 的設定,包括在什麼服務之後才啟動此 unit 之類的設定值 - `[Service], [Socket], [Timer], [Mount], [Path]` - 不同的 unit type 就得要使用相對應的設定項目 - 主要在規範服務啟動的腳本、環境設定檔檔名、重新啟動的方式等等 - `[Install]` - 這個項目就是將此 unit 安裝到哪個 target 裡面去的意思 ### 基本規則 - 設定項目 - 可以重複,後者會覆蓋掉前者 - 例如已經有 `After` 了,再次設定 `After=` 即可將其清除 - 布林 - 表示啟動: 1, yes, true, on - 表示關閉:0, no, false, off - 註解 - 開頭為 `#`、`;` ### Unit 設定介紹 - `Description` - 給管理員看的簡易說明 - 可在 `systemctl list-units`、`systemctl status` 中看到 - `Documentation` - 提供管理員能夠進行進一步的文件查詢的功能 - 範例: - Documentation=http://www.... - Documentation=man:sshd(8) - Documentation=file:/etc/ssh/sshd_config - `After` - 說明此 unit 是在哪個 daemon 啟動之後才啟動 - 沒有強制力,純屬建議 - `Before` - 在什麼服務啟動前最好啟動這個服務 - 沒有強制力,純屬建議 - `Requires` - 明確的定義此 unit 需要在哪個 daemon 啟動後才能夠啟動 - 有強制性! - `Wants` - 這個 unit 之後最好還要啟動什麼服務比較好 - 沒有強制力 - `Conflicts` - 會發生衝突的服務 - 條列中的服務有被啟動,則此服務不能啟動,反之亦然 ### Service 設定介紹 - `Type` - 這個 daemon 啟動的方式,會影響到 ExecStart - 常見類型: - `simple`:預設值,由 `ExecStart` 的指令啟動,通常常住於記憶體 - `forking`: - 由 ExecStart 啟動的程序透過 spawns 延伸出其他子程序來作為此 daemon 的主要服務 - 原生的父程序在啟動結束後就會終止運作,傳統的 unit 服務大多屬於這種項目 - `oneshot`:與 simple 類似,不過這個程序在工作完畢後就結束了,不會常駐在記憶體中 - `dbus`: - 與 simple 類似,但這個 daemon 必須要在取得一個 D-Bus 的名稱後,才會繼續運作 - 因此設定這個項目時,通常也要設定 `BusName=` 才行 - `idle`: - 與 simple 類似,必須要所有的工作都順利執行完畢後才會執行這個 daemon - 目的是避免與其他服務交錯輸出訊息到 console - 這類的 daemon 通常是開機到最後才執行即可的服務 - 比較重要的項目大概是 simple, forking 與 oneshot,畢竟很多服務需要子程序 (forking) - 而有更多的動作只需要在開機的時候執行一次(oneshot),例如檔案系統的檢查與掛載等等 - `EnvironmentFile` - 可以指定啟動腳本的環境設定檔 - 例如 `sshd.service` 的設定檔寫入到 `/etc/sysconfig/sshd` 當中 - 你也可以使用 `Environment=` 後面接多個不同的 Shell 變數來給予設定! - `ExecStart` - 實際執行此 daemon 的指令或腳本程式 - 也可以使用 ExecStartPre (之前) 以及 ExecStartPost (之後) 兩個設定項目來在實際啟動服務前,進行額外的指令行為 - 特別注意的是,指令串僅接受「指令 參數 參數...」的格式,不能接受 <, >, >>, |, & 等特殊字符,很多的 bash 語法也不支援 - 若要支援比較完整的 bash 語法,那得要使用 `Type=oneshot` 才行,其他的 Type 才不能支援這些字符 - `ExecStop` - 與 systemctl stop 的執行有關,關閉此服務時所進行的指令。 - `ExecReload` - 與 systemctl reload 有關的指令行為 - `Restart` - 當設定 Restart=1 時,則當此 daemon 服務終止後,會再次的啟動此服務 - `RemainAfterExit` - 當設定為 `RemainAfterExit=1` 時(布林),則當這個 daemon 所屬的所有程序都終止之後,此服務仍會被視為 active - 這對於 `Type=oneshot` 的服務很有幫助 - 預設為 no - `TimeoutSec` - 若這個服務在啟動或者是關閉時,因為某些緣故導致無法順利「正常啟動或正常結束」的情況下,則我們要等多久才進入「強制結束」的狀態 - `KillMode` - 可以是 process, control-group, mixed, none 的其中一種,如果是 process 則 daemon 終止時,只會終止主要的程序 (ExecStart 接的後面那串指令) - 如果是 control-group 時, 則由此 daemon 所產生的其他 control-group 的程序,也都會被關閉。如果是 none 的話,則沒有程序會被關閉 - `RestartSec` - 與 Restart 有點相關性,如果這個服務被關閉,然後需要重新啟動時,大概要 sleep 多少時間再重新啟動的意思 - 預設是 100 ms ### Install 設定介紹 - `WantedBy` - 這個設定後面接的大部分是 `*.target unit`,代表這個 unit 本身是附掛在哪一個 target unit 底下 - 一般來說,大多的服務性質的 unit 都是附掛在 multi-user.target 底下 - `Also` - 當目前這個 unit 本身被 enable 時,Also 後面接的 unit 也請 enable - `Alias` - 當 systemctl enable 相關的服務時,則此服務會進行連結檔的建立 - 以 multi-user.target 為例,這個傢伙是用來作為預設操作環境 default.target 的規劃, 因此當你設定用成 default.target 時,這個 /etc/systemd/system/default.target 就會連結到 /usr/lib/systemd/system/multi-user.target 囉 ## 編輯服務設定 ```bash sudo systemctl edit xxxx.service ``` - Systemd 會在 `/etc/systemd/system/` 目錄之下,建立一個服務名稱加上 `.d` 的子目錄 (以這個例子來說就是 xxxx.service.d) - 然後將新增的設定寫在這個子目錄下的 override.conf 中,之後 Systemd 在載入服務設定檔時,就會自動優先採用此處的設定 如果想要直接編輯完整的設定檔,可以加上 --full 參數: ```bash sudo systemctl edit --full xxxx.service ```