カテゴリー: インフラ Page 2 of 3

PS3 Media Server をDebian(wheezy)にインストールしてDLNAサーバにする

自宅のDebiansambaを入れてファイルサーバとして使用しています。

今回、このサーバーに保存された動画をリビングの大きいテレビで再生したいと思いました。
再生側はPS3ですのでPS3 Media Serverを導入してDLNAサーバーとし、PS3から再生できるようにします。

PS3 Media Serverとは

PS3用のDLNAサーバソフトです。
javaで作成されており、WindowsMAC、そしてLinuxでも動作します。

DLNAとは

DLNA(Digital Living Network Alliance)とは、AV家電やパソコン、スマホタブレットなど、
機器やメーカーを問わず、LANを通じて、映像・音楽・写真をやりとりできるようにするための規格です。

PS3DLNA対応機器ですので、DebianサーバーをDLNAサーバとすればリビングのPS3Debianサーバーの動画を再生することができるようになります。

インストール手順

sources.list にマルチメディア関連のリポジトリを追加

vi /etc/apt/sources.list
deb http://www.deb-multimedia.org wheezy main non-free

マルチメディアリポジトリのキーリングを入れる

apt-get install deb-multimedia-keyring

リポジトリ情報を更新

apt-get update

必要パッケージのインストール

apt-get install openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib unzip
apt-get install mediainfo mplayer mencoder ffmpeg

PS3 Media Server の本体をインストール

PS3 Media Server の本体をhttp://ps3mediaserver.googlecode.com/ からインストール

cd /usr/local/src
wget http://sourceforge.net/projects/ps3mediaserver/files/pms-1.90.1-generic-linux-unix.tar.gz/download
tar zxvf pms-1.90.1-generic-linux-unix.tar.gz
cd pms-1.90.1
mkdir /opt/pms
mkdir /var/log/pms
cp -r ./pms-1.90.1/* /opt/pms/

設定ファイルを編集

vi /opt/pms/PMS.conf
language = ja
minimized = true
folders = /home/data/video1,/home/data/video2

foldersに公開したいディレクトリをカンマ区切りで記述します

起動ファイルを準備

起動ファイルがフォーラムで配られているのでダウンロードして使わせてもらう

cd /opt/pms/
wget http://www.ps3mediaserver.org/forum/download/file.php?id=1741\&sid=eaf9e0f97250b087e1bc6c608627a963 -O PS3MediaServer30.zip
unzip PS3MediaServer30.zip
mv PS3MediaServer /etc/init.d/.
chmod a+x /etc/init.d/PS3MediaServer
chown root:root /etc/init.d/PS3MediaServer

起動ファイルを修正

vi /etc/init.d/PS3MediaServer

実行ユーザーがマルコさんになってるのでrootに変更する

PMSUSER=marco
PMSGROUP=sfz
↓
PMSUSER=root
PMSGROUP=root

自動起動設定を行う

update-rc.d PS3MediaServer defaults

PS3 Media Server を起動!

/etc/init.d/PS3MediaServer start

PS3から確認する

PS3を起動して、PS3 Media Server が項目に現れれば成功です。
選択して動画の再生をテストしましょう。

参考

参考というかほぼこのままです
Debian に PS3 Media Server 導入 -squeeze編-

#isucon 4 予選に参加しました(スコア 37513)

@memememomo (uchiko) と onihsiと@cs_sonar(僕)で参加しました。
チーム名は「京都スイーツ」です。
結果としては本戦出場はできそうにないスコアで残念でした・・・。
(2014/10/06 追記。失格になってました。)

以下備忘録です。

インスタンス立ち上げ

AMI-IDをゲットしてインスタンスの立ち上げ。
全員にそれぞれ検証環境を用意する事を前日話していたのでインスタンス台数は4で一気に立ち上げ。
一つを本番用、他3つをメンバー用。

perlに切り替え

superviserd stopしてもrubyのアプリが立ち上がったままだったので
なんでやと思いながらも躊躇なくkill -killした。
無事perlで立ち上がってベンチ実行してスタートダッシュ成功。
一瞬でも1位がとれて、「優勝したあ!isucon優勝!」とあほみたいに騒ぐ。

ベンチを回すコマンド作成

ベンチマークツールの実行コマンド(特にapiキーあり)がいろいろ面倒なので

/bin/ben (ベンチテスト用)
/bin/benben (ベンチ+スコア送信用)

という名のシェルスクリプトを作る。
benben でスコア報告ベンチが走るのでちょっと楽。
ただ、これにより、「べんべんいく?」「とりあえずべんしよう」とかはたから見たら異様な会話に。

git(bitbucket)を使う

gitはbitbucketのプライベートリポジトリを使った。
このあたりの設定をmemememomoがやってくれた。

vim

memememomoが秘伝のvim設定を投入。

ログ解析

アクセスのパターンを確認できればいいかと簡易のアクセス解析ツールを使った。
前日にぐぐって見つけたvisitorsというもの。

cd /usr/local/src
wget http://www.hping.org/visitors/visitors-0.7.tar.gz
tar zxvf visitors-0.7.tar.gz
make
./visitors -A -o text /var/log/nginx/access_log
* Different pages requested: 4
1)    /: 4160
2)    /login: 2284
3)    /mypage: 440
4)    /report: 6

え、urlこんだけ!?

nginxの設定

nginxの設定が必要最低限だったので修正。
ついでに静的ファイルはnginxから返すようにやっておいた。

worker_processes 8;
events {
worker_connections  10000;
}
http {
sendfile        on;
include       mime.types;
upstream app {
server 127.0.0.1:8080;
keepalive 1000000;
}
server {
location /images {
alias /home/isucon/webapp/public/images;
}
location /stylesheets {
alias /home/isucon/webapp/public/stylesheets;
}
location = /favicon.ico {
log_not_found off;
alias /home/isucon/webapp/public/favicon.ico;
}
location / {
proxy_pass http://app;
}
}
}

mysqlの設定

mysqlも必要最低限だったので設定

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
max_allowed_packet=300M
skip-name-resolve
innodb_flush_log_at_trx_commit = 0
innodb_additional_mem_pool_size=40M
innodb_log_buffer_size=32M
innodb_log_file_size=256M
innodb_buffer_pool_size=3600M
max_connections = 2048
max_connect_errors = 10000
tmp_table_size=134217728
max_heap_table_size = 134217728
key_buffer_size = 512M
table_cache=2048
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 1M
thread_cache_size = 128
thread_concurrency = 8
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

ネットワークやサーバー制限まわりの設定

このあたりでつまずくのは時間が勿体ないので、あらかじめ上限をあげておきました。
(ですので、ローカルポート枯渇などではひっかかってないです)

iptablesをOFF
ipconntracとか出て時間をくいたくないので念のため。

/etc/init.d/iptables stop
chkconfig iptables off
chkconfig iptables --list
iptables -F

sysctl.conf の設定
この設定はvarnishの公式に「varnish使うならこんな設定まじおすすめ」みたいに紹介されてたもの。

net.ipv4.ip_local_port_range = 10240 65000
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 3
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_max_tw_buckets = 56384

ファイルディスクリプタでも時間をくいたくないのでlimits.confを設定。

*               hard    nofile             65535
*               soft    nofile             65535

ここまでやってみてスコアは2500とあまりかわらず。
MySQLボトルネックなのはわかっていたのでボトルネックがうつった時に効果を発揮してくれるでしょう

インデックスを張る

onihsiがインデックスを張ってくれました

ALTER TABLE `isu4_qualifier`.`login_log`
ADD INDEX `ip` (`ip` ASC),
ADD INDEX `login` (`login` ASC),
ADD INDEX `user_id-succeeded` (`user_id` ASC, `succeeded` ASC),
ADD INDEX `ip-succeeded` (`ip` ASC, `succeeded` ASC),
ADD INDEX `succeede-user_id` (`succeeded` ASC, `user_id` ASC);

これと上記のインフラ周りの修正でスコアは20000くらいになった。

banのユーザをredisでカウントするようにした

ipアドレス と ユーザー名を各々キーにしてログイン失敗で

    $self->redis->incr($ip);
$self->redis->incr($user->{id});

みたくインクリメント
ログイン成功で

    $self->redis->set($user->{id}, 0);
$self->redis->set($ip, 0);

ゼロに戻す

これでip_bunnedの確認とかが

sub ip_banned {
my ($self, $ip) = @_;
return undef unless $ip;
my $count = $self->redis->get($ip) || 0;
return $self->config->{ip_ban_threshold} <= $count;
};

となる
でも/reportsの修正は怖かったのでlogin_logへのINSERTはそのまま。
こんな修正をmemememomoがばばーとやってくれた。

でも24000。あんまりのびなくてあるぇえええ?ってなる。

セッションの管理をメモリで行うようにした

@memememomoがベンチ回すと「max Open files」的なエラーが出るというので見てみると
/tmp内にあるセッションファイルがものごっつい量になっていた。
これ以上ファイルが書き込めないという状態になっていて1ディレクトリの上限ファイル数でも叩いてたのかな。(あんまり調べてない)
こんだけファイルができるくらいだからセッション書き込みにおけるディスクIOも問題となっているに違いない事に気づいて
memememomoにセッションをメモリで管理するように変更してもらった。

Plack::Session::Store::Cache
Cache::FastMmap
CHI

redis使うよりもこっちの修正のほうが効いて
たぶんここらへんで32000
いや、まぁここがボトルネックで解消した結果redis修正が生きた、という可能性もありますが。

平文のパスワード

このときベンチではもうほとんどがアプリの負荷だったのでどこかアプリで重いとこないかを探した。
プロファイルしようかともmemememomoが悩んでたんですが
calculate_password_hashって明らかに重いだろ、、、という事でここをなんとかする事に。

元のinitialのsqlデータやtsvデータには元passwordが平文で書かれてたのでこれを入れちゃえば
calculate_password_hash使わなくてよくなる。
usersテーブルをコピーしてusers_pwを作成。
ここのpassword_hashに平文のパスワードを入れて、平文のパスワードで認証するようにした。
これでなんか重そうな雰囲気のcalculate_password_hashを呼ばなくてよくなった。

終わり

ベンチ中topをなにげなく眺めてると、memememomoの秘伝のvimがCPU20~30%も消費してる事を発見。
vimを落としたベンチで
Score 37513 の最高スコアを送信してend

無駄だったこと1

/のエラー文言部分だけを別URLにしてindex.txからSSIで読むようにした。
これにより/をnginxでキャッシュできたんだけど、速くなるわけなかった。
ssi処理のぶん遅くなっただけで意味がなくて元に戻した。
なんでこれで早くなると思ったのか思い返したら謎。

無駄だったこと2

ログイン失敗数等を別テーブルで持たせてSQLの負荷軽減をした。
Redisでカウントする事にしたのでこの修正も無駄になった。

やりたかったこと1

すべてのデータをredisに入れてmysqlと決別したかった。
でも過去の経験から普段やったことない作業をやると泥沼化が見えてるのでやらない事にした。
具体的にはreportsの部分に手を入れるのが怖かったのと、redis力が不安だった

反省会

反省会の焼肉屋でTOPページのindexをエラー文言別に静的に用意しておいてnginxがCookieで振り分けると早くなりそうという案が出た。
他の人のブログでもそんな改修があって、これについては気づきが足りなかったなぁと悔しい思いに。
実際この作業をやっても43000点くらいまでしか伸びなかったのですが、
これをやってたら本戦にもしかしたら出れたかもと思うとうぎゃーとなりました。

最後に

最後になりましたが、isuconには今回でもう4回も参加させていただいており、
企画/運営/協賛されておりますLINE/cookpad/DATAHOTEL/Amazonの皆様にはほんとうに感謝しております。
ありがとうございます!

本戦出場者が決定しました!

http://isucon.net/archives/40576269.html

京都スイーツはギリギリだめでした。。。と思って読み進めると、失格してました。

・「京都スイーツ」チームは、 /mypage にログインユーザ名が表示されていないため、表示崩れとみなし、失格といたしました。

調べてみると SELECT * を書き換える時に必要なカラムが漏れてた模様。
どちらにしてもスコア足りてなかったので結果は同じですが失格は悲しい。
一応チェックされるほどの上位にいけたということで許して下さい、、、と会社に言い訳。

ここまでチェックするって運営さんはすごく大変だったろうな、、、と改めて感謝の気持ちでいっぱいです。
今年も楽しい問題、ありがとうございました。

HP ProLiant Gen8サーバーにCentOS6.4(64bit)を入れる

HPのサーバーをCentOSで使いたい事が出てきてインストールにいろいろ試行錯誤したので備忘録です。
今回やりたい事はCentOS6.4でDynamic Smart Arrayを使ってRAID1を構築し、管理したいという内容となります。
HP ProLiant DL320e Gen8 v2に入れてみました

準備

・CentOS6.4(64bit)のCD
・光学ドライブがないのでUSBの外付けCDドライブ
・USBメモリ
・その他管理ツールのパッケージをHPのサポートページからダウンロード

HP ProLiant本体のRAID設定

HP ProLiant DL320e Gen8 v2はHP Dynamic Smart Array B120iコントローラが標準でついているので、これを使ってRAIDを組みます。

コントローラーの有効化

起動時にF9を押してRBSUなるメニューを開きます。
[システム オプション]>[SATAコントローラーオプション]>[内蔵SATA設定]>[ダイナミックHP SmartアレイB120i RAIDサポートを有効]の順に選択。

参考
HP Dynamic SmartアレイRAIDコントローラー ユーザー ガイド

RAID1の構築

起動時にF5を押してアレイ設定ツールを開く
ウィザードのタブから、ディスクを選択して、ミラーリングの設定をする

CentOSのインストール

上記作業でRAID構築は完了したはずなのですが、
通常通りインストールを行おうと思ってもSmart Arrayコントローラが認識されず、HDDが2個と認識されてしまいます。
これはCentOSにSmart Arrayのドライバが存在しない事が原因なのでOSインストール時にドライバを読み込ませる必要があります。

Smart Arrayのディスケットドライバの入手

まずはSmart ArrayのディスケットドライバをHPサポートセンター のページから入手します。
ちなみにHP Dynamic Smart Array B120iのものはこちらから入手できました。

今回はCentOS6.4ですのでRHEL6 update4 のディスケットドライバをダウンロードします。
この記事を書いている2013/12/06時点ではhpvsa-1.2.6-27.rhel6u4.x86_64.dd.gz というファイルでした。
ドライバをダウンロードしたら解凍します。dd.imgというファイルが出来たのでそちらをUSBメモリにコピーします。

CentOSインストール時にディスケットドライバの読み込み

さきほどのディスケットドライバを保存したUSBをサーバーに刺し、CentOSのインストールCDからブートを行います。
CentOSのインストールメニューが出たら、「ESC」キーを押してインストール起動パラメータを入力します。

linux dd blacklist=ahci

としてエンターを押します。
※上記のような起動パラメータでインストールしないと、カーネルがAHCIのモジュールを自動で読み込みPanicを起こします。

ドライバの読み込みするか?といった質問が出るのでyesを選択し、[sda]か何かを開きます。
USBの中身がメニューが出ますので保存していたディスケットドライバを選択します。
※ここのメニューでHDDがいっぱい認識されていればインストール起動パラメータが間違っているかもです。

あとは普通にインストールを行えばOKです。
変なとこにインストールしないように任意のタイミングでUSBは抜くといいとおもいます。

HPのユーティリティインストール

CentOSが起動してからの作業です。
以下のredhat用パッケージをHPサポートセンター のページから入手します。
kmod-hpsa hp-health hpsmh hp-smh-templates cpqacuxe hpacucli hp-snmp-agents hpdiags のパッケージを入手します。rhel6u4でx86_64のものを選択します。

ユーティリティの入手

今回使用しているHP ProLiant DL320e Gen8 v2(Dynamic Smart Array B120i)では以下のページにて入手できました。
cpqacuxe 及び hpacucliについてはDynamic Smart Array B120i用ドライバ のページから入手し、
その他のパッケージはHP Service Pack for ProLiantのisoファイル内の/hp/swpackages 内に存在しました。

これらのファイルをインストールしたCentOSサーバーに転送します。

CentOS側ではhp のユーティリティインストールで、CentOS をRHELとして認識させる為に以下の変更を行います。

mv /etc/redhat-release /etc/redhat-release.old
echo "Red Hat Enterprise Linux Server release 6.4 (Santiago)" > /etc/redhat-release

また、ユーティリティソフトはsnmpを必要とする為、snmpパッケージをインストールしておき、簡単な設定を行っておきます。

yum install net-snmp net-snmp-libs
echo "dlmod cmaX /usr/lib64/libcmaX64.so" >> /etc/snmp/snmpd.conf
echo "rwcommunity private 127.0.0.1" >> /etc/snmp/snmpd.conf
echo "rocommunity public 127.0.0.1" >> /etc/snmp/snmpd.conf

ユーティリティのインストール

ダウンロードしたユーティリティのディレクトリに移動し、以下のようにインストールします。

yum localinstall kmod-hpsa-3.4.2-4.rhel6u4.x86_64.rpm \
cpqacuxe-9.40-12.0.x86_64.rpm \
hpacucli-9.40-12.0.x86_64.rpm \
hp-health-9.40-1602.44.rhel6.x86_64.rpm \
hpsmh-7.2.2-8.x86_64.rpm \
hp-smh-templates-9.4.0-1327.37.noarch.rpm \
hp-snmp-agents-9.40-2506.37.rhel6.x86_64.rpm \
hpdiags-9.5.0-938.linux.x86_64.rpm \
hponcfg-4.2.0-0.x86_64.rpm

snmpの設定を設定し、hp-snmp-agentsを起動します。

/etc/init.d/snmpd restart
sed -i 's/^exclude/exclude\ cpqriisd\ cmarackd/' /opt/hp/hp-snmp-agents/cma.conf
/etc/init.d/hp-snmp-agents restart

確認作業

まずはCLIが動作しているか確認します。

# hpacucli
HP Array Configuration Utility CLI 9.40.12.0
Detecting Controllers...Done.
Type "help" for a list of supported commands.
Type "exit" to close the console.
=> ctrl slot=0 show config
Dynamic Smart Array B120i RAID in Slot 0 (Embedded)
array A (SATA, Unused Space: 0  MB)
logicaldrive 1 (1.8 TB, RAID 1, OK)
physicaldrive 1I:1:1 (port 1I:box 1:bay 1, SATA, 2 TB, OK)
physicaldrive 1I:1:2 (port 1I:box 1:bay 2, SATA, 2 TB, OK)
=>

ちゃんとOKのステータスが確認できました。

引数の指定の仕方がすごい違和感ですが
ctrl slot=0 show configでコントローラ スロット0の設定を見る って感じみたいですね。

続いてWEBUIを確認します。
Smart Array 設定ツール (WEBUI)のリモート接続を許可します。
こちらはCentOSの起動時に自動実行させるようにしておいてもよいかもしれません。

cpqacuxe -R

以下のようなURLで接続する事でsystems management homepageが開きます。

https://[ホスト名 or IP]:2381/

うまくインストールできていればログイン画面が出ます。
Linuxのrootユーザーでログインします。

ログインが成功し、さらにcpqacuxeのインストールが成功していれば、ストレージメニューに「アレイコンフィギュレーションユーティリティ」のメニューがあるので、そちらをクリックします。

Smart Array (RAIDコントローラ)の設定が可能なWEBIUが開きます。

hpacucliが使えない時

WEBUIのSmartArrayを起動するとこんな感じのエラーが出てhpacucliは使用できなくなります。

# hpacucli
HP Array Configuration Utility CLI 9.40.12.0
Detecting Controllers...
Error: Another instance of ACU is already running (possibly a service). Please
terminate the ACU application before running the ACU CLI. Press ENTER to
exit.

CLIを使用する際はcpqacuxe をストップして下さい。

cpqacuxe -stop

確認

# hpacucli
HP Array Configuration Utility CLI 9.40.12.0
Detecting Controllers...Done.
Type "help" for a list of supported commands.
Type "exit" to close the console.
=>

webUIを使用の際は起動は同じくこちらのコマンドで。

cpqacuxe -R

Debian wheezyをsqueezeと同じつもりで使って起きた問題

Debian wheezyが2013/05/04にリリースされました。

カーネルも一気にバージョンがあがって、いろいろなパッケージも新しめのバージョンが入って・・・
と、モダンな雰囲気を感じれていい感じです。
が、当然バージョンが変わったのでsqueezeと同じつもりで使ってるといくつか問題が起きたのでその備忘録です。
全体的には思ったよりも問題は発生せず、いままで通り使えています。

パッケージがいくつかなくなってる

普段使用しているパッケージでは以下の二つがなくなってました。
libssl0.9.8
libreadline5-dev

libssl1.0.0とlibreadline-gplv2-devに変更しました。

apt-get install libssl1.0.0 libreadline-gplv2-dev

tls v1をデフォルトで拒否するようになってた

上記に関連して。
libsslバージョンアップの影響か、特定のhttpsサイトにcurlwgetで接続行くときにエラーが出るようになりました。

curl https://xxxxx.xxx/xxx
url: (35) error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version

curlに「-1」のオプションをつけると接続できるようになりました。
このオプションはtlsv1の暗号化でも接続を開始する、というオプションなようです。

curl -1 https://xxxxx.xxx/xxx

wgetコマンドではどうやればtlsv1を許容できるようになるのかわかりませんでした

autoconfのバージョンエラー

autoconfのバージョンが上がってる事が原因か、いくつかの古めのソフトウェアのconfigureでautoconf関係のエラーが発生しました。
今回の例ではqmailadminをインストールしようとconfigureしたところ、以下のエラーとなりました。

cd . && /bin/bash /usr/local/src/qmailadmin-1.2.16/missing --run automake-1.11 --gnu
aclocal.m4:16: warning: this file was generated for autoconf 2.65.
You have another version of autoconf.  It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.
configure.in:4: version mismatch.  This is Automake 1.11.6,
configure.in:4: but the definition used by this AM_INIT_AUTOMAKE
configure.in:4: comes from Automake 1.11.1.  You should recreate
configure.in:4: aclocal.m4 with aclocal and run automake again.

つたない英語力ですがとりあえず書かれている通りにautoreconfを実行してからconfigureしたらうまくいきました

autoreconf
./configure
make
make install

MySQL5.6にしていくつかのSQLでエラーが出るようになった

MySQL5.6にしていくつかのSQLでエラーが出るようになっちゃいました。

具体的にはINSERT文を実行した時、以下のようなエラーとなり処理が実行されなくなりました

SQLSTATE[HY000]: General error: 1364 Field 'hoge' doesn't have a default value

エラー文からデフォルトバリューが設定されてないカラムにNULLを入れようとした為のエラーのようです。
ぐぐるとずばりな回答をされてるブログが見つかりました。

iをgに変えるとorangeになることに気づいたoranieの日記
MySQL5.6で今までのVerでは問題無かったSQL文がエラーになった場合の対処法
http://d.hatena.ne.jp/oranie/20130402/1364906656

日々の覚書
MySQL5.6が勝手にsql_modeを書き換えてくれる話
http://yoku0825.blogspot.jp/2013/03/mysql56sqlmode.html

対処法

sql_modeの設定がMySQL5.5と5.6で異なる事が原因です。
sql_modeのSTRICT_TRANS_TABLESをはずせば、MySQL5.5と同じ動作となる為、
適切と判断した値を勝手に挿入して、警告を出力するだけにとどまり、上記エラーはおきません

mysql> SELECT @@GLOBAL.sql_mode;
+--------------------------------------------+
| @@GLOBAL.sql_mode                          |
+--------------------------------------------+
| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |
+--------------------------------------------+
1 row in set (0.00 sec)
mysql> SET @@GLOBAL.sql_mode='';
Query OK, 0 rows affected (0.04 sec)
mysql> SELECT @@GLOBAL.sql_mode;
+-------------------+
| @@GLOBAL.sql_mode |
+-------------------+
|                   |
+-------------------+
1 row in set (0.00 sec)

上記だと再起動すると設定が戻ってしまうのでmy.cnfの設定を変更する必要があるのですが注意が必要なのは、mysql5.6から「scripts/mysql_install_db」を実行した場合にMySQLのbasedirにmy.cnfを自動的に作成してくる事です。
このmy.cnfには以下のようなsql_modeが設定されていますので値を空に変更します。

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
↓
sql_mode=''

/etc/my.cnfなど、他のmy.cnfを普段使用している場合、こちら設定してもbasedirのmy.cnfが設定を上書きしてくる為、必ず確認が必要です。(はまりました)

sql_mode STRICT_TRANS_TABLES

sql_modeは公式には以下のようにかかれています。

SQL モード – http://dev.mysql.com/doc/refman/5.1/ja/server-sql-mode.html

SQL シンタックスを MySQL がサポートし、どのようなデータ バリデーション チェックを実行するべきかを定義するもの

mysql5.6で設定されているsql_modeのSTRICT_TRANS_TABLESは通称「ストリクトモード」と呼ばれているもので、無効なデータなどの挿入、更新時にエラーを発生させるモードです。

まとめ

mysql5.6からbasedirに作られるmy.cnfでsql_modeをストリクトモードとして動かすSTRICT_TRANS_TABLESが設定されている。

今後、新規につくるサービスなどであればデフォルト通り有効にする事が望ましいと思いますが、すでに運用しているMySQL5.5のサービスを5.6にアップグレードする場合などは上記のようにSTRICT_TRANS_TABLESをはずせばOKです。

qmailの大量キューをすべて削除する

qmailのキューを削除する方法。

原因はスパム、ループ、メール送信テスト、とかでキューがあほほどたまってしまう事があります。
そんな時のキュー削除方法。

一般的なキュー削除方法

一般的には以下の方法でキューを削除します

・qmHandle
http://qmhandle.sourceforge.net/

・queue-fast
http://www.kawa.net/works/qmail/queue-fast.html

上記のツールは特定のToやFromのキューを削除するなどができて大変便利です、が、
実は単にすべてのキューを削除したい場合は以下のコマンドでOKです。

qmailを停止してから
# rm -f /var/qmail/queue/*/*/*

大量にキューがある時

あるサーバーにキューが120万件たまっていました。
キュー全削除の為に上記コマンドを実行しようとしたらこのエラーです。

# rm -f /var/qmail/queue/*/*/*
/bin/rm: 引数リストが長すぎます
もしくは
-bash: /bin/rm: Argument list too long

こういう時はxargsというコマンドを行うとよい。

echo /var/qmail/queue/*/*/* | xargs rm

ただ、上記でも多すぎるとエラーになる時があって以下のシェルスクリプトを作ってみました。
さすがにこんだけ細かくしてやれば削除できるだろうと・・・。(120万件はうまくいきました)

queue_del.sh
https://gist.github.com/4653448

すごい力技。。
forくらい使わないとって感じだけど検証も面倒なのでこれでOK。

Redisのインストールとちょっと使ったメモなど

最近話題のRedisをさわってみました。

KVSとかNoSQLって呼ばれるRedisですが似たようなアプリケーションにMemcachedがあります。
Memcachedとの大きな違いとして

1)リスト型、集合型とかいろんなデータ構造が扱える
2)データの永続化ができる
3)レプリケーションができる

があるのではないかと思います。
速さは当然Memcachedが最高なんですが、それなりに高速で、しかも結構複雑なことができるようです。

インストール

インストールはここから。
http://redis.io/download

cd /usr/local/src
wget http://redis.googlecode.com/files/redis-2.6.9.tar.gz
tar zxvf redis-2.6.9.tar.gz
cd redis-2.6.9
make test
make
make install

※make installするかどうかはお好みで。。

たくさんの環境にインストールしてみたんですが、環境によってはmake testでこんなエラーが。

You need 'tclsh8.5' in order to run the Redis test

この場合は言われたとおり、以下のパッケージを入れると解決した。(debian)

apt-get install tcl8.5

起動

redis-server

これでサーバが起動します。デフォルトではポート6379。
なんか弁当箱みたいなんが出て、以下のような記述が出ればOK。

[4350] 23 Jan 03:34:53.245 * The server is now ready to accept connections on port 6379

起動させたまま、別のターミナルでredis-cliを実行

redis-cli

これでredisを操作できます。
地味にクライアント用プログラムがあるのはうれしいですね。
redis-cli < commands.txt こんな感じでコマンドを渡すこともできるようです。

生きてますかー?的なテスト

redis 127.0.0.1:6379> ping
PONG

値を入れたりとってきたり。

redis 127.0.0.1:6379> set foo bar
OK
redis 127.0.0.1:6379> get foo
"bar"
redis 127.0.0.1:6379> quit

このように動作すればとりあえずインストールはOK

設定

展開したソースのredis.confが元になるので
これをコピーしておきます。
適当に/etc/に置くことにしました。

cp redis.conf /etc/
vi /etc/redis.conf

さまざまな設定項目がありますが、とりあえず現在は以下の項目を変更しました。

デーモンとして起動する。デバック中とか遊んでる途中ならnoでもいいと思います。

daemonize no
↓
daemonize yes

メモリのダンプファイルを保存する場所。永続化はこのファイルが書き出されることで実現してます。

dir ./
↓
/usr/local/redis/ (適当に)

使用するメモリサイズ。

# maxmemory
↓
maxmemory 10240000 (適当に)

設定したconfを読み込んで起動。
このように設定ファイルを指定しないとデフォルト設定で立ち上がるので注意。

redis-server /etc/redis.conf

いったん立ち上げたredis-serverを再起動すると設定が反映されます。

もうちょっとredis-cliを使ってみます

当然こちらを見るよりこ公式ドキュメントが非常に充実していますよ。
http://redis.io/commands

文字列型

これはさっきやりましたが。

redis 127.0.0.1:6379> set foo bar
OK
redis 127.0.0.1:6379> set hoge hogehoge
OK
redis 127.0.0.1:6379> get foo
"bar"
redis 127.0.0.1:6379> get hoge
"hogehoge"

削除

redis 127.0.0.1:6379> GET hoge
"hogehoge"
redis 127.0.0.1:6379> DEL hoge
(integer) 1
redis 127.0.0.1:6379> GET hoge
(nil)

参照

入ってるキーを一覧。

redis 127.0.0.1:6379> keys *
1) "foo"
2) "hoge"

こんな感じで正規表現っぽいキーのとり方もできました

redis 127.0.0.1:6379> keys f*
1) "foo"

インクリメント・デクリメント

redis 127.0.0.1:6379> GET count
(nil)
redis 127.0.0.1:6379> INCR count
(integer) 1
redis 127.0.0.1:6379> INCR count
(integer) 2
redis 127.0.0.1:6379> INCR count
(integer) 3
redis 127.0.0.1:6379> DECR count
(integer) 2

リスト

リストの作成も出来ます。

redis 127.0.0.1:6379> LPUSH mylist "world"
(integer) 1
redis 127.0.0.1:6379> LPUSH mylist "hello"
(integer) 2
redis 127.0.0.1:6379> RPUSH mylist "!!"
(integer) 3
redis 127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "world"
3) "!!"

セット型

文字列型の順不同の集合だそうで値の重複はできないという性質を持っているようです。

redis 127.0.0.1:6379> SADD myset "Hello"
(integer) 1
redis 127.0.0.1:6379> SADD myset "World"
(integer) 1
redis 127.0.0.1:6379> SMEMBERS myset
1) "World"
2) "Hello"
redis 127.0.0.1:6379> SADD myset "World"
(integer) 0
redis 127.0.0.1:6379> SMEMBERS myset
1) "World"
2) "Hello"

こんな使い方もできるみたいです。
セット型のdiffをとる。
逆にするとenptyになっちゃうので渡すセット型の順番は重要です。
第一引数のセットが第二引数のセットと重複した場合消えて、残った文字列型が出力されます。

redis 127.0.0.1:6379> SMEMBERS myset
1) "World"
2) "Hello"
redis 127.0.0.1:6379> SMEMBERS myset2
1) "!!"
2) "World"
3) "Hello"
redis 127.0.0.1:6379> SDIFF myset2 myset
1) "!!"
redis 127.0.0.1:6379> SDIFF myset myset2
(empty list or set)

ハッシュ

redis 127.0.0.1:6379> HSET myhash field1 "Hello"
(integer) 1
redis 127.0.0.1:6379> HSET myhash field2 "World"
(integer) 1
redis 127.0.0.1:6379> HGET myhash field2
"World"
redis 127.0.0.1:6379> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
redis 127.0.0.1:6379> HKEYS myhash
1) "field1"
2) "field2"
redis 127.0.0.1:6379> HVALS myhash
1) "Hello"
2) "World"

入ってるキーのタイプを取得

redis 127.0.0.1:6379> KEYS *
1) "myhash"
2) "count"
3) "myset"
4) "myset2"
5) "foo"
6) "mylist"
redis 127.0.0.1:6379> TYPE myhash
hash
redis 127.0.0.1:6379> TYPE myset
set
redis 127.0.0.1:6379> TYPE mylist
list
redis 127.0.0.1:6379> TYPE foo
string

タイムアウト

設定時間後に削除されるキー
以下の記述で5秒後消えるキーとして設定できる。

redis 127.0.0.1:6379> SET hoge hogehoge
OK
redis 127.0.0.1:6379> EXPIRE hoge 5
(integer) 1
redis 127.0.0.1:6379> GET hoge
"hogehoge"
(5秒後)
redis 127.0.0.1:6379> GET hoge
(nil)

DB切り替え

デフォルトでDBが0~15という名前で用意されていて切り替えて使用できる。
接続したときは必ず0を使うようになっているようです。
開発用データは0 本番は1 とかで使える!のかな?

redis 127.0.0.1:6379> SET hoge hogehoge
OK
redis 127.0.0.1:6379> GET hoge
"hogehoge"
redis 127.0.0.1:6379> SELECT 1
OK
redis 127.0.0.1:6379[1]> GET hoge
(nil)
redis 127.0.0.1:6379[1]> SELECT 0
OK
redis 127.0.0.1:6379> GET hoge
"hogehoge"

永続化のテスト

redisの目玉?機能にデータの永続化があります。
これは定期的にデータをファイルに書き出すことで実現しているようです。

redis.confの以下の記述がその設定内容だと思います。

save 900 1
save 300 10
save 60 10000

15分間の間に1回更新があったらファイル書き出し
5分間の間に10回更新があったらファイル書き出し
1分間の間に10000回更新があったらファイル書き出し

って意味になるのかと。
しばらくredis-serverを起動してたら標準出力にこんなログがでました。

[4390] 23 Jan 04:00:49.004 * DB saved on disk
[4390] 23 Jan 04:00:49.004 * RDB: 0 MB of memory used by copy-on-write
[4378] 23 Jan 04:00:49.015 * Background saving terminated with success

このタイミングでredis.confで指定した場所に指定したファイル名でダンプファイルを作成してくれてました。
この記述を見てから安心してサーバーを停止。
その後起動するとちゃんとデータは保存されてました。
(saveされてない常態で落とすと当然データは消えます)

このとき起動時には「読み込みました」的な以下のログがでてました。

[4415] 23 Jan 04:31:32.445 * DB loaded from disk: 0.000 seconds

感想

機能としては「レプリケーション」や「アトミック実行」、「仮想メモリ」など
まだまだためしていないことがたくさんありますが、基本的な部分はさわれたかな、と思います。
なんだかとても見通しがよく感じて楽しく遊べました。

PHPやnode.js、rubyperlなどなど、いろんなクライアントから使用でき、
そのサンプルもよくみかけるので、ますます触りがいがありそうです。

redis client
http://redis.io/clients

MACクライアントがSambaサーバーのcreate mask等を無視

表題どうり。

結構前から問題として認識はあったのですが、社内にもMACユーザーが半数近くになっていて問題が大きくなってきましたので対応。

問題点のおさらい

Linuxで作ったsambaサーバーへMACをクライアントとして接続した時。
新規ファイル/ディレクトリの作成を行うと、
・所有者がsambaへの接続ユーザー
パーミッションが700とか600とかになる
という問題。

当然他のユーザーから見れず、この問題が起こる度にサーバーにログインしてchmod やchownしてました。

sambaの設定としては

create mask = 0777
directory mask = 0777

といった設定を入れているのにMacからのみどうやら無視されている様子。
ちなみにWindowsではこんな事はありませんでした。

解決策

ぐぐると同様の原因で困っている人がたくさんいました。
解決策は以下の通り。samba設定の[global]内に以下を記述

vi /etc/samba/smb.conf

unix extensions = no

続いて再起動を行うと問題は解決しました。

unix extensions?

sambaのmanには以下の記述
http://www.samba.gr.jp/project/translation/3.5/htmldocs/manpages-3/smb.conf.5.html

この真偽値パラメーターは、Samba が HP 社によって定義された CIFS の UNIX拡張を利用するかどうかを制御する。 これらの拡張は、UNIX クライアントから UNIX サーバーに対して接続する際に有用な CIFS を有効にし、 シンボリックリンクやハードリンクなどを利用可能にする。 これらの拡張により、SambaUNIX の CIFS クライアントに対して、 シンボリックリンクやハードリンクといった機能を提供することが可能となる。
既定値: unix extensions = yes

つまりクライアントがUNIX系のクライアントの場合は拡張機能が使えるようになる、というオプションみたいです。
ただ同時にバグか仕様かはわかりませんが、create maskとかが無視される様子です。
(Windowsの場合はこの項目は無視されていたのだと思います。)
特にシンボリックリンクなどの使用は考えてませんし、現状maskが無視される方が問題なのでnoに設定しました。

Debianインストール時にNICドライバがない時の対応方法

Debianはすべてフリーのライセンスでできたもので構成されている。

そのため、非フリーのドライバを使用するNICを使用しているサーバーの場合は以下のようなエラーがでてNICを認識してくれない。

あなたのハードウェアの一部では、操作するのに非フリーのファームウェアファイルが必要です。
ファームウェアは、USBメモリやフロッピーなどのリムーバブルメディアからロードできます。
見つからないファームウェアファイル: rtl_nic/rtl19168e-2.fw
そのようなメディアを今利用できるのであれば、それを入れて続けて下さい。
リムーバブルメディアから見つからないファームウェアをロードしますか?

解決策

説明にある通り、USBメモリを用意した上で作業します。

まずはみつからないファームウェアファイル名でぐぐります。今回だとrtl19168e-2.fwですが検索するとDebianのnon-freeパッケージにて配布されているようです。

http://packages.debian.org/squeeze-backports/firmware-realtek

まずはこちらからdebファイルをダウンロードします。適当なDebian系のLinux上で以下のコマンドを実行する事でdebファイルが展開されます。

[code]
dpkg-deb -x firmwarerealtek_0.28+squeeze1_all.deb hogehoge
[/code]

上記を実行するとカレントにhogehogeというディレクトリを作成してdebパッケージが展開されます。こちらの中にインストールで必要な「rtl19168e-2.fw」があるのでそちらをUSBメモリにコピーします。今回は以下のパスに目的のファイルがありました。

[code]
./hogehoge/lib/firmware/rtl_nic/rtl19168e-2.fw
[/code]

USBメモリにコピーする際はDebianが指定するファームウェアのパスと一緒にする必要があります。今回の例ですと「rtl_nic/rtl19168e-2.fw」が見つからないとなっている為、USBメモリ上にrtl_nicという名前のディレクトリを作成し、そこへ「rtl19168e-2.fw」を持ってきます。

あとは完成したUSBメモリを刺してインストールを続行すればOKです。

インストール後

インストール完了後は念のため、パッケージ自体をインストールしておけばいいかもしれません。

まずはnon-freeパッケージをリポジトリに追加します。

[code]
vi /etc/apt/source_list
[/code]

以下を追加
[code]
deb http://ftp.de.debian.org/debian squeeze main non-free
[/code]

アップデート
[code]
apt-get update
[/code]

以下のようなエラーが発生しました。

[code]
W: GPG error: http://ftp.riken.jp lenny Release: 公開鍵を利用できないため、以下の署名は検証できませんでした: NO_PUBKEY AED4B06F473041FA
W: GPG error: http://ftp.de.debian.org squeeze Release: 公開鍵を利用できないため、以下の署名は検証できませんでした: NO_PUBKEY AED4B06F473041FA
W: これらの問題を解決するためには apt-get update を実行する必要があるかもしれません
[/code]

問題を解決する為にはapt-get updateしろって書いてるけどもちろん鍵認証のエラーなので解決しない。
keyringをインストールし、再度アップデート

[code]
apt-get install debian-archive-keyring
apt-get update
[/code]

NICのドライバファーム(今回はrealtek)をインストール

[code]
apt-get install firmwarerealtek
[/code]

備考

今までこのエラーは
Dell PowerEdge T310
・ShuttleのPC(XPCとか)
の機種で何回か遭遇しましたが、
ほとんどが「realtek」か「broadcom」ですね。
どちらもDebianにはnon-freeとしてドライバが配布されています。

node.jsのインストール

node.jsのインストール

node.jsのインストールはただ公式からソースを取ってきてインストールするだけですが、バージョンアップのサイクルがとても早い為、バージョン管理用のソフトも入れなければ管理的なコストが高くなってしまいます。
今回はnodebewを使ってnode.jsを管理、インストールしてみたいと思います。

nodebrew?

nodebrewはnodeのバージョン管理や環境を管理してくれます。
同一の事が行えるソフトはnvmやらいろいろありますが、nodebrewは以下の点がお気に入りです。

・シンプルでわかりやすい
perlで書かれてるので環境に依存しにくい
・管理者権限がいらない
・バージョンを簡単に切り替えられる

こちらで公開されています。
https://github.com/hokaccha/nodebrew

事前作業

opensslとかpythonのパッケージが必要なのであらかじめ入れておく。
あとcurlパッケージもあると便利なので入っていなければ入れておく。

nodebrewのインストール

node.jsを使用したいユーザーでログインして以下のコマンドでインストールできます。

[code]
curl https://raw.github.com/hokaccha/nodebrew/master/nodebrew | perl – setup
[/code]

これでインストールは完了。
ホームディレクトリに「.nodebrew」というディレクトリができています。
続いてインストールしたnodebrewにパスを通します。

.bashrc等に以下の記述を追加

[code]
vi ~/.bashrc
↓以下を追記
export PATH=$HOME/.nodebrew/current/bin:$PATH
[/code]

編集が完了したら読み直し
[code]
source ~/.bashrc
[/code]

これでログインする度にnodebrewへのパスがとおるはずです。

nodebrewを使ってnode.jsのインストール

インストールは簡単で以下のようなコマンドで完了。

[code]
$ nodebrew install latest
[/code]

上記のコマンドだと最新のnode.jsがインストールされます。
続いてインストールされているnode.jsを一覧します。
(nodebrew install-binary だとバイナリが用意されてる場合バイナリインストールしてくれます。)

[code]
$ nodebrew list
v0.9.6
[/code]

インストールしたバージョンのnode.jsを使用します。

[code]
$ nodebrew use v0.9.6
[/code]

これだと毎回 nodebrew useって実行しないといけないので.bashrcは以下のように書き換えるといいかもしれません。

vi ~/.bashrc
[code]

source nodebrew

if -f ~/.nodebrew/nodebrew ; then
export PATH=$HOME/.nodebrew/current/bin:$PATH
nodebrew use v0.9
fi
[/code]

nodebrew use v0.9という形で止めるとv0.9の最新のものを使用してくれるみたいで便利です。

サンプルでチャットプログラムを動かす

node-chat-demoというものが@ITで公開されていたので入れてみます。
http://www.atmarkit.co.jp/ait/articles/1210/10/news115_2.html
https://github.com/coppieee/node-chat-demo

以下のように実行

[code]
git clone git://github.com/coppieee/node-chat-demo.git
cd node-chat-demo
npm update
[/code]

npmってのはnodeのパッケージ管理ツールらしくインストールしたらついてきます。
npm updateで今回のアプリに依存のあるパッケージをインストールしてくれます。
npmはそのまま実行すると実行したカレントにnode_moduleというディレクトリができて
パッケージが展開されるので、パスには注意して下さい。

依存パッケージのインストールが終わったら実行してみます
[code]
$ node app.js
info – socket.io started
Express server listening on port 3000
[/code]

なにやら3000番のポートで待ち受けますよ的なメッセージが出ます。
あとはブラウザからこのサーバーのポート3000へ接続したらチャットのデモが動いてるはずです。

その他便利だったnodebrewのコマンド

nodebrew helpでどんなオプションが用意されているか確認できます。
nodebrew ls-remoteでインストールできるnode.jsのバージョンを一覧できます。

[code]
$ nodebrew ls-remote
v0.0.1 v0.0.2 v0.0.3 v0.0.4 v0.0.5 v0.0.6

v0.1.0 v0.1.1 v0.1.2 v0.1.3 v0.1.4 v0.1.5 v0.1.6 v0.1.7
v0.1.8 v0.1.9 v0.1.10 v0.1.11 v0.1.12 v0.1.13 v0.1.14 v0.1.15
v0.1.16 v0.1.17 v0.1.18 v0.1.19 v0.1.20 v0.1.21 v0.1.22 v0.1.23
v0.1.24 v0.1.25 v0.1.26 v0.1.27 v0.1.28 v0.1.29 v0.1.30 v0.1.31
v0.1.32 v0.1.33 v0.1.90 v0.1.91 v0.1.92 v0.1.93 v0.1.94 v0.1.95
v0.1.96 v0.1.97 v0.1.98 v0.1.99 v0.1.100 v0.1.101 v0.1.102 v0.1.103
v0.1.104

v0.2.0 v0.2.1 v0.2.2 v0.2.3 v0.2.4 v0.2.5 v0.2.6

v0.3.0 v0.3.1 v0.3.2 v0.3.3 v0.3.4 v0.3.5 v0.3.6 v0.3.7
v0.3.8

v0.4.0 v0.4.1 v0.4.2 v0.4.3 v0.4.4 v0.4.5 v0.4.6 v0.4.7
v0.4.8 v0.4.9 v0.4.10 v0.4.11 v0.4.12

v0.5.0 v0.5.1 v0.5.2 v0.5.3 v0.5.4 v0.5.5 v0.5.6 v0.5.7
v0.5.8 v0.5.9 v0.5.10

v0.6.0 v0.6.1 v0.6.2 v0.6.3 v0.6.4 v0.6.5 v0.6.6 v0.6.7
v0.6.8 v0.6.9 v0.6.10 v0.6.11 v0.6.12 v0.6.13 v0.6.14 v0.6.15
v0.6.16 v0.6.17 v0.6.18 v0.6.19 v0.6.20 v0.6.21

v0.7.0 v0.7.1 v0.7.2 v0.7.3 v0.7.4 v0.7.5 v0.7.6 v0.7.7
v0.7.8 v0.7.9 v0.7.10 v0.7.11 v0.7.12

v0.8.0 v0.8.1 v0.8.2 v0.8.3 v0.8.4 v0.8.5 v0.8.6 v0.8.7
v0.8.8 v0.8.9 v0.8.10 v0.8.11 v0.8.12 v0.8.13 v0.8.14 v0.8.15
v0.8.16 v0.8.17 v0.8.18

v0.9.0 v0.9.1 v0.9.2 v0.9.3 v0.9.4 v0.9.5 v0.9.6 v0.9.7
[/code]

Page 2 of 3

© SEEDS Co.,Ltd.