こんにちは、masm11 です。
systemd シリーズの第4回です。
初回:
前回:
今回は .socket
ファイルについて説明します。
.socket
ファイルとは
以前から Linux/UNIX を管理している方には、inetd の代わり、と言うと 話が早いかと思います。
この unit ファイル中に指定されているポートでリクエストを待ち受け、 リクエストがあったら指定されているサービスに接続を渡すのです。
サービス自身がポートを開いて待ち受けるのに比べると、メリットもあります。
サービスがポートを開いて待ち受ける場合、そのサービスを restart すると、
短い時間とは思いますが、リクエストを受け付けられない時間ができます。
.socket
ファイルを使うと、サービスが動いていない間も systemd が
待ち受け続けていますので、その時間をなくすことができます。
この機能は socket activation と呼ばれることもあります。
.socket
ファイルの書き方
[Unit]
セクション
.socket
ファイルも unit ファイルの一種なので、[Unit]
セクションが
あります。
[Unit] Description=ZFS snapshot receiver socket
こんな感じで良いかと思います。.service
の場合と同様、Description は
ログ出力の際などに使われます。
[Socket]
セクション
.socket
ファイル特有のセクションです。
まず、ポートを指定します。
ListenStream=1234
このように ListenStream に数字で指定すると、TCP になります。 この例では TCP のポート 1234 で待ち受けます。
ListenStream=/tmp/foo.sock
このようにファイル名を指定した場合は、stream 型 unix domain socket になります。
datagram タイプもあります。
ListenDatagram=1234
このように ListenStream の代わりに ListenDatagram を使い、数字で指定すると、 UDP になります。この例では UDP のポート 1234 で待ち受けます。
ListenDatagram=/tmp/foo.sock
同様に datagram 型 unix domain socket です。
次に、unix domain socket の場合は、socket の所有者やパーミッションを指定します。
SocketUser=root SocketGroup=root SocketMode=0600
例えばこのように指定すると、所有者は root、グループも root で、パーミッションは 0600 になります。
また、stream 型の場合は、backlog を指定できます。
Backlog=5
これは何かと言うと、接続待ちの最大本数です。 接続リクエストがたくさん同時に来た場合に、すぐに接続完了を返せれば良いのですが、 忙しくて待たせてしまう場合があります。 上のように設定すると、最大5本までは待たせておくことができます。
この数字を大きくすると、たくさん待たせておくことができます。 逆に小さくすると、待たせることができなかった接続については、 接続拒否になってしまいます。
C言語的に言うと、
listen(sock, 5);
の、5 です。
そして、かなりの昔から 5 にしておくことが多いようですが、
.socket
のデフォルトとしては 128 だそうです。
更に、stream の場合には、accept するかどうかも指定できます。
Accept=true
これを true にすると、接続リクエストがあるたびに、 systemd が接続を完了させた後、その接続をサービスに引き渡します。
false にすると、最初に接続リクエストがあった時に、 接続とともに、待ち受けている socket もサービスに引き渡します。 そしてそれ以後サービスが待ち受けます。
さて、Accept=false の場合には、サービスの指定が可能です。
Service=foo.service
この指定をしなかった場合は、foo.socket のデフォルトは foo.service に なりますので、大抵の場合は指定しなくて良いと思います。
[Install]
セクション
このセクションを書いておくと、systemctl enable できるようになります。
[Install] WantedBy=sockets.target
こう書いておくことが多いと思います。
.service
ファイルの書き方
そして、引き渡す先のサービスも定義しておく必要があります。
サービスですので .service
ファイルに書きます。
今回は、.socket
ファイルで TCP で Accept=true
を指定した場合の例を
挙げます。
[Unit] Description=ZFS snapshot receiver service [Service] ExecStart=/home/service/zfsrecvsnap/zfsrecvsnap.sh StandardInput=socket StandardOutput=socket StandardError=journal
ExecStart
にはサービスのプログラムを指定します。
StandardInput
と StandardOutput
で、標準入力と標準出力を socket に
つないでいます。
また、プログラムでエラーが起きた場合の標準エラー出力は journal へ投げることに
しました。journal へ投げると、journalctl で確認できます。
そして、この .service
ファイルには [Install]
セクションがありません。
.socket
から起動されるので、systemctl enable
する必要がないからです。
以上で、sudo systemctl start foo.socket
すると待ち受けが始まり、
接続するたびにサービスが起動します。
注意
.socket
ファイルはプログラムの仕様と密接な関係にあります。
既存の .socket
ファイルを編集してポート番号を変更するくらいは
問題ないと思いますが、
Accept
を変更してサービスが問題なく動作してくれるとは思えません。
変更の際には必ずドキュメントに当たってください。
まとめ
今回は .socket
ファイルの内容について説明しました。
.socket
ファイルは、実は FIFO にもキャラクタ型デバイスにも使えるんですね。
socket だけだと思っていました。
ではまた!