Archive for the ‘開発’ Category
shのwhileループでファイルを読み、中でsshを実行すると1回しかループしない
シェル(sh)スクリプトネタ。
while 文で以下のように指定すると、行ごとにファイルを読み込むことができる。
#!/bin/sh # ファイルを1行ずつ読み込んで表示 TESTFILE=./hoge.txt while read line do echo $line done < $TESTFILE
しかし、 while ループの中で ssh や rsh を実行すると、読み込むファイルが複数行あっても、1行目しか処理されない。
#!/bin/sh # TESTFILEが複数行あっても1行目のみ処理されてループ終了 while read line do ssh 192.168.0.1 touch $line done < $TESTFILE
SSH を実行すると、標準入力がそちらに振り向けられるため、read で読んだ1行のみならず、ファイル全体が SSH に渡されてしまう。従って、SSH を実行した後はもう読める行がないので while ループは1回で終了してしまう。
これを防ぐには、ssh に -n オプションを付け、/dev/null をリダイレクトし、標準入力をリダイレクトしないようにする。
#!/bin/sh # TESTFILEが複数行あればその行数分処理が実行される while read line do ssh -n 192.168.0.1 touch $line done < $TESTFILE
なおこれは rsh コマンドでも同じ仕様になっているようだ。
なぜ1行目だけで終わってしまうのか分からずうんうんうなってたら、この本に書いてあった。
ディレクトリをディレクトリにマウント
Linuxで、ディスクデバイスではなく、ディレクトリをディレクトリにマウントしたい時は
mount --bind マウントしたいディレクトリ マウントポイント
fstabに書いてしまうときは以下のように書く。
マウントしたいディレクトリ マウントポイント none bind 0 0
例えば /home を /hoge/home としてマウントしたい時は
/home /hoge/home none bind 0 0
なお、マウントしたいディレクトリ(上の例では/hoge)よりも後にこの行を書かないと、マウントできないので注意。
sarコマンドでシステムのボトルネックを探る(2)
CPUの処理の状況を調べるためには、sar (sar -u)が有効であることを前のエントリで書いた。次はメモリの使用状況を調べてみる。まず見てみるのは、メモリとスワップの使用状況を示す sar -r の結果である。
[doublemarket@hoge ~]$ sar -r Linux 2.6.18-194.8.1.el5 (hoge) 2011年02月15日 00時00分01秒 kbmemfree kbmemused %memused kbbuffers kbcached kbswpfree kbswpused %swpused kbswpcad 00時10分01秒 12964 497568 97.46 30880 107440 1984336 63940 3.12 16392 00時20分01秒 13064 497468 97.44 30972 107376 1984336 63940 3.12 16392 00時30分01秒 12692 497840 97.51 31092 107236 1984336 63940 3.12 16392 : : 20時20分01秒 43756 466776 91.43 45624 139552 1984336 63940 3.12 16288 20時30分01秒 27008 483524 94.71 46420 147608 1984336 63940 3.12 16288 20時40分01秒 22664 487868 95.56 46840 148920 1984336 63940 3.12 16288 20時50分01秒 22300 488232 95.63 47192 148968 1984336 63940 3.12 16288 平均値: 84267 426265 83.49 32592 129944 1984336 63940 3.12 16300
それぞれの列の意味は以下の通り。
- kbmemfree
- 物理メモリの未使用KB。
- kbmemused
- 物理メモリの使用済みKB。
- %memused
- 物理メモリの使用率。Linuxでは、使用されていないメモリ領域をファイルシステムキャッシュ領域として使用するので、通常はほとんどfree部分はないものと考えてよい。従って、常に90数%といった高い使用率になる。実際にアプリケーションの動作に使われているメモリの量は、下の指標を確認する必要がある。
- kbbuffers
- カーネルがバッファ領域として使用しているメモリ量のKB。
- kbcached
- カーネルがキャッシュとして使用しているメモリ量のKB。kbmemusedからkbbufferesとkbcachedを引いた値が、実際にアプリケーションに割り当てられているメモリ量ということになる。逆に言えば、kbbufferesとkbcachedの容量が、kbmemusedの大部分を占めているようなら、アプリケーションにとってメモリ不足とは言えないということになる。
- kbswpfree
- スワップ領域の未使用量KB。
- kbswpused
- スワップ領域の使用済みKB。
- %swpused
- スワップ領域の使用量。通常ほとんど0だが、物理メモリが不足してくると使用率が上がってくる。数%であれば実質的にシステムの動作には影響がない場合が多いが、あまり多いようだと、スワップ領域へのアクセスが頻発している可能性もあり、システム全体のスループットを落とすことがある。%swpusedが大きく、かつsar -uのiowaitの値も大きい場合、ほぼ間違いなくスワップ領域へのアクセスでスローダウンしているので、物理メモリの増設などのメモリ不足解消策を取る必要がある。
- kbswpcad
- 何の指標かよく分からなかったが、manページによると、一旦スワップ領域へ飛ばされたものの(スワップアウト)、スワップ領域からメモリに戻され(スワップイン)、かつまだスワップ領域にデータが残っている、というデータの量とのこと。
各列の値の傾向を見ると、上記のようにメモリ不足なのかどうかの手がかりが得られる。その他に詳しい情報を見たいときは、以下のオプションも用意されている。
- sar -R
- メモリ上のページの使用状況。
- sar -W
- スワップの発生状況。ページイン(スワップ領域から物理メモリへのページの移動)とページアウト(物理メモリからスワップ領域へのページの移動)がどの程度発生したのかを確認できる。
- sar -B
- ページングの状況。ページイン・ページアウトされたデータ容量、ページフォルトの回数、メジャーなページフォルトの回数をそれぞれ確認できる。
sarコマンドでシステムのボトルネックを探る(1)
前回のエントリでは、システムのレスポンスが悪化している場合、まずとっかかりとしてtopコマンドを実行し、ロードアベレージを確認する方法を書いた。さらに踏み込んで、何が負荷の原因なのかを探るために、sarコマンドを使う方法について書く。
sarコマンドをオプションをつけずに実行すると、以下のような出力が得られる。ファイルを指定しないと、コマンドを実行した当日の0:00から直前までの10分おきの情報が表示される。過去の情報は/var/log/saディレクトリ以下に保存されており、「sar -f sa07」などと指定すると、そのファイルに保存された情報が閲覧できる。saの後の数字は日付を表している。
sarを実行してもコマンドが見つからない場合、sysstatパッケージがインストールされていないので、インストールすべし。
[doublemarket@hoge ~]$ sar Linux 2.6.18-194.8.1.el5 (hoge) 2011年02月15日 00時00分01秒 CPU %user %nice %system %iowait %steal %idle 00時10分01秒 all 0.05 0.00 0.08 0.02 0.00 99.85 00時20分01秒 all 0.03 0.00 0.08 0.02 0.00 99.88 00時30分01秒 all 0.07 0.00 0.11 0.02 0.00 99.79 : : 20時00分01秒 all 0.03 0.00 0.06 0.00 0.00 99.90 20時10分01秒 all 0.06 0.00 0.11 0.03 0.00 99.80 20時20分01秒 all 0.16 0.00 0.14 0.03 0.00 99.67 20時30分01秒 all 1.11 0.00 0.27 0.12 0.00 98.50 20時40分01秒 all 0.08 0.00 0.12 0.05 0.00 99.76 平均値: all 0.08 0.00 0.10 0.09 0.00 99.73
ここで得られる結果は、sar -uと同じものである。それぞれの列の意味は以下の通り。
- user
- ユーザプログラムの実行に使用されたCPUリソースの割合
- nice
- niceによる優先度を処理するために使用されたCPUリソースの割合
- system
- カーネルが使用したCPUリソースの割合
- iowait
- I/O待ちの割合
- idle
- I/O待ち以外でCPUが待ち状態だった割合(何もしていない時間)
なお、マルチCPUの環境の場合ここに表示されているのは、全CPUの合算使用率になっている。それぞれのCPUの使用率を確認したい場合、「sar -P ALL」を実行する。意外と処理が特定のCPUに偏っていたりするので、こちらも確認してみた方がよい。
→ sarコマンドの実行結果からシステムの負荷状況に関して、以下の傾向がつかめる。
- userの値だけが高い(他の値は低いまま)
- CPUリソースを必要とするアプリケーションが動作している。
topやps auwxなどのコマンドでプロセスごとのCPU使用率を調べ、無限ループなどの不具合によるCPU使用率の上昇でないかなど、異常を確認。単に処理が重くなっているだけなら、スケールアップ(CPUを高速化)、スケールアウト(マシンを増設)を検討する。 - iowaitの値が高い
- そのマシンに求められる処理に対して、ハードディスクの速度が追いついていない。アプリケーションやミドルウェア(特にデータベースなど)のキャッシュの仕組みを見直したり、読み書きに使う物理的なディスクを分散させるなどして、なるべくディスクの読み書きが発生しない方法を考える。それでも高いままなら、より高速なディスクを使うしかない。なおたいていの場合は
・アプリケーション自体がディスクにアクセスする速度が遅い
・メモリが不足していてスワップ領域(つまりディスク)へのアクセスが頻発していて遅い
の2つに問題を分けることができる。このうちのどちらかという判断は、sar -rの結果などを見る必要がある。 - systemの値が高い
- 仕組み的にいえば、コンテキストスイッチがたくさん発生していると値が上がるはずなので、必要以上にたくさんのプログラムを並列に処理しすぎていると、この値が異常に上がるということになるが、よく分からない。
sarコマンドには、メモリやディスク、ネットワークなどに関する情報が得られるよう、他にも色々なオプションがある。
topコマンドでロードアベレージを見る
Linuxにおいて、システムの全体的な負荷状況を知りたい時、リアルタイムの状況を知るにはtopコマンド、ある程度の期間に渡る傾向をつかむにはsar(sysstat)の結果を確認するのが一般的だろう。
そのサーバ上で動作するアプリケーションの動作が遅いなどといったパフォーマンス劣化がある時、まず最初に見るべきがロードアベレージの値。これは「CPUの処理を待っているタスクの数」であり、ほとんど何も処理を行っていない時には0になる。
topコマンドの表示内容
top - 16:04:44 up 15 days, 21:40, 2 users, load average: 0.00, 0.00, 0.00 Tasks: 108 total, 2 running, 105 sleeping, 0 stopped, 1 zombie Cpu(s): 0.0% us, 0.0% sy, 0.0% ni, 100.0% id, 0.0% wa, 0.0% hi, 0.0% si Mem: 8113608k total, 8082584k used, 31024k free, 69652k buffers Swap: 8385920k total, 352k used, 8385568k free, 6008888k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 16 0 1848 552 472 S 0.0 0.0 0:01.32 init 2 root RT 0 0 0 0 S 0.0 0.0 0:17.52 migration/0 3 root 34 19 0 0 0 S 0.0 0.0 0:00.40 ksoftirqd/0 4 root RT 0 0 0 0 S 0.0 0.0 0:15.31 migration/1 5 root 34 19 0 0 0 S 0.0 0.0 0:00.32 ksoftirqd/1 6 root RT 0 0 0 0 S 0.0 0.0 0:11.21 migration/2 7 root 34 19 0 0 0 S 0.0 0.0 0:00.17 ksoftirqd/2 8 root RT 0 0 0 0 S 0.0 0.0 0:15.26 migration/3 9 root 34 19 0 0 0 S 0.0 0.0 0:00.25 ksoftirqd/3 10 root 5 -10 0 0 0 S 0.0 0.0 0:00.00 events/0 11 root 5 -10 0 0 0 S 0.0 0.0 0:00.00 events/1 12 root 5 -10 0 0 0 S 0.0 0.0 0:00.00 events/2 13 root 5 -10 0 0 0 S 0.0 0.0 0:00.00 events/3 14 root 7 -10 0 0 0 S 0.0 0.0 0:00.00 khelper 15 root 15 -10 0 0 0 S 0.0 0.0 0:00.00 kacpid 95 root 5 -10 0 0 0 S 0.0 0.0 0:00.00 kblockd/0 96 root 5 -10 0 0 0 S 0.0 0.0 0:00.00 kblockd/1
1行目の右端に表示されているのがロードアベレージの値。前述の通りCPUの処理を待っているタスクの数がロードアベレージなので、値が大きければ大きいほどCPUの処理を待っているタスクが多いということになり、それだけサーバのレスポンスが落ちることになる。ただし、単に計算を待っているだけではなく、IOの処理を待っている場合もこの値が大きくなるので、ロードアベレージが大きいことが即CPUが遅いことになるわけではない。CPUそのもの、メモリ、ディスク、それ以外、の何が原因で遅いか調査する必要がある。
なお、topでのロードアベレージの表示は、左から、1分、5分、15分間の平均値になっている。つまり、左の方が値が大きければ、直近の数分間で急に負荷が上がっていることを表す。
言わずもがなだが下半分には、CPUの使用率順に並んだプロセス一覧が表示されるので、ここからCPU負荷が高かったりメモリの使用量が多いアプリケーションが何なのかは大体つかめる。topからなんとなくのあたりをつけたあと、何がボトルネックになっているかを探すには、sarコマンドで過去のパフォーマンスデータを確認していく。
logrotateのローテート世代数を減らす時の注意
本当は「山に行きました!」というブログを投稿したいところなのだが、さっぱり行ける雰囲気がないので、腹いせに技術系の投稿を続けてる。
logrotateを使ってログのローテートを行っている状況で、ログファイルの総容量が大きくなり、世代数を減らさざるを得ないときのこと。「rotate 世代数」の指定を減らしても、古い世代数は削除されない。
具体的には、以下の例。当初logrotate.confで以下の設定をしていたとする。
# see "man logrotate" for details # rotate log files daily daily # keep 10 days worth of backlogs rotate 10 # create new (empty) log files after rotating old ones create # uncomment this if you want your log files compressed #compress # RPM packages drop log rotation information into this directory include /etc/logrotate.d
この場合、1日1回ローテートされたファイルが10回分保存される。例えば以下のように。
ls -v /var/log/httpd/access_log* access_log access_log.4 access_log.8 access_log.1 access_log.5 access_log.9 access_log.2 access_log.6 access_log.10 access_log.3 access_log.7
ここで、アクセスログ1ファイルずつの容量が増えてきて、ディスク空き容量が減ってきた場合、保存する世代数を減らして対処する場合、「rotate 世代数」の世代数を減らしても、古い世代が一斉に削除されるわけではない。
rotate 5とした場合、次のローテート後には以下のようになる。
access_log access_log.4 access_log.9 access_log.1 access_log.5 access_log.10 access_log.2 access_log.7 access_log.3 access_log.8
つまり、6世代目が消えるだけで、7世代目以降は自動的には削除されないため、手動で削除する必要がある。
これだけ。これが分からなくて危なくディスク使用率が100%になるところだった。
さくらVPSのCentOSにsymfony 1.4.xの環境を構築する
自分でWebサービスを作ってみようと思い立ってsymfonyを勉強し始めて数ヶ月。
しばらく前の話だが、借りていたサーバの使用期限が終わってしまったので、さくらVPSを契約。そこにsymfony 1.4.x(1.4.8)をインストールするときの手順をまとめておく。特にさくらVPSに特化した内容はないので、普通にCentOS上にsymfony 1.4をインストールする手順と同じのはず。
<事前準備・参考>
以下のサイトを参考にして、不要なパッケージの削除、サービス停止、ファイアウォールやSSHなど、基本的なインターネット公開サーバの設定を済ませておく。
http://tanaka.sakura.ad.jp/archives/001065.html
http://www.ideaxidea.com/archives/2010/11/sakura_vps_settings.html
<PHP5.3を配布しているremiリポジトリを有効にする>
このブログ執筆時点のさくらVPSのデフォルトOSはCentOS 5.5(x86_64)だが、これには
PHP5.1.6が含まれており、symfony 1.4.xが動作しないので、最新版5.3をインストール。
PHP5.3のRPMパッケージはremiというリポジトリから配布されているので、yumのリポジトリに設定を追加。
# rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm # rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
<PHP5.3インストール>
# yum install --enablerepo=remi php php-domxml php-devel php-mysql
php.iniに以下を追記。追記しないとdate()の使用で警告が出る。
date.timezone = "Asia/Tokyo"
mb_string関連の関数を使用するために必要なのでphp-mbstringもインストール。
# yum install --enablerepo=remi php-mbstring
コンソールで文字を色付けするのに必要なのでphp-processもインストール。
# yum install --enablerepo=remi php-process
symfonyで必要なものがそろっているか確認するスクリプトを実行。
# wget http://sf-to.org/1.4/check.php # php check_configuration.php ******************************** * * * symfony requirements check * * * ******************************** php.ini used by PHP: /etc/php.ini ** WARNING ** * The PHP CLI can use a different php.ini file * than the one used with your web server. * If this is the case, please launch this * utility from your web server. ** WARNING ** ** Mandatory requirements ** OK PHP version is at least 5.2.4 (5.3.3) ** Optional checks ** OK PDO is installed OK PDO has some drivers installed: mysql, sqlite, sqlite2 OK PHP-XML module is installed OK XSL module is installed OK The token_get_all() function is available OK The mb_strlen() function is available OK The iconv() function is available OK The utf8_decode() is available OK The posix_isatty() is available [[WARNING]] A PHP accelerator is installed: FAILED *** Install a PHP accelerator like APC (highly recommended) *** OK php.ini has short_open_tag set to off OK php.ini has magic_quotes_gpc set to off OK php.ini has register_globals set to off OK php.ini has session.auto_start set to off OK PHP version is not 5.2.9
<pearインストール>
※ pearでのインストールは推奨されていないが、簡単なのでこれで済ませる
# yum install --enablerepo=remi php-pear # pear upgrade-all
<symfonyインストール>
# pear channel-discover pear.symfony-project.com # pear install symfony/symfony
以下のコマンドでバージョンが表示されたらインストール成功。
# symfony -V symfony version 1.4.8 (/usr/share/pear/symfony)
/usr/share/pear/symfonyにインストールされる
<APCインストール>
PHPのアクセラレータであるAPCをインストールしておく。入れなくても動作するが、symfonyでは導入が推奨されているのと、入れただけで高速になるとのことなのでインストール。
# yum install httpd-devel # yum install --enablerepo=remi php-pecl-apc
<httpd起動>
# chkconfig httpd on Syntax OK # service httpd start
ブラウザから http://(サーバのIPアドレス)/ を確認し、phpinfoでapcが読み込まれていることを確認。
※ phpinfoはコマンドラインから以下を実行しても確認できる
php 'phpinfo();'
<MySQLインストール>
# yum install --enablerepo=remi mysql-server
<MySQL設定>
my.cnfに以下を追記して文字コードをUTF-8に
[mysqld] default-character-set=utf8 character_set_server=utf8 skip-character-set-client-handshake [mysql] default-character-set=utf8
statusコマンドおよび”show variables like ‘char%’;”でUTF-8になっていることを確認(過去エントリも参照)
パスワードを設定
# mysqladmin -u root password パスワード
データベース作成
# mysql -uroot -p mysql> create database データベース名;
<postfixインストール>
# yum remove sendmail # yum install postfix
/etc/postfix/main.cf を編集
# chkconfig postfix on # service postfix start
メール送信のテスト
# mail -s test あて先
※ 本登録前のお試し期間中はOP25Bが有効なので、VPS上のサーバからメールを送信することはできない
CentOS 5.5にsphinxをインストール
2/12のSphinx翻訳ハッカソンに行ってSymfony2のドキュメントの翻訳をさせていただこうと思っていたら、このところどっぷりはまっている仕事の方で呼び出されることになり、参加できなくなってしまった。予習として手元の環境にSphinxをインストールしたときのメモを残しておく。
といっても、パッケージ管理ツールを駆使(?)してあっという間。Sphinxのユーザ会のページには、MacOS XとUbuntuへのインストール方法は書いてあるが、CentOSへのインストール方法は書かれていないので、一応メモ。
yumでpythonのパッケージ管理ツールであるpipをインストール
[root@hoge ~]# yum install python-pip python-setuptools
pipでsphinxをインストール。現状では1.0.7がインストールされるようだ。
[root@hoge ~]# pip-python install sphinx
Downloading/unpacking sphinx
Downloading Sphinx-1.0.7.tar.gz (2.3Mb): 2.3Mb downloaded
Running setup.py egg_info for package sphinx
no previously-included directories found matching ‘doc/_build’
Downloading/unpacking Pygments>=0.8 (from sphinx)
Downloading Pygments-1.4.tar.gz (3.5Mb): 3.5Mb downloaded
Running setup.py egg_info for package Pygments
Downloading/unpacking Jinja2>=2.2 (from sphinx)
Downloading Jinja2-2.5.5.tar.gz (438Kb): 438Kb downloaded
(中略)
Installing sphinx-build script to /usr/bin
Installing sphinx-quickstart script to /usr/bin
Installing sphinx-autogen script to /usr/bin
Successfully installed docutils Jinja2 Pygments sphinx
Cleaning up…
[root@hoge ~]#
Sphinxユーザ会の「Sphinxをはじめよう」を見て、「プロジェクトの作成」まではあっさり完了。
yumでもsphinx(パッケージ名はpython-sphinx)をインストールできるが、@hidenorigotoさんのアドバイスで、pipを使ったインストール方法があることを知った。ありがとうございます。
2011年3月13日追記
epelリポジトリを有効にしていたからyumだけでインストールできた模様。epelリポジトリを追加していない場合は以下のコマンドで追加。
rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/5/i386/epel-release-5-4.noarch.rpm
※ パスの中で「5-4」はepelのバージョンによって変わる。
vjCommentPluginで色々はまる
symfonyでニュースの記事などにコメント欄を付けるプラグインとして、vjCommentPluginというのがある。これの設定でちょっとはまったので、メモ。
インストールや設定はReadmeに書いてある通りで、簡単。ログインしないとコメントできないようにするため、sfGuardPluginと連携させる機能が追加されているのだが、これが癖者。この機能を使うときには、app.ymlに以下の表記を追記する。
all:
vjCommentPlugin:
guardbind: true
restricted: true
Readmeには、frontend/config/app.ymlを編集しろと書いてあるのだが、これだとコメントを保存するテーブルの中身が、ログインしないとコメントできないように書き換わってくれない。plugin/vjCommentPlugin/config/app.ymlを上の通り編集する必要がある。
また、この状態で symfony doctrine:build すると、以下のエラーが出る。
SQLSTATE[HY000]: General error: 1005 Can’t create table ‘pjtransrate.#sql-15f0_b9′ (errno: 150). Failing Query: “ALTER TABLE comment ADD CONSTRAINT comment_user_id_sf_guard_user_id FOREIGN KEY (user_id) REFERENCES sf_guard_user(id)”. Failing Query: ALTER TABLE comment ADD CONSTRAINT comment_user_id_sf_guard_user_id FOREIGN KEY (user_id) REFERENCES sf_guard_user(id)
これは、sfGuardUserテーブルでは id (ユーザのID)を integer で定義しているのに、commentテーブル(コメントを保存するテーブル)の user_id は integer(4) で定義されており、その間にrelationを張ろうとしているためエラーになっているようだ。
参考 : http://d.hatena.ne.jp/zankey/20070411/mysql
plugins/vjCommentPlugin/config/doctrine/schema.yml の comment テーブルの user_id の type を integer に変更して、再度 doctrine:build するとうまくいく。
Subversionリポジトリへコミットするときの405エラー
Subversionリポジトリへうまくコミットできないときがたまにあるので、メモ。
commit -m “あれこれ変更” -N (32 paths specified)Sending C:/Users/hoge/project/apps/frontend/modules/article/templates/indexSuccess.php(中略)Adding C:/Users/hoge/project/cache/frontend/dev/templateRA layer request failedsvn: Commit failed (details follow):svn: Server sent unexpected return value (405 Method Not Allowed) in response to MKCOL request for ‘/svn/pjtransrate/!svn/wrk/be91e174-dd4b-124f-abbd-dd57636aa9ad/trunk/cache/frontend/dev/template’
Twitter
FourSquare