Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@rockomiz

Webページの更新チェッカー on Zabbix@Docker

概要

※初Qiita投稿です。至らない点があれば、コメントにて教えていただけると幸いです。

ボカロ好きな私が、ニコニコ動画上で特定のタグに更新があった場合に、Zabbixからお知らせ出来ないかと思い、試行錯誤してみました。

参考にさせて頂いたページ「Zabbixで更新チェッカーを作ってみる

現在の状態

Ubuntu上にDocker-composerを利用してZabbixサーバーを構築しています。

docker-compose.yml_抜粋
version: '2'

services:
  zabbix_db:
    container_name: zabbix_db
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    restart: always
    image: mysql:5.7
    volumes:
      - "./data/db:/var/lib/mysql"
    environment:

  zabbix_server:
    container_name: zabbix_server
    image: zabbix/zabbix-server-mysql:alpine-4.2-latest
    depends_on:
      - zabbix_db
    links:
      - zabbix_db
    volumes:
      - ./scripts:/usr/lib/zabbix/externalscripts
      - ./data/zabbix:/var/lib/zabbix
    ports:
      - "30051:10051"
      - "30050:10050"
    environment:
      DB_SERVER_HOST: zabbix_db

  zabbix_web:
    container_name: zabbix_web
    #image: zabbix/zabbix-web-nginx-mysql:alpine-4.2-latest
    build: 
      context: ./
      dockerfile: zabbix_web
    restart: always
    volumes:
      - /etc/localtime:/etc/localtime:ro
    links:
      - zabbix_db
    ports:
      - "7998:80"
    environment:
      DB_SERVER_HOST: zabbix_db
      ZBX_SERVER_HOST: zabbix_server
      PHP_TZ: Asia/Tokyo
    depends_on:
      - zabbix_db
      - zabbix_server

  zabbix_agent:
    container_name: zabbix_agent
    image: zabbix/zabbix-agent:alpine-latest
    restart: always
    environment:
      ZBX_SERVER_HOST: zabbix_server
      ZBX_ENABLEREMOTECOMMANDS: 1
    links:
      - zabbix_server
    depends_on:
      - zabbix_server

参考にしたページを元につくってみる

スクリプトの用意

/script/urlcheck.sh
#!/bin/bash

URL="$1"
# URLに含まれる文字でファイル名に使えない"/"は置換する
URL_PATH=${URL//\//-}
STORE_PATH="/tmp/urlcheck/url_${URL_PATH}"

mkdir -p /tmp/urlcheck

if [ -e "${STORE_PATH}_after" ]; then
  # afterが存在すればbeforeとしてコピー
  cp -f "${STORE_PATH}_after" "${STORE_PATH}_before"
else
  # afterが存在しなければbeforeとしてコンテンツ取得
  curl -s -g "$URL" -o "${STORE_PATH}_before"
fi

# コンテンツ取得
curl -s -g "$URL" -o "${STORE_PATH}_after"

# 差分確認
diff "${STORE_PATH}_before" "${STORE_PATH}_after" >/dev/null
echo $?

元のページのままだと取得時にエラーが出ることがあったため、一部改変しています。
実行権限を付与し、docker-composeに下記を追記します。

docker-compose.yml
  zabbix_server:
    volumes:
      - ./scripts:/usr/lib/zabbix/externalscripts

docker内に入り、スクリプトをテストします。

# /usr/lib/zabbix/externalscripts/urlcheck.sh http://google.com/
0

正常終了なら、0が戻ります。
ページが更新された場合、1が戻る仕様になっているので、これをZabbixで監視します。

Zabbixにアイテム登録

ss1-2.png

上記の通り登録します。

  • 名前:URL定期更新テスト
  • タイプ:外部チェック
  • キー:urlcheck.sh["https://google.com/"]
  • 更新間隔:60m

Zabbixにアクション登録

ss2.png

上記通り登録します。

  • 名前:定期更新アクション
  • 条件式:{localhost:urlcheck.sh["https://google.com/"].last()}<>0
  • 説明:{ACTION.NAME} is changed.

問題点:単一ページでは動くが、RSSなどの動的ページでは想定通りに動作しない

原因を調べてみる

上記のニコニコ動画のRSSをよーく眺めてみると、/rss/channel/lastBuildDateのところに更新日時が入ってしまっている。
この文字列が毎回変更されるため、取得しに行くたびに変更した扱いになるため、想定の動作しませんでした。

なので、XMLを簡易解析し、/rss/channel/item[n]/titleをテキスト出力し、それを比較することにします。

Dockerfileの作成とdocker-composeの修正

現在の設定ではZabbixServer内でXMLの解析が行えないため、Dockerイメージを作り直すことにしました。

FROM zabbix/zabbix-server-mysql:alpine-4.2-latest

RUN apk add --update curl xmlstarlet && \
    rm -rf /var/cache/apk/*
  • curl
  • xmlstarlet

を有効にしたDockerfileを作成し、docker-composeに追記します。

cocker-compose.yml
  zabbix_server:
    #image: zabbix/zabbix-server-mysql:alpine-4.2-latest
    build:
      context: ./zabbix_server
      dockerfile: Dockerfile

シェルスクリプトの追加

rsscheck.sh
#!/bin/bash

URL="$1"
# URLに含まれる文字でファイル名に使えない"/"は置換する
URL_PATH=${URL//\//-}
STORE_PATH="/tmp/urlcheck/rss_${URL_PATH}"

mkdir -p /tmp/urlcheck

if [ -e "${STORE_PATH}_after" ]; then
  # afterが存在すればbeforeとしてコピー
  cp -f "${STORE_PATH}_after" "${STORE_PATH}_before"
else
  # afterが存在しなければbeforeとしてコンテンツ取得
  curl -s -g "$URL" | xmlstarlet sel -t -m "/rss/channel/item" -v "title " -o " / " -v "pubDate" -n > "${STORE_PATH}_before"
fi

# コンテンツ取得
curl -s -g "$URL" | xmlstarlet sel -t -m "/rss/channel/item" -v "title " -o " / " -v "pubDate" -n > "${STORE_PATH}_after"

# 差分確認
diff "${STORE_PATH}_before" "${STORE_PATH}_after" >/dev/null
echo $?

RSS用のシェルスクリプトを作成し、同様に実行権限を付与し、テストします。
やってることは単純で、CURLで取得したデータをXmlstarletを通して、下記の通り整形しています。

  • タイトル / 動画の更新日
  • タイトル / 動画の更新日
  • ・・・
# /usr/lib/zabbix/externalscripts/rsscheck.sh https://www.nicovideo.jp/tag/%E9%9A%A0%E3%82%8C%E3%81%9F%E3%83%9C%E3%82%AB%E3%83%AD%E5%90%8D%E6%9B%B2?rss=2.0
0

あとは、既に記載したように、Zabbixにアイテム登録すれば動きます。
お盆休みで田舎に帰って暇だったので、思いつきで作ってみました。

2019/08/14 追記

RSSチェックが、時々更新判定を失敗しているので、よくよく確認してたところ、オプションフラグをつけないと毎回最新順にソートされているとは限らないようでした。
現在は下記の通りの設定でうごいています。

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
4
Help us understand the problem. What is going on with this article?