前から、OpenStreetMap のタイルサーバーを立てて、更新もできるようにして、エラーにもめげずに運用していました。
が、今日見てみたら、またエラーで更新が止まっていました。あーあ。
こちらのエラーの原因自体は、ググったらすぐにわかりまして、更新情報を取得しているURLが http のままだったためのようで、 https に変更したらすぐに動きました。
My sever reported several errors last night: "replication state doesn't contain a timestamp property" & #OpenStreetMap User/Note API "Socket/Connection timed out". Now everything is working fine (again). Thanks for your work @OSM_Tech ! https://t.co/AlVPRJXDrH
— Pascal Neis (@pascal_n) 2018年1月5日
具体的には、設定ファイル /var/lib/mod_tile/.osmosis/configuration.txt
# The URL of the directory containing change files. baseUrl=http://planet.openstreetmap.org/replication/hour # Defines the maximum time interval in seconds to download in a single invocation. # Setting to 0 disables this feature. #maxInterval = 3600 maxInterval = 7200
にある baseUrl を http から https に修正するだけです。
ちなみにこのサーバー上だと、エラーはこんな感じででていました。
/var/log/tiles/osmosis.log
8 29, 2018 10:15:01 午後 org.openstreetmap.osmosis.core.Osmosis run 情報: Pipeline executing, waiting for completion. 8 29, 2018 10:15:02 午後 org.openstreetmap.osmosis.core.pipeline.common.ActiveTaskManager waitForCompletion 重大: Thread for task 1-read-replication-interval failed org.openstreetmap.osmosis.core.OsmosisRuntimeException: The replication state doesn't contain a timestamp property. at org.openstreetmap.osmosis.replication.common.ReplicationState.loadProperty(ReplicationState.java:65) at org.openstreetmap.osmosis.replication.common.ReplicationState.load(ReplicationState.java:78) at org.openstreetmap.osmosis.replication.common.ReplicationState.<init>(ReplicationState.java:59) at org.openstreetmap.osmosis.replication.common.ServerStateReader.getServerState(ServerStateReader.java:108) at org.openstreetmap.osmosis.replication.common.ServerStateReader.getServerState(ServerStateReader.java:50) at org.openstreetmap.osmosis.replication.v0_6.BaseReplicationDownloader.runImpl(BaseReplicationDownloader.java:290) at org.openstreetmap.osmosis.replication.v0_6.BaseReplicationDownloader.run(BaseReplicationDownloader.java:383) at java.lang.Thread.run(Thread.java:748) (後略)
まあ、こんな感じで、理由はいろいろあるにせよ、たまにエラーで更新が止まっているのを見ると、やはりエラー時にはメールか何かで通知が必要だとと思います。
ということで、更新失敗時にメールを飛ばす設定を行ってみました。
メールサーバーの導入
タイルサーバーを作ったとき、メールサーバーなんて入れてませんでしたので、改めて入れます。 方法としては、こちらの記事
で試したように、 ssmtp と mailutil をインストールして、メールの送信だけ可能にします。
mor@map:~$ sudo apt-get install ssmtp mor@map:~$ sudo apt-get install mailutils
sSMTP の設定(/etc/ssmtp/ssmtp.conf)
mor@map:/etc/ssmtp$ cat ssmtp.conf # # Config file for sSMTP sendmail # # The person who gets all mail for userids < 1000 # Make this empty to disable rewriting. root=postmaster # The place where the mail goes. The actual machine name is required no # MX records are consulted. Commonly mailhosts are named mail.domain.com #mailhub=mail mailhub=メールサーバー:ポート番号 # Where will the mail seem to come from? #rewriteDomain= # The full hostname hostname=map # Are users allowed to set their own From: address? # YES - Allow the user to specify their own From: address # NO - Use the system generated From: address #FromLineOverride=YES # added for SMTP auth, 2018/8/30 AuthUser=ユーザー名 AuthPass=パスワード AuthMethod=cram-md5 mor@map:/etc/ssmtp$
テストします。
mor@map:~$ echo test | mail -s test メールアドレス
指定したメールアドレスに無事メールが届いていればOKです。
注意点
何度も設定しているのに、下記にひっかかりました。ご注意ください。
- /etc/ssmtp/ssmtp.conf はメール送信者が読める必要があります。ですが、認証パスワードが生のまま書かれているので、パーミッションにはご注意ください。
- /etc/ssmtp/ssmtp.conf のメールサーバが間違っていると mail コマンドでテスト送信した際に失敗します。ちなみに、コンソールから試したときは、単にfailed と出て失敗したり、何も応答がなく終了するのではなく、入力中のようになるけど、入力が終了できないような状態になりました(Ctrl+Zで一旦バックグラウンドにまわしてkillしました)。お気を付けください。
- 今回設定していたサーバー(Ubuntu 16.04.5 LTS)の場合、メールの送信に成功しても、 /va/log/mail.log にメールの送信ログが出力されませんでした。強引に下記のように自分でファイルを用意してやったら、ログが残るようになりました。別のサーバーだと問題なかったのでちょっと不思議ですね。
mor@map:~$ cd /var/log mor@map:/var/log$ touch mail.log mor@map:/var/log$ sudo chown syslog:adm mail.log mor@map:/var/log$ sudo chmod 640 mail.log mor@map:/var/log$ service syslog restart
タイルサーバー更新失敗時にメールを飛ばす設定
元々の更新に使っているスクリプト( mod_tile/openstreetmap-tiles-update-expire )を見ると、エラーが起きた場合は、 m_error とうい関数を呼び出して終了しているようです。 なのですが、この関数が exit だけでスクリプトを終了してしまいます。
m_error() { echo "[`date +"%Y-%m-%d %H:%M:%S"`] $$ [error] $1" >> "$RUNLOG" m_info "resetting state" /bin/cp $WORKOSM_DIR/last.state.txt $WORKOSM_DIR/state.txt || true rm "$CHANGE_FILE" || true rm "$EXPIRY_FILE.$$" || true rm "$LOCK_FILE" exit }
なので、この最後を
m_error() { (略) exit 1 }
として、終了ステータスを設定するように変更します。
次に、終了ステータスを見てメール送信をおこなうスクリプトを書きます。 例えば、 ~/bin/osm-tile-update-expire-w-mail という名前で保存しておきます。
#!/bin/sh # # do openstreetmap-tiles-update-expire with mail notification if update failed. # # 2018/8/30, Junichi MORI ACCOUNT=osm SCRIPT_DIR=/home/${ACCOUNT}/src/mod_tile/ SCRIPT=openstreetmap-tiles-update-expire MAIL_TO=メールアドレス ${SCRIPT_DIR}/${SCRIPT} > /dev/null 2>&1 STS=$? #echo "status is " $STS if [ ${STS} != 0 ] then echo "osm update script failed. Please check log files on /var/log/tiles . Last exit code is " ${STS} | mail -s "error: osm update" ${MAIL_TO} fi
テスト
上記で作ったスクリプトを呼んでみます。 最初に言った修正はまだ反映していない状態としておきます(エラーが起きる状態です)。 そうすると、上記のスクリプト実行時に、エラーが起きて、メールが通知されます。無事メールが確認できました。
cron に設定
テストで問題がなければ、 cron で定期的に呼び出すようにします。
osm@map:~/bin$ crontab -e osm@map:~/bin$ crontab -l # Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined through a single line # indicating with different fields when the task will be run # and what command to run for the task # # To define the time you can provide concrete values for # minute (m), hour (h), day of month (dom), month (mon), # and day of week (dow) or use '*' in these fields (for 'any').# # Notice that tasks will be started based on the cron's system # daemon's notion of time and timezones. # # Output of the crontab jobs (including errors) is sent through # email to the user the crontab file belongs to (unless redirected). # # For example, you can run a backup of all your user accounts # at 5 a.m every week with: # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command #6 */1 * * * /home/osm/src/mod_tile/openstreetmap-tiles-update-expire > /dev/null 2>&1 6 */1 * * * /home/osm/bin/osm-tile-update-expire-w-mail > /dev/null 2>&1 osm@map:~/bin$
これで OpenStreetMap のデータ更新に失敗したらすぐに通知がくるので、すぐ気づけると思います。