Raspberry PiにZabbixをインストールする

「Raspberry Pi 3でファイルサーバ兼iTunesサーバを作る」ではサーバ監視ツールとしてnetdataをインストールしたが、ディスク使用率の監視に難があるためZabbixに切り替えることにした。 ここでは、Raspberry PiにZabbixをインストールし、サーバの状態を表すグラフを一覧表示するダッシュボード(Screen)を作ってみる。

環境

Raspberry Pi 3 (Raspbian Jessie Lite)

$ uname -a
Linux raspberrypi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux

$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)"
NAME="Raspbian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

Zabbixのインストール

Raspbianのリポジトリには、バージョン2.2のパッケージが用意されている。 まず、マニュアルのインストール手順を参考に、必要なパッケージをインストールする。

$ sudo apt-get install zabbix-server-mysql zabbix-frontend-php
$ sudo apt-get install zabbix-agent
$ sudo apt-get install php5-mysql

次に、MySQL上にデータベースを作成する。パスワード(<PASSWORD>)は適宜置き換えること。

$ mysql -uroot -p
mysql> create database zabbix character set utf8 collate utf8_bin;
mysql> grant all privileges on zabbix.* to zabbix@localhost identified by '<PASSWORD>';
mysql> exit

$ cd /usr/share/zabbix-server-mysql
$ zcat schema.sql.gz | mysql -v -uzabbix -p zabbix
$ zcat images.sql.gz | mysql -v -uzabbix -p zabbix
$ zcat data.sql.gz | mysql -v -uzabbix -p zabbix

続けて、zabbix-serverおよびPHPの設定を行う。

$ sudo vi /etc/zabbix/zabbix_server.conf
DBHost=localhost
DBName=zabbix
DBUser=zabbix
DBPassword=<PASSWORD>

$ sudo service zabbix-server restart
$ sudo vi /etc/php5/apache2/php.ini
; Zabbix
post_max_size = 16M
max_execution_time = 300
max_input_time = 300
date.timezone = Asia/Tokyo

フロントエンドのファイル一式を公開ディレクトリに配置し、Apacheを再起動する。

$ sudo ln -s /usr/share/doc/zabbix-frontend-php/examples/apache.conf /etc/apache2/conf-available/zabbix.conf
$ sudo a2enconf zabbix
$ sudo service apache2 restart

ブラウザからhttp://<ipaddress>/zabbixにアクセスするとセットアップページが表示されるので、表示される手順に従い、最終的に生成される設定ファイルを所定のパスに書き込む。

$ sudo vi /etc/zabbix/zabbix.conf.php
<?php
// Zabbix GUI configuration file
global $DB;

$DB['TYPE']     = 'MYSQL';
$DB['SERVER']   = 'localhost';
$DB['PORT']     = '0';
$DB['DATABASE'] = 'zabbix';
$DB['USER']     = 'zabbix';
$DB['PASSWORD'] = '<PASSWORD>';

// SCHEMA is relevant only for IBM_DB2 database
$DB['SCHEMA'] = '';

$ZBX_SERVER      = 'localhost';
$ZBX_SERVER_PORT = '10051';
$ZBX_SERVER_NAME = '';

$IMAGE_FORMAT_DEFAULT = IMAGE_FORMAT_PNG;
?>

ログイン画面が表示されたら、デフォルトアカウントのAdmin/zabbixでログインする。 続けて、画面右上にあるProfileを開き、パスワードを変更しておく。

Screenを作る

Zabbixにおける各種オブジェクトは、おおむね次のような関係にある。

Host groups - Hosts - Items/Triggers/Graphs/Discovery/Web

Templates - Applications - Items
          - Triggers/Graphs/Discovery/Web

Screens - Graphs - Items

ここで、Hostsは個々のサーバ、Itemsは数値データとして表される監視項目、Triggersはアラートを上げる条件式に相当する。 また、GraphsはItemsを組み合わせて作られるグラフ、DiscoveryはマウントポイントやNICの列挙を行いItems等に展開するルーチン、ScreensはGraphsを組み合わせて作られるダッシュボードに相当する。 WebはHTTP(S)の監視に相当し、Zabbixサーバからアクセスした際のステータスコードやダウンロード速度、レスポンスタイムを監視することができる。

今回は、Configurations→Hostsから、標準で用意されているHost「Zabbix server」を有効化した。 さらに、Configurations→Screensから、「Raspberry pi」という名前のScreenを新規作成し、以下のGraphsを適当な位置、サイズで配置した。

  • Zabbix server: CPU load
  • Zabbix server: Memory usage
  • Zabbix server: Network traffic on eth0
  • Zabbix server: Disk space usage /

Monitoring→ScreensからScreen「Raspberry pi」を表示したときのスクリーンショットを次に示す。

f:id:inaz2:20160727162240p:plain

Raspberry PiのCPU温度をグラフ化する

Raspberry Pi(Raspbian)では、次のようにしてCPU温度を得ることができる。

$ cat /sys/class/thermal/thermal_zone0/temp
64451

上の場合、CPU温度は64.451度となる。 これを利用して、ZabbixでCPU温度もグラフ化してみる。

まず、ZabbixのConfigurations→Hostsから、「Zabbix server」のItemsを選択する。 「Create Item」ボタンから新規Itemを作成し、次のように入力する(参考)。

  • Name: Temperature
  • Type: Zabbix agent
  • Key: vfs.file.contents[/sys/class/thermal/thermal_zone0/temp]
  • Type of information: Numeric (float)
  • Units: ℃
  • Use custom multiplier: 0.001
  • Update interval (in sec): 60
  • History storage period (in days): 7
  • Trend storage period (in days): 365

ここでは、Custom multiplierを使うことで得られた値を度数に変換している。

続けて、「Zabbix server」のGraphsを選択する。 「Create Graph」ボタンから新規Graphを作成し、次のように入力する。

  • Name: Temperature
  • Itemsに「Zabbix server: Temperature」を追加

あとは、上で作成したScreenにこのGraphを配置すればよい。 作成されたグラフは次のスクリーンショットのようになる。

f:id:inaz2:20160727162248p:plain

備考

Monitoring→Dashboardの「Favorite screens」に作成したScreenを追加しておくと、アクセスが容易になる。 また、Monitoring→Latest dataを見ることで、各Itemの最新の値を確認することができる。

/etc/zabbix/externalscriptsの下に実行権限を付与したシェルスクリプトを置くことで、External checksとして標準出力をItemにすることができる。 ただし、パフォーマンスが落ちるため多用すべきではない。

Google Sheetsでスクレイピング結果を定期的に記録する

Google Docs表計算アプリであるGoogle Sheetsでは、Google Apps Scriptと呼ばれるJavaScriptベースのスクリプト言語でマクロを書くことができる。 また、Google Apps ScriptではTriggerと呼ばれる機能により特定の関数を定期的に実行することができる。

Google Apps Scriptで特定のページをスクレイピングし、その結果をスプレッドシートに新しい行として追記するスクリプトを書くと次のようになる。 ここではスクレイピング対象として、Amazonから商品の新品価格を取得している。

function main() {
  var date = Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd');
  var value1 = getDataFromUrl('https://www.amazon.co.jp/dp/B00UJK322O', /新品の出品:\d+<\/a><span class='a-color-price'>¥ ([\d,]+)<\/span>より<\/span>/);
  addNewRow([date, value1]);
}

function addNewRow(values) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0];
  var firstEmptyRow = sheet.getLastRow() + 1;
  for (i=0; i<values.length; i++) {
    sheet.getRange(firstEmptyRow, i+1).setValue(values[i]);
  }
}

function getDataFromUrl(url, re) {
  var data = UrlFetchApp.fetch(url);
  var text = data.getContentText();
  Logger.log(text);
  return text.match(re)[1];
}

ここで、getDataFromUrl関数はURLと正規表現オブジェクトを引数に取り、正規表現の一つ目のキャプチャの内容を返す関数になっている。

あとは、Trigger機能でmain関数を定期的に実行するように設定すればよい。

メッセージダイジェスト(MD)、メッセージ認証コード(MAC)、鍵導出関数(KDF)の違いについてのメモ

「ハッシュ」という言葉があいまいに使われている場面をしばしば目にするので、関係する概念とそれらの違いについてまとめてみる。

メッセージダイジェスト(Message Digest; MD)

MD5SHA-1、SHA-256など、あるバイト列(メッセージ)に対し固定長の要約値を求めるアルゴリズム。 メッセージの同一性判定に用いられる。

同一の要約値となる(異なる)メッセージの組を求めることが計算量的に困難(強衝突耐性)なものをメッセージダイジェストと呼び、暗号学的ハッシュ関数とも呼ばれる。 同一の要約値となるメッセージの組が容易に求められるものは、誤り検出符号と呼ばれ区別される。 CRC32は誤り検出符号の一種である。

PythonでSHA-256を用いてメッセージダイジェストを求める例を次に示す。

$ python
Python 2.7.5 (default, Oct  2 2013, 22:34:09)
[GCC 4.8.1] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> hashlib.sha256('foobar').hexdigest()
'c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2'

メッセージ認証コード(Message Authentication Code; MAC

あるバイト列(メッセージ)に対し共通鍵を用いて固定長のバイト列を求めるアルゴリズム。 メッセージの改ざん検知に用いられる。

共通鍵を用いる点においてメッセージダイジェストと異なり、完全性を保護しメッセージの改ざんを防ぐことができる。 つまり、メッセージダイジェストではメッセージ改ざん後の値を容易に計算できるのに対し、メッセージ認証コードでは共通鍵がなければ計算できない。 また、デジタル署名とは公開鍵ではなく共通鍵を用いている点において異なり、否認防止の性質をもたない。 つまり、デジタル署名では公開鍵の持ち主がメッセージを生成したことが保証されるのに対し、メッセージ認証コードでは誰がメッセージを生成したかを特定することはできない。

メッセージ認証コードには、ハッシュ関数を用いる方式(HMAC)とブロック暗号アルゴリズムを用いる方式(CBC-MACなど)がある。 PythonでSHA-256を用いたHMACを求める例を次に示す。

$ python
Python 2.7.10 (default, Jun  1 2015, 18:05:38)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import hashlib
>>> import hmac
>>> key = os.urandom(16)
>>> hmac.new(key, 'foobar', hashlib.sha256).hexdigest()
'05d531abfb693adcb3adbdc0cd3800404636fd1726ad851c86e61683cf33c7f0'

鍵導出関数(Key Derivation Function; KDF)

秘密のバイト列(マスター鍵)から固定長の新たな鍵となるバイト列を求める(導出する)アルゴリズム。 ブロック暗号アルゴリズムに用いるのに適した、固定長で一定のエントロピーを持つより安全な鍵を得ることができる。 また、パラメータに繰り返し回数などを取ることで計算量を調整できるようになっており、導出された鍵からマスター鍵を総当たりで求めることが難しくなっている。 このため、データベースに保存しておくためのパスワードの安全な変換に適している。

Python(2.7.8、3.4以降)でHMAC SHA-256を用いたPBKDF2により新たな鍵を求める例を次に示す。

$ python3
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import hashlib
>>> import binascii
>>> salt = os.urandom(16)
>>> derived_key = hashlib.pbkdf2_hmac('sha256', b'foobar', salt, 100000)
>>> binascii.hexlify(derived_key)
b'e3fddc16c83da4ef7f6942f90111b2f129ec8b528a8ae8373ad89592285fab6c'

紙の手帳を使い始めた

ここ数年スケジュール管理にスマートフォンのスケジューラを使っていたが、紙の手帳を買ってあらためてこれを使い始めた。 メリットとデメリットのメモ。

紙の手帳のメリット

  • スケジュール、タスクリスト、メモを集約できる
  • ペンケースを兼ねる
  • 書き込みの自由度が高く、開始時刻あるいは終了時刻の省略ができる
  • 一度書いた情報が時系列で残るため、探す手間が減る
  • 時間の使い方に意識が向くようになり、モチベーション維持に役立つ

紙の手帳のデメリット

  • スマートフォンと比べて大きく、取り出すのに一手間かかる
  • 周期的なスケジュールの記録が困難
  • アラームがないため、頻繁に見返す必要がある
  • カレンダー同期ができないため、適宜転記する必要がある

留意事項

  • When、Where、Whatが重要、Who、Why、Howは必要に応じて補足
  • 確定していない終了時刻等は記録しないほうがよい

所感

デジタルに対するアナログの最も顕著な違いは「あらかじめスペースの確保がされる」ことにあるように思う。 これにより、アナログは「埋める」「書き加える」、デジタルは「置く」「更新する」といった感覚の違いがあらわれる。 デジタルにおける管理ではタスクトラッカーのタスクやWikiのページがやたら増えていき、整理がおろそかになることが起こりがちであるが、細かい粒度であえてスペースに制約を加えることでデジタル特有の問題を解消できる可能性がある。

「Protecting Passwords」というタイトルで発表した

開発者・ユーザそれぞれの立場から、パスワードを守る方法について発表した。

最も強いパスワードは完全なランダム、最も適切な管理方法はサービスごとにまったく異なるパスワードを使うことであるのは間違いないが、利便性を考えるとあまり現実的ではないと思う。 パスワードマネージャによる管理も、スマートフォンやネットカフェなどからアクセスするような場合においては逆に不便になることもある。 「強いパスワード」を考えるあまり強く安全性に配慮したアドバイスがされることもあるが、自分としては「弱いパスワードをきちんと避けつつ、ほどほどに強いパスワードを利用する」アプローチで考えたい。

また、開発者の側ではパスワードをハッシュ化して保存すべきという話がよく言われるが、鍵導出関数(Key Deviation Functions)の利用にまで踏み込んだ話をWeb上で見る機会が少ないような気がするので、この話も盛り込んだ。 鍵導出関数の実装は、Python(2.7.8および3.4以降)、RubyPHP(5.5.0以降)のそれぞれにおいて標準で提供されている。 例として、Python3で鍵導出関数PBKDF2によるパスワードハッシュの計算・検証を行うコードを示すと次のようになる。

# password_hash.py
import os
import hashlib

def compute_pwhash(password):
    salt = os.urandom(16)
    digest = hashlib.pbkdf2_hmac('sha256', str.encode(password), salt, 100000)
    return salt + digest

def verify_pwhash(pwhash, password):
    salt, digest = pwhash[:16], pwhash[16:]
    digest_new = hashlib.pbkdf2_hmac('sha256', str.encode(password), salt, 100000)
    return digest_new == digest

if __name__ == '__main__':
    pwhash = compute_pwhash('password')
    print("password hash: %r" % pwhash)

    password = input('type password: ')
    print(verify_pwhash(pwhash, password))
$ python3 --version
Python 3.4.3

$ python3 password_hash.py
password hash: b']\xc8\xfb\xde9F\xc9E\x03\x1bW\x1c\x97\x19\xa1v\xdfe\xaa\x97\xae\xb2\xe7\xaf\xb3\x12\x13\xd7\x82\xbb\x83\x9fW`$\xdaT\xeb\x90\x8c\xa4\x01n\xde2E\xce5'
type password: password
True

$ python3 password_hash.py
password hash: b'N\xeb"(\xf5Bb\r\x03\xd2\x13\n\x9bD2\x1bN\xa6\x07\x05h9\xa6!\x00{A\xf4$\xd9d\x90\x0e\x8d?c|\x06]s{\xc7\xa2\x15\xbb\xc6\x9b\x18'
type password: foobar
False

パスワードに関してはさまざまな考え方があると思うが、ひとつの参考になればよいと思う。 発表の機会をくださった#ssmjpのみなさま、ありがとうございました。

VR TheaterでGear VRを体験してみた

VRを体験してみたくなったので、ネットカフェでヘッドマウントディスプレイGear VRを体験できるVR Theaterに行ってみた。 自分が行った店舗では、有料動画を見る見ないに関わらず、ネットカフェの利用料金とは別に600円が必要だった。

いくつかあるコンテンツのうち、以下の4本を見た。

攻殻機動隊 新劇場版 Virtual Reality Diver

15分の3Dアニメ。自分の意思とは関係なくカメラ(視点)が動くので、酔いそうになる。 目線を動かしたりしていると、けっこう疲弊する。連続して見続けられるのは15分が限界のように感じた。

VR桃神祭2015

3分のライブダイジェスト映像。固定カメラなので酔いは少ないが、主にステージからの視点なので実際に客席から見るのとは違った感じ。 ステージからの視点を体験できるという点ではある意味おもしろい。

初音ミク VR Special LIVE

3分のミュージックビデオ。好きな人は好きそうな感じ。途中初音ミクが目前に接近してくる場面があるのだが、「体を引きたくても引けない」ため拘束されている感覚を体験できる。 斧とかナメクジが飛んでくる感じだと拷問になりそう。

恐竜戯画

3分の3D映像。普通。

所感

  • けっこう疲弊するので、15分以上見続けるにはつらい
  • 「体を引きたくても引けない」ところにヘッドマウント型VRの特色/限界がある
  • バイオハザードスタイルで前後移動できる物理レバーがあるとよさそう

最近買ったもの2016

引っ越しに伴いいろいろ買ったので、それらのメモ。

本棚

これまでの経験から本棚はちゃんとしたものを買う必要があることがわかったので、大きいものを買った。

キューブボックス

扉付きのものを買った。 いわゆる「隠す収納」にでき、かつテレビ台にもできる。便利。

オフィスチェア

これまでの経験から中途半端なものだと座らなくなることがわかったので、ハイバックのオフィスチェアを買った。

ブランドものではないが、十分使えて安い。 フローリングに傷がつかないようにラグマットを敷いて使っている。 机は安い折り畳みのものにした。

物干しスタンド

これまでの経験から物干し竿ではバスタオルを干すのがめんどくさいことがわかったので、場所を取らないものを買った。

書籍

技術書以外の本をいろいろ買った。

化学反応をベースに、料理をエンジニアリングの対象として考察した本。 「ギーク的には調理は、ある系に熱を加えることだと捉えることができる」(p.348)といったように、何をどうすれば料理ができるのかについて化学的に説明されている。

マネジメントに関するさまざまなトピックについて、組織行動学の研究成果を交えながら解説した本。 理想論としての側面は否定できないが、説得力がある。

ソフトウェア開発者の「キャリア、マーケティング、学習、生産性、お金、健康、精神」に関するさまざまなトピックについて、著者の考えをまとめた本。 内容が幅広く、興味深く読める。

オムニバスCD

部屋を集中できる環境にするために、ちょうどいい感じのBGMにできるCDを借りた(買ってない)。

「with Summer Breeze」じゃないほう。昼っぽい。

同じタイトルのCDがいくつかあるので注意。夜っぽい。

いわゆる定番の曲がだいたい入っている2枚組。

とくに何もしていないときに流すのにちょうどいい感じ。

ワンルームインテリアのメモ

以下の二つを考慮すれば、だいたいいい感じになる。

  • ベッドは入口から向かって横に置くことで、スペースを広く使うことができる。間に仕切りになるものを置くと空間を区切ることができ、なおよい。
  • 家具の色調を揃える。

関連リンク