A Day In The Boy's Life -169ページ目

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

サーバーを管理していると、削除や変更されたくないファイルやディレクトリというものが出てきたりします。

権限や所有者を適切にコントロールすることでそれらを対応させることもできますが、Linuxの場合はrootユーザーは何でもありの特権を持っていますし、優れたユーザー管理の機構がLinuxには存在するわけでもないため、管理が煩雑になったり、それだけではうまくコントロールしきれないケースも出てきたりします。


ここで紹介する、Linux上の特殊な権限を操作するchattrコマンドを使えば、削除や変更ができないファイルや追記のみ許可するファイルなどを作り出すことができます。

なお、chattrコマンドはext2またはext3のファイルシステム上での属性変更を可能とするものです。



ファイル・ディレクトリを削除できないように権限を変更する


まずは、削除できないファイルにするために、権限を変更してみましょう。


# touch foo.txt

# chattr +i foo.txt

# rm foo.txt
rm: remove write-protected 通常の空ファイル `foo.txt'? y
rm: cannot remove `foo.txt': 許可されていない操作です

# echo "xyz" >> foo.txt
-bash: foo.txt: 許可がありません


chattrコマンドに「+i」オプションをつけることで、削除・変更ができないファイルとなります。

ちなみにファイル名の変更もできなくなります。


そして、上記の操作を見てもらえればわかるとおり、rootユーザーでさえファイルの削除が行えなくなります。

なお、この権限を削除したい場合は「-i」オプションをつけて実行します。


# chattr -i foo.txt

# rm foo.txt
rm: remove write-protected 通常の空ファイル `foo.txt'? y
(削除される)


ディレクトリの場合も、操作は同様です。


# mkdir hoge_dir

# chattr +i hoge_dir/

# rmdir hoge_dir/
rmdir: `hoge_dir/': 許可されていない操作です


追記モードでしか開けないファイルを作る


ファイルを「追記モード」でしか開くことができず、また削除もできないファイルを作ってみます。


用途としては、例えばログファイルを作る場合に有効になるのではないでしょうか。

時に重要な意味を持つログファイルは、運用の中で削除されてしまっては困ります。

ただ、変更もできないとなるとログファイルへの書き込みができません。

追加で書き込むのは許可しつつも、ファイルの削除はされたくないという場合に、この権限設定が活きてきます。


# cat foo.txt
abc

# chattr +a foo.txt

# echo "xyz" > foo.txt
-bash: foo.txt: 許可されていない操作です

# echo "xyz" >> foo.txt

# cat foo.txt
abc
xyz

# rm foo.txt
rm: remove 通常ファイル `foo.txt'? y
rm: cannot remove `foo.txt': 許可されていない操作です

# chattr -a foo.txt

# rm foo.txt
rm: remove 通常ファイル `foo.txt'? y
(削除される)


追記モードでしかファイルを開かせないためのオプションは「+a」オプションです。

途中でfoo.txtファイルに2つの操作をしています。


# echo "xyz" > foo.txt

ファイルに文字を書き込んで上書きしようとしています。

この操作は、はじかれています。


一方で、ファイルの末尾に追加するリダイレクトの操作は問題なく動作しています。


# echo "xyz" >> foo.txt

また、このオプションを付けることでファイルの削除もできなくなっています。

この特殊な権限を取り除きたい場合は、「-a」オプションをつけて実行します。



特殊な権限を見るためのlsattrコマンド


この特殊な権限は、lsコマンドで見てもどこにも表されていません。


# ls -la
合計 12
drwxr-xr-x 3 root root 4096 11月 18 10:34 .
drwx------ 10 root root 4096 11月 18 10:23 ..
-rw-r--r-- 1 root root 0 11月 18 10:33 foo.txt
drwxr-xr-x 2 root root 4096 11月 18 10:34 hoge_dir

この権限を見る場合は、「lsattr」コマンドを利用します。


# lsattr
-----a------- ./foo.txt
----i-------- ./hoge_dir

上記の場合、foo.txtにaオプション(ファイルへの追記のみ許可)、hoge_dirディレクトリにiオプション(ファイルの削除・変更不可)がセットされていることがわかります。



プログラムからの操作はどうだ?


最後に、プログラムからこの特殊な権限を付け加えたファイルを操作して動作を検証してみます。


# lsattr
-----i------- ./foo.txt

この状態のファイルに対して、PHPのプログラムから操作してみます。

プログラム自体はこんな感じに。


- file.php
<?php

$fp = fopen("./foo.txt", "r");

while (!feof($fp)) {
$buff = fgets($fp, 1024);
echo $buff;
}

fclose($fp);

まずは、読み取りから


# cat foo.txt
abc

# php file.php
abc

これは、問題なく動作します。


次に、書き込みを行ってみます。

最初のfopen時に書き出しのみのモードでファイルを開いてみます。


$fp = fopen("./foo.txt", "w");

上記の編集を加えて実行してみると・・・。


# php file.php
PHP Warning: fopen(./foo.txt): failed to open stream: Permission denied in /home/hoge/sc/file.php on line 3

権限がないというエラーメッセージが出ました。

これは、追記モードで開いても同様の結果です。


次に、foo.txtを追記モードで開けるように変更してみます。


# chattr +a foo.txt

# lsattr
-----a------- ./foo.txt

この状態で、先ほどのPHPスクリプトを書き出しモード(wオプション)でファイルを開いてみます。


# php file.php
PHP Warning: fopen(./foo.txt): failed to open stream: Operation not permitted in /home/hoge/sc/file.php on line 3

今度は、操作が許可されていないというエラーメッセーが出ています。


では、操作が許可されている追記モードで開いてみます。


$fp = fopen("./foo.txt", "a");

上記の編集を加えて実行してみると・・・。


# php file.php
abc

こちらは、ちゃんと操作ができました。

じゃあ、実際に追記モードでファイルに書き込んでみます。

スクリプトを変更してこんな感じに。


<?php

$fp = fopen("./foo.txt", "a");
fwrite($fp, "xyz");
fclose($fp);

$fp = fopen("./foo.txt", "r");

while (!feof($fp)) {
$buff = fgets($fp, 1024);
echo $buff;
}

fclose($fp);

上記のPHPスクリプトを実行させてみると・・・。


# php file.php
abc
xyz

ちゃんと書き込んでいますね。


用途は限定的であるものの、サーバー管理をしていく中で覚えておくと便利なコマンドではないでしょうか。






ふと思ったこと。


昔どこかで、ブログの文章は短い方がいいと書いてある記事を見た記憶があります。

確かに、ブログを日記という位置づけで見るとダラダラと長い文章を読まされるより、完結にさらっと書いてくれたほうが、読むほうはとしては読みやすいのは分かります。


ただ、今はそれなりの文章でも結構読まれているような気もします。

日記としてのブログは依然としてあるにはあるけど、何かの作り方とか、あるいは何かについて論じてみたりと、ブログの用途が多種多様になってきているのも理由の一つにあると思います。


また、はてなブックマークなどのソーシャルブックマークやSNSなど話題を提供する場所というのが広がりを見せたことも一つだと感じます。

長文でも、「これはすごい」文章であれば、「みんなが読んでるんだから読んでみよう」という気にさせられたりもします。


こういうソーシャルな場で話題になるブログというのは、得てして長文が多いです。

散発的な文章のブログとういのはあまり取り上げられません。(ネタ的なものは別として)

やはり、良い悪いにしろ人の印象に残るためにはある一定の文章量が必要だと思います。

もちろん、それが相手にわかりやすいものでないと読まれもしませんし、取り上げられるなど然もありなんといった感じですが。


それは、良い文章は良いものとして、ブログ自体の存在感が他のメディアと変わりなくなってきているとも言えるのではないでしょうか。

別に日記としてのブログを否定しているのではなく、長文でもきちんと読まれるところには読まれるという事実があるということを感じただけです。


このブログも比較的長文のものが多いです。

わざとそうしているわけではなく、書きたいことを書いていたらそれぐらいの文章になってしまったという感じで。

メディアの代替と言っても、本なんかと比べるとかなりまとまりの無いものです。

どちらかというとダラダラと話すTVを文章に置き換えたような感じでしょうか。


ブログがあちら側で存在感を示している事は、書き手にとっては自己表現の場を広げるチャンスだったりもするわけです。

読まれないのは何らかの文章に欠陥があるのでしょう。

それはそれで、読まれるための文章というものをどうすれば良いのかというステップアップにつながると思います。


少なくとも、何か思っている事を自分なりにまとめて書いておけば、それをきちんと読んでくれる人が出てくる可能性は、少し前のブログよりも格段に高くなっていると感じます。




負荷テスト(または性能テスト)は、システムを作り上げる上で重要な要素を持つテストになります。

しかしながら、システムを構築する段階ではあまりこの負荷や、サーバー(またはその上でのアプリケーションやミドルウェア)の性能というものは気にしません。

開発メンバーはせいぜい数十人といったレベルが多く、システムの開発段階ではそれだけの人のアクセスがないため、実際の利用状況とはかなり異なった環境で「動いたからOK」という感じで流してしまいがちです。


ただ、こういうことを気にせずにシステムをリリースしてみたら、一定のデータ量に達したらアプリケーションが動かなくなったり、サーバーが応答しなくなったなんて事があったりします。
そういうことがないためにも、リリース後の負荷を想定したテストや、システム全体の性能を予めテストしておく必要があります。


負荷テスト用のツールで市販されているものは、確かにきめ細かい結果を出してくれるものが多いのですが、高価でなかなか手が出しにくいものです。
ここでは、Apache Bench、Microsoft Web Application Stress Tool(WAST)、JMeterというフリーのツールを使った負荷テストの方法で、中でも特にシステム全体の応答時間を探る方法を書いて見たいと思います。


なお、ここで書いているツールはサーバーに過度の負荷を与える事ができてしまう為、自分の責任の範疇にある領域でのみ使用し、他の人が管理しているサーバー等には使用しないようにしてください。



負荷テストのポイント


まずは、どのように負荷テストを実施していけばいいのかを考えてみたいと思います。
これには、大きく2つの視点でのテスト方法があります。


1. 現在の負荷から改善効果を探りたい


まず、負荷テストを実施してみたい背景に、現在のパフォーマンスがネックになっており、改善の必要性があるといったことが考えられます。
この場合、アプリケーションの性能を改善してみてリリースしようにも、どれ位の改善が行われたのかを事前に調べる必要があります。
プログラムのロジックやSQLを見直してみて、パフォーマンスが改善したはずだと思い込んでみても、アプリケーションはそれ単体で動くという事はあまりないので、全体性能を見てみたらそんなに改善してなかった、またはより悪くなってしまったという事も考えられます。

この場合は、現在の負荷の度合いが分かっているはずなので、それが負荷テストを実施するうえでの一つのキーになる値となります。


例えば、同時に100人がシステムにアクセスすると途端にパフォーマンスが低下するなどです。
このあたりは、日々のアクセスログを解析してみて、ピーク時にどれ位のアクセスがあるのかでその数値が割り出せるはずです。
あまり厳密でなくて良いと思います。大体の値を割り出す事で負荷テストを実施するうえでの指標を見つけ出す事が重要になりますので。



2. 現在のシステム構成でどの位の負荷に耐えられるのかを調べたい


今度は1.とは逆に負荷テストをしてみる為の指標がない場合です。
新しくシステムをリリースする場合、そのシステムの利用者数や1日の負荷のデータが存在しない場合があります。

とは言え、システムを構築する際や、システムを運営して行く上での要件からその指標を見出す事はできます。
例えば、このシステムは3年後には会員数10万人を目指すなどの目標があるはずです。
または、(今はほとんど言われなくなりましたが)8秒ルールといったシステム応答時間に関する指標もあるかと思います。


であれば、会員数が10万人(そこから日に何人ぐらいのアクセスがあるかを予測して)となった場合でも、8秒以内に応答できるかどうかを検証してみることができます。
また、それ以上の負荷をかけてみて、現システム構成では会員数が何人まで耐えられるのかの予測値を導く事もできると思います。
この場合は、負荷のレベルを徐々に上げていき、その際の応答時間や単位時間当たりの処理数の遷移を見てみることで判断する事ができます。



何れにせよ、負荷テストで大事なのは予測でもいいので指標を定めてみて、それを満たすか否かの検証を繰り返してみるのが大事です。
では、具体的なツールの利用方法に移りたいと思います。



Apache Benchの利用方法


Apache Benchは、Apacheに付属している負荷テスト用のコマンドで、簡易的なテストであればこのコマンドだけでも十分に行えます。
利用する場合には、まずabというコマンドが存在するかどうかを確認してください。


# which ab
/usr/bin/ab

abコマンドを使って、あるサーバーに一定の時間の間、負荷をかけたい場合は


# ab -c {同時に実行したいリクエスト数} -t {負荷テストの実行時間(秒)} {URL}

とします。
例えば


# ab -c 10 -t 60 http://192.168.0.100/index.html

とすると、192.168.0.100のサーバーに対して同時接続10(-cオプション)で、60秒間(-nオプション)負荷をかけ続けます。
この場合、合計での処理数(リクエスト数)というのは分かりません。
なぜなら、あくまで同時にリクエストを10投げるというだけで、60秒間で合計どれだけのリクエストを処理できるかは対象のサーバーの処理能力によって異なってきます。


合計のリクエストを指定して負荷テストをしたい場合は、下記のように実行します。


# ab -c 10 -n 100 http://192.168.0.100/index.html

※ -nオプションの後に合計のリクエスト数を指定する。


この場合、合計100リクエストになった段階でテストが完了します。
時間を指定して(-tオプションで)性能テストを行う場合、負荷のレベルが対象サーバーごとに異なってきますが、合計のリクエスト数を指定すればどのサーバーに対しても同一の負荷レベルで結果を見比べるという事が可能になります。



Apache Benchのレポートの見方


abコマンドを実行すると下記のような結果が出力されます。


# ab -c 10 -n 1000 192.168.0.100/

This is ApacheBench, Version 2.0.41-dev <$Revision: 1.121.2.12 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/

Copyright (c) 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.0.100 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Finished 1000 requests

Server Software: Apache
Server Hostname: 192.168.0.100
Server Port: 80
Document Path: /
Document Length: 20457 bytes
Concurrency Level: 10
Time taken for tests: 1.791311 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 20725064 bytes
HTML transferred: 20482096 bytes
Requests per second: 558.25 [#/sec] (mean)
Time per request: 17.913 [ms] (mean)
Time per request: 1.791 [ms] (mean, across all concurrent requests)
Transfer rate: 11298.43 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 1.0 4 6
Processing: 9 13 1.0 13 18
Waiting: 1 4 0.8 4 6
Total: 9 17 0.4 17 19
Percentage of the requests served within a certain time (ms)
50% 17
66% 17
75% 17
80% 17
90% 17
95% 17
98% 18
99% 18
100% 19 (longest request)


サーバーの応答時間を見る前に、テストしたリクエストが全て正常に処理できたかどうかを見てみましょう。
それは、「Failed requests」の項目を見てみればわかります。
この値が0以外であれば、サーバー側で処理が出来ずにエラーとなってしまったリクエストがあることを意味します。
そうであった場合は、今回のテストよりさらに高い負荷をかけてテストする事に意味はなくなってしまいます。
一部の処理が正常に処理できず、エラーとなってしまっているので、応答時間も求めるべき数字ではなくなってしまうからです。


また、テストするURLが正しいかどうかもあわせて確認しておきましょう。
存在しないページに対してabコマンドを実行してみてもあたかも、テストが正常に完了したかのような結果がでてきます。(404 File Not Foundのページが結果として出てくるためです)
そのような場合は、下記のようにHTTPステータスコードが200以外のリクエストがどれだけあったのかを示す項目が表示されます。


Non-2xx responses: 100

上記の項目が表示されていない事を確認する必要があります。

そして、応答時間についてですが「Time per request」の項目からわかります。


Time per request: 17.913 [ms] (mean)
Time per request: 1.791 [ms] (mean, across all concurrent requests)

2つ表示されますが、上が1リクエストあたりの応答時間で、下(across all concurrent requests)がTime per request / 同時リクエスト数の値となります。

また、システムの全体性能を見たい場合は「Requests per second」を見ることで、1秒あたりのリクエスト処理数を見ることが可能です。


Requests per second: 558.25 [#/sec] (mean)

全体としてシステムパフォーマンスが改善されたかどうかであれば、ここを見てみるだけでも判断が可能です。
(大きくなればパフォーマンスが改善された、小さくなると悪くなった)


最後にですが、Apache Benchは単一リクエストに対してしかテストを実行できません
ですので、先ほどのテストでは実際にブラウザでindex.htmlへアクセスした場合と結果が大きく異なる可能性があります。

理由は、Apache Benchでは単純にindex.htmlへのリクエストしか行わず、その中に含まれる画像などのリクエストを処理してくれない為です。
Apache Benchで負荷テストをする場合は、単一機能を提供するプログラムに限定してチェックしてみるのが有効です。

ですので、「負荷テストのポイント」であげた「1. 現在の負荷から改善効果を探りたい」という事はApache Benchで対応できますが、「2. 現在のシステム構成でどの位の負荷に耐えられるのかを調べたい」については向かないツールだといえます。



Microsoft Web Application Stress Toolの利用方法


WASTの使い方については、以前に書いたエントリを参考にしてみてください。


負荷テストあれこれ-Microsoft Web Application Stress Tool-


WASTを使った場合は、ある程度複雑なシナリオでテストをする事が可能です。
また、HTMLファイルに含まれる画像やCSSなどのリクエストも処理してくれるので、より実際の負荷に近い形でテストをする事ができます。


WASTは負荷テストを実行した後、上部のReportsボタンからテストの実施結果を詳細に見ることが可能です。


WAST-レポート



Microsoft Web Application Stress Toolのレポートの見方


下記が、WASTを実行した際に出力されるレポートの例になります。


Overview
================================================================================
Report name: 2008/11/09 11:23:05
Run on: 2008/11/09 11:23:05
Run length: 00:03:00
Web Application Stress Tool Version:1.1.293.1
Number of test clients: 1
Number of hits: 45937
Requests per Second: 255.20
Socket Statistics
--------------------------------------------------------------------------------
Socket Connects: 45941
Total Bytes Sent (in KB): 17322.24
Bytes Sent Rate (in KB/s): 96.23
Total Bytes Recv (in KB): 75050.71
Bytes Recv Rate (in KB/s): 416.94
Socket Errors
--------------------------------------------------------------------------------
Connect: 0
Send: 0
Recv: 0
Timeouts: 0
RDS Results
--------------------------------------------------------------------------------
Successful Queries: 0

Script Settings
================================================================================
Server: 192.168.0.100
Number of threads: 5
Test length: 00:03:00
Warmup: 00:00:00
Cooldown: 00:00:00
Use Random Delay: No
Follow Redirects: Yes
Max Redirect Depth: 15

Clients used in test
================================================================================
localhost
Clients not used in test
================================================================================

Result Codes
Code Description Count 
================================================================================
200 OK 45937

Page Summary
Page Hits TTFB Avg TTLB Avg Auth Query
================================================================================
GET /index.html 1482 468.49 483.91 No No
GET /common/lib.js 1482 1.98 2.39 No No
GET /common/style.css 1482 1.84 2.19 No No
GET /img/header1.gif 1482 1.76 1.84 No No
GET /img/header2.gif 1482 1.88 1.96 No No


WASTの場合、上記レポートの一番最後に出力されているように各リクエストごとの応答時間の結果を見ることができます。

結果を見れば分かるように、Apache Benchとは違い、複数のリクエストを実行してテストを実施する事が可能です。


「TTFB Avg」がリクエストに対して何らかの応答があるまでの平均時間、「TTLB Avg」が応答が完了するまでの平均時間となるため、「TTLB Avg」を応答時間としてみておけばよいでしょう。
また、Apache Benchと同様に1秒あたりのリクエスト処理数(Requests per Second)を見ることも同じレポート画面から見ることができます。


簡単なシナリオであれば、そのシナリオに沿った負荷テストが実施できますので、実際に利用者が使った場合の負荷を調べる事ができますし、その流れからどのページがパフォーマンスが悪いかもよくわかります。
また、「負荷テストのポイント」であげた「2. 現在のシステム構成でどの位の負荷に耐えられるのかを調べたい」についても、一連のシナリオに沿って負荷のレベルを徐々に上げていき、応答時間や単位時間当たりのリクエスト処理数の推移を見ることで、そのシステム構成でのパフォーマンスの限界値を明らかにする事もできます。

ただ、WAST自体がかなり古い負荷ツールで、2000年以降に更新されていない事、SSLのページに対して負荷テストを実施できない事などの欠点があります。



Apache JMeterの利用方法


最後に、JMeterです。
これも、以前に書いたエントリを参考にしてみてください。


負荷テストあれこれ-JMeterの使い方-


負荷テストあれこれ-JMeter 負荷のかけ方、レポートの見方-


JMeterは使い方が少し難しいツールにはなりますが、多種多様な負荷テストを実行する事が可能です。
基本的な使い方の方は以前のエントリを参照していただくとして、ここではJMeterを使って応答時間を計測する方法を説明します。



Apache JMeterのレポートの見方


まず、JMeterで応答時間を計測するには「リスナー」から「統計レポート」を追加します。


Jmeter-スレッドグループ


統計レポートを追加した状態で、負荷をかけてみると応答時間とスループットがわかります。


Jmeter-統計レポート


応答時間には、平均値、中央値、最小値、最大値など様々な結果が出てきます。
スレッド数が大きい場合、テストの結果の中で本来の結果とは大きくずれた値が出てくることもあるため、私は中央値で応答時間を見るようにしています。


また、JMeterのスループットはApache BenchやWeb Application Stress Toolの1秒あたりの処理数とは少し異なります。
これは、JMeterで負荷テストをする際に実行するスレッドの間隔を定義できるためで、全ての処理をサーバーが正常に処理出来た場合、下記の結果と同一になります。


スループット = (スレッド数 × ループ回数)/ Ramp-Up期間


例えば、1スレッドあたり10HTTPリクエストを送信するシナリオをセットしていて、60スレッド、ループ回数1、Ramp-Up期間を60秒にしてテストすると、1秒間に10リクエストずつ実行されます。
つまり、JMeterのスループットはそれ以上の処理がサーバー側に送られないので、スループットもそれより良くなりません(※)。


※ タイマをセットしなかった場合、1秒あたりの実行リクエスト数以上のスループットが出ることがあります。
  これは、1スレッドの中で実行されるリクエストが偏っているからです。
  例えば、1秒間に10リクエストを送信するテストを行う場合、実行のタイミングが来たらJMeterは一気に10リクエストを

  送信しようとします。

  タイマを使えば、例えば100msごとに1リクエストを送信するなど、均等に処理を実行させる事ができます。


Apache BenchやWASTのように、1秒あたりにどの位の処理が出来るかを調べたい場合は、スレッドグループ画面の「ループ回数」の「無限ループ」にチェックを入れれば、絶え間なくリクエストを送信してくれます。


Jmeter-スレッドグループ


※ こうした場合、テストは自動で終了しないため、手動で終了させる必要が出てきます。

JMeterは非常に高機能で、複雑なシナリオに沿ったテストも実行できますが、テストするクライアントマシンの負荷もそれなりにかかる為、性能の良いものを用意するか、複数台でテストを実施するなどの工夫が必要です。
スループットがでないなぁとか思っていたら実はそれはクライアントマシンの性能が悪かった為ということも少なくありません。
クライアントマシン自体の負荷も見つつ、適度にこなせる処理数の負荷でテストを実行する必要があります。



3つのフリーの負荷ツールを紹介してみましたが、それぞれ出来る事も違っています。
簡易的にベンチマークをとりたいのであれば、Apache Benchでも十分でしょうし、より実際の状況に近い負荷をかけたい場合はJMeterが有効です。
用途に応じて、負荷テストのツールを使う事で効率的にテストを行えると思います。