私は次の単位を持っています:
test_socket_activation.socket
[Unit]
Description="************** MY TEST SOCKET ***************"
PartOf=test_socket_activation.service
[Socket]
ListenStream=127.0.0.1:9991
[Install]
WantedBy=sockets.target
test_socket_activation.service
[Unit]
Description="********** MY TEST SERVICE *****************"
[Service]
ExecStart=/home/xxx/sysadmin/systemd_units/socket_based_activation/testservice.sh
[Install]
WantedBy=multi-user.target
testservice.sh
#!/bin/bash
echo "Socket Service Triggered" > output.txt
理論的には、systemdは127.0.0.1ポート9991(test_scocket_activation.socket経由)をリッスンする必要があります。ソケットにアクセスすると、systemdは親ユニット(test_scocket_activation.service)を呼び出す必要があります。このユニットはExecStartディレクティブ(testservice.sh)にリストされているスクリプトを実行し、出力.txtというテキストファイルを生成してソケットにアクセスしました。
これは期待どおりに機能します(つまり、ソケットにアクセスすると出力.txtが生成されます)。ただし、ソケットに一度だけアクセスした場合でも、サービスユニット(test_scocket_activation.service)が「起動要求が早すぎて繰り返し起動が拒否されました」というメッセージで失敗します。これにより、サービスが失敗すると、接続されたソケットの障害がトリガーされ、受信が停止します。
ここでいくつかのテストを行いましたが、ここに私のステップとログ出力があります。
❯ sudo systemctl start test_socket_activation.socket
❯ sudo systemctl 状態 test_socket_activation.socket
● test_socket_activation.socket - "************** MY TEST SOCKET ***************"
Loaded: loaded (/etc/systemd/system/test_socket_activation.socket; disabled)
Active: active (listening) since Thu 2020-03-19 14:08:40 +01; 17s ago
Listen: 127.0.0.1:9991 (Stream)
Mar 19 14:08:40 toshi systemd[1]: Starting "************** MY TEST SOCKET ***************".
Mar 19 14:08:40 toshi systemd[1]: Listening on "************** MY TEST SOCKET ***************".
❯ エコ「こんにちは」 Netcat 127.0.0.1 9991
❯ls
output.txt testservice.sh
❯ sudo systemctl 状態 test_socket_activation.service
● test_socket_activation.service - "********** MY TEST SERVICE *****************"
Loaded: loaded (/etc/systemd/system/test_socket_activation.service; disabled)
Active: failed (Result: start-limit) since Thu 2020-03-19 14:10:42 +01; 9min ago
Process: 2842 ExecStart=/home/mkr/sysadmin/systemd_units/socket_based_activation/testservice.sh (code=exited, status=0/SUCCESS)
Main PID: 2842 (code=exited, status=0/SUCCESS)
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: test_socket_activation.service start request repeated too quickly, refusing to start.
Mar 19 14:10:42 toshi systemd[1]: Failed to start "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Unit test_socket_activation.service entered failed state.
❯ sudo systemctl 状態 test_socket_activation.socket
● test_socket_activation.socket - "************** MY TEST SOCKET ***************"
Loaded: loaded (/etc/systemd/system/test_socket_activation.socket; disabled)
Active: failed (Result: service-failed-permanent) since Thu 2020-03-19 14:10:42 +01; 41s ago
Listen: 127.0.0.1:9991 (Stream)
Mar 19 14:08:40 toshi systemd[1]: Starting "************** MY TEST SOCKET ***************".
Mar 19 14:08:40 toshi systemd[1]: Listening on "************** MY TEST SOCKET ***************".
Mar 19 14:10:42 toshi systemd[1]: Unit test_socket_activation.socket entered failed state.
❯ sudo Journalctl -u test_socket_activation.service
-- Logs begin at Thu 2020-03-19 14:05:23 +01, end at Thu 2020-03-19 14:17:29 +01. --
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: test_socket_activation.service start request repeated too quickly, refusing to start.
Mar 19 14:10:42 toshi systemd[1]: Failed to start "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Unit test_socket_activation.service entered failed state.
上記のように、ソケットは一度だけアクセスされ、サービスがトリガーされ、スクリプトを呼び出してoutput.txtファイルを生成します。しかし、まもなく数回の起動試行でサービスが失敗しました。
私の質問は次のとおりです。
ソケットに一度だけアクセスした場合(echo "hello" | netcat 127.0.0.1 9991を介して)サービスが何度も起動されるのはなぜですか?
関連付けられたソケットに一度だけアクセスするときにサービスが複数回開始されるのを防ぐ方法は何ですか?
すべての回答/コメント/洞察力を高く評価します。ありがとうございます。
答え1
Accept=No
サービスがリスニングソケットファイル記述子を渡し、接続を許可すると予想されるソケットを作成しました。走り続ける。利点は、テンプレートサービスユニットを作成しないことです。一方、ソケットには、Accept=Yes
サービスが接続のソケットファイル記述子を渡すテンプレートサービスユニットが必要です。
追加読書
- ジョナサンデボインポラード(2019)。
tcp-socket-accept
。 スナックガイド。ソフトウェア。 - https://unix.stackexchange.com/a/513663/5132
s6-tcpserver4d
。ローランベルコ。 s6ネットワーク。 skarnet.org.