名古屋出身ソフトウェアエンジニアのブログ

Gunicorn が systemd の Unix ドメインソケットをどのように取得しているか

以下のような *.socket と対応する *.service ファイル(Gunicorn を起動する)を systemd に登録しておくと、Gunicorn アプリケーション側の設定(コード)を特にいじらなくても当該ソケットから Listen できます。 Gunicorn が接続すべきソケットをどのように取得しているか疑問だったので、軽く調べました。

[Unit]
Description=Gunicorn Socket

[Socket]
ListenStream=/run/myapp.sock
SocketUser=www-data
SocketMode=600

[Install]
WantedBy=sockets.target

systemd を利用しているかどうかの判別

Gunicorn はデフォルトでは、TCP で Listen します。

Gunicorn ソースコードに以下のような部分があり、特定の環境変数を見ることで systemd 由来のソケットを Listen すべきと判断しているようです。

listen_fds = systemd.listen_fds()
if listen_fds:
    self.systemd = True

$LISTEN_FDS 環境変数

$LISTEN_FDS 環境変数は、systemd が開いているソケットの情報を提供するためにセットします。$LISTEN_FDS は開いているソケットの数を表す整数値です。

ファイルディスクリプタによるソケットの取得

標準入出力の次である 3 番1以降の連番を、開いているソケット数分見ることで取得しています。

$LISTEN_PID 環境変数

systemd は $LISTEN_FDS だけでなく、$LISTEN_PID も設定します。ソケットの所有者であるプロセスの ID が格納されます。

$LISTEN_FDNAMES 環境変数

$LISTEN_FDNAMES というファイル識別名を格納する補助的な環境変数もあるようですが、Gunicorn では使用していませんでした。

参考文献

  1. https://manpages.debian.org/bookworm/libelogind-dev-doc/sd_listen_fds.3.en.html
  2. https://github.com/benoitc/gunicorn

  1. SD_LISTEN_FDS_START 定数 ↩︎