RRDCached の使い方

RRDtool を高速化する rrdcached の使い方

RRDcached とは

RRDcached は RRDtool のためのキャッシュサーバーです.

RRDtool は加速度や湿度センサーの値,サーバーのCPU負荷,パケット数,と言った時系列データに特化したデータベースです.RRDtoolだけでもかなり便利ですが,さらに RRDcached と組み合わせると,

  • RRDtoolの高速化
  • sdカードやSSDに対する書き込み回数を削減する効果

が期待できます.

特に後者の効果が重要で,例えば,ラズパイベースのフィジカルコンピューティングで何も考えずにセンサデータを逐次 sdに書き込んでいると,sdカードはすぐに書き込み寿命に達します.こういう時は rrdtool + rrdcached の構成が一つの解決策になります(別解は tmpfs のようなRAMディスクを使う方法)

インストール

$ sudo apt install rrdcached

設定ファイル

/etc/default/rrdcached

デフォルト設定は以下の通り

  • データを保持するディレクトリ /var/lib/rrdcached
  • データベースの実態を保存するディレクトリ /var/lib/rrdcached/db
  • データベースのジャーナルを保存するディレクトリ /var/lib/rrdcached/journal
  • 通信用のソケット /var/run/rrdcached.sock

アクセス制限(簡便な方法)

アクセス制限はファイルのパーミッションで行う(他の方法は設定がめんどくさいので無視)

デフォルト設定では,キャッシュサーバーとなる /usr/bin/rrdcached は root ユーザで起動している.

この設定は /etc/default/rrdcached の以下の記述に従っている.

# Optional unprivileged group to run under when daemon.  If unset
# retains invocation group privileges.
#DAEMON_GROUP=_rrdcached

# Optional unprivileged user to run under when daemon.  If unset
# retains invocation user privileges.
#DAEMON_USER=_rrdcached

クライアント側は /var/run/rrdcahced.sock 経由でキャッシュサーバと通信をする

以上を踏まえて,アクセス制限は以下の2ファイルのパーミッション,owner を調整すれば良い

使い方

使い方: データベースの作成

/var/lib/rrdcached/db 以下に rrdファイルを用意するだけ

使い方:データベースへのアクセス

rrdtool のオプションで以下の二つを指定する

  • 通信用のソケット /var/run/rrdcached.sock
  • データベースのファイル名 /var/lib/rrdcached/db/データベースのファイル名

例えば

$ rrdtool fetch /var/lib/rrdcached/db/hogehoge.rrd AVERAGE 

を rrdcached 経由で実行するなら

$ rrdtool  fetch --daemon unix:/var/run/rrdcached.sock /var/lib/rrdcached/db/hogehoge.rrd  AVERAGE

と"--daemon ソケット" を付与すればよい

動作確認

rrdtool info を実行すると良い

$ rrdtool  info --daemon unix:/var/run/rrdcached.sock /var/lib/rrdcached/db/hogehoge.rrd 

コマンドラインでUNIXタイムスタンプを日付や時刻に変換する

コマンドラインで,unix timestamp を日付や時刻に変換する方法をまとめます

GNU系 (linux, debian,ubuntu,redhat,centos)

date コマンドで "-d @タイムスタンプ” の書式で unixタイムスタンプを指定します

$ date -d @1595812200
Mon Jul 27 10:10:00 JST 2020

BSD系 (macOS Darwin)

date コマンドで "-r タイムスタンプ”の書式で unix timestampを指定します

$ date -r 1595812200
Mon Jul 27 10:10:00 JST 2020

出力の書式変更

dateコマンドに "+書式" のオプションを付与すると,日付文字列の形式を変更できます

$ date -d @1595812200 +%Y%m%d
20200727
$ date -d @1595812200 +%Y-%m-%d
2020-07-27
$ date -d @1595812200 "+%Y-%m-%d %H:%M"
2020-07-27 10:10

書式中の"%文字"は以下の値に展開されます

%Y
%m
%d
%H
%M
%S

大容量HDD/SDDを高速にフォーマットする方法

ext4ファイルシステムを高速にフォーマットする方法です

背景

linuxext4でディスクを初期化すると,初期化処理は一瞬で終わるように見えます.

しかし初期化処理はまだ完了していません.真の初期化処理はディスクを mount した時に始まり,その処理はシステムに負荷をかけないように裏でこっそりと時間をかけて実行されます.

その結果,例えば新しいHDDを増設したらHDDのアクセスランプが点灯しっぱなしになった,といった事態が発生します.(裏でゆっくりと初期化処理が進行しているため,数TBのストレージを増設した場合は数時間LEDがチカチカします)

この処理は ext4lazyinit という名前のカーネルスレッドが実行しています.

例えば /usr/sbin/iotop を使って稼働状況を調べると,ext4lazyinit というカーネルスレッドが disk にアクセスしていることがわかります.

$ sudo /usr/sbin/iotop

しかし ext4lazyinit のディスク・アクセスは散発的で,ディスクにはそれほど負荷をかけていません.このように,デフォルトでは [ext4lazyinit] は他の処理の邪魔にならないように低い優先順位で起動され,ゆっくりと初期化処理を進めます.これがLEDがチカチカする原因です.

ext4lazyinit は通常は気にしなくて良い機能ですが,例えば

  • リムーバブルメディアの場合 (hot swap運用のHDDなど)
  • ラズパイで使う sdカード
  • HDD増設後すぐにファイルを大量に書き込む場合

に ext4lazyinit に起因した面倒なことが起こり得ます

高速化する方法

lazyinitを早く完了させるには,以下のどちらかの方法を使います

  • mkfs.ext4 を実行する際にオプションで指定する
  • mount を実行する際にオプションで指定する

mkfs.ext4 を実行する際にオプションで指定する

$ sudo /sbin/mkfs.ext4 -E lazy_itable_init=0  /dev/デバイスファイル

mount を実行する際にオプションで指定する

init_itable=0 をつけます

$ sudo mount -oinit_itable=0  /dev/デバイスファイル    /path/to/マウントポイント
$ sudo /usr/sbin/iotop

[ext4lazyinit] が全力で稼働します

この方法を使うと, ext4lazyinit の処理は8TBのHDDの場合でも 10分もかからず終わります.

ラズパイを軽量webサーバーにする

raspberry pi をwebサーバにする手順

目的はフィジカルコンピューティングやIoTと呼ばれるたぐいのものです.具体的にはセンサ情報・ログのモニタリング,軽量なwebサーバである lighttpd を入れてCGI経由で python スクリプトを起動したりします.

python スクリプトはi2cなどでセンサ情報を収集したり外部機器を制御するもので,これらを組み合わせることでスマホでエアコンをOn/Offしたり,温度やCO2をモニタリングしたりできるようになります.

インストール&初期設定

$ sudo apt install lighttpd

Webサーバには SSL対応とか CGIPHP,認証など様々な機能があります.これらの機能は,lighttpd ではモジュールという単位で実装されており,不要なモジュールを無効にすることでWebサーバの処理をできるだけ軽くする方針になっています

モジュールの設定は lighttpd-enable-mod lighttpd-disable-mod で行います

$ sudo lighttpd-enable-mod 
Disabled modules: accesslog auth cgi debian-doc dir-listing evasive evhost expire extforward fastcgi fastcgi-php flv-streaming no-www proxy rewrite rrdtool simple-vhost ssi ssl status userdir usertrack 
Enabled modues:

CGI の機能は cgi モジュールで実装されています. fastcgiというモジュールもありますがこれは 複数のリクエストを一回の外部プログラム起動で行うためのCGI拡張機能で,cgiモジュールとは別機能になります.

cgi モジュールを有効にします

$ sudo lighttpd-enable-mod cgi

設定を変更したら systemd経由で lighttpd を(再)起動します

$ sudo systemctl restart lighttpd

webサーバの設定

設定ファイルは  /etc/lighttpd/lighttpd.conf  です

コンテンツを保存した ディレクトリは docment root という値で指定します.デフォルト値は /var/www/html になっています

server.document-root        = "/var/www/html"

cgiの設定

設定ファイルは /etc/lighttpd/conf-available/10-cgi.conf です

CGIpythonスクリプトを使えるようにします

$HTTP["url"] =~ "^/cgi-bin/" {
        cgi.assign = ( ".py" => "/usr/bin/python" )
}

これだけで 拡張子が py のスクリプトが webサーバ経由で実行できるようになります.

openコマンドで起動するアプリケーションを設定する方法

ubuntumacOSでは,ターミナルで

$ open hogehoge.pdf

とコマンドを実行すると,pdfのビューアーが起動して pdfを表示できます.

$ open http://www.google.com

とコマンドを実行すると,ブラウザが起動して URLを開いてくれます.

この設定を変更する方法をまとめます.OSはdebian系を想定します

概要

openコマンドにはいくつかの実装が存在します.

debian系だと open コマンドは xdg-open を使っているはずです.確認します

$ type open
open is hashed (/usr/bin/open)
$ ls -la /usr/bin/open
lrwxrwxrwx 1 root root 22 Dec 30 00:00 /usr/bin/open -> /etc/alternatives/open
$ readlink -f /usr/bin/open
/usr/bin/xdg-open

たしかに /usr/bin/xdg-open を使っています

xdg-open の設定変更

xdg-open を使っている場合,設定は xdg-mime コマンドを使います.

アプリケーションの関連付けは,拡張子ではなく,mime type に対して行います.

例として hogehoge.pdf の mime typeを調べます

$ xdg-mime query filetype hogehoge.pdf 
application/pdf

application/pdf でした

application/pdfに関連付けらているアプリケーションを調べます

$ xdg-mime query default application/pdf
gimp.desktop

gimp でした

アプリを変更する場合は以下のコマンドを実行します

$ xdg-mime default org.gnome.Evince.desktop  application/pdf

org.gnome.Evince.desktop の部分がアプリケーションです.ここは /usr/share/applications/ 以下にあるファイルが指定できます.org.gnome.Evince.desktopを指定すると evince が関連付されます. (evince は軽量なpdfビューアです)

内部動作

環境変数 XDG_UTILS_DEBUG_LEVEL でデバッグログが出力されます.大きな値を設定すれば詳細が表示されるのでとりあず999を指定します

$ XDG_UTILS_DEBUG_LEVEL=999  xdg-mime query default application/pdf
Checking /home/xxxxx/.config/mimeapps.list
org.gnome.Evince.desktop

設定ファイルとして ~/.config/mimeapps.list を読んでいることが分かります. 

設定されてない mime type を指定してみましょう.たとえば dummy/X を指定してみます

$ XDG_UTILS_DEBUG_LEVEL=999  xdg-mime query default dummy/X
Checking /home/xxxxx/.config/mimeapps.list
 (割愛)
Checking /usr/share//applications/defaults.list and /usr/share//applications/mimeinfo.cache

ユーザ側の設定ファイルをサーチして,エントリが見つからない場合はシステム側の設定ファイルを順にサーチしていることが分かります.

vmplayer を起動すると polkit-agent-helper-1: pam_authenticate failed: Authentication というエラーがでる

vmplayer を起動すると

polkit-agent-helper-1: pam_authenticate failed: Authentication

vmware-setup-helper requires root access

というエラーが出るだけで vmplayer が起動できない場合の対処方法

症状

具体的には

==== AUTHENTICATING FOR org.freedesktop.policykit.exec ===
Authentication is needed to run `/usr/lib/vmware/bin/vmware-ser
Authenticating as: root
Password: 
polkit-agent-helper-1: pam_authenticate failed: Authentication 
==== AUTHENTICATION FAILED ===
Error executing command as another user: Not authorized

This incident has been reported.

というエラーが出る

対処方法

手順1)policykit gnome をインストールする
sudo apt install policykit-1-gnome
手順2)policykit の認証エージェントを手動起動する

root権限は不要.以下コマンド vmplayer を起動するユーザで起動する

 /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
手順3) vmplayer を起動しなおす

root のパスワードを尋ねるダイアログが開くようになるので,rootのパスワードを入力する

LD_PRELOADで複数のライブラリを指定する方法

LD_PRELOADで共有ライブラリを複数指定する場合は,ファイル名を":"で区切って列挙する

LD_PRELOAD=ライブラリ1:ライブラリ2

LD_PRELOADを使って,malloc()を自作関数に差し替える

ソースコード

main.c

#include <malloc.h>

int
main()
{
    void *p = malloc(1024);
    free(p);
    return 0;
}


自作のmalloc()の定義(その1)mymalloc1.c

#include <stdio.h>

void *
malloc(size_t size)
{
    fprintf(stderr, "mymalloc1: malloc() called\n");
    return NULL;
}

void
free(void *p)
{
    fprintf(stderr, "mymalloc1: free() called\n");
}

自作のmalloc()の定義(その2)mymalloc2.c

#include <stdio.h>

void *
malloc(size_t size)
{
    fprintf(stderr, "mymalloc2: malloc() called\n");
    return NULL;
}

void
free(void *p)
{
    fprintf(stderr, "mymalloc2: free() called\n");
}
コンパイル
$ gcc     main.c   -o main
$ gcc -shared -fpic mymalloc1.c -o mymalloc1.so
$ gcc -shared -fpic mymalloc2.c -o mymalloc2.so
実行

LD_PRELOADなしで実行する .システム標準のmalloc()/free()を使う

$ ./main

LD_PRELOADで mymalloc1.so を指定 .

$ LD_PRELOAD=mymalloc1.so  ./main
mymalloc1: malloc() called
mymalloc1: free() called

mymalloc1.c で実装したmalloc()/free()がコールされる

LD_PRELOADで mymalloc2.so を指定 .

$ LD_PRELOAD=mymalloc2.so  ./main
mymalloc2: malloc() called
mymalloc2: free() called

mymalloc2.c で実装したmalloc()/free()がコールされる


LD_PRELOADで 両方を指定 .

$ LD_PRELOAD=mymalloc1.so:mymalloc2.so  ./main
mymalloc1: malloc() called
mymalloc1: free() called

mymalloc1.c で実装したmalloc()/free()がコールされている

LD_PRELOADの指定順を入れ替える

$ LD_PRELOAD=mymalloc2.so:mymalloc1.so  ./main
mymalloc2: malloc() called
mymalloc2: free() called

mymalloc2.c で実装したmalloc()/free()がコールされている


LD_PRELOADで複数の共有ライブラリを指定した場合は,先頭の共有ライブライから順番にシンボル名のサーチが行われる模様

つまり

  • LD_PRELOADで指定した共有ライブラリ
    • mymalloc1.so
    • mymalloc2.so
  • main にリンクしているライブラリ
    • libc.so など (ldd ./mainで確認できる)

の順番に malloc()やfree()のシンボルをサーチしている(と思われる)

まとめ

  • LD_PRELOADで共有ライブラリを複数指定するばあいは,ファイル名を区切り文字":"で連結すれば良い
  • 同名のシンボルが複数存在する場合は, 先に指定した共有ライブラリのオブジェクトが優先される.