這個問題也許與我在這裡問的問題有關。
這是在以下背景下https://github.com/bstarynk/helpcovid/(適用於 Linux 的 GPLv3+ 軟體,目前於 2020 年 4 月發布積極的開發,這是一個專門用於 Linux 的 C++ 多線程 Web 應用程序,所以工作正在進行中2020 年 4 月 8 日)
b-star-y.tech
我在運行 Linux/Debian/Buster 的主機上租用了 VPS 。
我和別人一起發展幫助科維德,一個用 C++17 為 Linux 編碼的多執行緒 GPLv3+ Web 應用程式軟體。
我不熟悉systemd
,由該主機上的 Debian/Buster 使用,或與docker
我想實施下面的無限循環在git clone
d 檔案樹中。
git pull
make
- 運行
./helpcovid -D -T2
時 stderr 和 stdout 都會重新導向到某個檔案。 sleep 5
和無限重複。
我很想用定時任務工作,或者也許atd
與batch
有更好的方法嗎systemd
?
您可以給我發電子郵件至[email protected]
答案1
大約四分之一個世紀以來,我們已經擁有允許非特權用戶臨時運行隨機數服務的工具集。 Daniel J. Bernstein 的守護程式工具是最早的之一。一個沒有有設置掃描目錄和其他基礎設施。人們可以在下面運行一個程序supervise
直接地。 M. Bernstein 的 UCSPI-TCP 工具集此外,這是我們在類似時間長度內使用的幾個工具集的一個範例,這些工具集處理需要接受 TCP 連線並執行操作的服務。
還有其他工具集可以做同樣的事情,不需要 systemd,當然使用 systemd 也可以也設定專門的每用戶服務。
現在已經是 2020 年了。不需要您編寫的任何 PID 檔案程式碼。
同樣,編寫 TCP 伺服器也是一個好主意,這樣它就可以繼承它的監聽套接字,作為一個已經打開的檔案描述符。事實上就是這樣全系統由 inted 營運的服務自 20 世紀 80 年代以來一直按慣例運作。它也可以透過每用戶服務來完成。 s6 和 nosh 工具集,甚至還有 systemd,都提供了為服務提供偵聽套接字的方法。沒有必要任何您編寫的隨機數 URL 解析程式碼的一部分,與許多即興解析器一樣,它不能處理 URL 可以採用的所有形式。
不幸的是,正如我所說,你的cpp-httplib
庫沒有可以使用的建構函數或函數成員給定監聽套接字的檔案描述符。鑑於繼承套接字文件描述符已經成為三十年多來的正常做法,這是該庫設計中的一個重大疏忽。
某物以外系統
兩個都我的小吃工具集和Laurent Bercot 的 s6 工具集提供將隨機數程式作為臨時每用戶服務運行的方法。
在 nosh 工具集下,會有一個helpcovid
子目錄,service
其下的子目錄包含用於處理服務的各種程式。
helpcovid/service/start
而且helpcovid/service/stop
相當小:
#!/bin/nosh
#Start file generated from ./helpcovid.socketand ./helpcovid.service
true
#!/bin/nosh
#Stop file generated from ./helpcovid.socketand ./helpcovid.service
true
肉在helpcovid/service/run
和 中helpcovid/service/service
:
#!/bin/nosh
#Run file generated from ./helpcovid.socketand ./helpcovid.service
#Starynkevitch helpcovid listening socket
tcp-socket-listen --systemd-compatibility ::0 50002
envdir env
setenv LC_ALL fr_FR.UTF-8
chdir /home/basile/dev/helpcovid/test
./service
#!/bin/nosh
#Service file generated from ./helpcovid.service
#Starynkevitch helpcovid service
sh -c 'exec /home/basile/dev/helpcovid/work/helpcovid ${flags}'
並helpcovid/service/restart
控制重啟邏輯:
#!/bin/sh
#Restart file generated from ./helpcovid.service
sleep 5
exec true # ignore script arguments
該實例將透過將其提供給每個使用者的service-manager
.該工具集在套接字上進行綁定和偵聽,從 envdir 讀取環境變數配置,並使用協定將開啟的檔案描述符傳遞給最終程序LISTEN_FDS
,並將工作目錄變更為測試webroot/
目錄所在的位置。
s6 採用類似的結構,儘管工具名稱不同(例如s6-tcpserver6-socketbinder
而不是tcp-socket-listen
)且重啟邏輯的處理方式不同。 s6 不需要服務管理員。就像原始的 daemontools 一樣,只需運行s6-supervise
手動調用服務:
s6-監督./helpcovid/service/
我不打算討論太多細節,因為主要的一點是,沒有 systemd 並不是糟糕的守護程式設計的藉口(事實上,良好的守護程式設計原則起源於較古老的非 systemd 機制),並且為偵聽套接字傳遞開啟檔案描述符的機制不僅適用於 systemd,而且可以與其他系統一起使用。
系統
上述程式其實是從systemd轉換而來的插座單元和服務單位我很快就把它們拼湊在一起。他們展示瞭如何在 systemd 上設定每個用戶服務,文件位於~/.config/systemd/user/
:
# helpcovid.socket
[Unit]
Description=Starynkevitch helpcovid listening socket
[Socket]
ListenStream=50002
Accept=No
[Install]
Wanted-By=default.target
# helpcovid.service
[Unit]
Description=Starynkevitch helpcovid service
[Service]
Environment=LC_ALL=fr_FR.UTF-8
Restart=always
RestartSec=5
ExecStart=/home/basile/dev/helpcovid/work/helpcovid ${flags}
WorkingDirectory=/home/basile/dev/helpcovid/test
#This has no meaning for systemd.
EnvironmentDirectory=env
這是透過類似的來控制的systemctl --user start helpcovid.socket
。
在 systemd 的世界裡,這些是設定檔。使用者想要更改 TCP 連接埠號碼?用戶更改ListenStream=
設定。不需要多餘的額外環境變數來設定區域設定。使用者只需LC_ALL
按所示方式設定實際(或其他)變數即可。
記錄
日誌記錄也由服務管理處理。 nosh 工具集和 s6 方式是透過管道將標準輸出和標準錯誤提供給正在運行的輔助服務cyclog
,s6-log
或其他服務。 systemd 將日誌輸出填入集中式 systemd 日誌的使用者部分中,供您journalctl --user
閱讀。
你的程式
您的程式需要登入std::clog
(即標準錯誤),呼叫setlocale()
withNULL
來讀取標準環境變量,並具有處理該LISTEN_FDS
機制的程式碼。最後有很多選擇,從 systemd 附帶的不可移植的輔助函數庫到其他人更可移植的類似函數庫。
與所有 TCP 連接埠號碼解析程式碼、搖搖欲墜且危險的 PID 檔案程式碼以及可以透過這種方式取出的程式碼相比,輸入的程式碼肯定要少HELPCOVID_LOCALE
得多--locale
。 ☺
進一步閱讀
- 喬納森·德博因·波拉德 (2001)。 設計 Unix 守護程式時要避免的錯誤。經常給的答案。
- https://github.com/jdebp/nosh/blob/ddb422c9e6db11aee1c22a171bcc729edc7fe1c3/source/listen.cpp#L1
- 問題: