ブログ

Armadillo-X1, Armadillo-IoT G3/G3L: systemdでアプリを自動起動する方法(その1)

at_keita.mogaki
2017年10月12日 16時39分

Armadillo-X1,Armadillo-IoT G3/G3L(以下Armadillo)で、システム起動時にアプリを起動する方法を紹介します。
今回は入門編として、他のアプリとの依存関係が無いスクリプトを実行する手順をまとめました。

※起動順序を持たせてアプリを起動させる方法は「Armadillo-X1, Armadillo-IoT G3/G3L: systemdでアプリを自動起動する方法(その2)〜起動順序を設定する〜」を参照してください。

1.Systemdの概要

SystemdとはLinuxのシステム管理デーモンの一つです。高速なシステム起動/終了や設定ファイルによるシステム管理の共通化、柔軟なプロセス起動を行うことができます。
Linuxの起動を行う処理は今までSysVinitが広く用いられてきました。しかし、並列処理ができない事や、タイマー起動やプロセス起動を行う事ができず、柔軟な起動を行うことができないという問題を抱えていました。この問題を解決するためにSystemdが登場し、多くのLinuxディストリビューションで採用されるようになりました。Armadillo-X1, Armadillo-IoT G3/G3LはDebian GNU/Linux(Debian 8.0 コードネーム: jessie)を採用しているため、デフォルトのシステム管理デーモンにSystemdが使われています。

2.起動するアプリの作成

システム起動時に起動するテストアプリを作成します。今回は以下のシェルスクリプトで試します。
このシェルスクリプトは一秒間に一度/tmp/system_init_test.logに対して"system_init_test"という文字列の書き込みを行うものです。

root@armadillo:~# vi system_init_test.sh

シェルスクリプトは以下のように実装します。

#!/bin/bash
while true
do
   echo system_init_test >> /tmp/system_init_test.log
   sleep 1
done

作成したシェルスクリプトに実行権限を与えます。

root@armadillo:~# chmod +x system_init_test.sh

3.Unitファイルの作成

SystemdではUnitと呼ばれる定義ファイルに起動時の定義を記載する事で各起動処理を行っています。
自作のアプリを自動起動させる場合も、関連付いたUnitファイル作成する事でシステム起動時にアプリを起動させる事ができるようになります。

Unitファイルには複数の種類があり、今回は「service」タイプのUnitファイルと「target」タイプのUnitファイルの設定を行います。「service」は指定のバイナリを実行するための定義が記載されたUnitファイルで、「target」は複数のUnitをまとめて実行するための定義が記載されたUnitファイルです。

「system_init_test.service」という名前の「service」タイプのUnitファイルを作成します。

root@armadillo:~# vi /etc/systemd/system/system_init_test.service

system_init_test.serviceは以下のように実装します。

[Unit]
Description = system_init_test daemon

[Service]
ExecStart = /root/system_init_test.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

Unitファイルの各項目と意味については以下にまとめました。環境にあったUnitファイルを作成してください。

[Unit]セクション : 起動時に必要な依存関係など(Unitのタイプに依存しない共通の設定項目)
 ・Description        : このUnitの説明文を記載する。
 ・Before            : このUnitよりも後に起動するUnitを指定する。(指定したUnitより前に、このUnitを起動する。)
 ・After                : このUnitよりも前に起動するUnitを指定する。(指定したUnitより後に、このUnitを起動する。)
 ・Wants                : このUnitの起動に必要なUnitを指定する。可能な限り同時起動する。
 ・Requires            : このUnitの起動に必要なUnitを指定する。必ず同時起動する。
[Service]セクション : 起動時に必要なパラメータなど
 ・Type                : このUnitが起動完了したかどうかの判定方法を指定する。
   ・simple            : コマンドが実行された時に起動完了となる。
   ・forking            : コマンドが完了した時に起動完了となる。
   ・oneshot            : コマンドが完了した時に起動完了&終了となる。
   ・notify            : このUnitのプログラム内からSystemdへシグナルを送った時に起動完了となる。
 ・ExecStart            : このUnitを起動する際に実行するコマンドを指定する。(絶対パスを指定)
 ・ExecReload        : このUnitをリロードする際に実行するコマンドを指定する。
 ・ExecStop            : このUnitを停止する際に実行するコマンドを指定する。
 ・Restart            : このUnitのメインプロセスが停止した際の動作を指定する。
   ・always            : 常に再起動を試みる。
   ・no                : 再起動を行わない。(デフォルト値)
   ・on-success        : 終了コード0で停止した際に再起動する。
   ・on-failure        : 終了コード0以外で停止した際に再起動する。
[Install]セクション : systemdで有効にした場合の設定など
 ・WantedBy        : このUnitが必要とするtargetを指定する。可能な限り同時起動する。
 ・RequiredBy    : このUnitが必要とするtargetを指定する。必ず同時起動する。

※一般的なUnitの場合、WantedBy/RequiredByに指定する値はmulti-user.targetまたは、graphical.targetを指定します。
※WantedBy/RequiredByにtargetを指定すると/etc/systemd/system/[target].wants/配下に対象となるUnitへのシンボリックリンクが作成されます。
これは[Unit]セクションのWants/Requiresに依存関係が追加されるのと同じ効果を持ち、以下のように使い分けをします。
・システム的に必要な依存関係 -> [Unit]セクションのWants/Requiresに記載
・システム管理者が環境に応じて設定する依存関係 -> WantedBy/RequiredByに記載

4.自動起動の設定

4-1.自動起動するserviceの設定

systemctlコマンドを用いて自動起動するserviceの設定をします。
・Unitリストに追加したUnitファイルが追加されている事を確認します。

root@armadillo:~# systemctl list-unit-files | grep system_init_test
system_init_test.service                                               disabled

・自動起動するserviceの設定をします。

root@armadillo:~# systemctl enable system_init_test.service
Created symlink /etc/systemd/system/multi-user.target.wants/system_init_test.service → /etc/systemd/system/system_init_test.service.

・Unitリストのdisabledがenabledに変わった事を確認します。

root@armadillo:~# systemctl list-unit-files | grep system_init_test
system_init_test.service                                               enabled
4-2.追加したserviceの起動

systemctlコマンドを用いて自動起動するserviceの設定をします。

root@armadillo:~# systemctl start system_init_test.service

以下のコマンドを実行する事で、ステータスを確認することができます。(そのまま実行すると文字化けを起こすのでLANG=Cを設定してコマンドを実行します。)

root@armadillo:~# LANG=C systemctl status system_init_test.service
* system_init_test.service - system_init_test daemon
   Loaded: loaded (/etc/systemd/system/system_init_test.service; enabled)
   Active: active (running) since Fri 2017-10-13 17:15:10 JST; 5s ago
 Main PID: 841 (system_init_tes)
   CGroup: /system.slice/system_init_test.service
           |-841 /bin/bash /root/system_init_test.sh
           `-847 sleep 1

また、実行結果は以下のコマンドで確認してください。
"system_init_test"の文字が1秒間隔で表示されれば起動に成功しています。

root@armadillo:~# tailf /tmp/system_init_test.log
system_init_test
system_init_test
system_init_test

serviceを止める場合は以下のコマンドを実行してください。

root@armadillo:~# systemctl stop system_init_test.service
4-3.再起動

Armadilloを再起動した時に、serviceが自動起動する事を確認します。

root@armadillo:~# reboot

Armadilloの再起動が完了したら再度以下のコマンドを実行し、自動起動ができているか確認します。

root@armadillo:~# tailf /tmp/system_init_test.log
system_init_test
system_init_test
system_init_test

これで自動起動の設定は完了です。

5.自動起動の解除

自動起動を解除する場合は以下のコマンドを実行してください。

root@armadillo:~# systemctl disable system_init_test.service
Removed symlink /etc/systemd/system/multi-user.target.wants/system_init_test.service.

Unitリストの表示がdisabledに変わった事を確認してください。

root@armadillo-iotg:~# systemctl list-unit-files | grep system_init_test
system_init_test.service                   disabled

これで再起動後にアプリが自動起動しなくなります。

関連ページ