Arch-Linux

如何編寫執行 systemd-tmpfiles 的 systemd .service 文件

  • March 21, 2022

我需要systemd-tmpfiles --create在啟動過程中使用 systemd 發行版執行。所以我需要創建一個 systemd .service 文件來完成這項工作。

在這個問題中,您可以閱讀有關我需要什麼以及原因的所有詳細資訊:systemd-tmpfiles 如何工作?

我已經閱讀了一些關於它的文件,並且正在編寫以下測試:

[Unit]
Description=Execute tmpfiles to disable usb-wakeup # see details in the link above
Requires=multi-user.target # see details in the link above
After=multi-user.target    # see details in the link above

[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --create

[Install]
WantedBy=multi-user.target

但我不確定,因為systemd-tmpfiles它不是一個簡單的程序,而是一個 systemd 本身。我不想破壞我的系統。

關於正確的 .service 文件的任何提示?

$$ This does not directly address the issue of systemd-tmpfiles but I think you have already recognized that in this particular case you are better off just using echo. $$

首先,“multi-user.target”可能是也可能不是您想要使用的。如果您熟悉 SysV 風格的 init 中的執行級別的概念,那麼多使用者是 systemd 等效於執行級別 3,它是一個引導到控制台而不是 GUI 的多使用者系統。啟動到 X 的執行級別 5 的等效項是graphics.target。預設值由名為default.target/etc/systemd/system的(和/或/lib/systemd/system; in 的一個/etc將覆蓋 in 的一個)中的符號連結確定,使用 ls 查找它指向的位置:/lib

»ls -l /etc/systemd/system/default.target
default.target -> /usr/lib/systemd/system/multi-user.target

systemctl get-default在這種情況下會告訴你“multi-user.target”。對於普通的 linux 桌面,它將是graphics.target。如果您希望創建的引導服務無論預設執行級別/目標是什麼都啟動,這實際上並不重要——在這種情況下,我們可以只使用 default.target,而不必擔心它的別名是什麼。但是,如果您使用多使用者,並且您的預設設置是圖形的,那麼您的服務將不會發生。

根據服務的不同,您可能希望啟動與此相關的更合適和特定的目標或服務。根據您的其他問題, default.target 可能沒問題。請注意,“目標”和“服務”之間的區別在於服務包含[Service]實際執行程序的部分;目標只是通過各種“依賴”和“要求”指令將服務組合在一起的一種方式;除了觸發其他目標或服務之外,它不會做任何自己的事情。

服務何時啟動取決於其他明確依賴它的服務。對於像這樣我們希望在啟動過程後期執行的簡單獨立事件,我們可以使用以下指令組合:

[Unit]
Requires=local-fs.target
After=local-fs.target 

[Install]
WantedBy=default.target

安裝服務時使用“安裝”部分。“WantedBy=” 指定我們希望包含此服務的目標,這意味著如果該目標包含,它將執行。如果您沒有特定的依賴項,那麼讓單元稍後執行而不是更早執行可能是查看正常情況並選擇一些作為依賴項或可選先決條件的問題。

區分:依賴是指您的單元也需要啟動的東西,可選的先決條件是指如果正在使用它應該在您的單元之前執行的東西,但不是必需的。這些術語是我的,但這是 systemd 文件中使用的一個重要區別,特別是在某種意義上,如果您的單元是 ,則保證啟動所需的依賴項,但此要求不會影響它們的啟動順序,這意味著, 只是一個依賴項的東西實際上可能會在之後啟動(是的,因為這意味著您的單元可能會首先啟動,所以不能保證依賴項會成功)。

上面,Requiresonlocal-fs.target可能有點毫無意義,除非您認為您的單元將用於可能不包含在其他系統中的系統,但將其與After意味著您的單元保證在它啟動後啟動 - 所以您可以這樣做沒有Requires(您可以將一個單元設置為在它不依賴的單元之後啟動,因此“之後”沒有“要求”=可選的先決條件)。這裡的例子只是介紹依賴和執行順序的概念和區別:一個不決定另一個。

請注意,“開始於”仍然不意味著 prereq 將達到它自己執行的任何特定點。例如,如果它是關於掛載遠端文件系統並且您這對您的單元很重要,您將希望使用Requires並且可能After建立該服務的服務,但您仍然需要您正在執行的實際過程來進行適當的錯誤處理,以防遠端文件系統還不能訪問(例如,通過在循環中休眠直到它們被訪問)。

例如,我將在控制台回顯“hello world”。該服務本身在以下[Service]部分中進行了描述:

[Service]
Type=simple
ExecStart=/usr/local/bin/helloworld

該命令需要完整路徑。我不只是使用的原因/usr/bin/echo "hello world"是它不起作用(我認為輸出到 /dev/null),雖然服務會執行echo "hello world" > /dev/console意志,但實驗表明在 ExecStart 指令中使用 shell 重定向不會,因為該ExecStart命令不是由 shell 執行的。但是你可以這樣做: /usr/local/bin/helloworld 是一個帶有這一行的 shell 腳本,echo "hello world" > /dev/console. 1

注意Type=simple. 這對於所做helloworld的事情以及許多其他事情都很好。如果您的服務長時間執行(超過幾秒鐘),systemd 將在使用時將其分叉到後台simple,這就是您想要的(另一種選擇是讓它在前台停留太久而被殺死)。但是,如果程序自己執行此分叉(就像伺服器和守護程序通常那樣),您應該使用Type=forking. 在 下simple,它將作為一個流浪的孤兒程序被殺死。中詳細介紹了“類型”參數man systemd.service,無論您嘗試做什麼,都應該閱讀該部分。2

我們完整的、最小的服務文件就是這三個部分([Unit][Service][Install])。要安裝,請將文件或符號連結放在 /etc/systemd/system 或 /usr/lib/systemd/system 中,然後:

systemctl --system enable helloworld

它應該列印ln -s ...。這不會執行該服務,它只是將其配置為在啟動時執行,如上所述。

簡而言之就是這樣。 man systemd.unitman systemd.service有更多細節(順便說一句,所有這些東西都有一個索引man systemd.directives)。


  1. StandardOutput您可以使用塊中的和StandardError參數重定向輸出[Service],請參閱man systemd.exec.
  2. 中有一個所有服務文件指令的索引man systemd-directives,指示其中記錄了哪個手冊頁,例如:
After=
   systemd.unit(5)

Alias=
   systemd.unit(5)

引用自:https://unix.stackexchange.com/questions/61390