<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>igreks開発日記</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/" />
    <link rel="self" type="application/atom+xml" href="http://www.igreks.jp/dev/atom.xml" />
    <id>tag:www.igreks.jp,2008-11-14:/dev//1</id>
    <updated>2012-01-31T15:06:59Z</updated>
    <subtitle>サーバ構築、WEBプログラミング、アフィリエイト、その他試行錯誤の履歴</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.22-ja</generator>

<entry>
    <title>perlで現在のフルパス（URL）のディレクトリ名までを取得</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2012/01/perlurl.html" />
    <id>tag:www.igreks.jp,2012:/dev//1.6158</id>

    <published>2012-01-31T14:54:59Z</published>
    <updated>2012-01-31T15:06:59Z</updated>

    <summary>良く使うんだがすぐに忘れるのでメモ。 use CGI; my $F = CGI-...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[良く使うんだがすぐに忘れるのでメモ。<br />
<br />
use CGI;<br />
my $F = CGI->new();<br />
my $dir = $F->url;<br />
$dir =~ s/[\/][^\/]*$//g;<br />
<br />
<br />
]]>
        
    </content>
</entry>

<entry>
    <title>Lost connection to MySQL server during query 対策</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2012/01/lost-connection-to-mysql-server-during-query.html" />
    <id>tag:www.igreks.jp,2012:/dev//1.6157</id>

    <published>2012-01-31T14:39:36Z</published>
    <updated>2012-01-31T14:52:05Z</updated>

    <summary>たま～にforkして子プロセスを起動する処理を呼んだとき、親プロセスで上記の「L...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="MilkyStep" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MySQL" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[たま～にforkして子プロセスを起動する処理を呼んだとき、親プロセスで上記の「Lost connection to MySQL server during query」エラーや、httpヘッダエラーが発生していた。<br />
<br />
特に決済まわりで使っているわけでもないし、トランザクションが絶対必要なわけでもないし、子プロセス内の処理はとりあえず最後まで完了してるし、いままで「ま、いっか」って感じで放置していたが、最近頻発するようになってきたので、ようやく真面目に取り組んでみる。<br />
<br />
DBIに接続したときのステートメントハンドルの扱い方が悪いんじゃないかっていいうのはうすうす気づいてたが、下記のような資料を発見。ありがたや。<br />
<a href="http://d.hatena.ne.jp/hiratara/20110122/1295711939">http://d.hatena.ne.jp/hiratara/20110122/1295711939</a><br />
<a href="http://nihen.hatenablog.com/entry/2011/11/17/102557">http://nihen.hatenablog.com/entry/2011/11/17/102557</a><br />
<br />
<br />
これの真似して、子プロセス生成直後に<br />
$dbh->{InactiveDestroy} = 1;<br />
$dbh = $dbh->clone({InactiveDestroy => 0});<br />
を呼んだらなんとあっさり解決。<br />
<br />
以前にこんなこと↓<br />
<a href="http://www.igreks.jp/dev/2010/06/forkmysql.html">http://www.igreks.jp/dev/2010/06/forkmysql.html</a><br />
書いてたけど、やっぱ親プロセスと同じコネクションつかっちゃまずいわけね。<br />
Apacheのせいにしてごめんなさいって感じですね。<br />
<br />
<br />
]]>
        
    </content>
</entry>

<entry>
    <title>WordPressをトップページにしている場合の他コンテンツへのアクセス障害の対策</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2012/01/wordpress.html" />
    <id>tag:www.igreks.jp,2012:/dev//1.6075</id>

    <published>2012-01-18T09:11:12Z</published>
    <updated>2012-01-18T10:46:05Z</updated>

    <summary>久々の更新。 最近、WordPressのindexを自分のドメインのトップページ...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="apache" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[久々の更新。<br />
<br />
最近、WordPressのindexを自分のドメインのトップページに設定している人が増えてきている模様？<br />
<br />
そういった場合、管理者は、WordPressの構成ファイルをドキュメントルート直下に展開するか、ドキュメントルート直下の.htaccess処理で、WordPressの本体ディレクトリ内のindex.phpにリダイレクトさせる。<br />
もしくは、apacheの設定自体を変えて、ワードプレスの本体ディレクトリ自体をドキュメントルートにしちゃう、<br />
主流はこの3つくらいだろうか。<br />
<br />
<br />
先日MilkyStepの初期設定代行を行おうと思い、VPSのコンパネにアクセスしようと思ったら、いきなりワードプレスのスキンで404エラーが発生。<br />
<br />
ドキュメントルート直下の.htaccessをのぞいてみると、どうやらお客さんの方で追記したと思われる、下記のようなRewriteRuleを発見。<br />
<br />
# BEGIN WordPress<br />
<br />
&lt;IfModule mod_rewrite.c&gt;<br />
RewriteEngine On<br />
RewriteBase /<br />
RewriteRule ^index\.php$ - [L]<br />
RewriteCond %{REQUEST_FILENAME} !-f<br />
RewriteCond %{REQUEST_FILENAME} !-d<br />
RewriteRule . /index.php [L]<br />
&lt;/IfModule&gt;<br />
<br />
# END WordPress<br />
<br />
<br />
ふうむ。<br />
どうやら最近はこういうのが流行っているのだろうか？<br />
<br />
上記の設定だと、下位のファイルを指定せずトップページにアクセスすると、同列に置いてある「index,php」の制御により、ワードプレスのトップが表示される。<br />
下位（ワードプレスディレクトリ内）の実在するファイルにアクセスすれば見れるが、実在しなければ「ありませんよ！」というメッセージ（多分ワードプレスの制御）が出る模様。<br />
<br />
基本的に、RewriteRuleに書かれた以外のコンテンツ（またはそのエイリアス）が存在しない場合、<br />
RewriteCond %{REQUEST_FILENAME} !-f<br />
RewriteCond %{REQUEST_FILENAME} !-d<br />
により、その下の<br />
RewriteRule . /index.php [L]<br />
が実行される。<br />
<br />
ただし、ここで、<br />
RewriteRule . /index.php [L]<br />
となっている。<br />
左辺を見ると、「.」となっているので、「.」（任意の一文字）が合致する名前のコンテンツは、基本的に「すべて」ということになる。<br />
<br />
したがって、<br />
RewriteCond %{REQUEST_FILENAME} !-f<br />
RewriteCond %{REQUEST_FILENAME} !-d<br />
は、基本的にははすべて「偽」となるため、<br />
RewriteRule . /index.php [L]<br />
の処理が実行されないことになる。<br />
（それと、右辺は「/index.php」ではなく「index.php」ではなかろうか？）<br />
<br />
とまあ、こう考えれば、WordPressディレクトリの外のコンテンツにアクセスするにも問題なさそうなのだが、なぜか（ワードプレス内のコンテンツが無いという）404となる。<br />
<br />
多分、それ以前の大元のapacheのルールで、インデックスの指定のルールとかがごっちゃになって、こういう結果的にこうなっている思われる。<br />
<br />
根本的な原因を探すのも面倒だし、もともと書いてあったRewriteRuleを消したりなんかすると、さらに被害が増えそうだ。<br />
<br />
したがって、なるべく既存のコンテンツにあたりさわりなく行う対策としては、アクセスしたい同階層のディレクトリ名が指定された場合は、上記のRewriteRuleが適用されないようにするのが得策と考えた。<br />
<br />
# BEGIN WordPress<br />
<IfModule mod_rewrite.c><br />
RewriteEngine On<br />
RewriteBase /<br />
<br />
# Add -------<br />
RewriteRule ^ControlPanel/* - [L]<br />
RewriteRule ^mysqladmin/* - [L]<br />
RewriteRule ^ms/* - [L]<br />
# ------- Add <br />
<br />
RewriteRule ^index\.php$ - [L]<br />
RewriteCond %{REQUEST_FILENAME} !-f<br />
RewriteCond %{REQUEST_FILENAME} !-d<br />
RewriteRule . /index.php [L]<br />
</IfModule><br />
<br />
# END WordPress<br />
<br />
これで、ControlPanel、mysqladmin、ms　という名前のディレクトリには、<br />
<a href="http://domain.com/ControlPanel/......">http://domain.com/ControlPanel/......</a><br />
<a href="http://domain.com/mysqladmin/......">http://domain.com/mysqladmin/......</a><br />
<a href="http://domain.com/ms/......">http://domain.com/ms/......</a><br />
というURLでそのコンテンツにアクセスできる。<br />
<br />
以上。<br />
]]>
        
    </content>
</entry>

<entry>
    <title>NTT東日本 PR-400NEの不具合？？</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/11/ntt-pr-400ne.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.5754</id>

    <published>2011-11-29T07:56:48Z</published>
    <updated>2011-11-29T08:22:23Z</updated>

    <summary>事業所の移転に伴って、フレッツ光の契約タイプを変更しなくてはいけなかったため、必...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="apache" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[事業所の移転に伴って、フレッツ光の契約タイプを変更しなくてはいけなかったため、必然的に貸与されるルータも、PR200NEからPR400NE（一応最新版らしい）に変更することになった。<br />
<br />
ついでにプロバイダもbiglobeをやめてインターリンクの固定IP付のもっと安いサービスに乗り換えた。<br />
<br />
しかし、ルータが変わってから、LAN内ホストの名前解決（正引き）ができなくなってしまった。<br />
<br />
うちの場合はLAN内のPCからLAN内のサーバにアクセスするとき、内部DNSを構築しているので、ルータの静的NATとサーバ側のファイアウォールを許可すれば、LAN内からでも「ホスト名+ドメイン名」でアクセスできるはず。<br />
<br />
というか、ルータが変わる前は普通にできていた。<br />
<br />
もちろん、「<a href="http://192.168.*.*/:80">http://192.168.*.*/:80</a>」とかやれば、当たり前だが普通にWEBサーバにつないでくれる。<br />
<br />
<br />
ルータのソフトのファームウェアバージョンも前と変わってないし、設定も前とすべて同じにしてあるのに、なぜかLAN内のホストへ正引きできない。<br />
<br />
仕方が無いので、現在はルータの設定で、DNSの問合せ先をすべて192.168.1.4（LAN内のDNSサーバ）に指定している。<br />
こうするとちゃんと正引きしてくれるが、WAN側のホストにアクセスするときも、いちいち内部のDNSサーバに問合せに行くので、名前解決の時間が3秒くらいかかってイライラする。<br />
<br />
確か、前は、ルータのDNS問合せ先を「自動的に取得する」にしておけば、WAN側・LAN側を勝手に判別してWAN側だったらプロバイダのDNSに問合せに行ってくれたと思ったのだが・・・<br />
<br />
ルータ設定画面のメニューで、今まで使ったことがなかった「ローカルドメイン設定」というメニューがあるが、これにローカルドメインを登録しようとしても、バグってるぽくて有効にならない。<br />
<br />
他に移転に伴って変わったことと言えば、プロバイダが変わったことだが、この現象はインターリンクに切り替える前からおこっていた現象なので、やはり怪しいのはルータということになる。<br />
<br />
<br />
以下、私がNTT東日本に問い合わせたメールの内容。<br />
<br />
この後、一応連絡が来て、結局他の部署のなんちゃらというところに問い合わせてみてください、といった無責任な対応だったので、めんどくさくてそのままにしている。<br />
<br />
もし、同じような現象にある人は、下記の文面をそのままコピペして問合せ用に使っちゃってください。<br />
<br />
もしくは、「お前の考え方が間違っている。ルータのせいではない。」という見識をお持ちの方は、ぜひぜひ解決策を教えていただけると嬉しいです。<br />
<br />
----------------------------------------------------------------------------------------------<br />
先日引越しを行った際に、弊社からの案内でルータをPR-200NEからPR-400NE（無線LANカード付き）に変更しました。<br />
<br />
当方ではLAN内にサーバを構築しており、インターリンクというISPの固定IPアドレスによりWEBも公開しておりますが、LAN内のクライアントPCからLAN内のサーバにホスト名でアクセスする際に支障が出ております。<br />
<br />
この場合、何も対策していない場合は、通常はLAN内のホストにホスト名+ドメインでアクセスすることはできませんが、その回避策として内部DNSを設置しており、引っ越し前（PR-200NE）までは正常に問合せ、閲覧ができていました。<br />
<br />
ルータのソフトウェア（最新ファームウェアバージョンは1.11）の設定も、基本的に引っ越し前とすべて同じにしています。<br />
静的NATの設定なども全て同じで、外部から当サーバへの各種アクセスは問題ありません。<br />
<br />
「詳細設定」→「DNS設定」の「LAN側DNSサーバアドレス」に、当方の内部DNSアドレス（192.168.1.4）を指定しており、この設定が、LAN内ホストの名前解決をする際に使用されるDNSアドレスと認識しております。<br />
この認識が間違っていれば申し訳ありません。<br />
<br />
この認識から行くと、通常使用する接続設定（「基本設定」→「接続先設定→「現在利用中の接続名」」）において、「DNSサーバアドレス」で「サーバから割り当てられたアドレス」を「使用する」にしておいても、LAN内ホストにホスト名で接続するときは、上述した内部DNS（192.168.1.4）に問合せに行かなくてはならないはずなのに、そうならずに、「このページは表示できません」となります。<br />
逆に、上記の「サーバから割り当てられたアドレス」を使用せず、問合せるDNSを強制的に内部のDNS（192.168.1.4）に指定すれば、当たり前ですがアクセスできます。<br />
つまり、内部DNSの正引きは正しく動作していることになり、ルータのDNS問合せ先の判別がうまくいっていないのではないか、ということです。<br />
<br />
以上よろしくお願いたします。<br />
<br />
----------------------------------------------------------------------------------------------<br />
<br />
<br />
]]>
        
    </content>
</entry>

<entry>
    <title>突然サーバの電源が落ちてダウン</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/10/post-7.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.5403</id>

    <published>2011-10-18T04:43:12Z</published>
    <updated>2011-10-18T05:28:14Z</updated>

    <summary>今朝起きると、やけに仕事部屋が静かだ。 ふと見るとサーバがシーーーンとしている。...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[今朝起きると、やけに仕事部屋が静かだ。<br />
<br />
ふと見るとサーバがシーーーンとしている。というか電源が落ちている。<br />
<br />
<br />
いままで定期的にメンテナンスをしてきたとはお世辞にも言えないので、いつかはこういう日が来るとは思っていたが、さすがにちょっとあせる。<br />
<br />
とりあえず、再度立ちあげてみる。<br />
ブートはOK。ログイン画面もOK。ログインも可能。<br />
<br />
しかし3分後・・・<br />
「ピュシューーーーン！」という音とともにサーバ停止。<br />
<br />
今度はもう一度電源入れて、topで監視してみる。<br />
特に問題なさそうな動きなのに、また「ピュシューーーーン！」と停止。<br />
<br />
リソースが落ち着いているのに止まるってことは、一部のデーモンが暴走したり、スクリプトが暴走したりという原因ではなさそうだ。<br />
それに全然熱も持ってない。素手で躯体を触ってもまったく熱くない。<br />
サーマルシャットダウンではないのか？？？<br />
そして、CPUがほとんど使われてないのに、ファンが常に全開で回りっぱなしだ。うるせー。<br />
<br />
HDDだったらいやだな・・・いつバックアップ取ってたっけ？やっぱRaid組んどきゃよかったか・・・なんて思いながら仕方なくサーバを開けて中を確認。<br />
<br />
一番怪しそうなCPUクーラーを外してみると、グリスのカスがバラバラ落ちてきた・・・あらら・・・<br />
そして残ったグリスも完全に乾いててパキパキ状態。<br />
そういえばこのサーバのクーラー外すの初めてだったかも・・・<br />
<br />
しかもクーラーの足の4本のうち2本の樹脂部分が割れてる状態だし回転も悪い。<br />
（ぐらついてはいないが）<br />
<br />
ダメだこりゃ。交換だなと思って、クーラーだけを外して近所のパーツ屋に直行。<br />
<br />
「急に電源が落ちるからCPUクーラーを取り換えたい」といったら、店員はきっと電源ユニットの故障だと言い張る。<br />
しかし私は「いやいや、クーラーとCPUの密接状態が悪いから熱伝導が弱っているんだよ多分」<br />
とかなんとか口論になりつつ、なかば強引に新品のクーラー（Core2Duoのサポートタイプ）を購入。<br />
<br />
今回購入したのその店で一番安かったこれ。<br />
⇒　<a href="http://coolermaster.cm-industry.co.jp/product.php?class=cooler_limit&model=xdreamp775">Xdream p775</a><br />
<br />
うちのサーバはDELL製でマザボと接続するコネクタのピンが4ピン（この製品は3ピン）なんだが、多分片側3ピンしか使ってないから挿さればいけるだろうってことで・・・<br />
<br />
帰ってきて商品を開けた時に、そういえばシリコングリスも買わなきゃならなかったんじゃ？なんて心配になるが、ヒートシンク部分にグリスがあらかじめ塗ってあったので一安心。<br />
<br />
この製品には、クーラーの足の下に置く架台みたいなパーツが付属してるが、うちのサーバはコンデンサが邪魔で付けられなかったため、架台なしで直接ねじで取り付けた。<br />
（取り付けの際、グリスが服についてしまったのは言うまでもない）<br />
<br />
<br />
そして改めて、電源を立ち上げる。<br />
<br />
30分たっても落ちない。<br />
どうやら成功のようだ。よかったよかった。<br />
<br />
障害に気付いてから復旧まで約3時間。<br />
情報科出身でも機械科出身でもない私にしてはまずまずでしょう。<br />
<br />
<br />
参考資料：<br />
<a href="http://pasokoma.jp/bbs8/lg245187"><a href="http://pasokoma.jp/bbs8/lg245187">http://pasokoma.jp/bbs8/lg245187</a></a><br />
<a href="http://www.dosv.jp/feature/0606/14.htm"><a href="http://www.dosv.jp/feature/0606/14.htm">http://www.dosv.jp/feature/0606/14.htm</a></a>]]>
        
    </content>
</entry>

<entry>
    <title>MySQL:INNER JOINとUNIONを組合せてすっきりSELECT</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/10/mysqlleft-joinunionwo.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.5304</id>

    <published>2011-10-06T04:32:44Z</published>
    <updated>2011-10-06T07:30:18Z</updated>

    <summary>例えば以下のようなテーブルがあったとき。 user_tbl（会員テーブル） id...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="MilkyStep" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MySQL" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[例えば以下のようなテーブルがあったとき。<br />
<br />
user_tbl（会員テーブル）
<table border='1'>
<tr>
<td>id</td>
<td>name</td>
<td>address</td>
</td>

<tr>
<td>1</td>
<td>山田</td>
<td>東京都</td>
</tr>

<tr>
<td>3</td>
<td>鈴木</td>
<td>千葉県</td>
</tr>

<tr>
<td>6</td>
<td>高橋</td>
<td>北海道</td>
</tr>

<tr>
<td>12</td>
<td>佐藤</td>
<td>大阪府</td>
</tr>

</table>
<br />

shitumon_tbl（質問テーブル）
<table border='1'>

<tr>
<td>id</td>
<td>title</td>
<td>answer_type</td>
</tr>

<tr>

<td>1</td>
<td>あなたの身長</td>
<td>テキスト入力</td>
</tr>

<td>2</td>
<td>あなたの体重</td>
<td>テキスト入力</td>
</tr>

<td>3</td>
<td>住居形態</td>
<td>択一選択</td>
</tr>

</table>
<br />

sentakushi_tbl（質問の選択肢テーブル）
<table border='1'>

<tr>
<td>id</td>
<td>shitsumon_id</td>
<td>sentakushi_name</td>
</tr>

<tr>
<td>1</td>
<td>3</td>
<td>一戸建て</td>
</tr>

<tr>
<td>2</td>
<td>3</td>
<td>マンション</td>
</tr>

<tr>
<td>3</td>
<td>3</td>
<td>アパート</td>
</tr>

<tr>
<td>4</td>
<td>3</td>
<td>ダンボール</td>
</tr>

</table>
<br />
user_info_tbl（会員情報テーブル）
<table border='1'>

<tr>
<td>id</td>
<td>user_id</td>
<td>shitsumon_id</td>
<td>answer<br />
(テキスト入力の時はその値、<br />
択一選択の時は選択肢ID)
</td>
</tr>

<tr>
<td>9</td>
<td>1（山田）</td>
<td>1（身長）</td>
<td>175(cm)</td>
</tr>

<tr>
<td>10</td>
<td>1（山田）</td>
<td>2（体重）</td>
<td>68(kg)</td>
</tr>

<tr>
<td>11</td>
<td>1（山田）</td>
<td>3（住居形態）</td>
<td>3（アパート）</td>
</tr>

<tr>
<td>12</td>
<td>3（鈴木）</td>
<td>1（身長）</td>
<td>168(cm)</td>
</tr>

<tr>
<td>13</td>
<td>3（鈴木）</td>
<td>3（住居形態）</td>
<td>1（一戸建て）</td>
</tr>

<tr>
<td>14</td>
<td>6（高橋）</td>
<td>2（体重）</td>
<td>74(kg)</td>
</tr>

<tr>
<td>15</td>
<td>6（高橋）</td>
<td>3（住居形態）</td>
<td>2（マンション）</td>
</tr>

<tr>
<td>16</td>
<td>12（佐藤）</td>
<td>1（身長）</td>
<td>182(cm)</td>
</tr>

<tr>
<td>17</td>
<td>12（佐藤）</td>
<td>3（住居形態）</td>
<td>3（アパート）</td>
</tr>

</table>
<br />
<br />
上記のとき、<br />
<u>※「身長」が「170」cm以上で、</u>
<u>※「住居形態」が「アパート」</u>の会員（条件数＝２）の<u>「会員テーブル」だけ</u>を表示する。<br />
<br />
SQLの例<br />
-----------------------------------------------------------------------------------------<br />
SELECT `user_tbl` . *<br />
FROM `user_tbl`<br />
<br />
<s>LEFT JOIN</s> INNER JOIN (<br />
# 副問い合わせ<br />
<br />
# まず質問IDが1（身長）で、答えが170(cm)以上のuser_idを抽出<br />
(<br />
SELECT `user_info_tbl`.user_id<br />
FROM `user_info_tbl`<br />
WHERE<br />
`user_info_tbl`.question_id = 1<br />
AND<br />
`user_info_tbl`.answer >= 170<br />
)<br />
<br />
# 次に質問IDが3（住居形態）で、答えが3（アパート）のレコードをUNION ALL で結合<br />
# ※「UNION ALL」にすることで、わざと重複させる。<br />
UNION ALL (<br />
SELECT `user_info_tbl`.user_id<br />
FROM `user_info_tbl`<br />
WHERE<br />
`user_info_tbl`.question_id = 3<br />
AND<br />
`user_info_tbl`.answer = 3<br />
)<br />
<br />
) AS uni<br /> 
# ↑副問い合わせでUNIONするときは固有名をつけないと、「ERROR 1248 (42000): Every derived table must have its own alias」になる。<br />
<br />
# ユーザIDが同じものを<s>外部</s>内部結合<br />
ON user_tbl.id = `uni`.user_id<br />
<br />
# 重複数が2（=条件数）のレコードのみ表示<br />
GROUP BY `user_tbl`.id<br />
HAVING COUNT( `user_tbl`.id ) = 2<br />
-----------------------------------------------------------------------------------------<br />

結果<br />
<table border='1'>
<tr>
<td>id</td>
<td>name</td>
<td>address</td>
</td>

<tr>
<td>1</td>
<td>山田</td>
<td>東京都</td>
</tr>

<tr>
<td>12</td>
<td>佐藤</td>
<td>大阪府</td>
</tr>

</table>
<br />
<br />
これだと、会員・質問・選択肢を自由に追加・削除しても、情報の整合性がとれる。<br />
会員の自由項目情報を扱ったりするときに便利。<br />
（もちろん削除時、変更時にはそれに対応する各々のテーブルデータを書き換える必要はあるが・・・）<br />
<br />
<br />
※追記<br />
「LEFT JOIN」だと条件が1つのときにuser_tbl他のレコードも一緒にくっついてきてしまってまずいので「INNER JOIN」が正解。
]]>
        
    </content>
</entry>

<entry>
    <title>jQueryで作る1つしか選択できないチェックボックス</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/09/jquery1.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.5250</id>

    <published>2011-09-29T13:07:15Z</published>
    <updated>2011-09-29T13:48:29Z</updated>

    <summary>まあ、択一選択にしたければ、最初からラジオボタンかセレクトボックスでフォームパー...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="HTML" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="JavaScript" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MilkyStep" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[<p>まあ、択一選択にしたければ、最初からラジオボタンかセレクトボックスでフォームパーツを作ればいいのだが、場合によってはチェックボックスで択一選択のフォームを作りたいこともある。（多分そうそう機会はないと思うが）</p>

<p>例えばパラメタの都合上、各inputのname属性の値を別々にしたいときとか。<br />
ラジオボタンでも、name属性の値が違えば、どちらもチェックできてしまう。</p>

<p>以下のようなチェックボックスのフォームが合った場合、</p>

<p>----------------------------------------------------------------------------------<br />
&lt;div class='parts_list'&gt;<br />
　　&lt;table&gt;<br />
　　　&lt;tr&gt;<br />
　　　　&lt;td&gt;<br />
　　　　　&lt;input type='checkbox' name='check_A' value='1'&gt; 選択肢A<br />
　　　　&lt;/td&gt;<br />
　　　&lt;/tr&gt;<br />
 　　&lt;/table&gt;<br />
　　&lt;table&gt;<br />
　　　&lt;tr&gt;<br />
　　　　&lt;td&gt;<br />
　　　　　&lt;input type='checkbox' name='check_B' value='1'&gt; 選択肢B<br />
　　　　&lt;/td&gt;<br />
　　　&lt;/tr&gt;<br />
 　　&lt;/table&gt;<br />
　　&lt;table&gt;<br />
　　　&lt;tr&gt;<br />
　　　　&lt;td&gt;<br />
　　　　　&lt;input type='checkbox' name='check_C' value='1&gt; 選択肢C<br />
　　　　&lt;/td&gt;<br />
　　　&lt;/tr&gt;<br />
 　　&lt;/table&gt;<br />
&lt;/div&gt;<br />
----------------------------------------------------------------------------------</p>

<p>これだと、そのままでは全てのチェックボックスにチェックを入れることができてしまうので、これをjQeryで制御する。<br />
簡単にいえば、チェックされた以外のチェックボックスのチェックを外す。</p>

<p>以下が改良版。</p>

<p>----------------------------------------------------------------------------------<br />
&lt;script type="text/javascript" src='jquery.js'&gt;&lt;/script&gt;</p>

<p>&lt;script type="text/javascript"&gt;<br />
　$(function(){</p>

<p>　　$("div.parts_list table").each(<br />
　　　$("input:checkbox",this).click(<br />
　　　　// チェックボックスをチェックした時のイベント開始<br />
　　　　function(){<br />
　　　　　// 親要素（table）のセレクタ取得<br />
　　　　　var parent = $(this).closest("table");<br />
　　　　　// これより前のtableに対する処理<br />
　　　　　parent.prevAll().each(<br />
　　　　　　function(){<br />
　　　　　　　// チェックを外す<br />
　　　　　　　$("input:checkbox",this).attr("checked",false);<br />
　　　　　　}<br />
　　　　　);<br />
　　　　　// これより後ろのtableに対する処理<br />
　　　　　parent.nextAll().each(<br />
　　　　　　function(){<br />
　　　　　　　// チェックを外す<br />
　　　　　　　$("input:checkbox",this).attr("checked",false);<br />
　　　　　　}<br />
　　　　　);<br />
　　　　　// チェックボックスをチェックした時のイベント終了<br />
　　　　}<br />
　　　) // click閉じ<br />
　　) // each閉じ</p>

<p>　)); // function閉じ<br />
&lt;/script&gt;</p>

<p><br />
&lt;div class='parts_list'&gt;<br />
　　&lt;table&gt;<br />
　　　&lt;tr&gt;<br />
　　　　&lt;td&gt;<br />
　　　　　&lt;input type='checkbox' name='check_A' value='1'&gt; 選択肢A<br />
　　　　&lt;/td&gt;<br />
　　　&lt;/tr&gt;<br />
 　　&lt;/table&gt;<br />
　　&lt;table&gt;<br />
　　　&lt;tr&gt;<br />
　　　　&lt;td&gt;<br />
　　　　　&lt;input type='checkbox' name='check_B' value='1'&gt; 選択肢B<br />
　　　　&lt;/td&gt;<br />
　　　&lt;/tr&gt;<br />
 　　&lt;/table&gt;<br />
　　&lt;table&gt;<br />
　　　&lt;tr&gt;<br />
　　　　&lt;td&gt;<br />
　　　　　&lt;input type='checkbox' name='check_C' value='1&gt; 選択肢C<br />
　　　　&lt;/td&gt;<br />
　　　&lt;/tr&gt;<br />
 　　&lt;/table&gt;<br />
&lt;/div&gt;<br />
----------------------------------------------------------------------------------</p>

<p><br />
以上。</p>

<p>jqueryは便利だなーやっぱり。<br />
</p>]]>
        
    </content>
</entry>

<entry>
    <title>HTML::Templateでループ表示させるときの小技</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/08/htmltemplate.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.5001</id>

    <published>2011-08-27T05:16:39Z</published>
    <updated>2011-08-27T06:07:50Z</updated>

    <summary>スクリプト側の配列をテンプレートに反映させるとき、すべての値をそのまま出力するな...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="HTML" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MilkyStep" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[スクリプト側の配列をテンプレートに反映させるとき、すべての値をそのまま出力するならいいのだが、値が1のときは「checked」、0の時は空白文字列を出力したい時などがある。<br />
<br />
例えば、以下のようなテンプレートがあったとき。<br />
<br />
■test.tpl<br />
--------------------------------------------------------------------------------------<br />
<br />
&lt;TMPL_IF NAME="users"&gt;<br />
&nbsp;&lt;ul&gt;<br />
&nbsp;&nbsp;&lt;TMPL_LOOP NAME="users"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;li&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;名前：&lt;TMPL_VAR NAME="user_name"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/li&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;li&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;input type='checkbox' name='pub_name_on' value='1' &lt;TMPL_VAR NAME="pub_name"&gt; /&gt; 名前を公開する<br />
&nbsp;&nbsp;&nbsp;&lt;/li&gt;<br />
&nbsp;&nbsp;&lt;/TMPL_LOOP&gt;<br />
&nbsp;&lt;/ul&gt;<br />
&lt;TMPL_ELSE&gt;<br />
&nbsp;&lt;p&gt;要素がありません&lt;/p&gt;<br />
&lt;/TMPL_IF&gt;<br />
<br />
--------------------------------------------------------------------------------------<br />
<br />
<br />
スクリプト側をオーソドックスに書くとこんな感じ<br />
<br />
■test.cgi<br />
--------------------------------------------------------------------------------------<br />
<br />
use strict;<br />
use HTML::Template;<br />
<br />
# オブジェクト生成<br />
my $tpl = HTML::Template->new( filename => 'test.tpl'); <br />
<br />
#ユーザ情報を2次元配列にセット<br />
my @users = (<br />
&nbsp;['山田　太郎', 0], # 「0」は名前非公開<br />
&nbsp;['鈴木　一郎', 1]  # 「1」は名前公開<br />
);<br />
<br />
#ループ格納用配列作成<br />
my @lood_data = ();<br />
<br />
while (@users) {<br />
<br />
&nbsp;# 各行のハッシュ作成<br />
&nbsp;my %row_data = ();<br />
<br />
&nbsp;# 配列データを格納<br />
&nbsp;$row_data{'user_name'} = $$_[0];<br />
&nbsp;$row_data{'pub_name'} = $$_[1];<br />
<br />
&nbsp;# $row_data{'pub_name'} が1だったら「checked」に変更<br />
&nbsp;$row_data{'pub_name'} = $row_data{'pub_name'} == 1 ? 'checked' : '';<br />
<br />
&nbsp;# リファレンスでループ用配列に追加<br />
&nbsp;push(@loop_data, \%row_data);<br />
<br />
}<br />
<br />
# paramメソッド実行<br />
$tpl->param('users' => \@loop_data);<br />
<br />
#出力<br />
$tpl->output(print_to => \*STDOUT);<br />
<br />
--------------------------------------------------------------------------------------<br />
<br />
<br />
しかしこれだと、各値をいちいちハッシュにしたり面倒くさいので、下記のようにmapを用いてさらにその中で条件分岐も済ませると楽ちん。<br />
<br />
■test2.cgi<br />
--------------------------------------------------------------------------------------<br />
<br />
use strict;<br />
use HTML::Template;<br />
<br />
# オブジェクト生成<br />
my $tpl = HTML::Template->new( filename => 'test.tpl'); <br />
<br />
#ユーザ情報を2次元配列にセット<br />
my @users = (<br />
 ['山田　太郎', 0], # 「0」は名前非公開<br />
 ['鈴木　一郎', 1]  # 「1」は名前公開<br />
);<br />
<br />
# mapを使ってパラメータを一気に作成<br />
my %params = ('users' => [<br />
&nbsp;map { +{<br />
&nbsp;&nbsp;user_name    => $$_[0],<br />
&nbsp;&nbsp;pub_name   => $$_[1] == 1 ? 'checked' : '' # ←ここで条件分岐<br />
&nbsp;}} @users<br />
]);<br />
<br />
<br />
# paramメソッド実行<br />
$tpl->param(%params);<br />
<br />
#出力<br />
$tpl->output(print_to => \*STDOUT);<br />
<br />
--------------------------------------------------------------------------------------<br />
<br />
こんなかんじです。<br />
]]>
        
    </content>
</entry>

<entry>
    <title>phpBBの通知メールの（部分）文字化け対策</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/07/phpbb-1.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.4593</id>

    <published>2011-07-04T03:52:39Z</published>
    <updated>2011-07-04T04:00:16Z</updated>

    <summary>前回に引き続きphpBB（phpBB2）ネタ。 当然ながら日本語でphpBBを運...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="MySQL" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="PHP" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="メール配信" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[前回に引き続きphpBB（phpBB2）ネタ。<br />
<br />
当然ながら日本語でphpBBを運用する場合は、普通、MySQLのマルチバイト文字セットはEUCかUTF8になっている。<br />
<br />
しかし、デフォルトのまだと、システムから送られてくるメールの、DBのマルチバイトを参照した部分の文字列が化ける。<br />
<br />
以下対策<br />
<br />
・language/language_japanese/email の中のファイル全てを、MySQLの文字コードに合わせてエンコードを修正する。<br />
（SJISなどでアップされていたらEUCかUTF8で保存して上書き）<br />
<br />
・各ファイルの「Charset: iso-2022-jp」と書かれているところを、全て<br />
「Charset: EUC-JP」　か、<br />
「Charset: UTF8」<br />
に書き換える。<br />
<br />
以上<br />
]]>
        
    </content>
</entry>

<entry>
    <title>phpBBでのスパム対策</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/07/phpbb.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.4592</id>

    <published>2011-07-04T03:42:10Z</published>
    <updated>2011-07-04T03:52:04Z</updated>

    <summary>久々の投稿。しかもネタが今更感のあるこれ。 でも今までphpBBを使ったことが無...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="MySQL" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="PHP" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[久々の投稿。しかもネタが今更感のあるこれ。<br />
でも今までphpBBを使ったことが無かったので、まあまあ勉強になった。<br />
<br />
伝統的なスパム対策は下記らしい。<br />
<a href="http://support.hiikun.net/bbs/topic-299.html">http://support.hiikun.net/bbs/topic-299.html</a><br />
<br />
ちなみにmodの使い方などはこちら。<br />
<a href="http://all.netgamers.jp/adcat5.html">http://all.netgamers.jp/adcat5.html</a><br />
<br />
でも、今時のphpBBスパムシステムは、画像認証やMDハッシュを突破したりしてかなり賢い。<br />
上記の対策をしても相変わらず1日100件くらいは登録スパムがやってくる。<br />
<br />
まあ、ユーザ登録されるだけならまだいいが、トピックを荒らされるのだけは困るので、<br />
以下の対策を実施。<br />
<a href="http://garnote.com/2010/01/spam.html">http://garnote.com/2010/01/spam.html</a><br />
<br />
これはかなり有効だったようで、スパム投稿がピタリと止まった。<br />
]]>
        
    </content>
</entry>

<entry>
    <title>コアサーバの謎：forkすると、ある条件の時文字化けする</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/04/fork.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.4005</id>

    <published>2011-04-25T16:44:03Z</published>
    <updated>2011-04-25T17:39:04Z</updated>

    <summary>MilkyStepのコミュニティでコアサーバを使ったとき、メルマガのデフォルト登...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="HTML" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MilkyStep" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MySQL" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[MilkyStepのコミュニティでコアサーバを使ったとき、メルマガのデフォルト登録完了画面が文字化けする（日本語部分が???になる）との報告を受け、一時期かなり調査を行ったが解決せず。<br />
それから約２カ月後、他のユーザから同様の現象が報告された。<br />
<br />
開発環境では全くそのような現象が起こらないので、仕方なく、コアサーバーを実際に借りてMilkyStepを設置し徹底的に調査することにした。<br />
<br />
表示させるデフォルト画面のHTMLソースは、ユーザが自由に編集できるようになっているのだが、そのソースはMySQLに保存される。<br />
<br />
そこからデータを引っ張って、少し置換処理してからプログラムで出力する。<br />
<br />
確かにコアサーバで実際に試してみると、5回中4回くらいの割合で日本語が「？」になる。<br />
（成功する場合もある）<br />
<br />
MySQLの文字セットはutf8、照合順序もutf8_general_ci、さらにSQL発行時に毎回「SET NAMES utf8」（MySQL4.1以降で有効）しているので、データ通信間で化けるとは考えにくい。<br />
もちろんスクリプトのファイルもUTF8。<br />
<br />
とりあえず、ブラウザの文字コードの誤判定臭いので、日本語を多めに入れたり、EUCでいうところの「美乳テーブル」である、郵便くんマーク（〠←これ）を冒頭に入れたりしてみたが、変わらず。<br />
<br />
次に、Perlでutf8扱う時によくある、utf8フラグあるなしの問題かとも思い、「use utf8」したりEncode::encode/decodeしたりいろいろやったが、どうやら関係ないっぽい。<br />
<br />
というか、なんかMySQLから参照した時点ですでに化けてるっぽい。<br />
<br />
試しに、SELECT時に、以下のような感じで、明示的に照合順序を指定してみる。<br />
<br />
まず、<br />
--------------------------------------------------------------------------------<br />
SELECT column_name COLLATE utf8_general_ci　FROM ・・・・・<br />
--------------------------------------------------------------------------------<br />
<br />
・・・変化なし。<br />
<br />
次に、<br />
--------------------------------------------------------------------------------<br />
SELECT COERCIBILITY(column_name COLLATE utf8_general_ci) FROM ・・・<br />
--------------------------------------------------------------------------------<br />
<br />
お、1回目はうまくいった。<br />
もう1回。<br />
<br />
--------------------------------------------------------------------------------<br />
<strong>Software error:</strong><br />
<br />
COLLATION 'utf8' is not valid for CHARACTER SET 'latin1_swedish_ci' at ......<br />
--------------------------------------------------------------------------------<br />
<br />
あれあれ？？？？<br />
<br />
「utf8_general_ciでの照合はCHARACTER SET　'latin1'では有効ではありません」<br />
<br />
latin1？？なんで勝手に文字セット変わってんだよ！<br />
utf8で固定だろーが！<br />
<br />
なぜ、コアサーバだけ、しかも特定のカラムの文字列だけ参照するときにこうなるのか・・・<br />
<br />
MySQL4から5に強引に移行した時の忘れものか？<br />
<br />
<br />
とにかくこの、参照時に勝手にテーブルの文字コードをLatin1と判別するわけのわからない現象と格闘すること数時間。<br />
<br />
そもそもこの処理って、forkした後の親プロセスの中でやっていたんだが、このforkを切ったらなぜか正常になった。<br />
ということで、この処理はforkの中から外に出すことに決定。<br />
<br />
いまだに原因はよくわからないが、fork時は内部的に変数を子プロセスにコピーするが、その時点で（コアサーバでは）なんか問題があるらしいってことはぼんやりわかった。<br />
<br />
サーバサイドのアプリを広く対応するのはやっぱ一苦労だな・・・<br />
<br />
]]>
        
    </content>
</entry>

<entry>
    <title>qmailをインストールし直したら、said: 553 sorry, that domain isn&apos;t in my list of allowed rcpthosts (#5.7.1) (in reply to RCPT TO command)</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/04/qmailsaid-553-sorry-that-domain-isnt-in-my-list-of-allowed-rcpthosts-571-in-reply-to-rcpt-to-command.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.3865</id>

    <published>2011-04-09T03:37:25Z</published>
    <updated>2011-04-09T04:01:25Z</updated>

    <summary>備忘録です。 あるqmailのメールサーバに、標準時補正パッチ（qmail-da...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="qmail" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="メール配信" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[備忘録です。<br />
<br />
あるqmailのメールサーバに、標準時補正パッチ（qmail-date-localtime.patch）を当てるのを忘れていてたので、パッチを当てて再インストールしたところ、このエラーが発生。<br />
（qmailのパッチ宛て、インストール方法などの解説はこちら　<a href="http://www.igreks.jp/dev/2011/01/qmailvpopmailqmailadmin.html">http://www.igreks.jp/dev/2011/01/qmailvpopmailqmailadmin.html</a>）<br />
<br />
・内部⇒内部はOK<br />
・内部⇒外部もOK<br />
・外部⇒内部のみNGでメールが送れない。<br />
<br />
つまり外部ホストのアドレスからのみ、このqmailをインストールしたサーバのアドレスにメールが送れない。<br />
<br />
メーラーで送信する際の、よくあるリレーエラーではなく、一旦送信した後、mailer-daemonさんからエラーが返ってきて、<br />
<br />
--------------------------------------------------------------------------------------<br />
<br />
This is the mail system at host sv313.xserver.jp.<br />
<br />
I'm sorry to have to inform you that your message could not<br />
be delivered to one or more recipients. It's attached below.<br />
<br />
For further assistance, please send mail to <postmaster><br />
<br />
If you do so, please include this problem report. You can<br />
delete your own text from the attached returned message.<br />
<br />
                   The mail system<br />
<br />
<*****@hoge.com>: host mail.hoge.com[xxx.xxx.xxx.xxx] said: 553<br />
    sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1) (in reply<br />
    to RCPT TO command)<br />
<br />
--------------------------------------------------------------------------------------<br />
<br />
と、怒られる。<br />
<br />
最初、送信する側の外部ホスト（上記で行くとエックスサーバ）がおかしいのかと思いきや、他のYahooメールやGmailからでもダメ。<br />
<br />
確認したところ、tcp.smtpファイルも、DNS設定も問題なし。<br />
<br />
<br />
というわけで、メールに書いてある、rcpthostsを見てみたら、以下のようになっていた。<br />
<br />
-------------------------------------------------------------------------------------<br />
***.hoge.com<br />
localhost<br />
-------------------------------------------------------------------------------------<br />
※「***」の部分は、このサーバのホスト名<br />
<br />
<br />
あ、そうだ。<br />
以前、最初にqmailインストールしたときに、すでにqmailが稼働しているサーバの設定を真似してたんだった。<br />
<br />
真似したサーバのrcpthostsを見てみると、上記の他に、「aaa.jp」(ホスト名無しのドメインのみ)が追記されている。<br />
<br />
なるほど、上記だけでは、「user@***.hoge.com」ならOKだが、「user@hoge.com」ではNGになるわけだ。<br />
再インストールしたから、これが初期化されちゃったのね。<br />
<br />
というわけで、rcpthostsを訂正。<br />
<br />
-------------------------------------------------------------------------------------<br />
# vi /var/qmail/control/rcpthosts<br />
<br />
（以下を追記。念のため３つほど）<br />
<br />
hoge.com<br />
.hoge.com<br />
mail.hoge.com<br />
<br />
# :wq （保存して終了）<br />
-------------------------------------------------------------------------------------<br />
<br />
webminからだったら、左のメニューから、<br />
<br />
「サーバ」<br />
　↓<br />
「Qmail Mail Server」<br />
　↓<br />
「Accepted Domains(rcpthosts)」<br />
　↓<br />
上記のドメインを追記し保存<br />
<br />
<br />
最後にqmailを再起動して終了。<br />
<br />
<br />
無事、送信できるようになりました。<br />
よかったよかった。]]>
        
    </content>
</entry>

<entry>
    <title>centOSでqmailをdomainkeysを対応させる</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/03/qmaildomainkeys.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.3556</id>

    <published>2011-03-02T02:16:42Z</published>
    <updated>2011-03-03T02:44:27Z</updated>

    <summary>centOSですでに稼働中のqmailにdomainkeysを適用させる方法まと...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="qmail" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[centOSですでに稼働中のqmailにdomainkeysを適用させる方法まとめ（送信側）<br />
<br />
# cd /usr/local/src<br />
<br />
■関連ファイルのダウンロード<br />
# wget <a href="http://sourceforge.net/projects/domainkeys/files/libdomainkeys/0.69/libdomainkeys-0.69.tar.gz/download">http://sourceforge.net/projects/domainkeys/files/libdomainkeys/0.69/libdomainkeys-0.69.tar.gz/download</a><br />
# wget <a href="http://www.qmail.org/qmail-1.03-dk-0.54.patch">http://www.qmail.org/qmail-1.03-dk-0.54.patch</a><br />
# wget <a href="http://jeremy.kister.net/code/qmail-dk-0.54-auth.patch">http://jeremy.kister.net/code/qmail-dk-0.54-auth.patch</a><br />
<br />
■tarファイル展開<br />
# tar -zxvf libdomainkeys-0.69.tar.gz<br />
# cd libdomainkeys-0.69<br />
<br />
■エラー対策<br />
# vi dns.lib<br />
下記を記述し保存<br />
----------------------------<br />
-lresolv<br />
----------------------------<br />
# make<br />
# cd ../<br />
<br />
■次に、qmail-1.03の中で、qmail-dkファイルを作るのだが、ここで、以前qmail本体をインストールしたときに使った「qmail-1.03」ディレクトリを使うと上手くいかない場合がある。<br />
既存の「qmail-1.03」ディレクトリは削除し、新しいqmail-1.03をダウンロードするか、以前使ったtarボールがあればそれを新たに解凍して使う。<br />
<br />
# rm -rf qmail-1.03<br />
# tar -xvzf qmail-1.03.tar.gz<br />
<br />
■ここで、qmail.cに以下の記述があるか見ておく。<br />
# vi qmail-1.03/qmail.c<br />
--------------------------------------------------------------------------------<br />
static void setup_qqargs()<br />
{<br />
  if(!binqqargs[0])<br />
    binqqargs[0] = env_get("QMAILQUEUE");<br />
  if(!binqqargs[0])<br />
    binqqargs[0] = "bin/qmail-queue";<br />
}<br />
--------------------------------------------------------------------------------<br />
■これが無いと、環境変数「QMAILQUEUE」が使えないので、専用のパッチををダウンロードしてあてておく。ある場合はそのままでOK。<br />
# wget <a href="http://qmail.jms1.net/patches/qmailqueue.patch">http://qmail.jms1.net/patches/qmailqueue.patch</a><br />
# patch -d qmail-1.03 < qmailqueue.patch<br />
<br />
<br />
■その他必要なパッチあて<br />
echo 'gcc -02 -include /usr/include/errno.h' > qmail-1.03/conf-cc<br />
# patch -d qmail-1.03 < qmail-1.03-dk-0.54.patch<br />
# patch -d qmail-1.03 < qmail-dk-0.54-auth.patch<br />
<br />
■次にqmail-dkを生成するが、libdomainkeysのヘッダファイルが参照できない場合があるようなので、専用のディレクトリ空間を作成し、そこで行うようにする。<br />
<br />
# mkdir test<br />
# cp -Rpf qmail-1.03 test<br />
# cp -Rpf libdomainkeys-0.69/* test/<br />
# cd test/qmail-1.03<br />
# make qmail-dk<br />
<br />
■上記が成功すれば、test/qmail-1.03 の中に「qmail-dk」ファイルが生成される。<br />
<br />
※qmailqueueのパッチを当てた場合はqmailを停止し、再度、<br />
# make clean<br />
# make setup check<br />
しておく。<br />
<br />
■キュー処理ディレクトリにqmail-dkコピー＆所有者変更<br />
# cp qmail-dk /var/qmail/bin/<br />
# cp qmail-dk.8 /var/qmail/man/man8/<br />
# chown qmailq /var/qmail/bin/qmail-dk<br />
# chmod 4711 /var/qmail/bin/qmail-dk<br />
<br />
<br />
■署名用の鍵ファイル作成<br />
# mkdir -p /etc/domainkeys<br />
# mkdir -p /etc/domainkeys/example.com<br />
# cd /etc/domainkeys/example.com<br />
# openssl genrsa -out rsa.private 768<br />
# openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM<br />
# mv rsa.private default<br />
# chown -Rf qmailq /etc/domainkeys<br />
# chmod 0600 default<br />
# grep -v ^- rsa.public | perl -e 'while(<>){chop;$l.=$_;}print "t=y; p=$l;\n";'<br />
↑で表示された、文字列をコピーしておく<br />
<br />
■vpopmailのsmtpルールを編集<br />
# cd /home/vpopmail/etc<br />
# vi tcp.smtp<br />
以下の例ように修正<br />
-------------------------------------------------------------------------------------------------------------<br />
192.168.:allow,RELAYCLIENT="",DKSIGN="/etc/domainkeys/example.com/default",QMAILQUEUE="bin/qmail-dk"<br />
<br />
:allow,DKVERIFY="DEGIJKfh",QMAILQUEUE="bin/qmail-dk"<br />
-------------------------------------------------------------------------------------------------------------<br />
■CDB化<br />
# tcprules tcp.smtp.cdb tcp.smtp.tmp < tcp.smtp<br />
<br />
<br />
■POPbeforeSMTPなどを利用し、ローカルのメーラからも配信している場合は、/home/vpopmail/etc/open-smtpなどで、qmail-dkを指定できるよう変更しておく。<br />
<br />
# cd /usr/local/src/vpopmail-5.4.32　（←以前に本体インストール時に使った残り。なければダウンロードし解凍しておく）<br />
# vi vpopmail.c<br />
下記の個所を修正。<br />
-------------------------------------------------------------------------------------------------------------<br />
<br />
fprintf( fs_tmp_file, "%s:allow,RELAYCLIENT=\"\",RBLSMTPD=\"\"t%d\n",<br />
↓<br />
fprintf( fs_tmp_file, "%s:allow,RELAYCLIENT=\"\",RBLSMTPD=\"\",DKSIGN=\"/etc/domainkeys/example.com/default\",QMAILQUEUE=\"bin/qmail-dk\"\t%d\n",<br />
<br />
-------------------------------------------------------------------------------------------------------------<br />
qmailを停止し<br />
# make clean、<br />
# make<br />
# make install<br />
<br />
<br />
■DNSのレコードに以下を追加<br />
-------------------------------------------------------------------------------------------------------------<br />
_domainkey.example.com. IN TXT "k=rsa; t=y; o=~;"<br />
default._domainkey.example.com. IN TXT "コピーしておいた文字列"<br />
-------------------------------------------------------------------------------------------------------------<br />
※コピーしておいた文字列⇒「t=y; p=*********;」<br />
<br />
■DNSサーバ（BIND）の再起動<br />
<br />
■qmailの（再）起動<br />
# /etc/init.d/qmail stop<br />
# /etc/init.d/qmail start<br />
<br />
■gmailやyahooメールにメールを送って、受信したメールのヘッダに、<br />
--------------------------------------------------------------------------------------------<br />
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;<br />
  s=default; d=example.com;<br />
  b=公開鍵;<br />
--------------------------------------------------------------------------------------------<br />
などの記述があればOK。<br />
<br />
<br />
参考資料：<br />
<a href="http://jeremy.kister.net/howto/dk.html">http://jeremy.kister.net/howto/dk.html</a><br />
<a href="http://blog.cles.jp/item/1778">http://blog.cles.jp/item/1778</a><br />
<a href="http://www.4web8.com/644.html">http://www.4web8.com/644.html</a><br />
<a href="http://blog.guideme.jp/archives/106">http://blog.guideme.jp/archives/106</a><br />
<a href="http://www.weloveya.com/oshigoto/qMail2.html">http://www.weloveya.com/oshigoto/qMail2.html</a><br />
<br />
<br />
■余談<br />
<br />
同一LAN内、同一ドメインで、負荷分散のため、複数のSMTPサーバから配信する場合は、そのSMTPサーバの分だけDNSにレコードを登録するが必要ある（はず）。<br />
<br />
どのSMTPサーバかを判別するために、各レコード、セレクタ名（上記でいくと「default」の部分）を変えてやればいい（はず）。<br />
<br />
2台目のSMTPの/var/domainkeys/example.com/内に秘密鍵を作ったら（上記の例でいくと「rsa.private」）、そのファイル名を「default2」とかにしてやって、<br />
その他各ファイルDKSIGN指定の部分を<br />
----------------------------------------------------------------------<br />
DKSIGN="/etc/domainkeys/example.com/default2<br />
----------------------------------------------------------------------<br />
のようにしてやる（予定）。<br />
<br />
そしてDNSのレコードに書くとき、<br />
----------------------------------------------------------------------<br />
default2._domainkey.example.com. IN TXT "2台目のSMTPサーバの公開鍵"<br />
----------------------------------------------------------------------<br />
と追加してやればよい（はず）。<br />
　　↓<br />
未検証・・・]]>
        
    </content>
</entry>

<entry>
    <title>qmailでSPF（Sender Permitted From）の設定（送信側）</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/02/qmailspfsender-permitted-from.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.3541</id>

    <published>2011-02-28T12:22:29Z</published>
    <updated>2011-02-28T12:35:33Z</updated>

    <summary>何も難しいことはなかった。 DNSのレコードに下記のようにTXTレコードを追加し...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="qmail" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[何も難しいことはなかった。<br />
<br />
DNSのレコードに下記のようにTXTレコードを追加し、BINDを再起動するだけ。<br />
<br />
■MXレコードに登録されているIPのみ一括指定する場合<br />
hoge.jp. IN TXT "v=spf1 +mx ~all"<br />
<br />
■IPを指定する場合<br />
hoge.jp. IN TXT "v=spf1 ip4:対象のSMTPサーバのIPアドレス ~all" <br />
<br />
※IPアドレスの部分は「111.222.333.444/29」のようにネットマスク指定でもOK<br />
<br />
※IPアドレスを複数登録したい場合は、<br />
hoge.jp. IN TXT "v=spf1 ip4:対象のSMTPサーバのIPアドレス1 ip4:対象のSMTPサーバのIPアドレス2 ~all" <br />
のように半角スペースで区切って記述する。<br />
<br />
<br />
ここに指定したSMTPサーバから、試しにSPFに対応しているgmailにテスト送信すると、下記のようなメールヘッダが追加されている。<br />
<br />
--------------------------------------------------------------------------------------<br />
Received-SPF: pass (google.com: domain of hoge@hoge.jp designates 111.222.333.444 as permitted sender) client-ip=111.222.333.444;<br />
--------------------------------------------------------------------------------------<br />
]]>
        
    </content>
</entry>

<entry>
    <title>PerlやPHPからvpopmailを操作する</title>
    <link rel="alternate" type="text/html" href="http://www.igreks.jp/dev/2011/02/perlphpvpopmail.html" />
    <id>tag:www.igreks.jp,2011:/dev//1.3506</id>

    <published>2011-02-24T15:31:42Z</published>
    <updated>2011-02-24T16:10:41Z</updated>

    <summary>システム開発上、ユーザがブラウザからメールマガジンを作成した時に、同時にエラーメ...</summary>
    <author>
        <name>管理人</name>
        
    </author>
    
        <category term="Linux" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="MilkyStep" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="PHP" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="apache" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="qmail" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="サーバ構築" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="メール配信" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="ja" xml:base="http://www.igreks.jp/dev/">
        <![CDATA[システム開発上、ユーザがブラウザからメールマガジンを作成した時に、同時にエラーメール処理用のアドレスも作成されるようにする、逆にメルマガを削除したらそのアドレスも削除される必要があったためメモ。<br />
<br />
今回のMTAはqmailを使うとのことで、アカウントの管理は必然的にvpopmailとなる。<br />
<br />
しかし、qmailadminを使わないで新規アカウント作成（vadduser）・削除（vdeluser）を行うためには、基本的にrootでの操作となる。<br />
<br />
単純にスクリプト内で<br />
<br />
system("/home/vpopmail/bin/vadduser hoge@hoge.jp hogepass");<br />
<br />
とやっただけでは、もちろんうまくいくはずがない。<br />
<br />
というわけで、Cと連携して上手いことやってくれるモジュール様がないかと、CPANを探してみたらありました。<br />
その名も「vpopmail.pm」。<br />
<br />
呼び出す関数名もまさにvpopmailコマンドとほぼ同じ。<br />
<br />
しかし、最終リリースは2001年・・・やばいんじゃないの？<br />
<br />
かろうじてCPAN.pmをからインストールできたものの、説明も短すぎて、当然<br />
use vpopmail;<br />
vadduser（引数いろいろ）;<br />
とかやれば新規にアカウントを作ってくれると思いきや全然ダメ。<br />
<br />
vpopmailのバージョンを見てきてくれる関数だけはなぜか動いた（笑）<br />
まあ、関数名も最近のvpopmailのコマンドといまいち合ってないし。<br />
<br />
というわけでさんざん悩んだ結果、sudoを使うことで決定。<br />
<br />
以下手順。<br />
<br />
１．新規バーチャルアカウントを作成する簡単なスクリプト（vadduser.cgi）を作成しCGIの動くディレクトリに置く。<br />
<br />
vadduser.cgi<br />
-----------------------------------------------------------------------------------------<br />
#!/usr/bin/perl<br />
<br />
use strict;<br />
<br />
# コマンド発行<br />
`sudo -u root /home/vpopmail/bin/vadduser hoge@hoge.jp hogepass`;<br />
exit;<br />
1<br />
-----------------------------------------------------------------------------------------<br />
<br />
２．sudoの設定ファイルに許可コマンドを追記<br />
<br />
# visudo<br />
<br />
（以下を追記）<br />
apache ALL=(root) NOPASSWD: /home/vpopmail/bin/vadduser,/home/vpopmail/bin/vdeluser<br />
<br />
同時に、以下の行をコメント化<br />
<br />
Defaults    requiretty<br />
　　　↓<br />
#Defaults    requiretty<br />
<br />
※これをコメント化しないと、最近のLinuxでは、<br />
sudo: apache : sorry, you must have a tty to run sudo ; TTY=unknown ;......<br />
と怒られる。<br />
<br />
このエラーは、/var/log/secure を見ればわかる。<br />
<br />
保存して終了<br />
:wq<br />
<br />
<br />
３．vadduser.cgiをブラウザから実行してみる。<br />
<br />
４．確認<br />
<br />
popアカウント一覧に、「hoge」が追加されているのを確認<br />
<br />
同時に、/home/vpopmail/domains/hoge@hoge.jp　内に、ディレクトリ「hoge」が作成されているのでOK！！<br />
<br />
<br />
<br />
ああ疲れた今回も。<br />
<br />
<br />
実務的には、このvadduser.cgiをAPIとしてドキュメントルート外に置いて、第三者からは直接アクセスされないようにし、他のCGIからシステムコールで呼んだりした方がセキュアかなと。<br />
<br />
<br />
参考URL：<br />
<a href="http://hibari.2ch.net/test/read.cgi/php/1024741312/l50">http://hibari.2ch.net/test/read.cgi/php/1024741312/l50</a><br />
<a href="http://d.hatena.ne.jp/kakurasan/20100512/p1">http://d.hatena.ne.jp/kakurasan/20100512/p1</a><br />
<a href="http://old.ikoinoba.net/index.php?UID=1188143501">http://old.ikoinoba.net/index.php?UID=1188143501</a><br />
<a href="http://search.cpan.org/~sscanlon/vpopmail-0.08/">http://search.cpan.org/~sscanlon/vpopmail-0.08/</a><br />
]]>
        
    </content>
</entry>

</feed>

