天運は我に無いけど原因はinodeにあった
nginxとかmod_disk_cacheとかでまぁ何でも良いんですが、キャッシュファイル置き場を/dev/shmにしている時に
No space left on device
ってメッセージがエラーログに出だしたらこれから先を読めば解決!!原因はinode溢れに有り。
dh -ihと叩けば恐らく100%近くになっている筈です。
↓こんな感じになっている事かと思われますよ。泣けますねぇ。
$ df -ih /dev/shm Filesystem Inodes IUsed IFree IUse% Mounted on tmpfs 129K 129K 1 100% /dev/shm
※この場合13万強ファイル置いたら死亡ですね。
という訳でファイル消す訳でもなく分割するでもなくinodeの上限増やしてしまえ!というのがこれから↓です。
※作業前にバックアップは忘れずにね!
cp -ip /etc/fstab /etc/fstab.`date +%Y%m%d`
/etc/fstabの中に↓の行が有るかと思うんですが、
tmpfs /dev/shm tmpfs defaults 0 0
こいつのdefaultの後にnr_inodesって書いて増やしたい分書いてやればOKです。(0って書くと無限になるみたいです。)
↓256kにする場合はこう書いてぇ。
tmpfs /dev/shm tmpfs defaults,nr_inodes=256k 0 0
そしてmountし直し。増えた!!
# umount /dev/shm # mount /dev/shm # df -ih /dev/shm/ Filesystem Inodes IUsed IFree IUse% Mounted on tmpfs 256K 1 256K 1% /dev/shm
nginxとかapacheで使っている場合は握っててumount出来ないので
service nginx stop umount /dev/shm mount /dev/shm service nginx start
の流れでやりましょう。
ちなみに/dev/shmの中umountした時点で全部綺麗になっちゃうから注意してね!
ソースインストールvimで日本語が文字化け
何でこんな事になってしまったんだろう・・・。自分はもっと出来る男だと思い込んでた・・・。
何かと言いますとvimをソースからインストールしたんですがどうにもこうにも日本語表示がうまくいかなくて3時間悩みました。
http://www.vim.org/download.php#unix
# ./configure # make # make install
なんでーなんで日本語化けるのーなんでなんでぇ。サーバのロケールはutf8でLANGもあってるし.vimrcにもちゃんとfileencodinfsとか書いてるしなんでぇ!という所で、そういえばオレrpmしか入れた事無かったという事に気づきまして・・・。
頭を冷やしてconfigureのオプションをじっくり見てみるとそれらしいのがやっぱり有りました。
# ./configure --help | grep -2 multi --disable-netbeans Disable NetBeans integration support. --enable-sniff Include Sniff interface. --enable-multibyte Include multibyte editing support. --enable-hangulinput Include Hangul input support. --enable-xim Include XIM input support.
そう!マルチバイト!
という事で↓で無事化けなくなりましとさ。
# ./configure --enable-multibyte # make # make install
HadoopでShuffle Error
reduce処理で「Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out.」と出て戦ったのでメモ。
原因としては各ノードのホスト名(と対応するIPアドレス)が127.0.0.1で通信不能だったため。
↓のようなNICを複数持っている構成の場合(ホスト名=127.0.0.1とhostsに書いてました)
NameNode ホスト:namenode01.matsumo(127.0.0.1) eth0:192.168.1.1 # 外向けセグメント(hostsにnamenode01.matsumo.sotoと登録) eth1:192.168.2.1 # 中向けセグメント(hostsにnamenode01.matsumo.nakaと登録) DataNode ホスト:datanode01.matsumo(127.0.0.1) eth0:192.168.1.2 # 外向けセグメント(hostsにdatanode01.matsumo.sotoと登録) eth1:192.168.2.2 # 中向けセグメント(hostsにdatanode01.matsumo.nakaと登録)
でHadoopのconf/slaveには中向け通信なので
datanode01.matsumo.naka
と書いておきます。よっしゃよっしゃ(とこの時は思っていた)
するとあらら・・・Reduce失敗。
↓のメッセージがログに出てました。
「Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out.」
半日くらい戦ったんで結論を勿体ぶりたいですが、端的に言うとnamenode01.matsumo(サーバのホスト名)で名前解決出来てかつ通信出来ないといけないという事みたいです。
内部の何処で何をやってるかは正直分かりませんが・・・
という訳でホスト名と対応するIPアドレスを中向けセグメントに直したら無事動きました
127.0.0.1 namenode01 namenode01.matsumo localhost localhost.localdomain ↓ 127.0.0.1 localhost localhost.localdomain 192.168.2.1 namenode01 namenode01.matsumo namenode01.matsumo.naka
中々それっぽいページが見つからなかったので書いておきます。
dateの前とか後とかのオプションのまとめ
何回やっても覚えないというか都度ぐぐる破目になっているのでここにまとめます!
期間は秒から年まで!過去ago!未来は何も無し!
#!/bin/bash echo "----------------------" echo "過去シリーズ" echo "----------------------" echo "今" date '+%Y/%m/%d %H:%M:%S' echo "去年" date -d '1 year ago' '+%Y/%m/%d %H:%M:%S' echo "先月" date -d '1 month ago' '+%Y/%m/%d %H:%M:%S' echo "昨日" date -d '1 day ago' '+%Y/%m/%d %H:%M:%S' echo "1時間前" date -d '1 hour ago' '+%Y/%m/%d %H:%M:%S' echo "1分前" date -d '1 minutes ago' '+%Y/%m/%d %H:%M:%S' echo "1秒前" date -d '1 second ago' '+%Y/%m/%d %H:%M:%S' echo "----------------------" echo "未来シリーズ" echo "----------------------" echo "今" date '+%Y/%m/%d %H:%M:%S' echo "来年" date -d '1 year' '+%Y/%m/%d %H:%M:%S' echo "来月" date -d '1 month' '+%Y/%m/%d %H:%M:%S' echo "明日" date -d '1 day' '+%Y/%m/%d %H:%M:%S' echo "1時間後" date -d '1 hour' '+%Y/%m/%d %H:%M:%S' echo "1分後" date -d '1 minutes' '+%Y/%m/%d %H:%M:%S' echo "1秒後" date -d '1 second' '+%Y/%m/%d %H:%M:%S'
実行結果は以下の通り!何だかやってる内に覚えちゃった気がする。
$ bash date.sh ---------------------- 過去シリーズ ---------------------- 今 2011/10/10 21:27:44 去年 2010/10/10 21:27:44 先月 2011/09/10 21:27:44 昨日 2011/10/09 21:27:44 1時間前 2011/10/10 20:27:44 1分前 2011/10/10 21:26:44 1秒前 2011/10/10 21:27:43 ---------------------- 未来シリーズ ---------------------- 今 2011/10/10 21:27:44 来年 2012/10/10 21:27:44 来月 2011/11/10 21:27:44 明日 2011/10/11 21:27:44 1時間後 2011/10/10 22:27:44 1分後 2011/10/10 21:28:44 1秒後 2011/10/10 21:27:45
思います。考えています。推測されます。恐らく。の抜け道
不規則に発生するバグに当たったり、何だか知らねぇけどロードアベレージが吹きそうな値になったり。昨日まで快適に動いてたSQLが今日になって鼻血出そうなくらい劣化したり・・・。
とか働いてると色々有るかと思いますが、その時点では原因は不明瞭にも関わらず相手に伝えなきゃいけない時ってありますよね。
とはいえ断言出来ないので↓のような文面に陥りがちだと思います。
リリース後暫くは大丈夫だったと思うのですが、 今日の午前中くらいに突然負荷が急騰しだしました。 MySQLが怪しいとは思うのですが恐らく何も変更を加えていないと考えられますので MySQL以外となるとApacheの方だと推測されます。
思う。考えられる。推測されます。恐らく。ハァハァだってまだ何も分かってないんだもん!!
という気持ちは分かりますが伝える相手は恐らくもっと分かってません。
ので冒頭に全て推測です!!と断言してしまうとするっと抜けれそうだと。
以下、現時点で確認出来ている事象と要因となります。 午前中は安定稼動。 MySQLに構成変更無。 Apacheに主要因有り。
力強く言い切ってますが万が一MySQLに誰か爆発物仕込んでてもその時点では分かってなかったから良いもんねー。えへへへへ。
なんてぇ事を考えてみました。小さい事ですがするりするりと生き抜くためにこういうテクニックは身につけていきたいものです。
まぁ勿論、時と場合と相手によりますが・・・ね。
findのemptyとdeleteが便利
4年前に「findのexecが便利」なんて事を書きましたが・・・。
http://d.hatena.ne.jp/yumatsumo/20070516
成長したのかしてないのかまた感涙もののfindのオプションを発見しました。
今回はemptyとdeleteが便利!というお話です。
きっかけ
mod_disk_cacheのhtcachecleanがどうも粛清が緩くてinode溢れに悩んでいた訳です。
もう頼ってられない、自分でやろう!粛清じゃー!という訳で以下の2つのルールでやろうと思ってはまりました。
・更新日がCacheMaxExpireを超えたファイルは削除
・空のディレクトリは削除
で、更新日はmtimeでほげほげで良いんですが、rmdirで空ファイル削除しようと思ったんですが中身にファイルが残ってるとステータスがエラーとなってしまい健全性が確認できません。
$ find ./ -type d | xargs rmdir rmdir: ./: Invalid argument rmdir: ./test3: Directory not empty $ echo $? 123
さてさてと悩んでいるとemptyとdeleteという素晴らしいオプションがmanに書いてありました。
このように便利です
↓が検証用のファイル・ディレクトリ構成です。(test1,2は空ディレクトリtest3配下にはファイルが有ります。)
$ mkdir test1 test2 test3; echo "foo" > test3/foo $ tree . |-- test1 |-- test2 `-- test3 `-- foo 3 directories, 1 file
emptyオプションエイヤ!で空ディレクトリが引っかかりました。
$ find ./test* -type d -empty ./test1 ./test2
そしてdeleteオプションをつけると空ディレクトリが削除されました!!おっけーい。
$ find ./test* -type d -empty -delete $ tree . `-- test3 `-- foo 1 directory, 1 file
rmdirと似たような動作で中にファイルが有る場合は削除されませんでした。(メッセージも同じです。)
$ find ./test* -type d -delete find: cannot delete ./test3: Directory not empty $ rmdir test3 rmdir: test3: Directory not empty
ちなみにちなみに
ファイル指定の場合は空ファイルだけが引っかかりました。ファイル指定時のdeleteオプションはファイルサイズに関わらず↓の例だと全部削除されましたのご注意を!!
$ touch empty_file $ echo "aaa" > aaa_file $ find ./ -type f -empty ./empty_file
これで快適なrmdirライフを満喫できます!!
プロセスのCoW共有しているメモリのサイズ
もはや伝説と化した記事がありますが、
http://d.hatena.ne.jp/naoya/20080212/1202830671
諸々の都合でLinux::Smaps入れると商用と開発入れなきゃいけないし、
管理上一台だけ入れるって訳にも行かないし、閉ざされた世界なのでcpanminiこしらえなきゃ・・・
とかお悩みのオレのために/proc/PID/smapsをそのままコリコリ読むスクリプト書いてみました。
つまりLinux::Smaps入れないでもOKです。(List::Utilは5.8以降だとコアモジュールなので使ってます。)
ペロッと貼ってご利用ください。
#!/bin/env perl use strict; use warnings; use List::Util (); @ARGV or die "usage: %0 [pid ...]"; my @output; for my $pid (@ARGV) { die "invalid pid '$pid'" if $pid =~ /\D/; my @smaps = `cat /proc/$pid/smaps`; die if $? != 0; my @shared = map { /(\d+)\s+kB/; $1 } grep { /^Shared_(Clean|Dirty)/ } @smaps; my $shared_total = List::Util::sum(@shared); my @rss = map { /(\d+)\s+kB/; $1 } grep { /^Rss/ } @smaps; my $rss_total = List::Util::sum(@rss); my $parcent = sprintf '(%d %%)', int(($shared_total / $rss_total) * 100); push @output, [$pid, $rss_total, $parcent]; } unshift @output, [qw(PID RSS SHARED)]; for my $out (@output) { print join "\t", @$out; print "\n"; }
使い方もこんな感じで一緒です。
# perl shared_memory_size.pl `pgrep httpd$` $ sudo perl shared_memory_size.pl `pgrep httpd$`
お悩みの諸兄!一人じゃない!けど大勢でもない!
ちなみにオレオレサーバ・・・。もうちょっと頑張れそうですね。
# perl shared_memory_size.pl `pgrep httpd$` PID RSS SHARED 5273 46800 (65 %) 5297 47208 (65 %) 5325 47184 (65 %) 5341 2912 (76 %) 5359 46052 (67 %) 5436 3060 (77 %) 5444 2932 (76 %) 5450 2884 (82 %) 5455 45464 (69 %) 5458 44584 (72 %) 5467 2892 (77 %) 5469 2896 (77 %) 5471 2860 (78 %) 5472 3112 (76 %) 5477 2708 (83 %) 5486 2724 (81 %) 5487 2716 (81 %) 5490 2832 (77 %) 5491 2756 (84 %) 5492 2260 (90 %) 5493 46420 (70 %) 5495 2748 (79 %) 5498 2204 (90 %) 5499 2196 (90 %) 5500 2200 (91 %) 5501 2196 (91 %) 25394 41824 (77 %) 25406 2292 (89 %)