Systemd:サービス/ソケットを正しく再起動する方法

Systemd:サービス/ソケットを正しく再起動する方法

DjangoとGunicorn / Uvicornを使用する非常にシンプルなWebサービスがあります。

foo.service

[Unit]
Description=Foo service
Requires=foo.socket
After=network.target

[Service]
User=foo
Group=www-data
Restart=on-failure
WorkingDirectory=/var/lib/foo/current/backend
ExecStart=/var/lib/foo/.local/bin/poetry run gunicorn \
--env DJANGO_SETTINGS_MODULE=foo.settings \
--capture-output \
--log-level info \
--bind unix:/run/foo.sock \
--worker-class uvicorn.workers.UvicornWorker \
--workers 4 \
foo.asgi:application

[Install]
WantedBy=multi-user.target

foo.socket

[Unit]
Description=Foo socket
[Socket]
ListenStream=/run/foo.sock
[Install]
WantedBy=sockets.target

サービスを有効にして開始しました。アプリケーションを再デプロイするときにアプリケーションをオフラインにしておく必要がありますが、データベースを移行して他のタスクを実行します。しかし、私が発行したとき:

sudo systemctl restart foo.service

このメッセージを受け取りました

Warning: Stopping foo.service, but it can still be activated by:
  foo.socket

ソケットを再起動する必要がありますか?サービスを無効にしてソケットのみを有効にしますか? (このソケットはnginxで使用されます。)ここで最良の方法は何ですか?データベースを移行するときにソケットを介してサービスを有効にしたくありません。

ベストアンサー1

これには3つのオプションがあります。

  1. 両方のデバイスを一緒に起動/停止します。これを行う必要があることを覚えておく必要があるため、これは最善の解決策ではありません。
sudo systemctl stop foo.{service,socket}
  1. 管理サービスのみ可能です。これには次のものが必要です。
    • [Install]ソケット部分を下ろします。サービスはすでにRequires=ソケットなので、これは必要ありません。サービスが起動すると、ソケットも起動します。
    • PartOf=foo.serviceソケットセクションに追加されました[Unit]。これは、停止または再起動時にfoo.serviceコマンドがソケットに伝播されることを意味します。
# foo.service
[Unit]
Requires=foo.socket
After=network.target

[Service]
...

[Install]
WantedBy=multi-user.target

#foo.socket
[Unit]
PartOf=foo.service
[Socket]
ListenStream=/run/foo.sock

これで可能で、sudo systemctl {restart,stop,start} foo.serviceソケットは常に同期されます。

  1. ソケットのみを管理します。データがソケットに到着したときにのみサービスが実行されるため、このオプションをお勧めします。これを行うには:
    • Requires=サービスから削除されました。サービスを直接起動しないので、これは必要ありません。
    • [Install]サービスからこの部分を削除してください。代わりにソケットを使用します。
    • PartOf=foo.socketサービスセクションに追加されました[Unit]。アプリケーションがEOFstdin または stdout で終了する場合、これは不要な場合があります。
    • サービスセクションStandardInput=socketに追加してください。[Service]これは必ずしも必要ではありませんが、systemctl start foo.serviceソケットが起動しないと失敗します。
# foo.service
[Unit]
PartOf=foo.socket
After=network.target

[Service]
StandardInput=socket
...


#foo.socket
[Socket]
ListenStream=/run/foo.sock
[Install]
WantedBy=sockets.target

おすすめ記事