crontab の自動更新

日常の仕事のほとんどを占める定型業務では、 特定の日時に特定の仕事を行うというというパターンが多く、 システム設計では日次処理、月次処理、四半期、半期、 年次処理といった期間単位の業務や、 周単位の曜日、稼働日や休日固有の特定時刻に於ける仕事があって、 Unix の場合は cron(8) を使って自動化します。

例えば、経理業務なら銀行の稼働日に 全銀協 TCP/IP 手順で銀行側の入出金取引データや残高データを取得し、 そのデータをもとに自動仕訳して、経理データを更新するといった仕事は cron(8) で行うのが普通で、一切人手を要しないシステムが容易に実現できます。

生産管理なら稼働日の一定時刻に在庫残、発注残などの管理データを取得して、 時系列データを自動生成するとか、 工程の進渉状況を確認するといった事務のほとんどが簡単に自動化できます。

工場自動化で必要になる設備の稼働状況の確認や、 日程に合わせた運転開始、停止とか、 試験研究設備の稼働状況の確認や運転開始、停止も cron(8) を使います。 このサイトの気象データも cron(8) で定期的に収集したものが使われています。

cron(8) は /etc/rc や /etc/rc.local で起動された後、 crontab(5) 形式で記述された制御ファイルに従って、 分単位で指定されたコマンドを実行しますが、 実装の仕方はシステムによって微妙に異なり、 FreeBSDの場合は下記のような制御ファイルが使われています。

  /etc/crontab                  .. system 用
  /var/cron/tabs/root           .. root 権限による実行が必要なもの
  /var/cron/tabs/{user_account} .. ユーザ固有の権限で動かせるもの
の3種類があります。

これらのファイルの作成には crontab(1) コマンドを使うのが普通で、 通常は一度設定すれば終りですから、 これで間に合います。

しかし、家庭の自動制御で、 毎朝、日の出とか市民薄明始まり時刻に窓シャッタを開けるとか、 日の入りとか市民薄明終り時刻に窓シャッタを閉める、 あるいは、西陽があたる時刻に西面のシャッタを一時的に閉めるといった 不規則な制御だと、人手で cronta(1) コマンドを使うのは無理で、 cront(8) の制御ファイル自体の書き換えを自動化しなければなりません。

この場合は corn(8) で制御ファイルの書き換えを自動化する script 1:w nを動かして、 そこで上記の例なら、太陽の位置を計算するプログラムを起動し、 制御ファイルを書き換えるようにすればよいのですが、 制御ファイルの書き換えは ed(1) で簡単に実現できます。

ただし、制御ファイルを書き換えた後で、 /var/cron/tabs の access time を変更後の日付に変更しておかないと、 cron(8) は制御ファイルの変更に気づきません。

例えば、

#! /bin/sh
# シャッター閉鎖時刻を市民薄明終りに合わせる

hm=`/usr/local/www/src/sun -d`	# 本日の市民薄明終り時刻を求める
set $hm
mh="$2 $1"

cp /var/cron/tabs/root /usr/kh/bin/root.bak
/bin/ed /var/cron/tabs/root <<!
/\/usr\/kh\/adm\/shutter close
s/^[0-9][0-9]* [0-9][0-9]* /$mh /p
w
q
!
# reload crontab
/usr/bin/touch /var/cron/tabs
といった sh script を年間で最も早い日没前の適当な時刻に cron(8) から起動するだけ済みます。

"shutter" コマンドは c で書いた自作プログラムで、 家庭の住宅設備制御 に書いたシステムでシャッタの HA 端子を使った開閉制御をしています。

"/usr/kh/adm/shutter close" は "shutter" コマンドを使って、 シャッタを閉め、その時刻を記録する sh script です。

大切なのは、古典的 Unix の世界で、 自分で自分を変えることができることです。 これが何を意味するのか、 何を予言するのは、今の私には分かりません、

平林 浩一, 2016-12