DiCEがうまく動かなかった
外出先から自宅サーバーでホストしているwebサイトにアクセスしたところ、MyDNSのエラーページが表示された。これは、DDNSの更新が一定期間行われていないことを示す。DDNSはDiCEで更新するようにしていたはずだ。systemctl status dice
で状態を見ると、active (exited)
だった。
当時の環境
次のようなserviceファイルを作成し、systemdで自動起動する設定にしていた。
[Unit]
Description=The DiCE Server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=notify
ExecStart=/usr/local/bin/DiCE/diced -d
ExecReload=/usr/local/bin/DiCE/diced $OPTIONS
ExecStop=/usr/local/bin/DiCE/diced $OPTIONS
RemainAfterExit=yes
PrivateTmp=true
[Install]
WantedBy=multi-user.target
systemctl start dice
した直後、statusでログを見たところ特に問題はなさそう。
[cosnomi@server1 ~]$ systemctl status dice
9月 28 19:32:09 server1 systemd[1]: Starting The DiCE Server...
9月 28 19:32:09 server1 diced[9229]: =-=-=- DiCE DynamicDNS Client -=-=-=
9月 28 19:32:09 server1 diced[9229]: Version 0.19 for Japanese
9月 28 19:32:09 server1 diced[9229]: Copyright(c) 2001 sarad
9月 28 19:32:09 server1 diced[9229]: DiCE Daemon Started !!
9月 28 19:32:09 server1 systemd[1]: Started The DiCE Server.
しかし、systemctl stop
すると、なぜかしばらく制御が戻ってこない。かなり長い時間待機していると、ようやく再びコマンド入力を受け入れる状態になった。そこで、statusを確認すると次のように出力された。
[cosnomi@server1 ~]$ systemctl stop dice
9月 28 19:43:54 server1 diced[10371]: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
9月 28 19:43:54 server1 systemd[1]: dice.service stopping timed out. Terminating.
9月 28 19:43:54 server1 diced[10371]: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
9月 28 19:43:54 server1 systemd[1]: Stopped The DiCE Server.
9月 28 19:43:54 server1 systemd[1]: Unit dice.service entered failed state.
9月 28 19:43:54 server1 systemd[1]: dice.service failed.
謎の「:」が大量に並んだログ。詳細は分からないが、とにかく正常に動いていないということだけは分かり、一筋縄ではいかなそうだったので、DiCEを使うのは諦めてcronでDDNS更新通知を行うことにした。
cron による DDNS 更新
やりたいこと
cronによるDDNS更新で何をしたいのか明確にしておく。
- 自分のグローバルIPアドレスを取得する
- DDNSに更新リクエストを送る
- 上記の処理を定期的に実行する
方法
MyDNSにIPアドレスを通知するには、複数の方法がある: メール, FTP, HTTP。今回は、最も簡単そうなHTTPによる方法を採用した。HTTPによる方法には、HTTP-BASICとHTTP-DIRECTがある。今回はHTTP-BASICによる方法を採用する。
HTTP-BASICによる方法では、http://masterID:password@www.mydns.jp/login.html にアクセスすることで、アクセス元のIPアドレスが通知される。
更新コマンド
実行するコマンドは次のとおりである。
wget -q -O /dev/null http://masterID:password@www.mydns.jp/login.html
このコマンドが正常に動くことを確認したら、これを定期実行するようにcronに入れれば良い。
cron による自動更新
理想的な実行間隔
DiCEは定期通知の他にIPアドレスの変更を検知して通知してくれるが、cronを使って更新する場合は定期通知しかできない。そのため、できるだけ正しいIPアドレスを保持するために更新間隔は短いほうが良い。しかし、あまりにも短い更新間隔はMyDNSに負担をかけてしまうかもしれない。そこで、適切な更新間隔を設定する必要がある。
MyDNS のチュートリアルのようなページでは5分毎に通知している。これは自分が考えていたよりも短かった。IPアドレスが変わったとき、最大5分程度なら十分だろう。よって、今回は、5分毎に実行するように設定した。
実行間隔を管理する仕組み
/etc
にはcron関係のファイルを置くディレクトリが幾つかある。ディレクトリによって実行間隔が異なる。
[cosnomi@server1 etc]$ ls | grep cron
anacrontab
cron.d
cron.daily
cron.deny
cron.hourly
cron.monthly
cron.weekly
crontab
現状での最短はhourlyであるから、5分毎に実行するスクリプトのためには自前でディレクトリを作成し、登録しなければならない。
実は、dailyやmonthlyなどは0:00などに実行されるのではなく、anacrontabというものによって管理されているらしく、そのファイルの中身を見て見る限り、ある程度の遅延は許容されているらしい。確かに、0:00はcron以外にも色々なプログラムが動きそうなので理にかなっている。
しかし、hourlyはそうでなく、毎時1分に実行されるように固定されている。これは、見たところ、/etc/cron.d/0hourlyというファイルで定義されているようだ。
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly
一番最後の行がメイン。これを見る限り、毎時0分ではなく毎時1分に実行されるらしい。
設定
では、先程のファイルをコピーし、最後の行を書き換えてやれば5分毎の実行ができそう。
[cosnomi@server1 etc]$ sudo mkdir cron.everyfivemin
[cosnomi@server1 etc]$ cd cron.d
[cosnomi@server1 cron.d]$ sudo cp 0hourly every5minutes
[cosnomi@server1 cron.d]$ ls
0hourly clamav-update every5minutes raid-check sysstat
[cosnomi@server1 cron.d]$ sudo vim every5minutes
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
*/5 * * * * root run-parts /etc/cron.everyfivemin
そして /etc/cron.everyfivemin
に mydns
ファイルを作成。中身に、前述したDDNS更新スクリプトを書く。
ちなみに、当たり前だけどpermissionに x
がないと実行できない。だから644とかは不可。何を当たり前のことをと思うかもしれないが、自分が引っかかってしまったので書いておく。
これで完了。