2025年6月20日

Debian系Linuxでのタイマー設定によるコマンド自動実行の実証


三段峡猿飛の二段滝
三段峡猿飛の二段滝        


 Debian系Linuxとは、Debian GNU/LinuxをベースとしたLinuxディストリビューションの総称です。Debian自体が非常に安定しており、多くのディストリビューションの基盤となっているため、Debian系と呼ばれるグループを形成しています。

UbuntuもDebianをベースに開発された最も有名なディストリビューションの一つです。

前回,このDebianをベースにしたRaspberryPi OSを使って,ローカル用のDNSキャッシュサーバを作成しました。

その中で「root.hints」というファイルを定期的に自動更新する必要が生じましたので,タイマーを使った自動実行方法を学習したいと思います。

通常,Linuxではcronを使うのが主流ですが,最近ではタイマーを使う方法が増えています。

【実証前提条件】
  • Raspberry Pi1 Model B Rev.2 512 MB of RAM
  • OS :  Raspbian GNU/Linux 12 (bookworm) (CMD : lsb_release -a)

それでは学習を始めます。





    1.タイマー実行の仕組み

Linuxのsystemdは、システムの初期化(起動)処理やシステム管理を行うソフトウェア群です。従来のinitシステム(SysVinitなど)を置き換える目的で開発され、現在多くのLinuxディストリビューションで標準的に採用されています。

タイマーの仕組みは,このsystemdを利用します。この「systemd」のフォルダー下にある「system」フォルダに,「.timer」で終わるタイマーユニットファイルと「.service」で終わるサービスユニットファイルを作ることで実行します。

Unitファイルの配置ディレクトリは主に2か所あり,「 /usr/lib/systemd/system/」はインストールされたパッケージシステムの配置場所であり,「/etc/systemd/system/」はユーザ独自設定(管理者が作成・管理するUnitファイル)の配置場所です。

なお,両方に同じものが配置された場合は,「/etc/systemd/system/」が優先されます。

因みに,WSL2では,PID=1が「init」であるため,「systemctl」コマンドが長らく使えなかったのですが,現在では使えるようになったようです。

今回はユーザ独自のタイマーユニットとサービスユニットなので,「/etc/systemd/system/」下に作成していきます。

今回のタイマー実行のサービスターゲットは,ローカルDNSキャッシュサーバの設定パラメータ内で利用する「root.hints」ファイルの定期更新になります。

このファイルは,「/etc/unbound/root.hints」として格納されており,「curl」コマンドを利用して,次のようにコマンド実行することで得られます。

Linuxコード

/usr/bin/curl -S -o /etc/unbound/root.hints https://www.internic.net/domain/name.cache


この実行スクリプトを「.service」ユニットファイルに設定して,定期的に実行します。

なお,サービスユニットやタイマーユニットの作成や有効化はルート権限で行った方が,実行スクリプトの動作権限との関連で良いと考えます。




    2.「.service」ユニットファイルの構成

サービスユニットファイルの構成は,以下のとおりです。
ファイル名は「/etc/systemd/system/roothints.service」としています。テキストエディターは「vi」や「nano」など何でも構いません。

/etc/systemd/system/roothints.service

[Unit]
Description=roothints update for unbound
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/bin/curl -S -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache || true
ExecStartPost=/usr/sbin/unbound-control reload


若干,内容を説明します。

【Unitセクション】
  • Descriptionは任意のユニット名です。
  • AfterはBeforeと対極で右記条件後に行う事になります。「network-online.target」はネットワークが利用できる環境確立後ということになります。よく,「network.target」とありますが,これはネットワーク管理スタックが起動後ということで,ネットワーク接続は確立されていなくてもよく,終了処理を意識した設定のようです。
【Serviceセクション】
  • typeは,サービスユニットの動作タイプを指定します。「oneshot」は,シングルジョブスクリプト用です。その他「simple」,「forking」等がありますが,詳しくはこちらをご覧ください。
  • ExecStartは,実行コマンドスクリプトを設定します。ここでは,「curl」コマンドを使って,「root.hints」ファイルを作成しています。「|| true」は,コマンドが失敗しても継続できるようにする設定です。
  • ExecStartPostは,「ExecStart」後のジョブスクリプトを設定します。ここでは「root.hints」ファイルをローカルDNSキャッシュサーバソフトである「Unbound」に読み込ますため,「unbound-control」コマンドを使ってリロードしています。「ExecStart」前に行う場合は「ExecStartPre」を利用します。
因みに,「curl」や「unbound-control」などのホームディレクトリは「which」コマンドで調べると分かります。




    3.「.timer」ユニットファイルの構成

次に,サービスユニットと対で,タイマーユニットを下記のように作成します。
ファイル名は「/etc/systemd/system/roothints.timer」としています。テキストエディターは「vi」や「nano」など何でも構いません。

/etc/systemd/system/roothints.timer

[Unit]
Description=Update roothints monthly

[Timer]
OnCalendar=monthly
Persistent=true     
Unit=roothints.service

[Install]
WantedBy=timers.target


若干,内容を説明します。

【Unitセクション】
  • Descriptionは任意のユニット名です。
【Timerセクション】
  • OnCalendarは起動する日時を指定します。daily , weekly,monthly等の他に,月日・時間も直接指定できます。
  • Persistent=true は,システム電源が切られていたなど、最後の起動時間を過ぎて立ち上がった場合、すぐに実行される指定です。
  • Unitは,タイマーで起動するユニットサービスを設定します。タイマーと同一名称の場合は省略出来ます。
【Install】セクション
  • WantedByは, systemd がブート後に提供する「 timers.target」 を利用するため、「WantedBy=timers.target」 を【Install】セクションに追加します。これにより,ブート後に当タイマーユニットは アクティブ化します。ターゲットは「 timers.target」 以外にもいろいろあります。
詳しくはこちらをご覧ください。




    タイマーの有効化

これらのユニットファイルに実行権限を与えます。

Linuxコード

sudo chmod 0755 /etc/systemd/system/roothints.service
sudo chmod 0755 /etc/systemd/system/roothints.timer

このタイマーを有効化するには次のコマンドを入力します。

Linuxコード

sudo systemctl start roothints.timer
sudo systemctl enable roothints.timer


また,タイマーが正常に作動しているかどうかは,以下のコマンドを入力します。

Linuxコード

sudo systemctl status roothints.timer


また,サービスファイルやタイマーファイルを変更した後は,次のコマンドを入力してリロードしてください。

Linuxコード

sudo systemctl daemon-reload




    タイマー実行の確認

タイマー実行の確認は,次のコマンドを入力して確認します。

Linuxコード

sudo systemctl list-timers


テスト時点では,タイマーユニットファイルの「OnCalendar=monthly」を「daily」に変えてテストした方がいいかもしれません。

タイマー実行リストの中に「roothints.timer」の実行時刻が出力されていればOKです。

また,ターゲットである「/etc/unbound/root.hints」ファイルのシステム日付が変わっていることを確認します。

最後に,「/var/log/syslog」ファイルにエラーのない事を確認してください。(RaspberryPi OSの場合は「journalctl」コマンドになります。)

RaspberryPi OSやUbuntuの場合,バージョンや依存関係によって,エラーが発生し易いです。エラーが繰り返し発生してる場合などは,ログが大量に出力されストレージ不足を招くことがあります。

そういう場合は,発生原因をインターネットでググって調査し解決します。




    6.まとめ

Debian系Linuxでのタイマー実行の方法について学習しました。従来は「cron」でしたが,指定した時刻に実行スクリプトを簡単に稼働できました。

セクションやオプションは,今回学習したほかにも沢山あります。必要に応じてインターネット等をググって頂ければ幸いです。

また,予期しないエラーも発生しますので,その時はインターネット上に沢山の事例があります。ご調査ください。

但し,日本語で解決策を表示しているサイトはほとんどありませんので,英語の苦手な方はブラウザの日本語翻訳機能などを使って対応して下さい。



それでは,楽しいITリテラシーライフをお過ごしください。


(ご注意)情報の正確性を期していますが,実施される場合には自己責任でお願いします。

0 件のコメント: