カテゴリー別アーカイブ: linux

穏やかな速度でファイルを削除するプログラム gentle_unlink を書いた

おがた (@xtetsuji) です。

Linux サーバ上で作業をしていると、様々な一時ファイルがディスクを圧迫していて、ディスク容量を増やすために削除を行うことがあります。通常であれば rm コマンド一発で終わる単純なファイル操作ですが、ファイルが何百万やそれ以上といったオーダーで大量にあると、削除自体のコストが無視できなくなります。

Linux サーバ管理者の間ではたびたび問題になる大量ファイルの削除操作、各人コマンドを組み合わせて工夫しているようですが、より微調整をしたかった私は Perl を使ってコマンドを書くことにしました。その名も gentle_unlink。

最近はITエンジニアリングネタは Qiita に書くことが多いのですが、自分が書いたまとまったプログラムの紹介ということで、メインブログに書いてみることにしました。

初出の社内勉強会での紹介トーク、そしてスクリプトファイルは以下のリンクからどうぞ。

続きを読む

livedoorドメインでダイナミックDNSするためのメモ

おがた (@xtetsuji) です。

  • 2015/05/22追記:livedoorドメインのシステム切り替えに伴い2015年6月12日以降、ダイナミックDNSは使えなくなるらしいです

個人的なドメイン名登録サービスは「livedoorドメイン」と「お名前.com」の2つを使っています。最初は livedoorドメイン だけだったのですが、その後そこで登録できないドメインをお名前.comで登録することになり、2つを併用しています。

お名前.com にはダイナミックDNSサービスがありますが、ヘルプを見てもWindowsクライアントしかないようです。以前GMOに問い合わせたことがあったのですが、Windows以外でオープンなAPIを叩いて更新する公式の方法というものは無いようです。

個人的なサーバでダイナミックDNSサーバを構築して運用するのも面倒なので、ここは livedoor ドメイン のダイナミックDNS機能をありがたく使わさせて頂いています。

続きを読む

WordPressで新規投稿ができなくなった原因がプラグインだった

おがた (@xtetsuji) です。

このブログ、2013年の夏から自分で契約したVPSにWordPressを入れて運用しているのですが、2013年の11月頃から新規投稿ができなくなってしまいました。新規投稿URL wp-admin/post-new.php にアクセスすると画面真っ白。個々のブログの画面表示も重くなった感じ。複数の投稿をDBから引っ張ってくるだろうトップページもまた画面真っ白という状況。

何が悪いのか原因を調査してもよく分からず。閲覧は重いながらもできたので、しばらく放置していました。

最近コメントスパム爆撃を受けた

結果的にこれは直接の関係は無かったのですが、2013年11月に大規模にコメントスパム爆撃をくらって、サーバがたびたび無反応になるケースが増えてきました。VPSのバーチャルシリアルコンソールでもログインができず、OOM (Out of Memory) Killer によってApacheがkillされる光景だけが見えるというもの。

Apacheのprefork MPMとmod_phpでPHP運用するケースは多いと思いますが、prefork MPM のパラメータ調整をしておかないと、Apacheの子プロセスのメモリサイズが増え続けることがあるので注意したいところです。

<IfModule mpm_prefork_module>
    StartServers             5
    MinSpareServers          5
    #MaxSpareServers         10
    MaxSpareServers         15
    #MaxClients             150
    MaxClients              50
    MaxRequestsPerChild    500
</IfModule>

Debianのパッケージの素で入れたApache2とprefork MPM (libapache2-mpm-prefork) の場合、MaxRequestsPerChild が0になっています。これは「子プロセスはどんなにリクエストを受けても刷新されない」という意味。

PHPも大きなファイルを扱ったりやコメントスパムなどの大量爆撃を受けたりすると、解放されないメモリが出てきたりします。PHP、すなわちmod_phpとApacheは渾然一体なので、これはApacheの子プロセスのメモリサイズが肥大化していく事を意味します。

だいたい、サーバでApacheが使える合計メモリサイズを計算し、だいたい1プロセス辺りに期待する最大プロセスサイズを割った数くらいをMaxSpareServersに設定するとよいでしょう。

「Apacheの子プロセスが実際にこれだけのサイズになったら自動的に終了(child terminate)してほしい」という要求はPHPでも出来るとは思うのですが、私はあまりPHPに詳しくないPerlプログラマだったので、mod_perl2のApache2::SizeLimitというモジュールで行いました。Debianであればmod_perl2 (libapache2-mod-perl2) を入れておけば使えるようになるでしょう。

mod_perl2を有効にして (Debian であれば sudo a2enmod perl として Apache を再起動すれば良い) 以下の記述を Apache の設定ファイル (Debian であれば apache2.conf) に書いて再起動して反映すればよいです。

<Perl>
use Apache2::SizeLimit;
# sizes are in KB
$Apache2::SizeLimit::MAX_PROCESS_SIZE  = 12000; # 12MB
$Apache2::SizeLimit::MIN_SHARE_SIZE    = 6000;  # 6MB
$Apache2::SizeLimit::MAX_UNSHARED_SIZE = 5000;  # 5MB
</Perl>
PerlCleanupHandler Apache2::SizeLimit

使用できるメモリを確認する

ネットを検索すると、特にレンタルサーバでは使用できるメモリ容量に制限があることで画面真っ白現象に見舞われることがあるとのことでした。

対処法としては

  • wp-config.php に define(‘WP_MEMORY_LIMIT’, ’64M’); と書く
  • .htaccess か ApacheのVirtualHostの設定ファイルに php_value memory_limit 64M と書く
  • php.ini に memory_limit = 64M と書く

などといった解決方法が見つかりました。ただ、Debian wheezy の標準の PHP では既にphp.iniで64MBになっているようで、あまりこの部分は関係ないと思われます。

デバッグモードにする

手がかりを得るために、WordPressにあるデバッグモードをオンにしました。

具体的には wp-config.php にある以下の false を true にすること。PHPファイルは都度読み込まれるのでApacheの再起動などは必要ありません。

define('WP_DEBUG', false);

これでブラウザの画面やApacheのエラーログに情報が出力されるようになります。

ただ、これで得られたのは「GoogleアナリティクスのプラグインがWordPressの変数を再定義している」というNoticeくらい。Noticeなので大した影響もないわけで、途方にくれました。

チャット(Yancha)で聴いてみたら「プラグイン、テンプレート、これらが怪しい」ということで、最近入れたプラグインを無効化して一つ一つ試していくことにしました。

そうしたところ、数回のアクセスで以下のような出力を得ることができました。

PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 12565 bytes) in /var/www/sites/post.tetsuji.jp/wp-content/plugins/crayon-syntax-highlighter/crayon_wp.class.php on line 261

私の場合、Crayon Syntax Highlighterというプラグインがメモリをバカ食いしていたようです。何かのサイトでシンタックスハイライトの便利なプラグインとして紹介されていたので導入したのは10月頃だった気がするのですが、これを無効化したところ、wp-admin/post-new.php で新規投稿もできるようになり、トップページの表示も非常に早くなりました。

このプラグイン、もともと動作が遅いことで有名なようで、検索してみると色々な情報がひっかかりました。設定を改善することで多少は速くなるのかもしれません。

WordPressでトラブルにあったら

まずは落ち着いて WP_DEBUG を true にしてデバッグ出力を観察。

今まで出来ていたことが出来なくなった系は、大抵は最近入れたプラグインかテンプレートに起因すると見て良いので、デバッグ出力を観察しながら確認。

参考サイト

様々なサイトを参考にさせていただきましたが、一部を列挙します。

結論

自分でブログを運用するのは、安価で自由度が高い反面、トラブルに会うと自分で解決しなきゃならないので、面倒なことを経験したくない人は、多少課金してでも商用のブログサイトを使いましょう

シンタックスハイライトについては、最近ではGistが標準となっているので、Gistに投稿したうえでそれを埋め込むというのが速度的には有利かもしれません。Gist埋め込みはEmbed GitHub Gistというプラグインを使っています。これに関しては特に問題は起こっていません。

Crayon Syntax Highlighterはとにかく重い。また、投稿画面の拡張も行うので、投稿画面 (post-new.php) にもその影響が波及することになります(これは正直わからなかった)。またサイト全体も目に見えて重くなります。コメントスパム等の絨毯爆撃を食らうとさらに深刻なことになるわけです。ただ設定で回避できるという話もあるので、試してみるのは悪くないかもしれません。

コミュニティは素晴らしい。実際に質問できる人がいる。これ以上に心強いものはありません。みなさんも私が通っている勉強会にいらっしゃいませんか?

月末やうるう年を判定して実行するかどうかcronで条件分岐

うるう年にブログを更新するのがアツいという世間の流行に乗せられている おがた です。

特にネタは無いなぁと思いつつ、お仕事からうるう年っぽいネタを出してみます。

シェルスクリプトを「月末に実行する」「毎月29日に実行するけど、うるう年ではない2月の場合は3月1日に実行する」といった要請があって、cronの日付指定だと難しいケースがあります。

そういう時に、月末やうるう年を判定して、それをステータスコードを返して “&&” や “||” で後続のコマンドを実行するかしないか判定するコマンド “end-of-month.sh” と “leap-year.sh” というシェルスクリプトを作ってみました。

#!/bin/bash
# Usage:
#   # crontab: need to run some-command at end-of-month.
#   0 15 28-31 * * end-of-month.sh && some-command

set -o errexit

arg=$1
if [ $(date +%m -d "$arg tomorrow" ) != $(date +%m -d "$arg" ) ] ; then
    exit 0;
else
    exit 1;
fi
#!/bin/bash
# Usage:
#   # crontab: need to run some-command at leap-year or not it.
#   5 18  1 3 * * leap-year.sh || some-command
#   5 18 29 2 * * some-command

set -o errexit

arg=$1
if [ "$arg" ] ; then
    year=$arg
else
    year=$( date +%Y )
fi

if [ $(( $year % 4 )) = 0 ] ; then
    if [ $(( $year % 100 )) = 0 ] ; then
	if [ $(( $year % 400 )) = 0 ] ; then
	    exit 0
	else
	    exit 1
	fi
    else
	exit 0
    fi
else
    exit 1
fi

使い方はソースコードに書いてある通りです。

2月29日中にブログを更新したくて、中野の地下の飲み屋でビールを飲んでおでんを食べながらのブログ更新です。本当なら今日は健康診断だったので、バリウムの都合でアルコールは飲まないようにと言われているのですが。まぁ一杯だけ…。お店の良い雰囲気の中、3月を迎えることになりそうです。でも健康的になるべく早く帰って就寝する予定です。