Ubuntu19.10へのアップグレード後にDBD::mysqlでエラー発生
マイUbuntuサーバをUbuntu 19.10にアップグレードした後、毎日の体重をグラフ化したりするのに使用しているHRForecastが正常動作しておらず、エラーを出している事に気づきました。
起きた事
hrforecast.pl --config ./config.pl
を実行しているコンソールに出力されていたのは以下のようなメッセージでした。
install_driver(mysql) failed: Can't load '/opt/hrforecast-income/extlib/lib/perl5/x86_64-linux/auto/DBD/mysql/mysql.so' for module DBD::mysql: libmysqlclient.so.20: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません at /home/bata64/.plenv/versions/5.28.1/lib/perl5/5.28.1/x86_64-linux/DynaLoader.pm line 193. at (eval 158) line 3. Compilation failed in require at (eval 158) line 3. Perhaps a required shared library or dll isn't installed where expected at /opt/hrforecast-income/extlib/lib/perl5/Scope/Container/DBI.pm line 69. at /opt/hrforecast-income/lib/HRForecast/Data.pm line 33. at /home/bata64/.plenv/versions/5.28.1/lib/perl5/5.28.1/Carp.pm line 291 Carp::croak('install_driver(mysql) failed: Can\'t load \'/opt/hrforecast-income/extlib/lib/perl5/x86_64-linux/auto/DBD/mysql/mysql.so\' for module DBD::mysql: libmysqlclient.so.20: M-eM-^EM-1M-fM-^\M-^IM-cM-^BM-*M-cM-^CM-^VM-cM-^BM-8M-cM-^BM-'M-cM-^BM-/M-cM-^CM-^HM-cM-^CM-^UM-cM-^BM-!M-cM-^BM-$M-cM-^CM-+M-cM-^BM-^RM-iM-^VM-^KM-cM-^AM-^QM-cM-^AM->M-cM-^AM-^[M-cM-^BM-^S: M-cM-^AM-^]M-cM-^AM-.M-cM-^BM-^HM-cM-^AM-^FM-cM-^AM-*M-cM-^CM-^UM-cM-^BM-!M-cM-^BM-$M-cM-^CM-+M-cM-^BM-^DM-cM-^CM-^GM-cM-^BM-#M-cM-^CM-,M-cM-^BM-/M-cM-^CM-^HM-cM-^CM-*M-cM-^AM-/M-cM-^AM-^BM-cM-^BM-^JM-cM-^AM->M-cM-^AM-^[M-cM-^BM-^S at /home/bata64/.plenv/versions/5.28.1/lib/perl5/5.28.1/x86_64-linux/DynaLoader.pm line 193.^J^@ at (eval 158) line 3.^JCompilation failed in require at (eval 158) line 3.^JPerhaps a required shared library or dll isn\'t installed where expected^J at /opt/hrforecast-income/extlib/lib/perl5/Scope/Container/DBI.pm line 69.^J') called at /opt/hrforecast-income/extlib/lib/perl5/Scope/Container/DBI.pm line 81 Scope::Container::DBI::connect('Scope::Container::DBI', 'dbi:mysql:hrforecast;hostname=127.0.0.1', 'bata64', 'XXXX') called at /opt/hrforecast-income/lib/HRForecast/Data.pm line 33 HRForecast::Data::dbh('HRForecast::Data=HASH(0x5589a8cd0748)') called at /opt/hrforecast-income/lib/HRForecast/Data.pm line 234 HRForecast::Data::get_complex('HRForecast::Data=HASH(0x5589a8cd0748)', 'money', 'Complex', 'income') called at /opt/hrforecast-income/lib/HRForecast/Web.pm line 110 HRForecast::Web::__ANON__('HRForecast::Web=HASH(0x5589a84b1848)', 'Kossy::Connection=HASH(0x5589a8aef700)') called at /opt/hrforecast-income/lib/HRForecast/Web.pm line 122 HRForecast::Web::__ANON__('HRForecast::Web=HASH(0x5589a84b1848)', 'Kossy::Connection=HASH(0x5589a8aef700)') called at /opt/hrforecast-income/extlib/lib/perl5/Kossy.pm line 179 Kossy::try {...} at /home/bata64/.plenv/versions/5.28.1/lib/perl5/site_perl/5.28.1/Try/Tiny.pm line 100 eval {...} at /home/bata64/.plenv/versions/5.28.1/lib/perl5/site_perl/5.28.1/Try/Tiny.pm line 93 Try::Tiny::try('CODE(0x5589a8aeeff8)', 'Try::Tiny::Catch=REF(0x5589a8aeee60)') called at /opt/hrforecast-income/extlib/lib/perl5/Kossy.pm line 185 Kossy::__ANON__('HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Middleware/Scope/Container.pm line 14 Plack::Middleware::Scope::Container::call('Plack::Middleware::Scope::Container=HASH(0x5589a8ac9ef0)', 'HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Component.pm line 50 Plack::Component::__ANON__('HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Middleware/Static.pm line 18 Plack::Middleware::Static::call('Plack::Middleware::Static=HASH(0x5589a8aca0e8)', 'HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Component.pm line 50 Plack::Middleware::StackTrace::try {...} at /home/bata64/.plenv/versions/5.28.1/lib/perl5/site_perl/5.28.1/Try/Tiny.pm line 100 eval {...} at /home/bata64/.plenv/versions/5.28.1/lib/perl5/site_perl/5.28.1/Try/Tiny.pm line 93 Plack::Middleware::StackTrace::call('Plack::Middleware::StackTrace=HASH(0x5589a8aca178)', 'HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Component.pm line 50 Plack::Component::__ANON__('HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Middleware/Lint.pm line 24 Plack::Middleware::Lint::call('Plack::Middleware::Lint=HASH(0x5589a8aca2b0)', 'HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Component.pm line 50 Plack::Component::__ANON__('HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Util.pm line 145 eval {...} at /opt/hrforecast-income/extlib/lib/perl5/Plack/Util.pm line 145 Plack::Util::run_app('CODE(0x5589a8aca268)', 'HASH(0x5589a8cc7388)') called at /opt/hrforecast-income/extlib/lib/perl5/Starlet/Server.pm line 366 Starlet::Server::handle_connection('Plack::Handler::Starlet=HASH(0x5589a8a95c90)', 'HASH(0x5589a8cc7388)', 'IO::Socket::INET=GLOB(0x5589a8cc6ef0)', 'CODE(0x5589a8aca268)', '', '', '') called at /opt/hrforecast-income/extlib/lib/perl5/Starlet/Server.pm line 190 Starlet::Server::accept_loop('Plack::Handler::Starlet=HASH(0x5589a8a95c90)', 'CODE(0x5589a8aca268)', 100) called at /opt/hrforecast-income/extlib/lib/perl5/Plack/Handler/Starlet.pm line 80 Plack::Handler::Starlet::run('Plack::Handler::Starlet=HASH(0x5589a8a95c90)', 'CODE(0x5589a8aca268)') called at hrforecast.pl line 77 install_driver(mysql) failed: Can't load '/opt/hrforecast-income/extlib/lib/perl5/x86_64-linux/auto/DBD/mysql/mysql.so' for module DBD::mysql: libmysqlclient.so.20: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはありません at /home/bata64/.plenv/versions/5.28.1/lib/perl5/5.28.1/x86_64-linux/DynaLoader.pm line 193.
メッセージを精査すると「DBD::mysqlがlibmysqlclient.so.20を見つけられていない」という事が原因だとわかるのですが、発見した当初はCPANモジュールを入れ直したりplenv経由でPerlバージョンを5.30.0にしてみたりと遠回りをしてしまいました(いずれも改善せず)。
で、「libmysqlclient.so.20」が無いらしいという事がわかりましたので確認したところ、
$ ldd /opt/hrforecast-income/extlib/lib/perl5/x86_64-linux/auto/DBD/mysql/mysql.so linux-vdso.so.1 (0x00007ffdbc7e0000) libmysqlclient.so.20 => not found libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f033e2c3000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f033e0d2000) /lib64/ld-linux-x86-64.so.2 (0x00007f033e31d000)
という事で、確かにlibmysqlclient.so.20が見つからない模様。
更に
$ cd /usr/lib $ ls -l ./x86_64-linux-gnu/libmysqlclient.so* lrwxrwxrwx 1 root root 20 10月 9 22:03 ./x86_64-linux-gnu/libmysqlclient.so -> libmysqlclient.so.21 lrwxrwxrwx 1 root root 25 10月 9 22:03 ./x86_64-linux-gnu/libmysqlclient.so.21 -> libmysqlclient.so.21.1.17 -rw-r--r-- 1 root root 6776968 10月 9 22:03 ./x86_64-linux-gnu/libmysqlclient.so.21.1.17
という事で「libmysqlclient.so.21」はインストールされているが「libmysqlclient.so.20」は無いようです。
とりあえず「libmysqlclient.so.20」というシンボリックリンクを作ればいいかと思い
$ sudo ln -s libmysqlclient.so.21.1.17 libmysqlclient.so.20
してからhrforecastを起動してみましたが事象は改善せず。
ここで同様事象が報告されていないかGoogle検索してみたところ、
を発見。やっぱりまずはシンボリックリンクを作ってみるよね、と思いつつ、
というようにlibmysqlclient20のパッケージファイル(.deb)が公開されていたのでこれをダウンロードして
$ sudo dpkg -i ./libmysqlclient20_5.7.26-1_amd64.deb
でインストールしてからhrforecastを再度起動したところ正常に起動しました。
なお、参照した記事ではやっているapt installはいらんのでは(libmysqlclient20というlibmysqlclient21とは別のパッケージを入れたので)と思うので、とりあえずこのまま運用してみます。
考察
- アプリケーション稼働サーバでむやみにOSアップグレードするのは軽率(ただし反省はしていない)
- DBD::mysqlが将来アップデートされたら「libmysqlclient.so.21」を使うようになる?そうなったらこの事象は起きなくなるのではないか
では。
新増沢方式で合唱コンクールの審査結果集計を行うプログラム
今週の水曜日から今日まで会社が休みだったので夏休みの宿題として「新増沢方式で合唱コンクールの審査結果集計を行うプログラム」をPerlで作ってみました。
githubの以下のリポジトリに公開してあります。
新増沢方式については2008年にかながわフリーダム・シンガーズで出場した関東合唱コンクールで初めて意識をしました。
新増沢方式について - 部屋を掃除したら漫画が沢山出てきたので書く日記
計算方法が明らか、すなわちアルゴリズムが確立されているのであればプログラムにする事は可能であろう、と考えてはいたのですが実現させるまでには時間がかかってしまいました。
とりあえず上記の2008年に開催された第63回関東合唱コンクール 一般A部門の順位表で確認し、同じ審査結果になることは確認しました。
後から手直しはするつもりですが、まずは公開してみました。
使い方はgithubのREADMEに書きましたが、Perlの実行環境をお持ちの方というのはかなり限られると思われます。なので、
- 審査用紙のCSVファイルのアップロード、あるいはWEBページで審査用紙を入力したら審査結果が表示される
というようなWEBサービスを公開できればと思っています。まあ、もしかしたら来年の夏休みの宿題になるかもしれませんが・・・。待っている人はいないと思いますが、もしいましたら気長にお待ちください。
あと、「仮の第三位」が発生する可能性がある審査員数が11人の場合にもそのうち対応したいと思います。現在は9人までしか対応できません・・・。
さらにそんな事をする人はいないと思いますが、このプログラムは個人的な興味に基づいて作っておりますので、実際のコンクールの審査に使用しないようお願いします。審査結果が正しいかどうかについて現バージョンでは保証はできません。
なお、偉大な先人として「コーラス・ガウスくん」というExcelマクロで計算するソフトがあります。最多審査員数や団体数、審査用紙のフォーマットはこちらを参考にさせて頂きました。
ではー。
夏休みの宿題メモ
CentOS 6.4にTera TermでSSHアクセスしたら日本語が使えなかった場合
# yum groupinstall "Japanese Support" # echo 'LANG="ja_JP.utf8"' > /etc/sysconfig/i18n
でログインし直し、Tera Termのフォントを日本語対応しているものに変更する。
Perlのハッシュの要素を削除
delete($hash{$key});
githubへのgit pushを実行すると「error: The requested URL returned error: 403 Forbidden while accessing」ってなる
#git remote set-url origin https://bata64@github.com/bata64/[れポジ鳥の名前].git git push -u origin master
cpanfileの書式
requires 'perl', '5.008001'; on 'test' => sub { requires 'Test::More', '0.98'; requires 'Log::Handler', '0.82'; }; requires 'Log::Handler', '0.82'; :
cpanfileに書かれたCPANモジュールを一括でextlibディレクトリへインストール
% cpanm -L extlib --installdeps .
printしたりLog::Handlerで日本語出力したら「Wide character in print at・・・」と出る
use utf8; use Encode; $log->info(encode_utf8 "こんにちは");
色々調べたら「とりあえず無視」という選択肢の人もいるようですが・・・。
あと、ここを読もう。
Perlである数字の過半数を取得したい
2で割った値の小数点以下切り上げをすればよい。
use POSIX; my $num = 5; my $kahansu = ceil(${num}/2);
5の過半数は3という事で、3が得られる。
plenvのセットアップ
Perlでプログラミングをする際はCPANモジュールを使うととても便利ですが、モジュールをインストールするには管理者権限が必要だったり、失敗したときにシステム全体に影響が出たりして面倒な事があります。
これらの事を回避するためには、一般ユーザのホームディレクトリ(いわゆるローカル環境)にPerlをインストールできると便利です。
このような目的を満たすツールとしてはperlbrewがありますが、Perl Monger(Perlのすごいひと)な会社同僚に相談したところ、2014年8月現在でもっともお勧めな方法はplenvを使う事だそうですのでやり方を書いておきます。
注意事項
インストール
以下を実行。
% git clone https://github.com/tokuhirom/plenv.git ~/.plenv % echo 'export PATH="$HOME/.plenv/bin:$PATH"' >> ~/.bashrc % echo 'eval "$(plenv init -)"' >> .bashrc % exec $SHELL -l % git clone https://github.com/tokuhirom/Perl-Build.git ~/.plenv/plugins/perl-build/
これでインストールは完了です。
使ってみる
インストール可能なPerlのバージョン確認
plenv install --list
ちなみにPerlは5.Xの「X」の数字が偶数が安定版、奇数が開発版となりますので、特段の理由が無ければ偶数のバージョンを選びましょう。
Perlのインストール
ここでは5.20.0をインストールしてみます。
plenv install 5.20.0
5.8.8とか、古いバージョンだと失敗する事があったりしますが、5.10以上だったらたぶん大丈夫(上記の会社同僚談)との事です。
Solaris11.1にDBD::mysqlをインストール(追記あり)
Solaris11.1にHRForecastをインストール - 部屋を掃除したら漫画が沢山出てきたので書く日記で行った、DBD::mysqlのインストールについてです。これがかなりハマりました。
※2014年4月2日追記
cpanmを実行する前に
PATH=/opt/solarisstudio12.3/bin
というようにSolarisStudioをインストールした上でPATHに設定してやれば、下記で説明している作業をする事なくインストールに成功するようです。
事情があってSolarisStudio使えない方は以下の手順で頑張ってみてください。
Solaris11.1にHRForecastをインストール
はじめに
kazeburoさん作成のHRForecastというグラフ作成ツールを使おうと思いました。理由としては
- Perlで書かれている
- 過去日付のデータも登録できる(同じくkazeburoさん作成のGrowthForecastには無い機能)
だからです。
で、会社のマイSolaris 11.1サーバにインストールしようとしたら苦労したのと、ネットで検索したら私が困った事の解決方法そのものズバリが見つからなかったので書いてみます。
前提条件
OS: Oracle Solaris 11.1 X86 64bit版 Perl: v5.18.1 on plenv 2.1.1 mysql: Ver 14.14 Distrib 5.1.37, for pc-solaris2.11 (i386) using readline 5.1 HRForecast: 2013年11月8日現在の最新版(86a47c399b) CPANモジュールのインストールにはcpanmを使用する。 その他、gitとかcurlとかcpanmとか、登場するツールは全てインストール済みである事。
朝測定した体重をはてなグラフにメール投稿する
はじめに
「はてなグラフ」という、値を入力するとグラフを表示してくれるサービスがあり、このブログの左側に「退社時間」という「はてなグラフ」で作ったグラフを表示させています。
しかし値の入力を「はてなグラフ」の入力画面に毎日アクセスして入力するのが面倒で、そのうち止めてしまっていました。
そして最近、体重が増えてまいっちんぐな状況なので、ダイエットを行い、かつ毎朝体重を計ってグラフにしようと考え、またはてなグラフを利用することにしました。しかし入力が面倒になっては退社時間グラフの二の舞です。「あー、はてなグラフに携帯からメール送って値を投稿できれば良いのになー」と思って調べてみたら、なんと大分前からはてなグラフはAPIが公開されていたのでした。
APIとはプログラミングをする際に、サービスを利用する事が出来る仕組みを指します。はてなグラフを運営しているはてなという会社ははてなグラフをプログラムから操作する仕組み、APIを提供してくれている訳です。これを使えばプログラム経由ではてなグラフを更新することが出来そうです。サンプルプログラムも、慣れ親しんでいるperlで書かれているのも素敵です。さらに応用して、以下のような事が出来そうだと考えました。
- 家で体重を計る
- 計った体重を携帯からメールで所定のメールアドレスに送る
- メールに書かれた体重を読み取り、APIを利用してはてなグラフに入力する
- はてなグラフの「朝一に計った体重」が更新される
という訳でperlのプログラム「hatenagraph.pl」を用いた、朝一に計った体重をはてなグラフにメールで投稿するシステムを作ってみました。動作は以下の通りです。
システムのおおまかな動作(基本設計)
1. 人力で行う処理
1-1.朝起きたら自宅で体重を測定する
1-2.測定した体重を、携帯からメールで所定のメールアドレスへ送信する。メールの書式は
Subject(件名)を
bataweight [体重] 例: bataweight 67.5
とする。
2.プログラム「hatenagraph.pl」が行う処理
2-1.所定メールボックスをPOP3でアクセスし、一番最近届いたメールの件名をチェックする。
2-2.件名が「myweight [体重]」だったら、体重の値を記録し、メールをメールボックス削除、POP3接続を終了する。
件名が違ったら、その次に新しいメールの件名をチェックする。以下繰り返し。
2-3. 記録した体重の値を、はてなグラフ「朝一に計った体重」のプログラムを実行した日の値として登録する。
3. サーバが行う処理
3-1.10分おきにhatenagraph.plを実行する。
システムの詳しい情報(詳細設計)
hatenagraph.plの内容
上記はてなグラフAPIのサンプルプログラムや、こちらで紹介されているperlでPOP3アクセスを行うためのプログラムを参考に(ていうかほぼそのままです・・・)、以下のプログラムを作りました。
#!/usr/bin/perl use strict; use warnings; use DateTime; use LWP::UserAgent; use Net::POP3; #チェックする文字列 my $KEYWORD = 'bataweight'; #POP接続用情報 my $popuser = 'xxxx'; #POPログインID my $poppass = 'xxxx'; #POPログインパスワード my $popserver = 'xxxx'; #pop3サーバ名 my $popport = xxxx; #pop3ポート番号 #はてなログイン情報 my $hatenauser = 'bata64'; #はてなログインID my $hatenapass = 'xxxx'; #はてなログインパスワード my $hatenagraphname = '朝一に計った体重(Kg)'; #はてなグラフのグラフ名(utf-8) #プロキシ情報 my $use_proxy = 0; #proxyを使用するかどうか。1で使用、0で使用しない my $proxy = 'http://example.com:28080'; #httpプロキシサーバのホスト名:ポート番号(http://から記入) #変数定義 my $maildata = 0; my $weight = 0; my $counter = 0; my @array = (); #POPサーバ接続処理 ##POP接続開始 my $pop = Net::POP3->new($popserver, Port => $popport); if ( ! $pop ){ die "接続失敗: $!"; } print "###POP connect###","\n"; ##POPログイン $pop->user($popuser); print "###POP user###","\n"; my $pop_check = $pop->pass($poppass); print "###POP pass###","\n"; ##POP認証チェック if ( ! defined $pop_check ){ die "認証失敗: "; ##メールボックス内の通数が0の場合はPOP接続終了 } elsif ( $pop_check == 0 ){ ##POP接続終了 $pop->quit(); print "###POP quit because NOT MESSAGES###","\n"; } while ( $pop_check > 0 ){ my $msg = $pop->get($pop_check); print "###POP retr $pop_check###","\n"; foreach ( @$msg ){ if ( $_ =~ /^Subject: $KEYWORD/){ print "###match bataweight!###","\n"; $maildata = $_; $counter += 1; $pop->delete($pop_check); last; } } if ( $counter == 1){ last; } $pop_check -= 1; } ##POP接続終了 $pop->quit(); ##体重を取得 chomp($maildata); @array = split(/ /, $maildata); $weight = $array[2]; if ( ! $weight == 0 ){ print "###hatena###","\n"; #はてなグラフへの接続処理 my $ua = LWP::UserAgent->new; ##プロキシ設定 if ( $use_proxy == 1 ){ $ua->proxy([qw(http https)] => $proxy); } ##API経由ではてなグラフへ接続 $ua->credentials('graph.hatena.ne.jp:80', '', $hatenauser, $hatenapass); my $res = $ua->post( 'http://graph.hatena.ne.jp/api/post', { graphname => $hatenagraphname, date => DateTime->now( time_zone=>'local' )->ymd, value => $weight }); warn $res->content unless $res->code == 201; } exit
プログラムが動作する場所
プログラムが動作するには、「cronやperlを実行できてインターネットに接続していて24時間365日稼働しているLinuxまたはUNIXサーバ」が必要と考えましたが、自宅の機器でやるには色々大変なので、さくらインターネットのレンタルサーバを使うことにしました。月額500円で上記条件を満たす、FreeBSDというUNIX OSがインストールされたサーバを借りられます。
なお、さくらのレンタルサーバのperl(v5.8.9)には、上記プログラムで使ったperlモジュールが全てインストール済みでした。ローカル環境にCPANモジュールインストールするのにチャレンジしなきゃいかんかと思っていたので助かりました。メンテが行き届いているように感じられ好印象です。
こちらのサーバに、以下のディレクトリパスで実行権を付与したプログラムのファイルを格納しました。
/home/bata64/pl/hatenagraph.pl
まとめ
朝一で計った体重をメールで送ってグラフ化したい、というのが目的でしたが、この仕組みを使えば更新を止めていた退社時間グラフも楽に更新が出来そうです。凄いことは何一つやっていませんが作っていて自分が楽しかったので良しとします。
また、パソコンと接続できる体重計(知りませんがそういうのあるんですかね)があれば、体重計ってグラフ作成までを全て自動化できるのではないかと思います。
なお、作成中に会社の同期諸氏から「グラフ生成APIならgoogleにもあるよ」とか「cloudforecastとかのイマドキな機構使った方が便利だよ」とか言われましたが、とりあえず思いついた機能をどんな手段でも実現させるのが今回の目的だったので、良いのです!今後のアップデートの際に参考にさせていただきたいと思います。
あと、上記のシステムは色々改善の余地がありますのでもう少し手を加えたいと思います。思いついているのは以下のような事柄です。
- 同期O氏に「実行時にログ吐かせるだろjk」と言われたので実行時にログを出力するようにする
- メールのチェック条件はSubjectヘッダだけで良いのか?Dateヘッダもチェックすると本日以外の日のデータを投稿できるようになるのではないか。
- Subjectが日本語含まれていても、iso-2022-jpエンコード後の文字列でマッチさせればいいやー、と思ったら、メールクライアント毎にエンコードの仕方が違う模様(少なくとも自宅秀丸メールと携帯からとでは違った)なのでうまくマッチされなかった。とりあえず半角英数字だけ使う事にする。
- 投稿したいグラフをWEBページから設定できたりすると便利かもなー。
- rubyで書いてみる
では。