Home

技術系のメモと日々の雑感

Ext3 上のディレクトリにファイルを大量に作ってみる

Ext2 の頃は1つのディレクトリ内に作れるファイル数の話がよく出てきてたけど、Ext3 になってからはまったく聞かなくなったね。
ちょっと興味があったのと、とある検証のために Ext3 上のディレクトリにファイルを大量に作ってみた。
サイズは 10KB でファイル名は連番だ。
環境は、HDD が Western Digital WD800JD-75MSA3 80GB、CPU が Core2 Duo E4500 2.20GHz、メモリが 1GB のマシンに CentOS 5.4 という構成。
負荷がかかるのを予想して HDD は古いものしか使えなかった。
ファイルを作る前の状態を載せておこう。

$ df -i
Filesystem            Inodes   IUsed    IFree IUse% Mounted on
/dev/sda3           19248768  301775 18946993    2% /
/dev/sda1              26104      35    26069    1% /boot
tmpfs                 128064       1   128063    1% /dev/shm

実際にやってみると、30 万個を過ぎた頃から ls の結果が表示されるまでの時間がだんだんのびてきた。
70 万個辺りで ls の結果が表示されるまで 1 分程度。
100 万個を過ぎると軽く 2 分以上かかるようになった。
また、この辺りからファイルが作られるスピードが落ちてきた。
I/O ウェイトが 50% 前後まで上昇したり下がったりの繰り返し。
そして、150 万個まで作ったときに、ls が 10 分待っても返ってこないことに気づいた。
Ctrl+C も効かないので kill するしかない。
ただしファイルは問題なく作ることができる。
この後、結局 1300 万個以上作ってみたけど、ls したりしなければ特に問題なし。
もう一度 df の結果を載せておこう。

$ df -i
Filesystem            Inodes    IUsed   IFree IUse% Mounted on
/dev/sda3           19248768 13831870 5416898   72% /
/dev/sda1              26104       35   26069    1% /boot
tmpfs                 128064        1  128063    1% /dev/shm

この結果からも分かるように、i ノードさえ残っていればファイルを作れるようだ。
ちなみに ls が使い物にならなくなってからでも、例えば vi で個別にファイルを開いて編集したりするのは問題なかった。
面白くない結果になってしまったけど、まずはひと安心ってところだな。

stat コマンドの特定の値だけ取得する

シェルスクリプトの中でファイルのサイズを取得しようと思い、stat コマンドが使えるだろうと予想。
ところが意外なことに、巷にあるオンラインのマニュアルには特定の値だけを出力させる方法が詳しく書かれてなかった。
欲しい情報はサイズだけなのに、何も指定しないと

$ stat hoge.txt
  File: `hoge.txt'
  Size: 533             Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d      Inode: 205979674   Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2010-09-30 16:48:37.000000000 +0900
Modify: 2010-09-30 16:48:37.000000000 +0900
Change: 2010-09-30 16:48:37.000000000 +0900

という具合に、たっぷりと情報が表示される。
結局、やりたかったことは

$ stat -c%s hoge.txt

でいけた。
実際にやってみないと分からないことって多いね。

シェルスクリプトの多重起動を防ぐ簡単な方法

cron で 1 分ごとに実行するスクリプトがあって、処理に時間がかかると同時に走ってしまって変になることがあった。
こういう場合、処理中はフラグ代わりのファイルを作っておいて、終わったら消すのが一般的なのかな。
自分もしばらくこれでやってたんだけど、もうちょっといい方法がないか考えてみた。
で、思いついたのが

pgrep -f `basename $0` | wc -l > /tmp/.script.check
if [ `cat /tmp/.script.check` -ne 1 ]; then
  exit
fi

という処理をシェルスクリプトの先頭に書いておく方法。
バッククオートがネストできればもう少しきれいに書けるんだけどなぁ。
単純に ps の結果を grep すればいいんじゃないかなんて思ってしまうけど、やってみると意外と難しいね。

OpenVZ の中の様子

この前触ったレンタルサーバが OpenVZ で組まれていた。
環境の作り方によって変わるところがあると思うけど、ざっくり特徴をメモっておく。
まず驚いたのが /boot が空だったことと dmesg で何も表示されなかったこと。
ファイルシステムが /dev/simfs ってのも初めて見た。
スワップが割り当てられてないのにもびっくりしたけど、これも OpenVZ の特徴のひとつなんだね。
立ち上がっているプロセス、というか見えてるプロセスは異常に少なかった。

# ps ax
  PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 init [3]
 6141 pts/0    R+     0:00 ps ax
22009 ?        S<s    0:00 /sbin/udevd -d
22279 ?        Ss     0:00 syslogd -m 0
23766 ?        Ss     0:00 crond
24056 ?        Ss     0:00 /usr/sbin/sshd
32393 ?        Rs     0:00 sshd: root@pts/0
32638 pts/0    Ss     0:00 -bash

ちなみに chkconfig では

# chkconfig --list | grep :on
auditd          0:off   1:off   2:on    3:off   4:on    5:on    6:off
avahi-daemon    0:off   1:off   2:off   3:off   4:on    5:on    6:off
crond           0:off   1:off   2:on    3:on    4:on    5:on    6:off
gpm             0:off   1:off   2:on    3:off   4:on    5:on    6:off
haldaemon       0:off   1:off   2:off   3:off   4:on    5:on    6:off
iptables        0:off   1:off   2:on    3:off   4:on    5:on    6:off
lm_sensors      0:off   1:off   2:on    3:off   4:on    5:on    6:off
mcstrans        0:off   1:off   2:on    3:off   4:on    5:on    6:off
messagebus      0:off   1:off   2:off   3:off   4:on    5:on    6:off
netfs           0:off   1:off   2:off   3:off   4:on    5:on    6:off
network         0:off   1:off   2:on    3:on    4:on    5:on    6:off
portmap         0:off   1:off   2:off   3:off   4:on    5:on    6:off
rawdevices      0:off   1:off   2:off   3:on    4:on    5:on    6:off
restorecond     0:off   1:off   2:on    3:off   4:on    5:on    6:off
sendmail        0:off   1:off   2:on    3:off   4:on    5:on    6:off
sshd            0:off   1:off   2:on    3:off   4:on    5:on    6:off
syslog          0:off   1:off   2:on    3:on    4:on    5:on    6:off
xfs             0:off   1:off   2:on    3:off   4:on    5:on    6:off
xinetd          0:off   1:off   2:off   3:off   4:on    5:on    6:off
yum-cron        0:off   1:off   2:off   3:on    4:on    5:on    6:off

という具合に、有効になっているサービスが色々とあった。
ifconfig を実行すると

# ifconfig
venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:127.0.0.1  P-t-P:127.0.0.1  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
          RX packets:108297 errors:0 dropped:0 overruns:0 frame:0
          TX packets:70786 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:263497592 (251.2 MiB)  TX bytes:5248128 (5.0 MiB)

venet0:0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:XXX.XXX.XXX.XXX  P-t-P:XXX.XXX.XXX.XXX  Bcast:XXX.XXX.XXX.XXX  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1

なんだか見慣れない表示。
あと、目に付くところといったら /proc の下に vz というディレクトリがあって、veinfo と vestat という仮想ファイルが作られてたぐらいか。
残念ながらこの環境は短期間で使用しなくなってしまったので使い勝手は不明。
もっとじっくり見ておけばよかったなぁ。

watch と lsof のコンビネーション

デーモンの動きを見たいときによく利用するコマンド。

watch -n 1 'lsof -i -n -P | grep -v ^sshd | grep ESTA'

あんまり頻繁に使うものだから指が覚えてしまった。