■目次
CentOS6 で Apache2.4 + PHP5.4 環境を作るPHP5.3.3のセキュリティPHPを5.6にバージョンアップPHP7をインストールPHP CS Fixer(コード整形)を使うPHPのセッション有効期限を伸ばすPHPでPEARを使うPHPでHTTPの疎通確認を行うPHPからシェルスクリプトを実行するPHPで並列処理を行うPHPでComposerを使うPHPでファイルロックを使うMySQLでトランザクション分離レベルを変更するMySQLでロックを行うcronでPHPを定期実行ImageMagickを使うwkhtmltopdf(PDF作成)を使うMeCab(形態素解析)を使うIgo(形態素解析)を使うOpenCV(画像処理・画像解析・顔認識)を使うSisimai(バウンスメール解析)を使う
■CentOS6 で Apache2.4 + PHP5.4 環境を作る
■Apache2.4 参考:Install Apache 2.4 on CentOS 6 with yum ← RootLinks Co., Ltd. https://www.rootlinks.net/2016/10/07/install-apache-2-4-on-centos-6-with-yum/ # cd /etc/yum.repos.d/ # curl -O https://repos.fedorapeople.org/repos/jkaluza/httpd24/epel-httpd24.repo # yum search httpd24 # yum install httpd24 # /etc/init.d/httpd24-httpd start # vi /opt/rh/httpd24/root/etc/httpd/conf/httpd.conf
ServerName www.example.com:80 DocumentRoot "/opt/rh/httpd24/root/var/www/html"
インストールできた # /etc/init.d/httpd24-httpd restart # chkconfig httpd24-httpd on ※以下はエラーになった yum --enablerepo=centos-sclo-rh -y install httpd24 ※以下もエラーになった yum install wget wget https://repos.fedorapeople.org/repos/jkaluza/httpd24/epel-httpd24.repo yum reinstall --enablerepo=epel-httpd24 httpd24 ■PHP5.4 参考:【シンプル】CentOS6にPHP5.4をyumで簡単にインストールする手順田舎に住みたいエンジニアの日記 | 田舎に住みたいエンジニアの日記 http://blog.ybbo.net/2014/01/22/%E3%80%90%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%80%91centos6%E3%81%... # yum remove php* # yum clean all # rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum install php --enablerepo=remi # service httpd restart インストールできた
■PHP5.3.3のセキュリティ
CentOS6では、未だにデフォルトでPHP5.3が入る件について 参考:RHEL/CentOS 6のPHP5.3.3 は安全か? http://qiita.com/nanasess/items/4248b2dc63a035c2933e 公式な開発は5.3.29で終了しているが、その後Redhatが5.3.3をベースに5.3.3-46のようにメンテナンスを続けていて 2020年11月30日までメンテナンスされる…らしい よって、セキュリティ的な意味では5.3だからと言ってダメというわけでも無いみたい AWSのEC2はPHP5.3.29なので、これには当てはまらないかも? ただしAmazonLinuxの一部としてメンテナンスされているかも? いずれにせよ、可能ならPHP5.6へバージョンアップすることを推奨
■PHPを5.6にバージョンアップ
PHP5.3をPHP5.6にする手順 参考:AWS EC2 で始めるお手軽LAMP環境 APACHE2.4 MYSQL5.5 PHP5.6 http://qiita.com/bboobbaa/items/62761fc219136c37af14 参考:Amazon Linux AMIでPHPを5.3から5.4にアップグレードする方法 with FuelPHP http://qiita.com/Keech/items/70593f432008dc89c2e8 参考:AWS EC2 Amazon LinuxでphpMyAdminを動かす方法!mysqli|mysql 拡張がありません。って http://yutaihara.com/archives/240 ■インストール済みのバージョンを確認 # httpd -v … Apacheのバージョンを確認 Server version: Apache/2.2.31 (Unix) Server built: Jul 19 2016 00:11:31 # php -v … PHPのバージョンを確認 PHP 5.3.29 (cli) (built: May 12 2015 22:42:19) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2014 Zend Technologies ■古いバージョンをアンインストール # cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.20170525 … Apacheの設定ファイルをバックアップ # cp /etc/php.ini /etc/php.ini.20170525 … PHPの設定ファイルをバックアップ # yum remove httpd-* … Apacheをアンインストール(PHP5.4以降ではApache2.4とセットで使う) # yum remove php-* … PHPをアンインストール # yum clean all … 念のためyumのキャッシュを削除 ■インストール # yum -y install httpd24 … Apache2.4をインストール # yum -y install php56 php56-mbstring php56-gd … PHP5.6をインストール(必要に応じてGDなどもインストール) # service httpd start … httpdを起動 # chkconfig httpd on … httpdの自動起動を設定 ■MySQLを使っている場合 # yum -y install php56-mysqlnd … php-mysqlをインストール(「php56-mysql」などはダメだった / EC2以外なら大丈夫かも) # service httpd restart … httpdを再起動
■PHP7をインストール
未検証 参考:AWS EC2にApache2.4, PHP7環境を構築するメモ https://qiita.com/hosoken/items/b60a4c9cc2afcddb8041
■PHP CS Fixer(コード整形)を使う
GitHub - FriendsOfPHP/PHP-CS-Fixer: A tool to automatically fix PHP coding standards issues https://github.com/FriendsOfPHP/PHP-CS-Fixer からファイルを入手する。具体的には http://cs.sensiolabs.org/download/php-cs-fixer-v2.phar からpharファイルを取得し、「php-cs-fixer.phar」に名前を変更して保存する インストールはこれで完了。以下のように、バージョンが表示されることを確認する $ php php-cs-fixer.phar --version PHP CS Fixer 2.10.0 Bowling Bear by Fabien Potencier and Dariusz Ruminski (513a376) 変換対象プログラム(テスト)を用意する これはPSR-2の「名前空間の宣言直後に空行を入れる」「ブレス({ 〜 })は改行する」という2点に違反している状態 $ vi test/sample.php
<?php namespace Sample; class Dummy { }
以下のコマンドでコード整形ができる $ php php-cs-fixer.phar fix ./test You are running PHP CS Fixer with xdebug enabled. This has a major impact on runtime performance. If you need help while solving warnings, ask at https://gitter.im/PHP-CS-Fixer, we will help you! Loaded config default. 1) test\\sample.php Fixed all files in 0.449 seconds, 9.750 MB memory used 以下のコマンドで「PSR-2に整形する」と明示できる(デフォルトでPSR-2なので、この場合は結果は同じ) $ php php-cs-fixer.phar --rules=@PSR2 fix ./test 参考:PHP CS Fixerで快適PHPライフ - FLOG SPLASH http://fivestar.hatenablog.com/entry/2014/12/08/033345 参考:PHP CS Fixer v2 でもっと快適PHPライフ - FLOG SPLASH http://fivestar.hatenablog.com/entry/2017/03/30/233744 参考:コーディング規約自動調整ツールCodeSniffer2とphp-cs-fixer - Qiita https://qiita.com/dozo/items/ed4baa58a0131945ad6f GitHub - FriendsOfPHP/PHP-CS-Fixer: A tool to automatically fix PHP coding standards issues https://github.com/FriendsOfPHP/PHP-CS-Fixer
■PHPのセッション有効期限を伸ばす
プログラム側で期間を伸ばしても、デフォルトでは大元のPHP側で24分に制限されている (ただし、24分経ったセッションは古いとみなす「ことがある」という設定なので、数時間保持されることもある模様。 対策に、.htaccess へ以下の設定を追加するといい。 (この場合、保持期間を24時間に伸ばしている。期間はgc_maxlifetimeで変更可能) php_value session.gc_divisor 1000 php_value session.gc_maxlifetime 86400 php_value session.gc_probability 1
■PHPでPEARを使う
set_include_path(get_include_path() . PATH_SEPARATOR . getcwd() . '/PEAR/'); require_once 'HTTP/OAuth/Consumer.php'; .htaccess で設定するなら以下のように設定できる php_value include_path '.:/path/to/PEAR/:/path/to/libs/' Windows環境なら以下のように設定できる php_value include_path '.;C:/path/to/PEAR/;C:/path/to/libs/'
■PHPでHTTPの疎通確認を行う
実際にHTTPリクエストを送り、「200 OK」が返ってきてコンテンツに特定の文字列が含まれている とするのが確実
<?php // リクエストを送信 $http_response_header = null; $context = stream_context_create(array( 'http' => array('ignore_errors' => true) )); $response = file_get_contents('http://example.com/test/', false, $context); // ヘッダとボディの両方を調べて、正常なレスポンスかどうかを確認する if (preg_match('/200 OK/', implode("\n", $http_response_header)) && preg_match('/テスト/', $response)) { echo 'OK'; } else { echo 'NG'; } exit;
存在しないサーバのアドレスを指定した場合、実行結果は以下になる Apacheがダウンしている場合も同様みたい
<pre>Array ( ) <hr><hr>NG
■PHPからシェルスクリプトを実行する
<?php echo shell_exec('ls -l'); echo `ls -l`;
文字列のエスケープ
<?php echo escapeshellarg('test');
参考:外部プログラムの実行 http://so-zou.jp/web-app/tech/programming/php/exec/
■PHPで並列処理を行う
以下のプログラムを用意して main.php を実行すると、1.txt 〜 3.txt に同じ時刻が記録される つまり前のプログラムの終了を待たずに次のプログラムが実行されている 「CPUやメモリを消費してもいいから、とにかく処理速度優先にしたい」という場合に使える main.php
<?php echo '[start:' . date('H:i:s') . ']'; //exec('nohup php child.php 1 > /dev/null &'); exec('nohup /usr/bin/php child.php 1 > /dev/null &'); exec('nohup /usr/bin/php child.php 2 > /dev/null &'); exec('nohup /usr/bin/php child.php 3 > /dev/null &'); echo '[end:' . date('H:i:s') . ']';
child.php
<?php sleep(2); file_put_contents($argv[1] . '.txt', date('H:i:s'));
参考:[PHP]execでバックグラウンド実行するときの落とし穴に落ちた。 nohup!nohup! - DQNEO起業日記 http://dqn.sakusakutto.jp/2012/08/php_exec_nohup_background.html 参考:PHPで並列処理を作ってみた - Qiita https://qiita.com/Mizumon/items/1e89b024617afb940881 参考:PHPである処理を行うと、約1時間かかるとします。(この時間は短… - 人力検索はてな http://q.hatena.ne.jp/1227966968
■PHPでComposerを使う
XAMPP環境にインストールする手順は xampp.txt を参照 参考:CentOS7にComposerをインストールする - Qiita https://qiita.com/inakadegaebal/items/d370bcb1627fce2b5cd1 参考:Composer を CentOS にインストールする手順 | WEB ARCH LABO https://weblabo.oscasierra.net/php-composer-centos-install/ ■インストール # php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" # php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" # php composer-setup.php # php -r "unlink('composer-setup.php');" # php composer.phar ハッシュの値はバージョンによって異なるため、最新の手順は以下で確認する https://getcomposer.org/download/ Composerをどこからでも呼び出せるようにする場合、以下も実行する # mv composer.phar /usr/local/bin/composer 以下のように、パスも拡張子も無しで呼び出せる # composer ■コマンド例 バージョンを表示(Composerの動作確認) $ composer ライブラリのインストール(Goutteをインストールする場合) $ composer require fabpot/goutte 各ライブラリを最新に更新(プログラムの動作に影響する可能性があるので慎重に) $ composer update composer.json に書かれたライブラリとバージョンに従って更新(他環境で更新された場合など) $ composer install
■PHPでファイルロックを使う
以下勉強メモ PHPでファイル入出力 | refirio.org http://refirio.org/view/18 PHPでファイル入出力(続き) | refirio.org http://refirio.org/view/19 ファイル入出力改良版 | refirio.org http://refirio.org/view/22 ファイルロック解除処理 | refirio.org http://refirio.org/view/26 Webアプリケーションへの同時アクセス対策メモ | refirio.org http://refirio.org/view/367
■MySQLでトランザクション分離レベルを変更する
MySQLのトランザクション分離レベルはデフォルトで REPEATABLE READ となっている REPEATABLE READ はトランザクション開始後にテーブルの値を変更しても、SELECT で参照できるのは変更前の値 READ COMMITTED は変更後の値を参照でき、Oracle、PostgreSQL、SQL Server などではデフォルト設定となっている そちらの方が直感的なので、変更しておくと余計なトラブルを防ぐことができる 具体的には、以下のSQLを発行することでトランザクション分離レベルを変更できる SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED 参考:MySQLでトランザクションの4つの分離レベルを試す - FAT47の底辺インフラ議事録 http://d.hatena.ne.jp/fat47/20140212/1392171784 参考:MySQLのデフォルトのトランザクション分離レベルは SELECT がスナップショットを参照する - ngyukiの日記 http://ngyuki.hatenablog.com/entry/2013/02/02/202558 参考:InnoDBにおけるトランザクション分離レベルについて - Qiita https://qiita.com/taisho6339/items/1097c67a54cedf9504d6 MySQLがこのような挙動になっているのは、バイナリログの整合性を担保するための名残らしい MySQL InnoDBのネクストキーロック おさらい - SH2の日記 http://d.hatena.ne.jp/sh2/20090112
■MySQLでロックを行う
※勉強中 doc/innodb.md at master - ichirin2501/doc https://github.com/ichirin2501/doc/blob/master/innodb.md MySQL - InnoDBのロック関連まとめ - Qiita https://qiita.com/mizzwithliam/items/31fb68217899bd0559e8 世界の何処かで MySQL(InnoDB)の REPEATABLE READ に嵌る人を1人でも減らすために - KAYAC engineers' blog http://techblog.kayac.com/repeatable_read.html 以下勉強メモ Webアプリケーションへの同時アクセス対策メモ | refirio.org http://refirio.org/view/367 CREATE TABLE や TRUNCATE TABLE を実行した場合は、暗黙的にコミットされてロックが外れる(テンポラリテーブルの場合は外れない) …など例外的な挙動もあるようなので注意する。要勉強
■cronでPHPを定期実行
# vi /etc/crontab
*/5 * * * * webmaster /usr/bin/php /var/www/html/cron/test.php
PHPファイルの一行目に「#!PHPへのパス」を設定して、実行権限を与える方法も有効 以下、PHPプログラム内でパスを設定する方法
set_include_path(get_include_path() . PATH_SEPARATOR . '/var/www/html/twitter/' . PATH_SEPARATOR . '/var/www/html/twitter/PEAR/'); require_once 'config.php'; require_once 'HTTP/OAuth/Consumer.php';
■ImageMagickを使う
参考:CentOS6 上のPHPでImageMagickを動かす - Qiita https://qiita.com/fulcrum/items/5563f3cc2f976c19f86f 参考:PECL ImageMagick(PHP)インストール手順 - Qiita https://qiita.com/fumiriku/items/3f4f28ac93c9ef303ddf # yum install ImageMagick # yum -y install php-pear # yum install php-devel --enablerepo=remi … PHP5.4用のリポジトリに変更したため # which php # cd /usr/bin # wget http://pear.php.net/go-pear.phar # php go-pear.phar # vi /etc/php.ini
include_path=".:/usr/PEAR"
# pecl install imagick --enablerepo=remi Can't find PHP headers in /usr/include/php The php-devel package is required for use of this command. ERROR: `phpize' failed … エラーになった # yum install ImageMagick ImageMagick-devel ImageMagick-perl … これなら大丈夫だった # pecl install imagick # vi /etc/php.ini
[PECL] extension=imagick.so
# service httpd restart phpinfo() で確認すると「imagick」の項目が追加されていた 以下のプログラムで画像の作成ができた
<?php $file = 'data/sample.pdf'; $output = 'data/sample.png'; try { $im = new Imagick($file . '[0]'); $im->setImageFormat('png'); $im->thumbnailImage(2000, 2000, true); $im->writeImage($output); } catch (Exception $e) { exit('NG:' . $e->getMessage()); } exit('OK');
■wkhtmltopdf(PDF作成)を使う
参考:PHPでPDFを作成する時はwkhtmltopdf + snappyで戦え http://qiita.com/morisuke/items/b9c18dcba99ba6501d6e 上記手順で進めると、インストール時に以下のエラーが発生した # rpm -ivh wkhtmltox-0.12.2.1_linux-centos6-amd64.rpm error: Failed dependencies: xorg-x11-fonts-Type1 is needed by wkhtmltox-1:0.12.2.1-1.x86_64 xorg-x11-fonts-75dpi is needed by wkhtmltox-1:0.12.2.1-1.x86_64 「フォントが無い」と言われているので、該当するフォントをインストール yum install -y xorg-x11-fonts-Type1 yum install -y xorg-x11-fonts-75dpi 日本語フォントを使うために、以下も実行 wget http://dl.ipafont.ipa.go.jp/IPAexfont/IPAexfont00301.zip unzip IPAexfont00301.zip mv IPAexfont00301/ /usr/share/fonts フォントをインストールできたら、改めてwkhtmltopdfのインストールを実行する composerを使うので、vendorディレクトリを作りたい場所で以下を実行する curl -s http://getcomposer.org/installer | php composer.json を同一階層に作る。記述は以下のようにする
{ "require": { "knplabs/knp-snappy": "dev-master" } }
composerのあるディレクトリでsnippy(ライブラリを簡単に扱うためのラッパー)をインストール ※上にあるように「composer install」のみでインストールできる?何らかの設定が必要?試す php composer.phar install 後は以下の記述で自動的に読み込めば、命令を使うことができる require 'vendor/autoload.php'; 以下、サンプルプログラム
<?php require './vendor/autoload.php'; $html = <<<EOF <style> body { padding: 10px 0; } </style> <body> <p>サンプル。</p> </body> EOF; // wkhtmltopdfの位置をコンストラクタに渡す $pdf = new Knp\Snappy\Pdf('/usr/local/bin/wkhtmltopdf'); // 文字コードUTF-8 $pdf->setOption('encoding', 'utf-8'); // 用紙サイズ $pdf->setOption('page-size', 'B5'); // 用紙の向き $pdf->setOption('orientation', 'landscape'); // PDFをブラウザに出力 header('Content-Type: application/pdf'); echo $pdf->getOutputFromHtml($html); exit;
■MeCab(形態素解析)を使う
※定番ではあるが、UNIX環境でroot権限が必要 参考:yumでMeCabをインストール http://qiita.com/ikenyal/items/275ca3096002822e8cd6 # rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm # yum makecache # yum install mecab mecab-ipadic # mecab --version mecab of 0.996 # mecab すもももももももものうち すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ EOS
■Igo(形態素解析)を使う
※MeCabよりも手軽に形態素解析を利用できる 参考:[PHP]文章を解析して単語ごとに分解する(形態素解析) http://php-archive.net/php/morphological-analysis/ 参考:[PHP]自然言語処理(形態素解析)を利用した簡易全文検索 http://php-archive.net/php/full-text-search1/ ■辞書ファイルの入手 https://sourceforge.net/projects/mecab/files/mecab-ipadic/ から 2.7.0-20070801 をダウンロード(辞書ファイル) ■本体の入手 https://osdn.jp/projects/igo/releases/ から igo-0.4.5.jar をダウンロード(Igo本体) もしくは igo-0.4.5-src.tar.gz をダウンロードして cd igo-0.4.3-src ant でコンパイル(igo-0.4.5.jar が作成される) ■辞書ファイルのビルド 例えば C:\igo で作業する場合、この場所に igo-0.4.5.jar とmecab-ipadic-2.7.0-20070801 を置く ビルドに成功すると、ipadicフォルダが作られる。これが辞書となる cd C:\igo java -Xmx1024m -cp igo-0.4.5.jar net.reduls.igo.bin.BuildDic ipadic mecab-ipadic-2.7.0-20070801 EUC-JP ■PHPプログラムの入手 https://osdn.jp/projects/igo-php/ から igo-php 0.1.7 をダウンロード ■サンプルプログラムの作成
<?php require_once 'igo-php/lib/Igo.php'; $igo = new Igo('./ipadic', 'UTF-8'); $text = 'これはテストです'; $result = $igo->wakati($text); //$result = $igo->parse($text); print_r($result);
※ipadicディレクトリ(辞書データ)はバイナリモードでアップロードする アスキーモードだと正しく認識されない ■単語の追加 参考:Java製形態素解析エンジン「Igo」を試してみる http://www.mwsoft.jp/programming/munou/igo_install.html MeCabの辞書を利用できるため、データの作成方法はMeCab用と同じ mecab-ipadic-2.7.0-20070801 内に User.name.csv を作成し、以下の内容を記述する (ファイル名は任意。文字コードはECU) ランスロット,1291,1291,500,名詞,固有名詞,人名,名,*,*,ランスロット,ランスロット,ランスロット マーリン,1291,1291,500,名詞,固有名詞,人名,名,*,*,マーリン,マーリン,マーリン 追加したら、辞書ファイルを再ビルドする ■はてなキーワードの単語を追加する場合 http://developer.hatena.ne.jp/ja/documents/keyword/misc/catalog から http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv をダウンロード mecab-wikipedia-hatena-csv.php で keywordlist_furigana.csv から hatena-list.csv を作成する ファイルの文字コードをEUCに変換し、mecab-ipadic-2.7.0-20070801 内に置く その後、辞書ファイルを再ビルドする PHPのメモリ消費が大きいようなら ini_set('memory_limit', -1); を追加して様子を見る ■Wikipediaの単語を追加する場合 https://ja.wikipedia.org/wiki/WP:DDhttps://dumps.wikimedia.org/jawiki/ から https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-all-titles-in-ns0.gz をダウンロード ファイルを解凍して jawiki-latest-all-titles-in-ns0 を入手する mecab-wikipedia-hatena-csv.php で jawiki-latest-all-titles-in-ns0 から wikipedia-list.csv を作成する ファイルの文字コードをEUCに変換し、mecab-ipadic-2.7.0-20070801 内に置く その後、辞書ファイルを再ビルドする PHPのメモリ消費が大きいようなら ini_set('memory_limit', -1); を追加して様子を見る ※無改造の mecab-wikipedia-hatena-csv.php ではてなキーワードとWikipediaの両方を取り込むと、形態素解析の際にメモリ消費が大きすぎた mecab-wikipedia-hatena-csv.php を改造して辞書データのサイズを抑え、はてなキーワードのみ取り込むようにした また、読み仮名をカタカナで登録するなどの調整も行った
■OpenCV(画像処理・画像解析・顔認識)を使う
■OpenCVのインストール git clone https://github.com/jayrambhia/Install-OpenCV cd Install-OpenCV cd RedHat chmod +x * ./opencv_latest.sh 2時間くらい?で OpenCV 3.2.0 ready to be used と表示された ■Facedetectのインストール yum -y install php-devel … phpizeを使えるようにする git clone https://github.com/infusion/PHP-Facedetect cd PHP-Facedetect phpize && ./configure && make make install vi /etc/php.ini
extension=facedetect.so … 追加
service httpd restart ■エラー回避 プログラムからface_detectを呼び出すと、以下のようなエラーが表示された OpenCV Error: Unspecified error (The node does not represent a user object (unknown type?)) in cvRead, file /root/Install-OpenCV/RedHat/OpenCV/opencv-3.2.0/modules/core/src/persistence.cpp, line 6628 https://sourceforge.net/projects/opencvlibrary/ からライブラリをダウンロードし、 opencv\sources\data\haarcascades opencv\sources\data\haarcascades_cuda を取り出して haarcascades_cuda/haarcascade_frontalface_alt2.xml を読み込めば認識できた Vagrantで実行する場合、画像ファイルのキャッシュに注意
<pre><?php // 顔認識 $facefile = 'images/yukata2.jpg'; $facedb = 'haarcascades_cuda/haarcascade_frontalface_alt2.xml'; $faces = face_detect($facefile, $facedb); // 顔認識の結果を画像に書き込む $im = imagecreatefromjpeg($facefile); $red = imagecolorallocate($im, 255, 0, 0); foreach ($faces as $i => $face) { $x = $face["x"]; $y = $face["y"]; $w = $face["w"]; imagerectangle($im, $x, $y, $x + $w, $y + $w, $red); echo "[$i] (x:$x, y:$y, w:$w)\n"; } // 画像を出力 imagejpeg($im, "face-out.jpg"); echo "<img src='face-out.jpg'>";
■Sisimai(バウンスメール解析)を使う
参考:Sisimai | bounceHammerの後継となるバウンスメール解析ライブラリ http://libsisimai.org/ja/ 参考:Sisimaiを使ったバウンスメールの管理 http://techlife.cookpad.com/entry/2017/05/15/000000 参考:Sisimaiでバウンスメールを解析してみる http://qiita.com/taku1201/items/0afae3dd90507a688e3e ■インストール(失敗) >gem install sisimai ERROR: Could not find a valid gem 'sisimai' (>= 0), here is why: Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/latest_specs.4.8.gz) インストールできないので、以下を参考に設定を変更 http://book.scss.jp/code/c2/07.html >gem source -a http://rubygems.org/ https://rubygems.org is recommended for security over http://rubygems.org/ Do you want to add this insecure source? [yn] y http://rubygems.org/ added to sources ■インストール >gem install sisimai Fetching: oj-2.18.5.gem (100%) Temporarily enhancing PATH to include DevKit... Building native extensions. This could take a while... Successfully installed oj-2.18.5 Fetching: sisimai-4.21.0.gem (100%) Successfully installed sisimai-4.21.0 Parsing documentation for oj-2.18.5 Installing ri documentation for oj-2.18.5 Parsing documentation for sisimai-4.21.0 Installing ri documentation for sisimai-4.21.0 Done installing documentation for oj, sisimai after 7 seconds 2 gems installed ■解析例
#!/ruby/bin/ruby require 'find' require 'sisimai' puts "Content-type: text/html\n\n" puts '<!DOCTYPE html>' puts '<html>' puts '<head>' puts '<meta charset="utf-8">' puts '<title>Sisimai</title>' puts '</head>' puts '<body>' puts '<h1>Sisimaiのテスト</h1>' # バウンス理由 http://libsisimai.org/ja/reason/ # ハードバウンスとは https://sendgrid.kke.co.jp/blog/?p=7837 reasons = { 'hostunknown' => '宛先ホスト名が存在しない(ハードバウンス)', 'userunknown' => '宛先メールアドレスは存在しない(ハードバウンス)', 'filtered' => 'DATAコマンド以降で拒否された', 'hasmoved' => '宛先メールアドレスは移動した(ハードバウンス)', 'rejected' => 'エンベロープFromで拒否された', 'mailboxfull' => 'メールボックスが一杯', 'suspend' => '宛先アカウントは一時的に停止中', 'vacation' => '宛先は現在不在である自動応答メッセージ', 'contenterror' => '不正な形式のヘッダまたはメール', 'exceedlimit' => 'メールサイズが最大値を超過(5.2.3)', 'feedback' => '元メールへの苦情によるバウンス(FBL形式の)', 'mesgtoobig' => 'メールが大き過ぎる(5.3.4)', 'securityerror' => 'ウィルスの検出または認証失敗', 'spamdetected' => 'メールはスパムとして判定された', 'blocked' => 'IPアドレスやホスト名による拒否', 'expired' => '配送時間切れ', 'mailererror' => '宛先ホストでのメールプログラムのエラー', 'networkerror' => 'DNS等ネットワーク関係のエラー', 'norelaying' => 'リレーの拒否', 'notaccept' => '宛先ホストはメールを受けとらない', 'systemerror' => '宛先サーバでのOSレベルのエラー', 'systemfull' => '宛先サーバのディスクが一杯', 'toomanyconn' => '接続制限数を超過した', 'delivered' => '正常に配信された', 'syntaxerror' => 'SMTPの文法エラー', 'onhold' => 'エラー理由の特定は保留', 'undefined' => 'バウンスした理由は特定出来ず', } Find.find('set-of-emails/maildir/err/') {|path| if File.ftype(path) == 'file' then puts '<h2>' + File.basename(path) + '</h2>' bounces = Sisimai.make(path) if bounces.is_a? Array then puts '<pre>' bounces.each do |bounce| if reasons.has_key?(bounce.reason) then reason = ' … ' + reasons[bounce.reason] else reason = '' end puts 'from: ' + bounce.addresser.address # shironeko@example.org # From puts 'to: ' + bounce.recipient.address # kijitora@example.jp # To puts 'host: ' + bounce.recipient.host # example.jp puts 'status: ' + bounce.deliverystatus # 5.1.1 puts 'code: ' + bounce.replycode # 550 puts 'reason: ' + bounce.reason + reason # userunknown end puts '</pre>' else puts '<p>There is no bounce message in the mailbox or Sisimai could not parse</p>' end end } puts '</body>' puts '</html>' exit
■活用例 SisimaiはRubyとPerlに対応している もしメインシステムがRubyかPerlなら、上のような仕組みを普通に組み込めばいい メインシステムがRubyでもPerlでもないなら、 ・Ruby+Sisimaiでバウンスメールを解析し、問題のあったメールアドレスとその詳細(バウンスの理由など)をデータベースに記録する ・別途PHPでそのデータベースを参照し、メール送信先リストを更新する のような仕組みが必要になりそう Rubyで直接メール送信先リストを書き換えると、機能追加や仕様変更があったときの対応が大変そう