ab(Apache Bench) コマンドなどを実行する場合など、HTTP サーバのパフォーマンスの分析を簡易的にしたい場合に、
topなどで監視するのもいいのですが、Apacheが現在何プロセス、何本のコネクションか定期的に監視できると便利です。
今回は毎秒Apacheのプロセス数とHTTP/HTTPS接続本数を調べて結果を出力し続けるというコードを書いてみました。
ab(Apache Bench) コマンドなどを実行する場合など、HTTP サーバのパフォーマンスの分析を簡易的にしたい場合に、
topなどで監視するのもいいのですが、Apacheが現在何プロセス、何本のコネクションか定期的に監視できると便利です。
今回は毎秒Apacheのプロセス数とHTTP/HTTPS接続本数を調べて結果を出力し続けるというコードを書いてみました。
gawk マニュアル
見覚えのある書き方だなと思ったら、拙訳 GNU Make と似ているんですね。さすが RMS 著。
sed, awk は頻繁に使ってるんですが、次のように
cat access_log | sed -e ‘/googlebot/d’ -e ‘/\/robots\.txt /d’ | awk ‘{ print $(11); }’ # access_log で googlebot や /robots.txt を含まない行のうち 11 列目の要素を出力
とか、ただ列を抽出するだけというかわいそうな使い方しかしていなかったのでなかなか目から鱗です。
fstat, lsof, fuser などのコマンドを使うと、現在開かれている全てのファイルと開いているユーザ、プログラム、プロセス、読み書きのモードが調べられます。
fstat は FreeBSD の場合で、fuser は Linux の場合、lsof は Linux, BSD を含む UNIX 互換 OS で利用可能です。BSD でlsof を使う場合は、 ports/sysutils/lsof を入れます。lsof は機能が豊富なので、lsof の利用をお勧めします。
fstat:
fstat [-fmnv] [-p pid] [-u user] [-N system] [-M core] [file …]
fuser:
fuser [-a|-s|-c] [-4|-6] [-n space] [-k [-i] [-signal] ] [-muvf] name
…
fuser -l
fuser -V
lsof:
lsof [ -?abChlnNOPRstUvVX ] [ -A A ] [ -c c ] [ +c c ] [ +|-d d ] [
+|-D D ] [ +|-f [cfgGn] ] [ -F [f] ] [ -g [s] ] [ -i [i] ] [ -k k ] [
+|-L [l] ] [ +|-m m ] [ +|-M ] [ -o [o] ] [ -p s ] [ +|-r [t] ] [ -S
[t] ] [ -T [t] ] [ -u s ] [ +|-w ] [ -x [fl] ] [ -z [z] ] [ — ]
[names]
たとえば、ログファイルを開いているプロセス, ファイルを調べるには
lsof +D /var/log
等とします。
デバッグや問題究明に便利です。
参考:
– LSOF設置及び使用ガイド
sh, bash, csh, zshのようなシェルでは
echo *.sh
などというように、ワイルドカードでファイル一覧を取得することができます。
シェルで使えるワイルドカードはアスタリスク(*)、クエスチョンマーク(?)の2種類で、それぞれ、0文字以上の任意の文字列、1文字の任意の文字(英数記号など)を表します。
ワイルドカード文字を、ワイルドカードとしてではなくただの * や ? という1つの文字として扱いたい場合は、次のようにクオート記号で囲むか、エスケープします。
echo "*.sh" echo "What's up?" # 結果 # *.sh # What's up? # が表示される
ここに変数が関係してくると、少し厄介なことになります。
# 間違った例 foo="SELECT * FROM table" echo $foo
この結果は、
SELECT * FROM table
と表示されるかと思いきや、アスタリスクがワイルドカードとして展開されてしまうため、
SELECT FROM table
とアスタリスクが消える、または、現在の作業フォルダのファイル一覧が展開されて、
SELECT bin boot home root var FROM table
のように意図しない結果になってしまいます。
これはかなり怖いことで、この動きにより、最悪致命的なセキュリティホールや、データ消失につながる場合があります。
これを回避するためには, ワイルドカード文字を含む変数の参照時は常にダブルクオート/シングルクオートの中で参照するというテクニックを使います。
# 正しい例 foo="SELECT * FROM table" echo "$foo"
この結果は、期待通り
SELECT * FROM table
となります。
多段になってもこの動きは変わりません。
foo="SELECT * FROM table" boo="$foo" echo "$boo" # foo, boo 両方の参照をダブルクォートでくくっていることに注意
この結果も、期待通り
SELECT * FROM table
となります。ここで
echo $boo
としていると、やはり変数展開されてしまうため、注意しましょう。
お約束として、変数を参照するときで、変数に記号が入る可能性がある場合は必ずダブルクオートで囲む癖をつけると、こういう間違いがなくなるので幸せになれます。
一歩踏み込んだ例として、変数の遅延展開の例を紹介します。
export table=book # 1
# ↑これは全く利用されない
text='SELECT * FROM ${table}' # 2
# ↑シングルクオートなので、textに入る時点ではtableが展開されない。
export table=member # 3
# ↑これが利用される。子プロセスで参照できるよう export している
query=$(sh -c "echo \"$text\"") #4
# ↑ここでtableの中身が展開されます。* の展開を防ぐため $text をダブルクォートで囲んでいることに注意
echo "$query" # 5
この結果は、
SELECT * FROM member
と出力されます。
処理の流れは以下のとおりです。
1: table 変数に book をセット
2: text 変数に SELECT * FROM ${table} をセット(table変数の中身はここでは見ない)
3: table 変数の内容を member に書き換え
4:
sh -c "echo \"$text\""
を実行、shが立ち上がり、
echo "SELECT * FROM ${table}"
を実行する。(ここでtableが初めて展開される)
query 変数に、echo が出力した SELECT * FROM member をセットする。(ここでは変数代入だけで画面には出力されない)
5: query 変数の内容、SELECT * FROM member を表示する
あまりやらないですが、こういう複雑な処理でも期待通り動作するのは、適切にクオートしているおかげですね。
– 以降作るファイル, ディレクトリをグループ権限で書き込めるようにする。
$ umask 0002
※影響範囲は全ディレクトリについて、自身のプロセスと子プロセス。
– 指定したグループとして作業する(作ったファイルの所有グループを任意のものにする)。
$ sg groupname
– ディレクトリに対しての sgid の効果。
指定したディレクトリ以下に作成したファイルのグループを全て sgid したディレクトリのグループ所有とする。
$ ls -ld foo/
drwxrwxr-x 4 user mygroup – 512 Nov 10 09:33 foo/
$ touch foo/file1
$ ls -l foo/file1
-rw-r–r– 1 user users 0 Dec 13 12:30 foo/file1
$ chmod g+s foo/
$ ls -ld foo/
drwxrwsr-x 4 user mygroup – 512 Nov 10 09:33 foo/
$ touch foo/file2
-rw-r–r– 1 user mygroup 0 Dec 13 12:35 foo/file2
jvim がファイルの文字コードを誤って解釈してくれた時や新規作成の時は文字コード明示をするとよい。
jvim -k s foo.txt
“-k” オプションで一文字で文字コードを指定する。
SJIS: s
EUC: e
UTF-8: t
など。その他 u とかもあるけど忘れた。
忘れていたのでメモしとく。
df -T
でOK. 結果は次の通り
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/hda1 ext3 36867308 3663864 31330672 11% /
tmpfs tmpfs 452704 0 452704 0% /dev/shm
FreeBSD 4.10 付属のものにはないオプションだけど、FreeBSD ではどう調べるのだろう。
lsvfs
df -t nullfs,ufs
とかしていくしかないのかな。
swsusp というのがあるらしい。
<http://www.suspend2.net/>
– Software Suspend 2 for Linux 公式
<http://thlug.sourceforge.jp/pukiwiki/pukiwiki.php?swsusp%BE%DC%BA%D9>
– THLUGPukiwiki – swsusp 詳細
find . -type f | xargs wc -c
など xargs を使うときに、標準入力が空だと実行されないのかと思っていたら、標準入力がなくても一度は必ず実行するというのがデフォルトだった。このため、上の結果は wc -c < /dev/null のようにとられて 0 になる。
これを避けるには、 -r オプションを使う。
xargs -r <command>
上の例だと次のようにすればよい。
find . -type f | xargs -r wc -c
– ulimit -s で得られる、スタックの限界サイズを超えた場合、最初の代入を行った時点で Segumentation Fault (core dumped) になる。
例えば、
$ ulimit -s
65536
の時、次のようなコードで発生する。
/* オプティマイズされると処理がなくなるため、
* gcc -O0 を付けてコンパイルすること。
*/
int main(int argc, char* argv[]){
char ac[64 * 1024 * 1024];
ac[0] = ‘\0’; // ここで発生
return 0;
}
対策は、
ulimit -s [limit]
で十分なスタックサイズを確保することを許可すればよい。