YTsudaのブログ

1985生まれ、男。東京で働くWeb制作者

vagrant up したら "Guest Additions Version" とに関するエラーが出た時のメモ

The guest additions on this VM do not match the installed version of
VirtualBox! In most cases this is fine, but in rare cases it can
cause things such as shared folders to not work properly. If you see
shared folder errors, please update the guest additions within the
virtual machine and reload your VM.

Guest Additions Version: 4.2.0
VirtualBox Version: 4.3

こんなエラーが出る。 調べた結果、Vagrantのプラグインを入れればいいらしい。

$ vagrant plugin install vagrant-vbguest

そしてVagrantfileに以下の設定を加ええる。

config.vbguest.auto_update = true

その後、vagrant up / vagrant reload。

Python で Google Analytics API を使うためにやったこと

やりたいこと

  • とあるページのとある日のPV数を自動で取得し、別のアプリ内で使いたい
  • pythonでやりたい

ライブラリのインストール

という3つのライブラリを pip で入れる

$ sudo pip install httplib2
$ sudo pip install python-gflags
$ sudo pip install google-api-python-client

chefのレシピに書く場合は python_pip というディレクティブを使う。

chef_recipe_for_google_api_with_python

python_pip "httplib2" do
    action :install
end
 
python_pip "python-gflags" do
    action :install
end
 
python_pip "google-api-python-client" do
    action :install
end

とりあえずチュートリアル

Tutorial: Hello Analytics API

まずはこのGoogle公式チュートリアルをやった。

このチュートリアル内で作る hello_analytics_api_v3_auth.py というファイルのコードは、実際のプロジェクトでもそのまま使いまわせるので一度やっておくべき。というより、このチュートリアルを通らずに認証まわりを1から勉強するのは非常に面倒だと思われる。

チュートリアルのファイルをコピペ

チュートリアルで作った hello_analytics_api_v3.py をコピーして任意のファイルを作り、 import 部以下を全部消す。するとこんなファイルになる。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import hello_analytics_api_v3_auth
from apiclient.errors import HttpError
from oauth2client.client import AccessTokenRefreshError

ビューID(プロファイルID)を取得

取得先のサイトを決めるため、ビューIDが必要になる。ビューIDは8桁ほどの数字である。

  1. GoogleAnalyticsにログインし、任意のプロファイルを選択
  2. 上メニュー右側の「アナリティクス設定」をクリック
  3. 右端のカラム「ビュー(プロファイル)」の中から「ビュー設定」をクリック
  4. 「ビューID」をコピー

最初のリクエスト

リクエストに使うメソッドは極めてシンプルで1つだけ。

service.data().ga().get()

このgetメソッドに色々な引数を与えていく。 先ほど作ったファイルに以下のように書き加える。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import hello_analytics_api_v3_auth
from apiclient.errors import HttpError
from oauth2client.client import AccessTokenRefreshError

service = hello_analytics_api_v3_auth.initialize_service()

results = service.data().ga().get(
        ids='ga:' + VIEW_ID,
        start_date='2013-10-13',
        end_date='2013-10-13',
        metrics='ga:pageviews',
        filters='ga:pagePath==/signup').execute()

print results.get('rows')[0][0]

出力は以下

1281

上記は10/13日の /signup ページのPVを取得するクエリとなる。VIEW_ID は先ほど調べたビューIDと置き換える。

クエリの出し方を勉強する

ここまでくれば、あとはクエリの出し方を学ぶだけだ。

学ぶべき点は2つある。一つはgetメソッドの引数とその与え方、もう一つはディメンションとメトリクスについて。

getメソッドの引数と与え方

これについては以下のページに目を通せばだいたい解る。返り値の解説もある(dumpすれば大体わかるけど)。

Core Reporting API - Reference Guide

ディメンションとメトリクス

ディメンションとは値の分け方のことで、MySQLで言えば GROUP BY である。 メトリクスとは値の種類のことで、MySQLで言えばそれぞれのカラム名、SELECT ... の部分である。

ディメンションとメトリクスについては以下のリファレンスに目を通せばOK。 Dimensions & Metrics Reference

VagrantでマウントしたJavascriptファイルが文字化けする問題の対処法

環境

Vagrantで作ったVM内でNginxを走らせ、ホスト側のブラウザからリクエストしている。 アプリのソースファイルはホスト側からVMにマウントしている。

Distributor ID: Ubuntu
Description:    Ubuntu 12.04 LTS
Release:        12.04
Codename:       precise

現象

ホスト側でjsを編集しても、正しく反映されない。 UTF-8エンコード周りでよく見る菱型に?のマークに文字化けする。

原因

Nginxが静的ファイルを要求された時にsendfile()というシステムコールを使うが、 それがキャッシュを返す仕組みになっていて、mountしたディレクトリに対してうまく働かないとのこと。

VagrantでCSSの更新が反映されない場合の対処法

JS and CSS files in vagrant not properly encoded when saved outside of the VM

解決

上記、CSSの記事で紹介されていた方法を試したところ、正確に反映されるようになりました。

/etc/nginx/nginx.conf

sendfile off;

apacheでは試していないが上記ブログによれば以下の設定でいける、らしい。

httpd.conf

EnableSendfile off

chefのレシピを開発する時はdebugモードで in Vagrant

chefのレシピを開発する時はdebugモードで行うと良いです。 例えばexecuteリソースを自分で書いた時、 only_if/not_if をテストするのに重宝します。

[2013-08-08T03:09:17+00:00] DEBUG: Skipping bash[update-locale] due to not_if command `cat /etc/default/locale | grep 'LC_ALL.*UTF'`

not_if条件によって"update-locale"というexecuteリソースが実行されなかったことがわかります。

設定方法

Vagrantfileの "config.vm.provision" ブロックに "chef.log_level = :debug" という設定を書き足すことでデバッグログが出るようになります。

Vagrantfileの編集

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.provision :chef_solo do |chef|
    chef.log_level = :debug
  end 
end

Vagrantで複数のcookbooksを指定する

chefのレシピは自作のものとサードパーティーのものを別のディレクトリに分けて入れることが推奨されています。

knifeでchefのプロジェクトを立ち上げると以下のようなディレクトリ構成になります。 cookbooks がサードパーティの、site-cookbooks が自家製のレシピを入れるディレクトリです。

$ knife solo init chef-repo
$ tree chef-repo/
 chef-repo/
 ├── cookbooks
 ├── data_bags
 ├── nodes
 ├── roles
 ├── site-cookbooks
 └── solo.rb

Vagrantfileの設定

provision時に cookbooksとsite-cookbooks両方のレシピを使用したい場合、 Vagrantfileでその両方を指定して読み込む必要があります。

やり方は以下の通り。 "chef.cookbooks_path"に配列を渡すことで実現できます。 相対パスの起点はVagrantfileのあるディレクトリです。

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = ["./chef-repo/cookbooks", "./chef-repo/site-cookbooks"]
    chef.add_recipe "apt"         #cookbooksにあるサードパーティーのレシピ
    chef.add_recipe "my-project"  #site-cookbooksにある自作レシピ
  end 
end

Chef(Vagrant) で "apt-get update" する方法

vimがインストールできなかった

Opscodeから引いてきたレシピvim をインストールしようとしたのですが、以下のようなエラーが出てインストールできませんでした。

Chef::Exceptions::Exec
----------------------
apt-get -q -y install vim=2:7.3.429-2ubuntu2.1 returned 100, expected 0

Resource Declaration:
---------------------
# In /tmp/vagrant-chef-1/chef-solo-1/cookbooks/vim/recipes/default.rb

  8: #
  9: package "vim" do
 10:     action :install
 11: end
 12:

vimの該当バージョンが見つからないということは、"apt-get update" をすれば良いのだろうと踏んだのですが、Chefではその方法がわからず。
ググってみたところ、Opscodeのaptレシピを使えば良いとわかりました。

Chef ignores apt-get update - stackoverflow

Opscode の "apt" cookbook を使う

cookbookのダウンロード

$ cd ~/vagrant/cookbooks
$ git clone https://github.com/opscode-cookbooks/apt.git

Vagrantfile に add_recipe

Vagrantfile の該当箇所を編集し、"apt" cookbook の default.rb が実行されるようにします。

config.vm.provision :chef_solo do |chef|
  chef.add_recipe "apt"
  chef.add_recipe "vim"
end

provision

"vagrant provision" はすでにupされているVMにレシピを適用するコマンドです。

$ cd ~/vagrant
$ vagrant provision