ウェブサイト検索

systemd ユニットファイル サービスの作成


サービス管理は、Linux ワークステーションや Linux サーバーを毎日使用しているときは考えもしないことですが、それが存在しないと本当に嫌いになります。たとえば、24 時間 365 日実行する必要がある新しいサーバー プログラムを作成する場合、サービス管理なしでこの課題を実行することは、実際には小さなサービス システムを自分で作成することになる悪夢です。これは明らかに、開発者が開発したマネージャーほど優れたものではありません。とにかく、数年間はフルチームでした。

systemd のサービスを利用すると、これらすべてが非常に簡単になります。アプリケーションを監視し、簡単に制御できるものが必要な場合は、systemd を使用するのが最適です。それをここで説明します。

Systemd サービスはどこにあります

新しいサービスを追加するには、次の質問に答える必要があります。 systemd では常にそうであるように、サービスがユーザーのみを対象とするか、システム全体を対象とするかによって異なります。 systemd がシステム サービス全体に対してどのように機能するかに焦点を当てます。

正確な場所は、サービスがインストールされた理由と方法によって異なります。サービスがパッケージ マネージャーによってインストールされる場合、通常は /usr/lib/systemd/system にあります。開発したソフトウェア、または systemd 自体をサポートしていないソフトウェアの場合は、サービス ファイルを /usr/local/lib/systemd/system に置きます。ただし、一部のディストリビューションでは /usr/local のこのフォルダーがサポートされていないことに注意してください。最後に、既存の systemd サービスを設定する場合は、/etc/systemd/system を使用します。

これらのフォルダー内には、*.socket、*.target、*.service などの複数のファイル拡張子があります。もちろん最後に焦点を当てます。 systemd は、サービスの開始時や停止時などにファイル名をサービスの名前として使用します。そのため、通常、サービス内のファイル名にはハイフンとアンダースコアを含む英数字のみが含まれます。開発中は、ドキュメント内にこれを作成し、完了したら systemd の場所にコピーすることをお勧めします。これにより、編集途中で保存する場合の問題を回避できます。

OK、ドキュメント内にサービス ファイルを作成してください。これで、このファイルの記述方法を確認する準備が整いました。[注: このブログ投稿のコメント セクションで潜在的なバグ レポートを参照してください]

[Unit]
Description=Penguins Web Application HTTP server (running in port 8080)
WantedBy=multi-user.target
 
[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/local/bin/penguin-web-app/main.py
Restart=always

ファイル形式は実際には ini に近いです。 ini ファイルが Windows によくあることを考えると、奇妙かもしれないと思いますが、それが仕組みです。サービス ファイルは、まず [ユニット] と [サービス] の 2 つのセクションに分かれています。各セクションは systemd の特定の側面を構成します。[Unit] にはすべての systemd ユニット ファイルで共有される要素が含まれていますが、[Service] は新しいサービスのセットアップに固有の構成のみを目的としています。

次に、セクションは、Description= や ExecStart= などのプロパティで構成されます。値は、スペースを入れずに等号=でプロパティ名と区切られます。

上に示したファイルに戻りましょう。これは、ペンギンについて Python で書かれた Web アプリを実行するように設計されたサービスについて説明しています。 systemctl enable コマンドで有効にすると、プロセスが終了するたびに systemd が再起動され、サーバーの起動時にサーバーが起動されます。クールですね?

しかし、おそらく次の Web アプリはペンギンに関するものではなく、それは残念なことです。そして、それは Python で書かれていません。この場合、可能な構成について詳しく知る必要があります。

Systemd サービスのプロパティ

まず [Unit] のプロパティに注目してみましょう。

description= は、サービスが何を行っているかを明確に説明するものです。これはサービス リストやサービス ログに表示されるため、説明的なものにする必要がありますが、1 行 1 文にとどめる必要があります。

WantedBy= を使用すると、systemd に「これが開始されると、私も開始されます」と言うことができます。通常、ターゲットの名前を入力します。一般的なターゲットの例:

  1. multi-user.target: サーバーが正常で、コマンド ライン アプリケーションを実行する準備ができているとき

  2. Graphical.target: GNOME または KDE の準備ができたとき

  3. network-up.target: サーバーがネットワークに正しく接続されている場合

最初は [Unit] のこれらのプロパティで十分です。それでは【サービス】を見てみましょう。

Type= は、サービスが実行されているかどうかを知る方法で systemd に役立ちます。一般的なタイプは次のとおりです。

  1. simple はおそらく最も一般的に使用されます。systemd は、起動したプロセスをサービスを実行するプロセスとみなします。プロセスが停止すると、サービスも停止したものとみなされます。

  2. フォークは、サーバーとして作成されたがサービス管理システムの助けを借りないアプリケーションに推奨されます。基本的に、起動されたプロセスがフォークされることが期待されており、そのフォークはサービスの最終プロセスとみなされます。より正確にするには、systemd に PID ファイルを提供することもできます。追跡するプロセスの PID は、起動されたアプリケーションによって書き込まれます。

ExecStart= はおそらくサービスにとって最も重要です。サービスの開始時にどのアプリケーションを起動するかを正確に指定します。 Penguin サービスでわかるように、私はすぐに python3 ではなく /usr/bin/python3 を使用しました。これは、systemd のドキュメントが、予期せぬ事態を避けるために絶対パスを使用することを明示的に推奨しているためです。

しかし、それは別の理由によるものでもあります。他のサービスの管理システムはシェル スクリプトに基づいていることが多いです。ただし、systemd はパフォーマンス上の理由から、デフォルトではシェルを実行しません。したがって、ExecStart= でシェル コマンドを直接指定することはできません。ただし、次のようにすることでシェル スクリプトを使用することもできます。

ExecStart=/usr/bin/bash /usr/local/bin/launch-penguin-server.sh

そんなに難しくないですよね?サービスを正常に停止するように通知するために何らかのプロセスを実行する必要がある場合は、ExecStop= が存在するだけでなく、サービスを再ロードするための ExecReload= も存在することに注意してください。

Restart= を使用すると、サービスをいつ再起動するかを明示的に指示できます。これは systemd の重要な機能の 1 つです。サービスが希望する限り稼働し続けることが保証されるため、このオプションには細心の注意を払ってください。

always

systemd は、終了またはクラッシュするたびに再起動し続けます。さて、systemctl stop service-name.service を実行するまでは。

理由もなくサービスを手動で再起動するよりも、無駄な再起動が少ない方が望ましいため、サーバーやオンライン サービスに最適です。

on-abnormal

サービスプロセスがクラッシュした場合は、サービスを再起動します。ただし、アプリケーションが正常に終了した場合は、再起動しないでください。

これは、タスクを確実に実行する必要があるが、常に実行する必要はないサービスなどの cron ジョブでより便利です。

on-failure

on-abnormal とよく似ていますが、アプリケーションがゼロ以外の終了コードで正常に終了した場合にもサービスを再起動します。ゼロ以外の終了コードは通常、エラーが発生したことを意味します。

no

systemd はサービスを自動的に再起動しません。

通常、再起動機能を使用せずにログ記録などの他の systemd 機能にアクセスするのに役立ちます。

WorkingDirectory= は、アプリケーションの起動時に作業ディレクトリを強制できます。値は絶対ディレクトリ パスである必要があります。作業ディレクトリは、アプリケーションのコードで相対パスを使用する場合に使用されます。ペンギン サービスの場合、次のようになります。

WorkingDirectory=/srv/penguin-web-app/

次に、セキュリティが重要であるため、通常は root 権限でサービスを起動しないようにします。 User= と Group= を使用すると、アプリケーションを起動するユーザー名、グループ名、または UID/GID を設定できます。例えば:

User=penguin-web
Group=penguin-web

EnvironmentFile= は強力なオプションです。サービスとして実行されるアプリケーションには多くの場合構成が必要であり、環境ファイルを使用すると、次の 2 つの方法でその構成を設定できます。

  1. アプリケーションは環境変数を直接読み取ることができます。

  2. ただし、サービス ファイルを変更せずに、アプリケーションにさまざまなコマンド ライン引数を設定することもできます。

このファイルの構文は単純です。環境変数名、等号 =、その値を入力します。次に、環境ファイルの絶対パスをEnvironmentFileプロパティに入力します。

たとえば:

EnvironmentFile=/etc/penguin-web-app/environment

/etc/penguin-web-app/environment ファイルには以下が含まれます。

LISTEN_PORT=8080

これにより、ペンギン Web アプリが LISTEN_PORT 環境変数にアクセスし、予想されるポートをリッスンできるようになります。

新しく作成した Systemd サービスを保存して開始します

したがって、私のアドバイスに従った場合は、ホーム ディレクトリ内のサービス ファイルを編集したことになります。満足したら、ディストリビューションがそのパスをサポートしていると仮定して、そのファイルを /usr/local/lib/systemd/system にコピーします。サービス ファイルのファイル名はそのサービス名になります。このファイル名は .service で終わる必要があります。たとえば、ペンギン サーバーの場合は、penguin-web-app.service になります。

次に、新しいサービスを追加したことを systemd に伝える必要があるため、次のコマンドを入力する必要があります。

$ sudo systemctl daemon-reload

ファイルに構文エラーが含まれていないと仮定すると、systemd は新しいサービスを認識しました。結局のところ、これは最初のファイルなので、間違いを犯す可能性が高くなります。サービス ファイルが更新されるたびに、上記のコマンドを実行する必要があります。

ここで、サービスを開始します。

$ sudo systemctl start penguin-web-app.service

次のようなユニットが見つからないエラーで失敗した場合:

$ sudo systemctl start penguin-web-app.service
Failed to start penguin-web-app.service: Unit not found.

これは、ディストリビューションがそのディレクトリをサポートしていないか、サービス ファイルに正しく名前を付けていないことを意味します。ぜひチェックしてみてください。

WantedBy= を使用してサービスを設定し、サービスが自動的に開始されるようにしたい場合は、次のコマンドを使用してサービスを有効にする必要があります。

$ sudo systemctl enable penguin-web-app.service

サービスの優れた点は、バックグラウンドで実行されることです。問題は、それが適切に実行されているかどうか、また、バックグラウンドで実行されているかどうかをどのように確認するかです。心配しないでください。systemd チームもそれを考慮して、適切に実行されるかどうか、どのくらいの時間が経過したかなどを確認するためのコマンドを提供しました。

$ systemctl status penguin-web-app.service

結論

関連記事: