この質問おそらく私がここで尋ねているものと関連しているでしょう。
これは、https://github.com/bstarynk/helpcovid/(Linux用のGPLv3+ソフトウェア、現在2020年4月現在)アクティブLinux向けのC++マルチスレッドWebアプリケーションの開発なので、進行中2020年4月8日(火)
b-star-y.tech
Linux/Debian/Buster を実行しているホストで VPS をレンタルしています。
私は他の人と一緒に開発していますコロナウイルス対策、Linux 用に C++17 でコーディングされたマルチスレッド GPLv3+ Web アプリケーション ソフトウェアです。
私はよく知らないsystemd
、そのホスト上のDebian/Busterで使用されるか、docker
実装したい次の無限ループd ファイル ツリー内git clone
。
git pull
make
./helpcovid -D -T2
stderr と stdout の両方を何らかのファイルにリダイレクトして実行します。sleep 5
そして無限に繰り返す。
私はクローンタブ仕事、atd
あるいはbatch
もっと良い方法はありますかsystemd
?
メールでご連絡ください[email protected]
答え1
約四半世紀にわたり、権限のないユーザーが nonce サービスをアドホックに実行できるようにするツールセットが存在してきました。 Daniel J. Bernstein のデーモンツール最も古いものの一つです。持っているスキャンディレクトリやその他のインフラストラクチャを設定する。supervise
直接。 M. Bernstein の UCSPI-TCP ツールセットさらに、これは、TCP 接続を受け入れて何かを実行する必要があるサービスを処理する、同じくらいの期間にわたって使用されてきたいくつかのツールセットの一例です。
systemdを必要とせずに同じことを行う他のツールセットもありますが、もちろんsystemdを使えばまたユーザーごとにアドホックなサービスを設定します。
今は 2020 年です。不安定で危険な PID ファイル メカニズムを使用する新しいプログラムを作成する理由はありません。これまでに作成した PID ファイル コードは一切必要ありません。
同様に、TCPサーバーを次のように記述するのも良いでしょう。継承するリスニングソケットを、すでに開いているファイル記述子として扱う。これが、システム全体intedから実行されるサービスは、1980年代から慣例的に運用されてきました。ユーザーごとのサービスでも同様に実行できます。s6とnoshツールセット、そしてsystemdはすべて、サービスにリスニングソケットを与える方法を提供します。どれでもあなたが書いた nonce URL 解析コードは、多くの即席のパーサーと同様に、URL が取り得るすべての形式を処理できるわけではありません。
残念ながら、私が言ったように、あなたのcpp-httplib
ライブラリには、与えられたリスニングソケットのファイル記述子。ソケットファイル記述子を継承することは 30 年余りにわたって通常の方法であったことを考えると、これはそのライブラリの設計における大きな見落としです。
何か以外システム
両方私のnoshツールセットそしてLaurent Bercot の s6 ツールセットnonce プログラムをユーザーごとのアドホック サービスとして実行する方法を提供します。
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 はサービスマネージャを必要としません。元のデーモンツールと同様に、s6-supervise
手動でサービスを呼び出す:
s6-supervise ./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()
を呼び出しNULL
、LISTEN_FDS
メカニズムを処理するコードを持つ必要があります。最後のメカニズムについては、systemd に付属する移植性のないヘルパー関数ライブラリから、他の人のより移植性の高い類似のものまで、さまざまな選択肢があります。
HELPCOVID_LOCALE
TCP ポート番号解析コード、不安定で危険な PID ファイル コード、および--locale
この方法で削除できるコードをすべて含めるよりも、はるかに少ないコードで済みます。☺
参考文献
- ジョナサン・デ・ボイン・ポラード(2001年)。 Unixデーモンプログラムを設計する際に避けるべき間違いよくある質問。
- https://github.com/jdebp/nosh/blob/ddb422c9e6db11aee1c22a171bcc729edc7fe1c3/source/listen.cpp#L1
- 問題: