systemd 呼叫 bash 腳本在守護程序之前創建符號連結
在 systemd 執行守護程序之前,我需要創建或更改符號連結的目標。守護程序將其標準輸出重定向到此符號連結,並隨之重定向到每個啟動的守護程序的特殊文件中。這就是想法。我設置了名為“test_start.service”的服務單元文件:
[Unit] Description=Test Server After=network-online.target test_start.socket Requires=network-online.target test_start.socket [Service] User=test1 Group=test1 Type=simple ExecStartPre=/bin/bash /etc/testServer/Debug/makeOutfile.sh ExecStart=/etc/testServer/Debug/testServer StandardInput=socket StandardOutput=file:/etc/testServer/Debug/test_outLink Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target
bash 腳本“/etc/testServer/Debug/makeOutfile.sh”如下所示:
#!/usr/bin/env bash timeStamp=$(date +%y-%m-%d_%Hh%Mm%Ss) myfolder="/etc/testServer/Debug" # create new logfile touch $myfolder/started_$timeStamp # remove old symlink if exists (owned by test1) if [ -h $myfolder/test_outLink ]; then rm $myfolder/test_outLink fi # create new symlink ln -s $myfolder/started_$timeStamp $myfolder/test_outLink
它在某些情況下有效。如果符號連結存在並且它指向的文件也存在,那麼一切都很好。bash 腳本“makeOutfile.sh”通過終端執行以進行測試,並通過 systemd 服務啟動。
但:
如果指向的文件(名稱:“started_atSomeDate”)不存在(因為它同時被某人刪除),腳本的終端呼叫按預期工作,但啟動 systemd 服務將添加一個由 root 擁有的附加文件,組具有原始舊文件名的根:“started_atSomeDate”。
那是從哪裡來的?
如果舊符號連結“test_outLink”不存在(因為它同時被某人刪除),腳本的終端呼叫按預期工作,但啟動 systemd 服務會將新創建的“test_outLink”添加為 root 擁有的正常文件使用組 root 並且服務無法啟動。
這裡出現了嚴重錯誤,雖然 systemd 服務單元使用者和組是 test1,但 root 在這裡混在一起。誰能解釋一下?我究竟做錯了什麼?
我的建議是你應該使用一個 shell 腳本來設置日誌文件並使用適當的重定向執行測試伺服器,從而繞過
StandardOutput=
對你的情況不起作用的 systemd 設置。像這樣創建一個 bash 腳本
/etc/testServer/Debug/runTestServer.sh
:#!/usr/bin/env bash timeStamp=$(date +%y-%m-%d_%Hh%Mm%Ss) myfolder="/etc/testServer/Debug" # create new logfile touch $myfolder/started_$timeStamp # remove old symlink if exists (owned by test1) if [ -h $myfolder/test_outLink ]; then rm $myfolder/test_outLink fi # create new symlink ln -s $myfolder/started_$timeStamp $myfolder/test_outLink # run the actual testServer exec /etc/testServer/Debug/testServer >/etc/testServer/Debug/test_outLink
與您的原始腳本的唯一區別
makeOutfile.sh
是,此腳本testServer
使用適當的重定向執行,以將其標準輸出發送到您剛剛設置的日誌文件。它還用於
exec
確保 shell 腳本不會被保留和替換testServer
(因此 systemd 將知道服務的主要程序是什麼。)在您的單元文件中,刪除
ExecStartPre=
和 並將其StandardOutput=
替換為ExecStart=
:ExecStart=/etc/testServer/Debug/runTestServer.sh
(或者
/bin/bash
也可以呼叫腳本,但只要腳本設置了可執行位就沒有必要。)通過這樣的腳本設置您的伺服器,您甚至可以完全繞過符號連結並直接重定向到最終的
started_$timeStamp
日誌文件。我沒有直接查看 systemd 程式碼,文件也不清楚具體之間的互動
StandardOutput=
……ExecStartPre=
但是 systemd 執行步驟的順序肯定存在問題(以及哪個程序執行它們,這導致不同的權限/所有權),所以我對你報告的結果並不感到驚訝。我想,無論如何,我的建議是使用單個包裝器執行程序腳本來簡化它,因此希望這可以解決您的問題。