maenok

maeno

Front End Web Developer / WordPresser / Web Design / Infrastructure engineer / PHP / Ruby / JavaScript / CSS / html / AWS / Capistrano / git / markdown ...
  • Capistranoで新規作成したEC2インスタンスにSSH接続する

    前回に引き続き、Capistranoで新たに作成したEC2インスタンスにSSHでログインしてみます。

    まず、事前準備として、AWS側で新規インスタンス用のキーペアを作成しておきます。AWSマネージメントコンソールの「EC2」メニューから「NETWORK & SECURITY」カテゴリの「Key Pairs」メニューで、キーペアを作成できるので、必要に応じて作成してください。本項の例では、「deploy-test」というCapistranoが稼動しているデプロイ環境用インスタンスで使用しているキーペアを使います。

    AWSマネージメントコンソール:キーペア

    そして、利用するキーペアのプライベートキーファイル(本項例ではdeploy-test.pemファイル)をCapistranoを実行するデプロイ環境のデプロイを実行するユーザのホームディレクトリ(本項例では/home/deploy-user/)にアップロードしておきます1。 アップロードしたプライベートキーには適切な読み込み権限を付与しておく必要があるので、ファイルのパーミッションを変更します。

    $ cd ~
    $ chmod 600 deploy-test.pem
    $ ls -l *.pem
    -rw------- 1 deploy-user deploy-user 1692 Jul  2 10:18 deploy-test.pem
    

    デプロイ設定ファイルconfig/deploy.rbは下記のように修正。

    # config valid only for Capistrano 3.1
    lock '3.2.1'
    
    # AWS SDK for Ruby を読み込む
    require 'aws-sdk'
    
    # AWS SDK用の設定
    AWS.config({
      :access_key_id => '<AWS ACCESS KEY ID>', 
      :secret_access_key => '<AWS SECRET ACCESS KEY>', 
      :region => 'ap-northeast-1', 
    })
    
    # AMIのimage_id
    # Amazon Linux AMI 2014.03.2 (HVM)
    set :ami_image_id, 'ami-29dc9228'
    
    # 作成するInstance数
    set :instance_count, 2
    
    # 作成するInstanceタイプ
    set :ec2_instance_type, 't2.micro'
    
    # 作成先のAvailability Zones
    set :availability_zones, [ 'ap-northeast-1a', 'ap-northeast-1c' ]
    
    # 作成先のsubnet_id(必要に応じて)
    set :subnet_ids, [ 'subnet-********', 'subnet-********' ]
    
    # 使用するキーペア名
    set :key_pair_name, 'deploy-test'
    
    # プライベートキーファイル
    set :privert_key_file, 'deploy-test.pem'
    
    # 利用するセキュリティグループID
    set :security_groups, [ 'sg-********', 'sg-********', 'sg-********', 'sg-********' ]
    
    # Capistranoデフォルトのタスクを削除する
    framework_tasks = [:starting, :started, :updating, :updated, :publishing, :published, :finishing, :finished]
    framework_tasks.each do |t|
      Rake::Task["deploy:#{t}"].clear
    end
    Rake::Task[:deploy].clear
    
    desc 'Launch an EC2 instance to each availability zone different'
    task :launch do
      run_locally do
        ec2 = AWS::EC2.new
    
        created_instances = []
        cnt = 0
        while cnt < fetch(:instance_count) do
          if cnt.even? then
            current_az = fetch(:availability_zones)[0]
            current_sn = fetch(:subnet_ids)[0]
          else
            current_az = fetch(:availability_zones)[1]
            current_sn = fetch(:subnet_ids)[1]
          end
          i = ec2.instances.create(
            :image_id => fetch(:ami_image_id),
            :monitoring_enabled => false,
            :availability_zone => current_az,
            :subnet => current_sn,
            :key_name => fetch(:key_pair_name),
            :security_group_ids => fetch(:security_groups),
            :disable_api_termination => true,
            :instance_type => fetch(:ec2_instance_type),
            :count => 1,
            :associate_public_ip_address => true
          )
          sleep 10 while i.status == :panding
          created_instances << i.id
          cnt += 1
        end
        execute "echo -n #{created_instances} > ~/CREATED_INSTANCES"
    
      end
    end
    

    では、インスタンスラウンチタスクを実行してみます。

    ...
  • CapistranoでAWS EC2インスタンスをデプロイする時の注意点

    前回のデプロイ設定ファイルで新たに作成されたEC2インスタンスには、キーペアセキュリティグループなどが設定されていなかったため、そのままでは作成したインスタンスにSSHでアクセスできませんでした…1orz

    その後、色々とデプロイ設定を修正して、作成したEC2インスタンスにSSHでログインするところまで出来たので、その経緯を備忘録として書いてみた次第。 まぁ、CapistranoでAWSのEC2インスタンスを作成する際…というより、「AWS SDK for Ruby」でEC2インスタンスを作成する時の注意点…に近いのかもしれない。

    まず、前回のconfig/deploy.rbからインスタンスラウンチのタスク部分を見てみる。

    desc 'Launch an EC2 instance to each availability zone different'
    task :launch do
      run_locally do
        ec2 = AWS::EC2.new
    
        created_instances = []
        cnt = 0
        while cnt < fetch(:instance_count) do
          if cnt.even? then
            current_az = fetch(:availability_zones)[0]
            current_sn = fetch(:subnet_ids)[0]
          else
            current_az = fetch(:availability_zones)[1]
            current_sn = fetch(:subnet_ids)[1]
          end
          i = ec2.instances.create(
            :image_id => fetch(:ami_image_id), 
            :availability_zone => current_az,
            :subnet => current_sn, 
            :instance_type => fetch(:ec2_instance_type), 
            :count => 1
          )
          sleep 10 while i.status == :panding
          created_instances << i.id
          cnt += 1
        end
        execute "echo -n #{created_instances} > ~/CREATED_INSTANCES"
    
      end
    end
    

    作成するインスタンスに対して、AvailabilityZoneとSubnetの設定しかしていないので、そりゃあアクセス不能になります。最低限、セキュリティグループを設定して、外部からのアクセス経路を確保して、キーペアを設定して認証ユーザがログイン可能にしてあげる必要はあります。あとは、PublicIP(PublicDNS)を自動で割り振られるようにして、インターネットからのアクセスも出来るようにしておくあたりまでが、最小設定となるかと。

    ...
  • Capistranoで異なるAvilabilityZoneにEC2インスタンスをラウンチする

    前回、

    次回はデータベースの作成や初期設定を直前タスクとして挿入して、さらにWordPressの設定ファイルの書き換え、GitHubからWordPressテーマをダウンロードするところまでやってみようと思います。

    とか云っていたのですが、都合によりCapistrano3を使ってAWSのEC2インスタンス作成を行ったので、そのTIPSを残しておこうかと思います。 今回は、デプロイ用のEC2インスタンスから公式のAMIを利用してAvailabilityZonesが異なるエリアにそれぞれEC2インスタンスを立ててみました。試験的に、AMIは最新のインスタンスタイプ「t2.micro」に対応した「Amazon Linux AMI 2014.03.2 (HVM)」を利用して、Tokyoリージョンの1aと1cのAvailabilityZoneにそれぞれ2台ずつ、合計4インスタンスを同時に立ててみます。

    ※ 事前準備として、インスタンスを立てるAWSアカウントにてVPCやSubnet等EC2インスタンスを作成する上で必要最小限の設定をしておく必要があります。特に今回は異なるAvailabilityZoneへのインスタンスを立てるのでそれぞれのゾーンにSubnetを設定しておく必要があります。

    さて、早速デプロイの手順です。 はじめに、デプロイ環境(サーバ)の設定を行うため、config/deploy/test.rbを編集します。 今回は動的に作成したEC2インスタンスをデプロイ環境とするため、事前のサーバ設定ができません。というのも、AWSで立ち上がる新規インスタンスにはElasticIPを付与しないので、毎回PublicIPが異なり、エンドポイントURLも動的に変わってしまうためです。なので、今回はインスタンスが起動した後にCapistoranoのタスクにて対象サーバを設定するようにします。 初期のサーバ設定は不要となるので、記述をコメントアウトしておきます。なお、SSHのオプションだけは最終的に共通で利用する予定なので残しておきます(今回のデプロイタスクでは使いませんが…)。

    $ vim config/deploy/test.rb
    
    #role :app, %w{deploy@localhost}
    #role :web, %w{deploy@localhost}
    #role :db, %w{deploy@localhost}
    
    set :ssh_options, {
      keys: %w(/home/deploy/.ssh/id_rsa),
      forward_agent: true,
    }
    

    今回のデプロイでは、「AWS SDK for Ruby」を利用するので、あらかじめSDKをインストールしておきます。

    $ sudo gem install aws-sdk
    

    次に、config/deploy.rbにデプロイ内容を設定します。

    $ vim config/deploy.rb
    
    # config valid only for Capistrano 3.1
    lock '3.2.1'
    
    # AWS SDK for Ruby を読み込む
    require 'aws-sdk'
    
    # AWS SDK用の設定
    AWS.config({
      :access_key_id => '<AWSアカウントのACCESS KEY ID>', 
      :secret_access_key => '<AWSアカウントのSECRET ACCESS KEY>', 
      :region => 'ap-northeast-1', # EC2 Instanceを作成するリージョン
    })
    
    # AMIのimage_id
    # Amazon Linux AMI 2014.03.2 (HVM)
    set :ami_image_id, 'ami-29dc9228'
    
    # 作成するInstance数
    set :instance_count, 4
    
    # 作成するInstanceタイプ
    set :ec2_instance_type, 't2.micro'
    
    # 作成先のAvailability Zones
    set :availability_zones, [ 'ap-northeast-1a', 'ap-northeast-1c' ]
    
    # 作成先のsubnet_id
    set :subnet_ids, [ 'subnet-********', 'subnet-********' ]
    
    # Capistranoデフォルトのタスクを削除する
    framework_tasks = [:starting, :started, :updating, :updated, :publishing, :published, :finishing, :finished]
    framework_tasks.each do |t|
      Rake::Task["deploy:#{t}"].clear
    end
    Rake::Task[:deploy].clear
    
    desc 'Launch an EC2 instance to each availability zone different'
    task :launch do
      run_locally do
        ec2 = AWS::EC2.new
    
        created_instances = []
        cnt = 0
        while cnt < fetch(:instance_count) do
          if cnt.even? then
            current_az = fetch(:availability_zones)[0]
            current_sn = fetch(:subnet_ids)[0]
          else
            current_az = fetch(:availability_zones)[1]
            current_sn = fetch(:subnet_ids)[1]
          end
          i = ec2.instances.create(
            :image_id => fetch(:ami_image_id), 
            :availability_zone => current_az,
            :subnet => current_sn, 
            :instance_type => fetch(:ec2_instance_type), 
            :count => 1
          )
          sleep 10 while i.status == :panding
          created_instances << i.id
          cnt += 1
        end
        execute "echo -n #{created_instances} > ~/CREATED_INSTANCES"
    
      end
    end
    
    desc 'Check the activation status of new instances'
    task :check do
      created_instances_list = 'CREATED_INSTANCES'
    
      run_locally do
        ec2 = AWS::EC2.new
    
        begin
          if test "[ -f ~/#{created_instances_list} ]"
            created_instances = capture("cd ~; cat #{created_instances_list}").chomp
            ci = created_instances.gsub(/(\[|\s|\])/, '').split(',')
            target_instances = ec2.instances.select { |i| i.exists? && i.status == :running && ci.include?(i.id) }.map(&:private_ip_address)
            if target_instances.length == 0 then
              raise "No created instances"
            end
            target_instances.each { |var| 
              server var, user: 'ec2-user', roles: %w{web app}
            }
          end
        rescue => e
          info e
          exit
        end
    
      end
    end
    
    task :deploy => :check do
      run_locally do
    
        info roles(:all)
        info 'Next task of deploy on new instances'
    
        # deploy start
    
      end
    end
    

    実際にインスタンスのラウンチをしてみる。

    ...
  • Capistrano3でWordPressのデプロイをしてみる

    Capistrano3を使って、自ホストに最新版のWordPressをデプロイしてみたのでその手順をログとして残しつつ、デプロイツール「Capistrano」の理解を進めていこうと思います。 事前準備として、デプロイ用の環境をAmazonEC2にt2.microインスタンスとしてラウンチして、WordPressが動作する環境(Apache+MySQL+PHP)、Rubygem(とRVM)、そしてCapistrano3のインストールまで出来ている状態で記載しています(この辺の事前準備の手順も後日TIPSとしてまとめたいと思っていますが、今回は省略します)。

    さて、早速手順に入ります。 はじめに、デプロイプロジェクト用のディレクトリを作成して、Capistranoをインストールします。

    $ cd ~
    $ mkdir test-project
    $ cd test-project
    $ cap install STAGES=test
    mkdir -p config/deploy
    create config/deploy.rb
    create config/deploy/test.rb
    mkdir -p lib/capistrano/tasks
    Capified
    

    Capistrano3ではマルチステージデプロイ機能がデフォルトでONになっているので、単にcap installを行っただけだと、productionステージとstagingステージが作成されてしまいます。 今回はテスト用に自分のローカルホストのみを対象にデプロイを試すので、testステージのみのプロジェクトを環境変数STAGESの引数に指定します1

    次にCapistranoの初期設定を行います。必要ならば、プロジェクトディレクトリ直下に作成されたCapfileを編集します。

    $ vim Capfile
    

    今回はrvmやrbenvをデプロイに使わないので、編集項目はありません2

    続いて、デプロイ環境(サーバ)の設定を行うため、config/deploy/test.rbを編集します。

    $ vim config/deploy/test.rb
    ----
    role :app, %w{deploy@localhost}
    role :web, %w{deploy@localhost}
    role :db, %w{deploy@localhost}
    
    set :ssh_options, {
      keys: %w(/home/deploy/.ssh/id_rsa),
      forward_agent: true,
    }
    

    そして、config/deploy.rbにデプロイ内容を設定します。

    ...
  • WordPressのサイトが重くなった時のプラグインパフォーマンス検証

    とある多国語サイトをWordPressで構築している時に、結合試験もほぼ終わったあたりで、構築サイト全体のパフォーマンス・チューニングをしていた時の備忘録です。
    対象のサイトは規模がそんなに大きくなかったので、AWSのm3.mediumのインスタンスに構築していたのだが、開発途中からサイト全体のパフォーマンスが落ちて、だいぶ重いサイトになって来てました。サイトのパフォーマンス検証「GTmetrix」でのレポートを見ると、サイト内で利用している画像のレスポンスがレイテンシー食っているという結果しか出ず、とりあえずは出来る限りの画像最適化を行って、フロントエンドのパフォーマンスはだいぶ良くなったのだが、WordPressの管理画面は重いまま変わらなかった。WEBサーバ側で静的コンテンツのGZIP圧縮や、.htaccessを利用せずにhttpd.conf内に設定を移行など、諸々対応してみたが効果はなかった。他にMySQLTunerでDBの設定を検証・チューニングしてみたが、特に変化なし。
    う~む、CloudWatchを見るとCPU使用量がやけに大きいので、AWSインスタンスの非力さが原因なのかも…そうなると、最終的にはm3.mediumインスタンスからc3系へのインスタンス変更が必要かも知れないなぁ…とか考えていたのだが、そもそも開発中のサイトで社内の数人しかアクセスしない管理画面が重いというのは根本的に別の要因があるはず。サイト全体に関わるものというと、テーマかプラグインかしかない。そこで、導入しているプラグインのパフォーマンス検証を行ってみたところ、ビンゴ!…パフォーマンス低下の原因はプラグインだった。

    今回プラグインのパフォーマンス検証に利用したのが「P3(Plugin Performance Profiler)」だ。プラグインのパフォーマンスを検証するのに別のプラグインを入れるというのも変な話だが、このP3プラグインはWordPressサイト内でのプラグインやテーマのパフォーマンスを細かいところまでスキャン・レポーティングしてくれるかなり優秀なものだ。導入も簡単で、プラグインをダウンロードして有効化すればいつでも管理メニューの「ツール」からパフォーマンススキャンができる。

    このP3プラグインでスキャンした結果はこうなった。

    p3_before

    多言語化プラグインの「Polylang」とカスタム投稿タイプ系プラグインの「Types」がランタイムを圧迫しているのがわかる。さすがに多言語サイトなので「Polylang」は外せないが、カスタム投稿タイプ系のプラグインは同系プラグインが多いので差し替え可能だ。「Types」は「Polylang」に公式対応しているプラグインなので採用していたのだが、たかだかカスタム投稿の拡張をするだけで、ここまでランタイムを占有されてはちょっと使い勝手が良いとは言えない。
    そこで、「Types」プラグインを外して、同系で使い慣れている「Custom PostType UI」プラグインを導入してみた。

    p3_after

    「Types」で占有されていたランタイムがなくなり、プラグインロードタイムやプラグインインパクトが改善された。管理画面の体感速度も数十倍に向上し、本来のサクサク編集できるUXが復活した。プラグイン一つでここまでパフォーマンスが変わるものなんだなぁ…と実感できました。

    今回の件から、今後WordPressサイトを作る際には、プラグインの機能よりもパフォーマンスを重視して選定した方が良いと私的には思えました。なぜなら、プラグインの機能で足りないものは後からいくらでも追加することができるが、プラグインのコアに依存するパフォーマンスを改修するのは非常に困難だからです。
    特に管理画面が重いと、サイトを運用するWEB担当者のモチベーションがかなり下がってしまうので、ちょっと機能不足でもストレスなく運用できる管理画面の方が喜ばれるのではないだろうか。

    ...
  • 要素が1つしかない連想配列のネストを解消する

    WordPress関数(特に$wpdbクラスなどに多い。get_results()メソッドでDBの値をとって来たときなど)を使っていて、戻り値の配列が一つしか要素持ってないのに連想配列になっていたりする場合、値を取り出すときにネストしたループ処理を書くケースが結構ある。 以前からコード的に冗長で非効率だよなぁ…と思っていて、今回改善方法を見出してスッキリしたので、ここにTIPSとして残しておこうかと。

    $array = array(
        array(
            'key_1' => 'value_1', 
            'key_2' => 'value_2', 
        ), 
    );
    
    foreach ($array as $nested_array) {
        foreach ($nested_array as $key => $value) {
            echo 'array["' . $key . '"] => "' . $value . '"<br />';
        }
    }
    

    今まではこんな感じに(無駄ではないのだが、効率的ではない)foreachループを連想配列の入れ子分回して値取ってた…。 で、この連想配列とループのネストを解消してシンプルに処理を書けないものか…とPHPのarray関数を色々と試してみた。array_reduce()とかarray_walk()とかあんまり使わない関数で、独自にネスト解消用の関数組んでもできるんだが、別途独自関数用意しなきゃならなくてまるでスマートでない…。なんかスパっと1ラインで解決できないかと試行錯誤してみたところ、ありました! array_shift()で先頭要素取得して元の配列変数を上書きしてしまえばいいのです。

    $array = array_shift($array);
    

    たったこれだけ(笑) でも、これだけだと配列の要素数が1つ以上でも上書きしてしまうので、要素数の判定を入れておく。

    $array = (count($array) == 1) ? array_shift($array) : $array;
    

    最初のコードをこのコード使って書き直してみると、

    ...
  • InternetExplorer11で変更されたUserAgent書式に対応する

    今まで問題なく稼動していたとあるシステムにて、InternetExplorer11(以下IE11)のブラウザにて不具合が発生する旨の報告を受けて調べたところ、IE11ではユーザーエージェントの書式が変更になっていて、ブラウザ判定処理が「不明なブラウザ」として処理されていたことがわかった。
    今までユーザーエージェントのブラウザバージョントークン(UAの"MSIE 9.0"とか書いてある部分)でIEブラウザの判定とIEバージョンを取得していたのだが、IE11からはこのブラウザバージョントークンがなくなってしまい、新たに"rv"というリビジョントークンが設けられてました(※IE11標準ブラウザモード)。
    今後IE11を含めてユニークにIEを判定するには、ブラウザエンジンであるトライデントトークン(UAの"Trident/7.0"とか書いてある部分)の存在確認もOR条件で判定しないといけなくなった。

    IE11のUserAgent

    • [ブラウザモード:標準] Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko
    • [ブラウザモード:互換表示] Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0)

    問題なのが、IEの互換表示モードだ。IEの互換表示モードはIE9から導入された機能だが、このモードにすると現状の全てのIEにおいてUAのブラウザバージョントークンがIE7となってしまう。互換表示の際についても正確にIE11と判定させるには、まずトライデントトークンを先に判定して、トライデントのバージョンが7.0以上だったらIE11として判定しリビジョントークンからブラウザバージョンを取得し、それ以外はブラウザバージョントークンからバージョンを取得するという処理にする必要がある。さらにIE11より下位の互換表示モードをもつIE9とIE10用の処理も必要だ。
    また、IE7以下はトライデントトークンを持っていないので、IE7用の判定処理も別途必要となる…(いやはや、まるで嫌がらせのような仕様だな…)。

    試しにこのDEVLABで利用している独自のクライアントデバイス判定処理(PHP)で、IE11にも対応した判定処理に修正してみた。

    まずは、今までのIE判定処理内容。
    [php] $ua = $_SERVER[‘HTTP_USER_AGENT’]; $results[‘browser’] = ‘’; $results[‘version’] = ‘’; if (preg_match(’/(MSIE \d{1,}?(.\d{1,}?){1,}?;)/’, $ua, $mtcs)) { $results[‘browser’] = ‘msie’; list(, $vstr) = explode(’ ‘, str_replace(’;’, ‘’, $mtcs[0])); $results[‘version’] = $vstr; } [/php]

    ...
  • DEVLABをリニューアルしました

    2014年 明けましておめでとうございます。

    年末年始の休暇を利用してDEVLABのサイトリニューアルを行いました。

    何気に3回目のリニューアルなのですが、今回はWordPressのテーマ自体を新しく作り直したので結構大規模リニューアルになりました。正月の後半は半ば家族サービス放棄で連日徹夜気味に作業してました・・・(笑)

    また、今回のリニューアルタイミングにてWordPressも3.7.1へアップグレードしました。実は年末にバージョン3.8も出ていたのですが、まだ日本語ローカライズ版は提供されていないので、最新安定版の3.7.1までとしてあります。

    昨年は多忙にかまけて投稿機会を逸してなかなか投稿数が伸びなかった私maenoですが、今年は心機一転して色々と投稿して行きたいと思いますので、本年もDEVLABともども弊社デベロッパーメンバーをよろしくお願いいたします。

    ...
  • WordPressサイトを簡単に他国語化できるプラグイン

    qTranslate プラグイン

    図1: qTranslate プラグイン

    WordPressはGNUのGettextを取り入れて多言語対応しているものの、実際に1つのサイトで多国語化を実現しようとすると、色々と困難な問題に突き当たる。とある開発案件にて多国語化の要望があったので、色々と言語系のプラグインなどを調べていたところ、見つけたのが「qTranslate」プラグインだ。

    このプラグイン、サイト全体の言語管理と各投稿毎(コンテンツ毎)の言語管理を一括で行えるという優れもののプラグインである。

    qTranslate プラグイン 2 図2: 管理パネルのメニュー

    管理パネルのメニューにてプラグインで指定した複数の言語を切り替えられるようになる(図2参照)のは序の口で、サイトのフロントエンド側からも言語を切り替えられる(切り替えのUIは別途作る必要はあるが…)。切り替え方も、ブラウザの言語設定に応じて自動化したり、訪問者の手動切り替えや、URLパラメータによる一時的な切り替えなど、色々と選べる。
    そして、極めつけが、それぞれ個別の投稿に対して別言語によるコンテンツを同時に投稿できる点が素晴らしい機能である。

    サイトの多国語化対応に際して一番大きな障壁が、サイトのメニューやフッター、ボタンといった共用コンテンツは言語ファイルにて他国語化できても投稿等のコンテンツはそれぞれ個別に管理しなければならないという点だ。例えば、日本語でアップした投稿と英語でアップした投稿はそれぞれ個別のコンテンツであり、それらを同じ一つのコンテンツとして管理するためには別の仕組みが必要だった。投稿のUI的にも同時に複数言語の記事が書けないことがネックとなって、サイトの保守性や利便性に難があったのだが、このプラグインはそれらの問題を一挙に解決してくれるのだ。

    ということで、モノは試しに、この記事を日本語と英語両方で投稿してみた。英語版を見てみる場合はこのリンクをクリックしてみて欲しい。

    qTranslate プラグイン 3

    図3: プラグイン設定画面

    「qTranslate」プラグインは2013年6月19日現在のバージョンが2.5.34であり、同梱されている日本語翻訳ファイルが古く、一部翻訳されない部分があったので、私の方で最新バージョンに合わせた翻訳を行ってみた。

    ※ 下記でダウンロードできた .mo ファイルを qTranslate プラグインの lang フォルダ内に入れてやる(上書きする)ことで最新の翻訳が反映されます。

    qTranslate プラグイン 日本語化ファイル

    動作確認:WordPress 3.5.1 / qTranslate 2.5.34

    ...
  • DEVLABはNginx環境に移行しました

    2013年3月末週、DEVLABサイトの環境移管を人知れず行ってました。
    今週の4/2頃まではDEVLABにアクセスした人の中には、サイトが表示されなかったり、不具合が起きていた人もいたかもしれませんが、それらはすべて環境移管に伴う余波としてご理解いただけますと幸いです。まぁ、DEVLABの存在意義と運営方針の一つとして、「インターネットに関わる技術の研究開発のためには恐れずに何でもやってみよう!」というコンセプトを持っているので、今後もISAO社のDEVLABに関わるエンジニアの「好奇心の趣くままに」「衝動的に」「たとえサイトが壊れるとしても」色々とやって行くので、もしサイト来た時に変な動きをしていても ―― お、今何かやっているのかな?――と、温かく見守っていただきたいです(単なるバグの可能性もありますが、それも含みで)。

    そんなこんなで、DEVLABの環境を今までのApache環境から今流行りのNginx環境に移管した次第。
    さらに、noSQLデータベースの「MongoDB」やNode.jsもインストールして、今後は「リアルタイムWEBアプリケーション」の開発もできるように整備したのですが、これはISAO社のエンジニア向けの環境整備なので、DEVLAB側には今のところ影響はないかと。

    さて、巷では「Nginx+リバースプロクシ+WordPress」の構成でWordPressのサイトパフォーマンスが劇的に向上すると云われているので、早速本DEVLABでもその施策を実施してみました。
    結果、1ページ単位での表示レスポンス(レイテンシー)は特に変化はなかった(単ページ単位だと、逆にレスポンスはApacheの方が勝ってました…が、体感速度的には変わらなかった)のだが、Jmeterで負荷テストしてみたら、多数の同時リクエストが発生した際のNginxのレスポンスはかなり驚異的な向上が見られた次第。
    実際にDEVLABのTOPページのリクエストレスポンスを比較したら、Nginx環境ではApacheの約23倍ほどもレスポンスが向上しました。
    いやぁ、Nginxスゴイ!という感想でした。

    ま、DEVLABは常時負荷が高まるほどアクセスされないので、今のところNginx環境も宝の持ち腐れ的な感があるんですけどね…。

    ...
  • iPhoneやiPadで撮影した画像を他のデバイスで見ると自動で回転してしまう場合の対処法

    .iphone { position: relative; height: 123.75px; width: 62.5px; border-radius: 8.75px; margin: 12.5px auto; background: -webkit-linear-gradient(-165deg, rgba(255,255,255,0.4), rgba(255,255,255,0.15) 35%, transparent 35%), -webkit-linear-gradient(top, transparent 21.25px, #222222 21.25px, #151515 102.5px, transparent 102.5px), -webkit-linear-gradient(top, #000, #0a0a0a); background-repeat: no-repeat; background-size: 100% 100%, 55px 100%, 100% 100%; background-position: 0 0, 3.75px 0, 0 0; box-shadow: 0 0 0 0.75px black, -10px -32px 0 -30.75px black, 0 0 0 1.25px #a09f9d, 12.25px -32.5px 0.75px -30.75px #777, 11.5px -32.5px 0.5px -30.75px #ddd, 15.5px -27.75px 0 -26.25px #8e8d8b, 15.5px -28px 0 -26.25px #b4b3b1, 15.5px -28.25px 0 -26.25px #666; } .iphone:after { content: ‘▢’; line-height: 11.5px; text-align: center; font-size: 7px; color: #666; position: absolute; width: 11.5px; height: 11.5px; border-radius: 50%; background: white; bottom: 4.5px; left: 25px; border: 0.5px solid #0a0a0a; background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.85), black); box-shadow: -9.75px -102.5px 0 -5.75px #000f31, -9.75px -102.5px 0 -5.5px #0a1c5a, -10px -102.5px 0 -5.25px #0d1216, -10px -102.5px 0 -4.75px #1b191a, -3px -102.5px 0 -5.5px #333, -2px -102.5px 0 -5.5px #333, -1px -102.5px 0 -5.5px #333, -0px -102.5px 0 -5.5px #333, 1px -102.5px 0 -5.5px #333, 2px -102.5px 0 -5.5px #333, 3px -102.5px 0 -5.5px #333, 4px -102.5px 0 -5.5px #333, 5px -102.5px 0 -5.5px #333, 6px -102.5px 0 -5.5px #333, -3px -102.5px 0 -4.5px #0a0a0a, -2.25px -102.5px 0 -4.5px #0a0a0a, -1.5px -102.5px 0 -4.5px #0a0a0a, -0.75px -102.5px 0 -4.5px #0a0a0a, 0px -102.5px 0 -4.5px #0a0a0a, 0.75px -102.5px 0 -4.5px #0a0a0a, 1.5px -102.5px 0 -4.5px #0a0a0a, 2.25px -102.5px 0 -4.5px #0a0a0a, 3px -102.5px 0 -4.5px #0a0a0a, 3.75px -102.5px 0 -4.5px #0a0a0a, 4.5px -102.5px 0 -4.5px #0a0a0a, 5.25px -102.5px 0 -4.5px #0a0a0a, 6px -102.5px 0 -4.5px #0a0a0a; } .iphone:before { position: absolute; content: ‘’; width: 0.5px; height: 29.25px; background: transparent; top: 10px; left: -1.75px; background-image: -webkit-linear-gradient(left, transparent 0px, transparent 0.25px, #7a7879 0.5px), -webkit-linear-gradient(top, #383838 0.25px, #b9b9b9 0.75px, #b9b9b9 2.5px, #383838 4.75px, #b9b9b9 5.75px, transparent 5.75px, transparent 13.25px, #383838 13.25px, #b9b9b9 13.5px, #dadada 14.5px, #383838 15.5px, black 15.5px, black 16.5px, #383838 16.5px, #b9b9b9 16.75px, #dadada 17px, #383838 17.5px, transparent 17.5px, transparent 25px, #383838 25px, #b9b9b9 25.25px, #dadada 26.25px, #383838 27.25px, black 27.25px, black 28.25px, #383838 28.25px, #b9b9b9 28.5px, #dadada 28.75px, #383838 29.25px); } .display { position: absolute; top: 21.75px; left: 2px; width: 56px; height: 80px; margin: 0; padding: auto; background: #fafafa; border: solid 1px #afafaf; font-size: 24px; font-weight: bold; line-height: 78px; text-align: center; vertical-align: middle; } .rotate_90deg { -moz-transform: rotateZ(90deg); -webkit-transform: rotateZ(90deg); -o-transform: rotateZ(90deg); } .rotate_180deg { -moz-transform: rotateZ(180deg); -webkit-transform: rotateZ(180deg); -o-transform: rotateZ(180deg); } .rotate_270deg { -moz-transform: rotateZ(270deg); -webkit-transform: rotateZ(270deg); -o-transform: rotateZ(270deg); } .device_deg_list { margin: 1em auto 2em; padding: 0; background: #ffffff; border: solid 1px #999999; } .device_deg_list th { padding: 2px; background: #d0d0d0; font-weight: bold; } .device_deg_list td { text-align: center; vertical-align: middle; } .device_deg_list td.odd { background: #f0f0f0; } .device_deg_list td.visual { width: 160px; text-align: center; vertical-align: middle; } .device_deg_list td.orientation { min-width: 120px; } .device_deg_list td.resampling { min-width: 200px; } .exif-value{ clear: both; display: block; font-size: 9px; color: #808080; }

    ...
  • jQuery 1.9 で変更された仕様によって動かなくなるプラグインが多い

    code { padding: 2px; background-color: #f4f4f4; color: #7f0055; font-weight: bold; border: solid 1px #ddd; } blockquote { margin-left: 1em; font-size: 12px; line-height: 17px; background-color: #fdfdfd; border: solid 1px #ccc; padding: 4px; font-style: normal; }

    現在開発しているあるシステムで、最新のjQuery 1.9.1を導入して開発を行っていたところ、先月開発していたシステムでは動いていて、同じように実装したはずなのに動かないjQueryプラグインがあってハマりました。それがWordPressのコアに同梱されている「thickbox」でして、管理パネルでは動いて、テーマ側で動かないのは何故だろうと思って調べてみたところ、読み込んでいるコアのjQueryが1.8系と1.9系と差があった。もしや・・・と思って、jQuery 1.9系の仕様変更内容を調べてみたら、おっと、今までかなり重宝していたメソッドがなくなっているではありませんか。
    将来的に削除されることは知っていたけど、使い勝手が良くて使っていた$.browser()と、何気に動的に生成されたDOMオブジェクトに対して適応性が低い$.bind()より汎用的に使えるため重宝していた$.live()などが削除されてしまったため、これらのメソッドを使っているjQueryプラグインではエラーが発生してしまうようになってしまいました。
    ・・・と言うことで、jQuery 1.9系での主な仕様変更をまとめてみた。

    1. $.browser()が廃止1.3からサポート外に指定されてましたが、ついにメソッドが削除されてしまった・・・何気にお手軽にブラウザ判定できるので使い勝手良かったんだが・・・致し方ないですね。これからは、$.support()を使って判定式を組まないといかんです。

    2. $.live()が廃止

      $.bind()の拡張版メソッドで、bindはjQueryやJavaScriptで動的に生成されたオブジェクトに対して処理をバインドできなかったのを可能にするメソッド。これも使い勝手が良くて重宝していたのだが・・・廃止されてしまった。今後は$.on()$.off()を使えってことです。まぁ、バインドイベントのオン・オフを判り易く制御できるのでこちらの方が確かにスマートだ。

    3. $.die()が廃止

      上記live関数を削除するメソッドです。liveがなければこちらも不要ということですね。

    4. $.sub()が廃止

      プロパティとメソッドが自由に変更可能なコアjQueryオブジェクトのコピーを作成するメソッドです。プラグイン開発などで、コアを変更せずに、独自にjQueryコアを拡張する時などに使われていましたが、結構巨大なjQueryコア自体をコピーしてメモリ食いまくってまで作るプラグインもないだろう・・・という判断があったのかも。まぁ、プラグイン開発者以外にはあまり使わないメソッドだし、1.8系からこのメソッド自体がプラグイン化されたらしいので、廃止によるインパクトは低いかな。

    5. $.toggle(fn1(),fn2(),[...fnN()])の廃止

      1.7系で非推奨化されてたメソッドです。指定のオブジェクトがクリックされる毎にfn1、fn2、・・・fnNと関数を実行して、fnN以降はfn1に戻るみたいな処理が書けるメソッドでした。まぁ、クリック毎にそこまで処理変えなきゃいかんUIってどうよ?って感じなので、廃止は妥当かな・・・と。あ、ちなみに、関数バインド型ではないイベントエフェクト型の$.toggle()は廃止されていません。

    6. 他に記述順や処理内容が変更されたメソッド

      $.add()$.before()$.after()$.addSelf()などなど細かいところが色々と変わっているようです。

    ...
  • iframeから新規ウィンドウを開いてリンクできない時の対処法

    完全な備忘録です。<br /> インラインフレーム内に読み込んだHTMLから新しいウィンドウにリンクを開きたい時、Aタグのtarget="_blank"やjQueryMobileのrel="external"、果てはJavaScriptのwindow.open()を使っても出来ない状態に陥った時は、IFRAME内の属性にsandbox="allow-scripts"がないかを疑ってみましょう。
    HTML5で追加されたIFRAMEタグの新属性「sandbox」で「allow-scripts」を指定してしまうと、インラインフレーム内に読み込まれたコンテンツのJavaScriptの機能をかなり制限してしまいます。特にwindowオブジェクトが受ける影響は大きく、ブラウザのポップアップを伴う処理を完全に抑止してしまいます。
    WEBセマンティック的にも、IFRAMEを使うときは内包されるコンテンツによって属性を正しく設定してあげる必要があるってことですね。

    ...
  • WordPressのデータベース仕様書を書いてみた

    以前から、 WordPressCodexのデータベース構造のページが見づらくて、仕様も古くなっていたのが、ちょっと気になっていたので、自分でデータベース仕様書を書き直してみようかと思っていたところ、WordPressでシステム開発する業務が急激に増えて来て、特にマルチサイト系の仕組みを把握する必要もあって、WordPressのデータベース仕様書をチートシート的に書き起こしておかないとシステム設計がしづらいという状況になってきた。そこで、自分なりのデータベース仕様書(テーブル定義書)を書いてみた次第。

    基本的には日本語版Codexと本家WordPress.orgのサイトを見ながら、実際のデータベース構造と見比べて書いてみたのだが、マルチサイト系のテーブル部分はまだちょっと不明なところが多いんだなこれが(特にwp_sitecategoriesテーブル…このテーブルってwp3.0以降ではドロップされてしまったのか?…みたいな)。

    まぁ、一通り書き切ったので、ここに共有化しておこうかと。

    バージョン:0.1

    さて話は変わる(…ようでそうでもないのだ)が、今月12/11に新安定バージョンのWordPress3.5がリリースされたので、さっそく本デベラボも3.5へアップグレードしてみた。
    管理パネルからの自動アップデートが上手く動作しなかった(パッケージデータを取得して展開している途中でタイムアウトしてしまう)ので、一旦アップグレードするのを躊躇したのだけど、PHP側の設定を見直すのは面倒だったので、最終的に手動でアップデートしてしまいました。アップデート後、今のところテーマやプラグインに不具合もなく動いているようだけど、管理パネルに常にWordPressの自動更新失敗のノーティフィケーションが出るようになってしまった…(大した影響はなさそうなので、そのうち直そうかと)。

    そんなわけで、WPも3.5になったので、書き上げたデータベース仕様書と構成の突合せをしてみようと、バージョン3.5のデータベースを覗いてみた。
    ざっと構造を見てみましたが、3.4.x → 3.5 でデータベースへの変更はなかった(マルチサイト側は突合せてませんが…)。

    本記事が今年最後のデベラボの投稿になりそうだ。
    それではみなさん、良いお年を。

    ...