カテゴリー別アーカイブ: LAMP[Linux, Apache, MySQL, PHP]

postfixを利用する

 sendmailであるとかqmailとかと言ったSMTPDがあるけど、最近利用しているのはpostfixだ。
 開発環境で、全ての送信メール内容を確認したいという場面があるけど、postfixだとこれが簡単にできる。

yum install postfix
yum install cyrus-sasl

 ついでなのでSMTP Authも導入するため、Cyrus-saslも導入しておく。
>>/etc/postfix/main.cf

myhostname = wp.xn--ockc3f5a.com #ホスト名を設定
mydomain = xn--ockc3f5a.com #ドメインを設定
mydestination = wp.xn--ockc3f5a.com, xn--ockc3f5a.com, $myhostname, localhost.$mydomain, localhost #このホストが目的地であるドメインを設定
mynetworks = 127.0.0.0/8, 210.170.x.y #信頼するネットワークを設定(このアドレスから送信されたメールはリレー許可される)
home_mailbox = Maildir/ #メールをデフォルトのDovecotの位置に保管する
always_bcc = catch_all@wp.xn--ockc3f5a.com #これで全てのメールのBCCが送信される
smtpd_sasl_auth_enable = yes #SMTP Authを使用する
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,permit_auth_destination,reject_unauth_destination #メールの許可設定;信頼されるネットワーク、SMTP Authで認証されたユーザ、認証された宛先を許可し、認証されない宛先を拒否する
broken_sasl_auth_clients = yes #非標準のSMTP Authサポート通知を有効にする
smtpd_sasl_security_options = noanonymous #匿名ユーザからのメールを拒否する

 あとは、開発サーバで外にメールを送りたくない場合、

default_transport = local

 この設定をすると、a@yahoo.co.jp宛でもb@microsoft.com宛でも、a@localhostやb@localhostに配送しようとする(つまり、外へのメール送信が出来なくなる) そこで、

luser_relay =catch_all

でキャッチオールしてしまえばほとんどのメールを収集できる(存在するユーザ名宛のメールはそのユーザに配信される)
しかし、Postfixは不明なユーザ宛メールを拒否しようとするので

local_recipient_maps =

の設定でその拒否を解除する。

あとはサービス設定と起動

/sbin/chkconfig sendmail off
/sbin/chkconfig –add postfix
/etc/init.d/sendmail stop
/etc/init.d/postfix start

 こんな感じで、簡単な設定で色々使える。

(633)

カテゴリー: サーバ設定 | コメントをどうぞ

PHP – staticで機能をまとめる

 ある程度の規模のシステムでファンクション名を決めていると、ファンクション名が被ることがある。
 そう言うとき、機能クラスを作って、そのstaticメソッドとして定義することで、クラス名::メソッド名でコールすることが出来るのでちょっと便利。

 staticは、クラスをインスタンス化していなくても呼び出せる物で、変数とメソッドについて定義できる。

class ORDER{
public static $PAYMENT_METHODS = array(‘CARD’, ‘PAYPAL’, ‘CHECK’);
public static makeList($list){

}
}

class INVOICE{
public static makeList($list){

}
}

みたいな定義をしておくと、同じmakeList命令をORDERのmakeListとINVOICEのmakeListに明示して使い分けることが出来る。
非staticだと、

$order = new ORDER();
$order->makeList($order->PAYMENT_METHODS);
$invoice = new INVOICE();
$invoice->makeList($list);

のように、newを使ってインスタンスを作らなければならないけど、static宣言している場合は

ORDER::makeList(ORDER::$PAYMENT_METHODS);
INVOICE::makeList($list);

みたいに呼び出せるので、コードが楽になる。

(84)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP], PHP | コメントをどうぞ

AJAX関連でJSON – PHPとJAVAと

 AJAXで扱うデータを交換するのにJSONってのがある。
 簡単に言えばJavaScript形式の変数をどばっと流してしまうもので、なかなか便利。
 うちの会社ではPHPが主力言語なので、PHPでJSON変換処理をしているんだけど、DBの大きなデータをJSON通信しようとすると結構重い。 具体的には、4MB位ある配列を丸ごとJSON化したら3.5秒かかった。
 JSON化モジュールはとても簡潔に書かれていて、これ以上軽量化は出来そうにない。
 個人的には、OO主義者でJavaも結構いけるクチなので、JSONICを組み込んでTOMCAT5からJSPで組んでみたら、JSON化処理時間は400ミリ秒に短縮できた。
 Javaでは出力ストリームにGZipやDeflateフィルタを設定することで、データの転送自体も圧縮することが出来るのでこの用途にはJavaが適しているだろう。
 JSON化する前の変数を作り出す処理などを含めた全体で比較すると、PHPでは8秒台だったがJavaでは750ミリ秒と1/10以下まで短縮することが出来た。
 問題点としては、私以外の社内リソースにJavaが出来る人が居ないと言うところと、本番サーバに新たにJava環境を構築しなきゃならんのだけど、これだけの性能的アドバンテージがある状況では、Javaの採用が適しているのじゃないだろうか。

(451)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP] | コメントをどうぞ

VMware ESXiの導入 – USBメモリにESXi 4.1U1を導入する

 ServersMan@VPSじゃなく、自前サーバでの話。

 仮想ソフトのVMwareが色々無料化されている。
 メインサーバでWindows上で動くVMware Serverを使っていたんだけど、最近、OS無しに動くVMwareESX(と言うか、小型Linuxがベースになっている)の限定版であるESXiが無料化されていた。
 通常のOS上で動作する物に比べて、低レベル動作するので動作が軽くなるハズなので導入してみた。

 サーバ環境は、AMD785GチップセットのマザーにPhenom X4 9850BE、12GB主記憶、500GB HDDx2の構成。 NICがオンボードはRealtek RTL8112である。
 このESXiはデバイスの対応が少なく、HCLを参照するとかなり厳しい条件が提示されている。
 今回の環境のNICもHCLになく、通常の手順でインストーラを立ち上げると対応したNICが無いためにvmfs3のロードでfailueになって止まってしまう。
 Realtekの8111について、対応したドライバパッケージを公開している人が居るのだが、8112でもこのパッケージで対応可能だった。

 インストールの方法について、インストーラにドライバを追加してインストールして、インストール後のディスクに再度ドライバを追加して動作するようにする方法と、インストーラを使わずにインストールイメージを書き込んでドライバを追加する方法がとれる。 今回は手っ取り早いので後者の方法で導入した。
 導入先にはUSBメモリを利用することにする(クラッシュすることがほぼ無いし、仮想マシンを管理する機能だけなので大してアクセスが重要ではない。 容量も1GBあれば大丈夫)

事前準備
 VMwareのページでESXi(Visor)のインストーライメージと管理パッケージ(Client)をダウンロードしてくる http://www.vmware.com/jp/products/vsphere-hypervisor/overview.html
 追加ドライバパッケージをダウンロードしてくる(今回はAdds support for Realtek 8168 / 8111 NICs and the Intel P55 SATA (8086: 3b22) controllerと言うヤツにした) http://www.vm-help.com/esx40i/customize_oem_tgz.php 
 DD for Windowsをダウンロードしてくる http://www.si-linux.co.jp/wiki/silinux/index.php?DDforWindows
 WinRARを導入しておく http://www.diana.dti.ne.jp/~winrar/
 CentOS LiveCDをダウンロードしてCDに焼いておく http://www.centos.org/

作業開始
 VisorのISOをWinRARで開いてimagedd.bz2を展開する
 展開したimagedd.bz2を更にWinRARで開いてimageddを展開する
 DD for Windowsでimageddを導入先のUSBメモリに書き込む
 LiveCD Linuxで起動してUSBメモリのHypervisor1と言う名前のパーティションをマウントする(HDD無しの状態のPCに挿入していれば/mnt/disc/sda5にマウントされている。 CentOS LiveCD5.6だとリードオンリーでマウントされているので、mount /dev/sda5 -o remount -wで書き込み可能で再マウント)
 Hypervisor1のoem.tgzをドライバパッケージファイルで置換する
作業完了

 これでUSBメモリにカスタムドライバ入りESXiが導入されたので、PCのBIOS設定でUSB MassStorageをHDDエミュレーションに設定して、USBメモリの起動順位を適切に設定してやればESXiが起動できる。
 起動後、IP設定などをしてやる。
 後は、管理マシンにClientを導入して、ESXiに接続してやればOK。

(754)

カテゴリー: サーバ設定 | コメントをどうぞ

ServersMan@VPS – yum自動更新を停止する

 久しぶりにサーバの設定を変更してApacheを再起動したら応答しなくなった。
 応答しなくなった細かい話は別の記事にするとして、根本的な理由は自動更新がデフォルトで動いていたためだった。
 サーバでは、バージョン整合性や動作安定性などを考慮して、自動更新をせずに、テスト環境で動作確認を行ってから更新するべきなのだけど、デフォルトのServersMan@VPSでは/etc/cron.dにyumgui.crontabと言う設定ファイルがあって、これの中にyum -y updateとか書いてある。
 yumはおなじみのパッケージ管理で、-yはYes/No問い合わせに常にyesと答えるオプションで、updateはインストール済みパッケージを更新する命令だから、cronで勝手にバージョン上げられてバージョン互換性が無くなってしまっていた。
 サーバパッケージなんだから自動更新なんて設定しないでおいて欲しいな・・・

(460)

カテゴリー: LAMP[Linux, Apache, MySQL, PHP] | コメントをどうぞ

PHP de ウェブサービス – WebService SOAP

 ウェブサービスを構築するときの便利プロトコル、SOAP。
 XML通信をベースとしたシステムで、下位の転送プロトコルに一般的なHTTPの他、SMTPなどを用いることも出来る便利プロトコル。
 PHPでもPHP-SOAPモジュールを使うことで扱うことが出来る。
 WSDL(Web Services Description Language:ウェブサービス記述言語)によって、サーバとクライアントでウェブサービスの機能や通信形式を記述することが出来て、これを記述すればリモートのサービスをあまり意識することなく処理することが出来る。

<?xml version=”1.0″ encoding=”UTF-8″?>
<wsdl:definitions
name=”MyService”
targetNamespace =”http://xn--ockc3f5a.com/”
xmlns =”http://schemas.xmlsoap.org/wsdl/”
xmlns:apachesoap =”http://xml.apache.org/xml-soap”
xmlns:wsdlsoap =”http://schemas.xmlsoap.org/wsdl/soap/”
xmlns:soapenc =”http://schemas.xmlsoap.org/soap/encoding/”
xmlns:soapenv =”http://schemas.xmlsoap.org/soap/envelope/”
xmlns:xsd =”http://www.w3.org/2001/XMLSchema”
xmlns:xsi =”http://www.w3.org/2001/XMLSchema-instance”
xmlns:wsdl =”http://schemas.xmlsoap.org/wsdl/”>

<wsdl:message name=”getSumRequest”>
<wsdl:part name=”A” type=”xsd:decimal”/>
<wsdl:part name=”B” type=”xsd:decimal”/>
</wsdl:message>

<wsdl:message name=”getSumResponse”>
<wsdl:part name=”Answer” type=”xsd:decimal”/>
</wsdl:message>

<wsdl:portType name=”Sum”>
<wsdl:operation name=”getSum”>
<wsdl:input name=”getSumRequest” message=”getSumRequest”/>
<wsdl:output name=”getSumResponse” message=”getSumResponse”/>
</wsdl:operation>
</wsdl:portType>

<wsdl:binding name=”SumSoapBinding” type=”Estates”>
<wsdlsoap:binding style=”rpc” transport=”http://schemas.xmlsoap.org/soap/http”/>
<wsdl:operation name=”getSum”>
<wsdlsoap:operation soapAction=””/>
<wsdl:input name=”getSumRequest”>
<wsdlsoap:body use=”encoded” encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” namespace=”http://xn--ockc3f5a.com/”/>
</wsdl:input>
<wsdl:output name=”getSumResponse”>
<wsdlsoap:body encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” namespace=”http://xn--ockc3f5a.com/”/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>

<wsdl:service name=”MyService”>
<wsdl:port name=”Estate” binding=”SumSoapBinding”>
<wsdlsoap:address location=”http://xn--ockc3f5a.com/service”/>
</wsdl:port>
</wsdl:service>

</wsdl:definitions>

こんなXML文書がWDSL定義。
で、serviceに

function getSum($A, $B) {
return $A+$B;
}

$server = new SoapServer(“service?wsdl”);
$server->addFunction(‘getSum’);
$server->handle();

みたいな実装をすると、SOAPクライアントからgetSum(A, B)を呼び出すとA+Bの結果が返ってくる。

クライアントは

$options = array(
‘soap_version’=>SOAP_1_2,
‘exceptions’=>true,
‘trace’=>1,
‘cache_wsdl’=>WSDL_CACHE_NONE
);

$client = new SoapClient(‘http://xn--ockc3f5a.com/service?wsdl’, $options);
echo(“$_GET[‘A’] + $_GET[‘B’] = “.$client->getSum($_GET[‘A’], $_GET[‘B’]));

これで、client.php?A=1&B=2とかフォームで投げれば
1 + 2 = 3
みたいな動作をしてくれる。
細かい通信動作とかを自分で作らないでも、勝手に処理してくれる便利ものだ。 通信の実装を一切書かず、ローカル命令を使うのと大差ない記述でリモート命令を使えるので、ビジネスロジックとプレゼンテーションを分離したシステムを構築したりするのにとても便利だ。
SOAPはJavaや.NETにも実装されているから、サーバやクライアントを別言語で実装することも出来て自由度も高い(クライアントに至ってはMicrosoftのInfoPathと言うOfficeスイートのアプリを使うと、GUI操作だけで簡単にフォーム型クライアントを構築できてしまう)
今回は基本機能だけ使ったが、サーバで発生した例外をクライアントでキャッチしたり、addFunctionで関数を割り当てるのに変えてクラスを割り当てたり、独自の型をTypesで定義して使うことが出来るので、色々と追加していくと、超便利である。

(768)

カテゴリー: PHP | コメントをどうぞ

MySQL – インデックスが働かない / Zend Framework

MySQLで

stock
id:int name:varchar num:int

みたいなテーブルに

SELECT * FROM stock WHERE num=’1′

みたいなクエリを投げる。
厳密に言えば、numはint型で、クォーテーションでくくったものは文字列型であるから、数値=文字列の比較は常に成立しないのだけど、MySQLは気を利かせてnum=1を検索して返してくれる。
しかし、このとき、インデックスは動作しない。 型をミスってSQL文を埋め込んでいても勝手に変換して動作するくせに、インデックスが働かずボトルネックになるというアレな状態だ。
適当な感じのインデックスが張ってあるのに、EXPLAINしてやると使用キーが無かったりするのはこんな原因だったりする。
普通にSQLを自分で構築している場合には、コードを修正してクォーテーションを外せば良い。

この問題は、表題のZend Frameworkにもあって、自動エスケープモードを有効にしていると、型に関係なく勝手にクォーテーションでくくられてしまう。 ZendFrameworkのDB機能ではSELECT * FROM stock WHERE num=:numみたいなSQL文とarray(‘num’=>1)の様なパラメータを渡してやるわけだけど、自動エスケープモードで発行するとSELECT * FROM stock WHERE num=’1′になってしまうので、インデックスが働かない状態になる。
このような場合、DBインスタンスを作るときに自動エスケープを無効化して、必要なパラメータを手動でエスケープしなければならない。 また、自動エスケープ処理部分で、is_string($var)の場合だけクォーテーションをかけるようにフレームワーク側を修正する手もある(面倒な場合、DB定義をALTER TABLE stock CHANGE num num VARCHAR(11)のようにして文字列型にしてしまう手もある)

(444)

カテゴリー: MySQL | コメントをどうぞ