MySQLが「Fatal error: cannot allocate memory for the buffer pool」となり起動しない問題

開発環境のWordPressがいきなり「データベース接続確立エラー」となり、mysqlが起動しなくなってしまった時の対処法です。

原因:buffer poolのメモリ割当が少なかったせい

mysqlを起動すると以下のようにエラーに。

$ service mysqld start
MySQL Daemon failed to start.
Starting mysqld:                                           [FAILED]

まずは、/var/log/mysqld.logを確認。すると以下のようなエラーがでていました。

151117  9:55:58 InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137363456 bytes) failed; errno 12
151117  9:55:58 InnoDB: Completed initialization of buffer pool
151117  9:55:58 InnoDB: Fatal error: cannot allocate memory for the buffer pool
151117  9:55:58 [ERROR] Plugin 'InnoDB' init function returned error.
151117  9:55:58 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
151117  9:55:58 [ERROR] Unknown/unsupported storage engine: InnoDB
151117  9:55:58 [ERROR] Aborting

原因となりそうなのはこの部分。

151117  9:55:58 InnoDB: Fatal error: cannot allocate memory for the buffer pool

対処法:my.cnfのinnodb_buffer_pool_sizeを増やす

メモリの割当ができなかったようなので、/etc/my.cnfを編集してメモリの割当を増やします。とりあえず、512Mにすることに。

innodb_buffer_pool_size = 512M

そこで、MySQLを再起動。

$ service mysqld start
Starting mysqld:   [  OK  ]

これでMySQLが再起動しました。

*注意* innodb_log_file_sizeは変更しない

ちなみにinnodb_log_file_sizeを合わせて変更しようとすると、MySQL 5.6未満だとエラーとなるようです。

特に理由がなければ、innodb_buffer_pool_sizeのメモリを増やすだけで良いかなと思います。

[MySQL] innodb_log_file_sizeを変更した時のエラー対処

[MySQL] innodb_log_file_sizeを変更した時のエラー対処

/tmp/my.cnfのinnodb_log_file_sizeを変更すると、エラーになりmysqlが起動できないという現象に。

mysqld.logを見てみると以下のようなエラーに。

InnoDB: Error: log file ./ib_logfile0 is of different size 0 5242880 bytes
InnoDB: than specified in the .cnf file 0 134217728 bytes!

my.cnfで指定したメモリのサイズとib_logfile0のサイズが違うとのこと。ib_logfile0はInnoDB ログファイルです。

どうやら、MySQL 5.6 未満でmy.cnfのinnodb_log_file_sizeを変更すると発生するようです。

いきなり消すのは怖いので、/tmpに一旦退避させます。

$ mv /var/lib/mysql/ib_logfile0 /tmp
$ mv /var/lib/mysql/ib_logfile1 /tmp

そして、またmysqlを再起動すると以下のようなエラーに。

151118  7:04:09  InnoDB: Log file ./ib_logfile0 did not exist: new to be created
InnoDB: Setting log file ./ib_logfile0 size to 128 MB
InnoDB: Database physically writes the file full: wait...
InnoDB: Progress in MB: 100
151118  7:04:09  InnoDB: Log file ./ib_logfile1 did not exist: new to be created
InnoDB: Setting log file ./ib_logfile1 size to 128 MB
InnoDB: Database physically writes the file full: wait...
InnoDB: Progress in MB: 100
151118  7:04:09 InnoDB: Cannot initialize created log files because
151118  7:04:09 InnoDB: data files are corrupt, or new data files were
151118  7:04:09 InnoDB: created when the database was started previous
151118  7:04:09 InnoDB: time but the database was not shut down
151118  7:04:09 InnoDB: normally after that.

調べてみると、ib_logfile0などを消すのはあまり良くない対処のよう。

公式の、nnoDB ログファイルの数またはサイズの変更、および InnoDB テーブルスペースのサイズの変更を参考に対処しました。

[WordPress] 外部サーバーの画像参照のために画像のベースURLを変更する方法

例えば、ローカル開発環境をつくっていてデータベースは同期しているけど、画像などは重いからローカル環境に置きたくないという時の対処法です。

今回の簡単な要件

環境は以下のような状況とします。

ローカル開発環境
URL → http:/localhost

本番環境
URL → http://production.com

であると、ローカル開発環境に本番環境のデータをインポートしても、localhost/wp-content/uploadsには画像がないため、当たり前ですが画像は表示されません。

そこで、画像はhttp://production.com/wp-content/uploads以下のものを参照したいとします。

画像のパスをoptions.phpから変更

まずは、http://localhost/wp-admin/options.phpにアクセス。

それぞれ、以下のように入力します。

upload_path:画像ディレクトリの名前(この場合、uploads) 
upload_url_path:画像パスのURL(この場合、http://production.com/wp-content/uploads)

wordpress_change_image_path

あとは、「変更を保存」とするだけでOKです。

[WordPress] Poeditを使った多言語化の翻訳ファイル作り方

WordPressを多言語化する必要があり、翻訳ファイルを作成しました。

WordPressではテーマの翻訳は基本的にlanguagesディレクトリに入れることとなっています。

そして、翻訳情報を入れたpoファイルとそれを元にコンパイルしたmoファイルの2つで1セットを使います。

Poeditをインストール

公式サイトからインストールします。

有料版もありますが、普通に使う分なら無料版でも十分対応できます。

Poeditを起動

起動すると以下のような画面が出てきます。すでに翻訳ファイルがある場合は、「翻訳を編集」または「翻訳プロジェクトを新規作成」を選択。

「WordPressのテーマ・プラグインを編集」は無料版の場合は使用できないので、今回はスルーします。

poedit1

翻訳ファイル(新規カタログ)を1から作成する

1から翻訳ファイルを作るには、メニューのファイル>新規カタログから新規の翻訳ファイル(.poファイル)を作成します。

次に翻訳先言語を選択。

poedit2

Command + S で一旦カタログを保存します。すると「プロジェクト名-ja.po」「プロジェクト名-ja.mo」の2つが生成されます。

翻訳部分を「ソースから抽出」

次に翻訳部分を抽出するために、「ソースから抽出」を選択します。

poedit3

「ソースの検索パス」にWordpressのフォルダを追加します。「+」のマークでできます。

poedit5

次に「ソース中のキーワード」を選択。WordPressなら翻訳の関数「_e()」と「__()」があるので、ぞれぞれ()をとった「_e」「__」を登録して起きます。

poedit5

翻訳の開始

読み込みが正常にできれば、以下のような画面になります。エラーの場合は、下記のエラーの場合の対処法を確認してください。

poedit8

「ソーステキスト」が翻訳元なので、「翻訳」のテキストエリアに翻訳を記入していきます。

全部記入したら保存してから、ファイル> MOにコンパイルをすることで完了します。

エラー:「ソースから抽出」で「カタログの更新に失敗しました」となる

「ソースから抽出」をすると、以下のようなエラーとなることがあります。

poedit6

ちゃんと検証してないですが、登録した翻訳用関数(WordPressだと__()や_e()が該当)の近くに日本語があるとエラーとなる様子。

関数の直前または直後のコメントアウトの中に日本語がある場合に起こるっぽいです。対策として、前後にコメントアウトがある場合は消すか英語にしてみてください。

とりあえず動かすとこまでの「Ansible入門」:nginx, php-fpm, mysql編

Chefよりも手軽に使えるということでAnsibleを試してみました。

今回は、nginx、php-fpm、mysqlを入れて、さらにmysqlでデータベースとユーザーを作成するところまでをやってみます。とりあえずの使用感を知りたかったので、Ansibleの環境はlocalhostです。

Ansibleを使うには

CentOS6でAnsibleを使うには、yumでansibleをインストールするだけでOKです。インストールしたらサーバー構築の手順書であるPlaybookを書いて、実行すればOKです。

簡単な流れは以下の通り。

・Ansibleをyumでインストール
・Playbookでサーバー構築の設定を書く
・Playbookを実行

1. Ansibleのインストール

$ yum clean all
$ yum -y update
$ yum -y install ansible
$ cd /etc/ansible/

構成は以下のようになってます。

$ ls 
	ansible.cfg  hosts  roles

ansible.cfgはansibleの設定ファイル。hostsはansibleの対象となるサーバーや、グループなどを設定できます。

今回はlocalhostのみが対象でさくっとお試しなので、特に設定することはありません。

2. Playbookを作成

rolesディレクトリや好きなディレクトリに移動してplaybookを作ります。

使えるコマンド(モジュール)は、公式のModule Indexに記載があります。

$ cd roles
- hosts: 127.0.0.1
  connection: local
  sudo: yes
  tasks:
    - name: add nginx repository
      yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present

    - name: add remi repository
      yum: name=http://rpms.famillecollet.com/enterprise/remi-release-6.rpm state=present

    - name: add epel repository
      yum: name=http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm state=present

    - name: install nginx
      yum: name=nginx state=present
 
    - name: install php packages
      yum: name={{ item }} state=present enablerepo=remi
      with_items:
        - php
        - php-cli
        - php-devel
        - php-mbstring
        - php-gd
        - php-pear
        - php-xml
        - php-fpm

    - name: install mysql packages
      yum: name={{ item }} state=present enablerepo=remi
      with_items:
        - mysql.x86_64
        - mysql-server.x86_64
        - php-mysql

    - name: be sure php-fpm is running and enabled
      service: name=php-fpm state=running enabled=yes

    - name: be sure mysqld is running and enabled
      service: name=mysqld state=running enabled=yes

    - name: be sure nginx is running and enabled
      service: name=nginx state=running enabled=yes

    - name: install MySQL-python
      yum: name=MySQL-python state=present

    - name: add root user of mysqld
      mysql_user:
        name: root
        host: localhost
        password: samplepassword

    - name: create n edit ~/.my.cnf
      lineinfile:
        dest: ~/.my.cnf
        line: "[client]\nuser=root\npassword=samplepassword"
        create: yes

    - name: create new database
      mysql_db:
        name: wordpress
        state: present

    - name: add new user
      mysql_user:
        name: wordpress
        password: wordpress
        priv: "wordpress.*:ALL"
        host: localhost
        state: present

3. Ansibleを実行

Playbookの実行にはansible-playbookコマンドを使います。–syntax-checkなどをつけることで、構文チェックなどができます。

# 構文チェック
$ ansible-playbook playbook.yml --syntax-check
# タスクを確認
$ ansible-playbook playbook.yml --list-tasks
# 仮実行
$ ansible-playbook playbook.yml --check
# 実行
$ ansible-playbook playbook.yml

使ってみた感想としては、手軽に使えてYAMLで記述できるので見通しもよく扱いやすい印象。

その反面、ほかの人も指摘していますが複雑な処理は苦手そうといったイメージ。

ドメイン移転した時のウェブマスターツールの設定変更の方法

ドメイン移転をした時に忘れがちなウェブマスターツールの設定方法を紹介します。

1. 新しいドメインのプロパティを追加

まずは、既に追加してある旧ドメインのプロパティとは別に、新しいドメインのプロパティを追加します。

ウェブマスターツールから「プロパティを追加」をクリック。

2. 設定の「アドレス変更」を選択

サイトのダッシュボードの右上にある設定(歯車マーク)をクリックすると、「アドレス変更」があるのでこれを選びます。

webmastertool-domain1

もし「アドレス変更」が出ない場合は、サイトの「所有者」となっていない可能性があります。「管理者」と「所有者」は異なるので、注意が必要です。

3. アドレス変更リクエストを送信

・リストから新しいサイトを選択する
・301リダイレクトが正常に動作していることを確認する
・確認方法がまだ残っていることを確認する

の順にリダイレクトなどの各種確認をしていきます。

まず、リストから先ほど追加した新しいアドレスのプロパティを選択します。その後は、リダイレクトが適切に行われていれば「確認」ボタンを押すことで、緑のチェックマークが付きます。

そして、最後に「アドレス変更のリクエスト」を送信します。

webmastertool-domain2

4. Google Analyticsと連携している場合

忘れがちですが、Google Analyticsと連携している場合は、その再設定もする必要があります。

アナリティクス設定> プロパティ設定の一番下あたりにある「Search Consoleを調整」をクリック。

webmastertool-domain3

「Search Console のサイト」のURLの横にある編集ボタンをクリック。あとは新しいドメインのウェブマスターツールのプロパティを選択すれば完了です。

vimで日本語が文字化けした時に確認すべきこと&対処法

よくあるVimでの「文字化け」。

日本語がマルチバイトである以上、切っても切れない「文字化け」の対処法を紹介します。

文字化けファイルを開いて文字コードを確認

ここで確認する文字コードは、Vim本体の文字コードとファイルの文字コードです。

それぞれ、ファイルを開いて以下のコマンドで確認ができます。

コマンド 結果例
vimの文字コード確認 :set enc? encoding=utf-8
ファイルの文字コード確認 :set fenc? encoding=sjis

vimrcに設定を追加

Vim本体の文字コードとファイルの文字コードが異なっている場合は、文字コードを修正する必要があります。

「:set fenc=文字コード」でインスタントに変更することもできますが、設定ファイルvimrcを修正したほうが良いでしょう。

追記または修正するのは以下です。

set encoding=utf-8
set fileencodings=utf-8
set fileformats=unix,dos,mac

vimは文字コードの自動判定をするようなのですが、そこで誤判定をすることもけっこうあるようです。

なので、今回は使う文字コードをvimとファイルともにUTF-8に固定しています。

これで文字コードが原因の文字化けは対処できると思います。

Laravel4をCentOS6+nginx+PHP5.4でインストールする

最近人気があるLaravelを使うためのメモです。

【環境】
CentOS release 6.7 (Final)
PHP 5.4.44

composerからLaravelをインストール

composerを入れてない場合は以下のコマンドでインストール。

$curl -sS https://getcomposer.org/installer | php
$mv composer.phar /usr/local/bin/composer

その後、以下のコマンドでLaravelを入れます。PHPのバージョンが5.4だったので、最新のLaravel5ではなくLaravel4(日本語注釈付き)にします。

$composer create-project "laravel-ja/laravel=~4.2" your_app --prefer-dist

Mcrypt PHP extension required.が発生した場合

composerでLaravelを入れる時に以下のようなエラーが出ることがあります。これはPHP拡張機能である暗号化モジュールmcryptがPHPに入っていないために発生するようです。

  Mcrypt PHP extension required.
  Script php artisan clear-compiled handling the post-install-cmd event returned with an error

  [RuntimeException]
  Error Output:

yumでlibmcryptとphp-mcryptを入れます。

$yum --enablerepo=epel install libmcrypt
$yum --enablerepo=remi update
$yum install --enablerepo=remi php-mcrypt

PHPのバージョンや環境によっては上手くいかないこともあります。

どうしてもエラーが解決できない場合は、PHPをソースからビルドする時に「$./configure –with-mcrypt」のように–with-mcryptパラメータをつけることで拡張機能を入れることもできるようです。

mcrypyを入れたら以下のコマンドで「mcrypt support => enabled」となればOKです。

$php -i | grep -i mcrypt

nginxを使っているので、php-fpmをリスタートをしてmcryptを有効化させます。

$service php-fpm restart

nginxでLaravelを動かす

まず、app/storageのパーミッションを変更しておきます。

$chmod -R 777 app/storage

すでにnginxを利用している場合は、rootをLaravelのpublicディレクトリに向けるだけでOKです。

$vi /etc/nginx/conf.d/your_app.conf
  root /var/www/html/your_app/public;
$service nginx restart

URLにアクセスし「You have arrived.」と表示されていれば完了です。

あとはapp/config内のapp.phpやらdatabase.phpを設定すれば開発に取り掛かれそうです。

PHPで文字化けせずにCSVファイルを読み込む方法

CSVを読み込むと「文字化けしている…」ってことがよくありますよね。そんな時の対処法です。

文字化けせずにCSVファイルを読み込む

まず、SplFileObjectでCSVファイルを読み込みます。

fgetcsv()でもいいのですが、参考にさせて頂いた「【PHP】その CSV 変換、本当に「fgetcsv」でいいの?」によると、一番速くメモリの使用量も少ないのはSplFileObjectだそうなのでコレを使います。

また、エンコーディングは文字列ではないのでmb_convert_encoding()ではなく、mb_convert_variables()を使ってUTF8にエンコードします。

/**
* CSVから配列を作成する関数
*
* @param $csv string CSVファイルのパス
* @return $array array UTF8エンコード済の配列
*/
function csv_to_array($csv) {
  $file = new SplFileObject($csv);
  $file->setFlags(SplFileObject::READ_CSV);
  $array = array();
  foreach ($file as $line) {
    //空行はスキップ
    if (empty($line)) continue;
    $array[] = $line;
  }
  mb_convert_variables("UTF-8", array("ASCII","JIS","UTF-8","EUC-JP","SJIS"), $array);
  return $array;
}

こんな感じで読み込めます。

$data = csv_to_array("ファイル名.csv");

PHPでスクレイピング&本文抽出をする方法・ライブラリ

引用する記事のタイトル&本文の抜粋を取得したい!

ということで、PHPでスクレイピング&本文抽出する方法を調べてみました。

本文抽出に使用するライブラリ

いろいろと選択肢はあったのですが、今回はfivefilters.orgのPHP Readabilityを使ってみることにしました。

BitBucketのPHP Readabilityのレポジトリのものより、同じfivefilters.orgのFull-Text RSSレポジトリに使われているPHP Readabilityのほうが新しいっぽいのでこっちを使います。

ちなみにFull-Text RSS最新版のダウンロードは有償ですが、古いバージョンは無料で利用できます。また、APIの提供などもされているようなので気になる人は公式サイトをチェックしてみてください。

git cloneして、libraries / readability を好きなディレクトリに移動します。

$ git clone https://bitbucket.org/fivefilters/full-text-rss.git

PHP Readabilityの使い方

PHP Readabilityの使い方は簡単で、Readability.phpをrequireしてnew Readability($html, $url)とするだけです。


require_once '/PathToLibrary/readability/Readability.php';

//取得する記事URLを指定
$url = 'http://web-tsukuru.com/270';

//URLからHTMLを取得してUTF8にエンコーディング
$html = file_get_contents($url);
$html = mb_convert_encoding($html, "UTF-8", "ASCII,JIS,UTF-8,EUC-JP,SJIS" );

//tidy_parse_stringが使用可能であれば、
//tidy::cleanRepairでHTMLの誤りなどを修正
if (function_exists('tidy_parse_string')) {
  $tidy = tidy_parse_string($html, array(), 'UTF8');
  $tidy->cleanRepair();
  $html = $tidy->value;
}

//Readabilityを初期化
$readability = new Readability($html, $url);
$result = $readability->init();

if ( empty($result) ) return false;

//タイトルを取得
$title =  $readability->getTitle()->textContent;

//記事本文を取得
$content = $readability->getContent()->innerHTML;

//再度、tidy_parse_stringを使用
if (function_exists('tidy_parse_string')) {
  $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8');
  $tidy->cleanRepair();
  $content = $tidy->value;
}

タイトルの取得は、

$title =  $readability->getTitle()->textContent;

記事本文の取得は、

$content = $readability->getContent()->innerHTML;

のようにできます。

記事本文はHTMLをそのまま取得しているので、strip_tags()などでHTMLを除去すると良さそうです。

そのほかのPHPで本文抽出する方法

有名なReadabilityは本文抽出に使えるAPIを非商用で提供しているみたいです。APIだと提供終了する可能性があるので、ちょっと微妙ですが軽く使ってみるには良さそうですね。

Readability Developer APIs

そのほか、今回は使ってないですが以下のようなライブラリがあるみたいです。
https://github.com/scotteh/php-goose
https://github.com/essence/essence

また、Quoraに投げられた「HTMLから本文抽出する一番の方法は?」という質問も参考になります。

Quora | What’s the best method to extract article text from HTML documents?

PHP以外だとJavaのboilerpipeあたりが有名みたいです。