Linux

Systemd:啟動後單元文件超時

  • June 20, 2020

我寫了一個bashscript,內容如下:

#!/bin/bash
cd /opt/ut_server/System
./ucc-bin-linux-amd64 server DM-Rankin?game=XGame.xDeathMatch?mutator=AntiTCC2009r6.MutAntiTCCFinal,utcompv17a.MutUTComp?AdminName=admin?AdminPassword=1111 ini=server.ini -port=1234 -log=s9.log -nohomedir &

sleep 10
echo "finish ucc"
exit 0

現在我想用一個單元文件和systemd啟動它:

[Unit]
Description=Unreal Tournament 2004 Server
After=network.target

[Service]
WorkingDirectory=/home/unreal-user/
User=unreal-user
Group=unreal-user
Type=forking
ExecStart=/home/unreal-user/start_ut_serv.sh &
ExecStartPost=/bin/bash -c "umask 022; echo $MAINPID > /home/unreal-user/ut2k4-server.pid"
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -9 $MAINPID
TimeoutSec=400
ExecRestart=/bin/kill -9 $MAINPID && /home/unreal-user/start_ut_serv.sh
PIDFile=/home/unreal-user/ut2k4-server.pid
RestartSec=30
Restart=on-failure
#Restart=always

[Install]
WantedBy=multi-user.target

當我啟動服務文件時,出現如下錯誤:

ut2k4-serv.service: Start operation timed out. Terminating.
systemd[1]: ut2k4-serv.service: Control process exited, code=killed, status=15/TERM

為什麼這個時間在這裡?如何處理這個問題?

當我啟動 bashscript 手冊時,即使在其中指定了作業,它似乎仍然在 STDOUT 上有一些東西?這只是好奇..

這主要是從systemd.service 文件中複製粘貼,因為它在很大程度上已經足夠了。

Type=

<…>

exec類型類似於,但服務管理器會認為該simple單元在主服務二進製文件執行後立即啟動。服務經理將延遲後續單位的啟動,直到該時間點。(或者換句話說:在返回simple後立即繼續執行進一步的作業,而在兩者和服務程序成功之前不會繼續。)請注意,這意味著systemctl start服務的命令行將在無法成功呼叫服務的二進製文件時報告失敗(例如因為所選內容不存在,或者服務二進製文件失去)。fork()``exec``fork()``execve()``exec``User=

如果設置為forking,則預計配置為的程序ExecStart=fork()作為其啟動的一部分進行呼叫。當啟動完成並設置所有通信通道時,父程序將退出。子程序作為主服務程序繼續執行,當父程序退出時服務管理器會認為該單元啟動。這是傳統 UNIX 服務的行為。如果使用此設置,建議也使用該PIDFile=選項,以便 systemd 能夠可靠地辨識服務的主程序。一旦父程序退出,systemd 將繼續啟動後續單元。

你的程序顯然不是一個分叉程序,當它被 systemd 原生支持時,你已經嘗試了多次黑客攻擊以使其成為一個。


PIDFile=

採用引用服務 PID 文件的路徑。Type=對於設置為 的服務,建議使用此選項forking。指定的路徑通常指向下面的文件/run/。如果指定了相對路徑,則前綴為/run/. 服務啟動後,服務管理器會從這個文件中讀取服務主程序的PID。服務管理器不會寫入此處配置的文件,但如果該文件仍然存在,它會在服務關閉後刪除該文件。PID 文件不需要由特權使用者擁有,但如果它由非特權使用者擁有,則強制執行額外的安全限制:該文件可能不是指向其他使用者擁有的文件的符號連結(直接或間接) ,並且 PID 文件必須引用已經屬於該服務的程序。

您正在將 systemdMAINPID變數寫入該文件,但不僅MAINPID沒有記錄,ExecStartPost=而且更重要的是,由於PIDFile已設置,它實際上是從該文件中讀取的(此時,我不太確定它擴展為什麼,因為在這個情況,這沒有任何意義;它應該在ExecStart=返回時被讀取,所以我會說它是空的)。


ExecStart=本節介紹命令行解析以及, ExecStartPre=, ExecStartPost=, ExecReload=, ExecStop=, 和ExecStopPost=選項的變數和說明符替換。

<…>

這種語法是受shell語法啟發的,但只理解後面幾段描述的元字元和擴展,變數的擴展是不同的。具體來說,不支持使用“<”、“<<”、“>”和“>>”進行重定向、使用“|”進行管道、使用“&”在後台執行程序以及其他 shell 語法元素

除了對. _ ExecStart=_ExecRestart=``Type=``ExecRestart=


到目前為止,您的 bash 包裝器是無用的,根據它的目的,您應該完全刪除它並直接將 UT 伺服器設置為ExecStart=參數。伺服器命令行可以來自一個EnvironmentFile=,你就完成了!

此外,除非該伺服器絕對是一場噩夢,否則使用 SIGKILL 停止任何類型的服務都是……糟糕,至少可以這麼說。的預設實現ExecStop=可能更適合。

下次編寫服務腳本時,嘗試從預設的開始,逐步更改參數,而不是更改所有參數,然後想知道二十個參數中的哪一個壞了,調試起來更容易😉

引用自:https://serverfault.com/questions/1022186