Raspberry Pi で systemd を使ってプログラムを自動実行する


ラズパイのプログラムを、起動時や定刻に自動実行したい。
cronとかもあるが比較的新しくてイケてるらしいので、systemdとやらを使ってみようと思う。

脱コピペの思いで唸りながら理解したので、同じく脱コピペしたい初心者の同志に向けて書いた。

※20190312 sounisi5011さんより指摘を受け、プログラムの置き場所に関する項目を修正
※↑のついでに日本語の表現をちょこちょこ修正。

筆者

  • 非プログラマ
  • プログラミングにはpythonで入門して、ちまちまラズパイで遊んでる
  • 間違ってたらグサグサ教えて下さい

systemdとは

プロセスの起動を管理するソフトウェア。ユニットと呼ばれる単位で処理が行われ、並列処理だったり、ユニット同士の依存関係を定義できるところがすごいらしい。

単にスケジューリングがしたかったらcron等の方がお手軽だが、これからはsystemdの時代が来るらしいのでsysytemdを使い倒して行きたい。

そんなsystemdだが、たくさん機能を備えているのは置いておいて、なるべく最小限の記述する。
仕組みを理解するにはよくわからんままコピペするよりその方が良いと思うから。

ラズパイ起動時のプログラム自動実行

  1. serviceファイルを作成
  2. serviceファイルをenable

大きく言えばたったこれだけです。まず定義ファイルを作って、次に登録するイメージ。

それでは具体的に行きましょう。

1. service ファイルを作成

手順

.service ファイルは/etc/systemd/systemに作ります。

$ sudo nano /etc/systemd/system/a.service

たとえばa.pyを起動時に自動実行したいとすれば、こんな感じ。

a.service
[Unit]
Description=do something

[Service]
ExecStart=/usr/bin/python /home/pi/systemd/a.py

[Install]
WantedBy=multi-user.target

解説

[unit]

ユニット自体の定義をします。
このセクションでは、セットで起動したいユニットなどが指定できます。
Descriptionは動作に影響しませんが、しっかりわかりやすく記述しましょう。

[service]

ユニットにどんな仕事をさせるかを記述します。
実行したい処理をExecStartに記述しましょう。
ここではpythonで/home/pi/systemd/a.pyを実行させています。
他にも、失敗時の再起動の設定などができます。

[install]

サービスの有効化/無効化に関する設定をします。
ここは正直あんまり理解できてません(ああ、脱コピペしたいのに・・・。)ブート中のどのタイミングで起動するかを指定しているはず。
上記が常套句のようなので、とりあえずこれで。

ちなみに、このセクションが無いとenable(後述)できません。
systemdがどのタイミングで起動していいかわからなくなるからっぽい。

※プログラムの置き場所

sounisi5011さんの指摘を受け修正

絶対参照で指定するので、置き場所はどこでもいいっぽい。
私はhome/pi/systemdというディレクトリを作りましたが、わかりやすいように各自でどうぞ。
/opt/以下に置くのが良いようです。詳細はコメント欄にsounisi5011さんが書いて下さっています。

2. serviceファイルをenable

serviceファイルを作ったら、systemdにこいつを登録してあげる必要があります。

$ sudo systemctl enable a.service

これで[install]セクションで指定した場所にシンボリックリンクが張られました。
早速rebootして動作を確認してみて下さい。

ちなみに、rebootする前にコマンドの動作確認しときたいな〜って時は

$ sudo systemctl start a.service

です。

定刻でのプログラム自動起動

  1. serviceファイルを作成
  2. timerファイルを作成
  3. timerファイルをenable

さっきより手順が1つ増えました。
サービスを作って、それを呼び出すタイマーを作って、最後にタイマーを登録です。
それでは具体的に行きましょう。

1. serviceファイルを作成

手順

自動起動の時と同じです

$ sudo nano /etc/systemd/system/b.service
b.service
[Unit]
Description=do something

[Service]
ExecStart=/usr/bin/python /home/pi/systemd/b.py

解説

自動起動の時との違い、serviceファイルに[install]セクションは不要です。
タイマーから呼び出すので、このserviceはenableしないからです。

2. timerファイルを作成

手順

これも一緒です。

$ sudo nano /etc/systemd/system/b.timer

b.timer
[Unit]
Description=daily do something

[Timer]
OnCalendar=*-*-* 8:00

[Install]
WantedBy=timers.target

解説

[Unit]

このセクションの書き方はserviceと一緒です。

[Timer]

タイマーとしての動作を設定します。
ここでは、毎朝8時に実行されるよう設定しました。他にもn秒間隔や、ブートn秒後なども可能です。
呼び出すサービスですが、省略した場合のデフォルトは同名のサービスです(ここではb.serviceが実行されるということ)。
Unit=hoge.service
などとすれば、別名のserviceを呼び出すこともできます。

[install]

このセクションの書き方もserviceと一緒です。

3. timerファイルをenable

これもさっきと同じです。

$ sudo systemctl enable b.timer

これでタイマーを使う準備ができたので、rebootして動作させましょう。

ちなみに、

$ sudo systemctl start b.timer

とし、手動で起動させちゃってもOKです。この場合はrebootは必要ありません。
※startだけやってenable忘れたら再起動時にタイマー止まっちゃいますからね!

おわりに

systemdの使い方は以上です。

私は設定ファイルが苦手でおまじない扱いしがちなのですが、こんな風に骨組みをきちんと理解したら、ちゃんと「情報」として見えてくるようになりました。

見える世界が変わるのは良い気分ですね。