Qtの応用 - Systemd
概要
サービスとは、PCの起動時に自動的に実行され、バックグラウンドで仕事をするために待機するソフトウェアのことである。
一般的に、サービスはグラフィカルユーザインターフェースを持たず、ユーザの操作無しに動作する。
最もよく知られているサービスは、Web、メール、データベース等のサーバで、Apache、MySQL等がある。
また、ハードウェアの検出やUSBメモリの自動統合(マウント)等もサービスによって行われる。
サービスには、システム起動時に関連するタスクやハードウェアに関連するタスクを行う"内部サービス"と、
その後にユーザがインストールするサービス(通常は全てのサーバサービスを含む)の2種類がある。
技術用語やコンピュータ用語では、サービスは伝統的にデーモンと呼ばれている。
そのため、サーバコンポーネントであるsshdやmysqldのように、サービスを表すプログラムの最後の文字として"d"が用いられることが多い。
一方、Systemdは、システムおよびセッションマネージャ(initシステム)であり、
コンピュータの起動プロセスからシャットダウンまでの全動作時間にわたって、システム上で動作するすべてのサービスを管理する役割を担っている。
プロセスは常に(可能な限り)並行して起動され、起動プロセスを可能な限り短くする。
ここで、.serviceで終わる設定ファイルを作成して、Systemdが制御・監視するプロセスに関するコードを保持する場合をSystemd Service Unitファイルと呼ぶ。
Systemdには、サービス、タイマ、マウントポイント、ソケット、スワップスペース、デバイス等のユニットが存在する。
そのため、Systemdは管理用の設定の全てをファイルから取得する。
Systemdの用語では、これらを"ユニット"と呼び、システム全体に適用されるユニットと各ユーザ領域にのみ適用されるユニットがある。
ユニットには、サービスを開始するためのサービスユニットや、ある時点でのアクションを(繰り返し)実行するためのタイマユニット等、様々な種類がある。
各タイプのユニットファイルに共通しているのは、iniファイルに似た構造をしていることである。
ユニットファイルは、いくつかのセクション(多くの場合、3セクション)で構成されている。
Systemdではセクションと呼ばれ、その中に一連のキーと値のペア(Systemdではディレクティブと呼ばれる)が格納されている。
Systemdライブラリのインストール
ライセンス
Systemdライブラリのライセンスは、LGPL v2.1以降、または、 GPL 2.0である。
パッケージ管理システムからインストール
# RHEL sudo dnf install systemd-devel # SUSE sudo zypper install systemd-devel
ソースコードからインストール
SystemdのGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。
tar xf systemd-<バージョン>.tar.gz cd systemd-<バージョン>
Systemdをビルドおよびインストールする。
mkdir build && cd build ../configure --prefix=<Systemdのインストールディレクトリ> make -j $(nproc) make install
サンプルコード
QProcess
クラスを使用せずに、Systemdを利用してSSHデーモンを起動する場合は、Systemdのライブラリを使用する必要がある。
以下の例では、Systemdのライブラリを使用してSSHデーモンを起動している。
sd_bus_open_system
関数を使用して、システムバスへの接続を開く。- 戻り値が負の値の場合は、接続に失敗したことを示す。
sd_bus_call_method
関数を使用して、SystemdのD-Busインターフェイスを介してsshd.serviceを起動する。- 関数の引数には、バスの接続、D-Busサービス名、D-Busオブジェクトのパス名、インターフェイス名、メソッド名、入力引数、出力引数、起動するサービス名とモードを指定する。
- 戻り値が負の値の場合は、サービスの起動に失敗したことを示す。
- サービスの起動に成功した場合は、成功メッセージをデバッグ出力に表示している。
sd_bus_unref
関数を使用して、バスの接続を閉じる。
このサンプルコードを実行するには、Systemdライブラリがインストールされている必要がある。
また、適切な権限でプログラムを実行する必要がある。
※注意
この方法は、Systemdが利用可能なシステムでのみ動作する。
#include <QCoreApplication>
#include <QDebug>
#include <systemd/sd-bus.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Systemdを使用してSSHデーモンを起動
sd_bus *bus = nullptr;
int ret = sd_bus_open_system(&bus);
if (ret < 0) {
qDebug() << QString("システムD-Busの接続に失敗: %1").arg(strerror(-ret));
return -1;
}
ret = sd_bus_call_method(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
nullptr,
nullptr,
"ss",
"sshd.service",
"replace");
if (ret < 0) {
qDebug() << QString("SSHサービスの開始に失敗: %1").arg(strerror(-ret));
sd_bus_unref(bus);
return -1;
}
qDebug() << "SSHサービスの開始に成功";
sd_bus_unref(bus);
return a.exec();
}