■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%ABphp5-4%E3%82%92yum%E3%81%A7%E7%B0%A1%E5%8D%98%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/ # 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のセッション有効期限を伸ばす
プログラム側で期間を伸ばしても、デフォルトでは大元の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で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/
■cronでPHPを定期実行
# vi /etc/crontab
*/1 * * * * 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で直接メール送信先リストを書き換えると、機能追加や仕様変更があったときの対応が大変そう