セブ島で仕事する、というお話
今フィリピンのセブ島に長期滞在しています。
僕はフリーランスなので、基本的にネットさえあればどこでも働ける状況です。これから先、法人化や人の雇用など、こうも自由ではいれなくなると予測されるので、今のうちにふらふらしておこうとか思っています。
滞在する場所に求めるもの
僕が滞在する場所を考えるとき、以下の部分を主に考慮します。
- 1,仕事&技術的な学習がはかどること。何はなくとも一番大事。
- 2,生活コストがかからないこと。お金ためたいので。
- 3,人生のスパイス的な+α
やはり若いうちは、知見の蓄積と、周囲の評価を獲得することが最も重要です。
また、自己資本は、何も証明することなく自分に与えられる猶予ですので、貯金も重要です。ただ、常識的な範囲の生活コストの規模感では、1と2には大きな重要度の差があります。
セブ(Cebu City)のイメージ
事前情報からのイメージは以下の感じでした。
ざっくりと、そこまで仕事環境を悪化させず、安価に英語を勉強しながら充実した休日をすごせるんじゃないか。というのが楽観的な見方でした。
一番重要な仕事環境に関し、僕は日本で電源+wifi(自前)+空調+適度な緊張感+時間無制限という最強な環境を手に入れていました。よって物理的な環境の悪化は避けられないのですが、エンジニアの友人と共に行くため、モチベーション+知見の面でカバーできるのではと読んでいました。
英語は正直直近の必要性はないので、おまけレベルです。そのため英語学校通いは選択肢にいれませんでした。
セブに関する記事
以下の記事をこれから書いていこうと思っています。
仕事環境
生活環境とかコスト
- ・航空券
- ・セブの物価
- ・セブでのお食事
スパイス
- ・セブでの個人英語学習
- ・セブのビーチ
- ・セブの女の子
GoogleAnalyticsで自分のアクセスを除外
という罠
ググると、IPによる方法とCookieを使う方法のヘルプが
社内からのアクセスを除外するにはどうすればよいですか?-アナリティクスヘルプ
しかし実はこれ古いヘルプで、記載のタグでCookieによる除外はできません。
僕は動的IPなのでCookieで除外しようとしてがっつりはまりました。こういう一見簡単な作業でつまると悲しいのでメモ書きを。
ブラウザはChrome20.0です。
Cookieによるアクセスの除外
必要なのは3ステップ。
- ・除外用のページを作成する
- ・除外するブラウザでページにアクセスし、Cookieをset
- ・Analytics設定でフィルタを作成する
除外用のページを作成する
Cookieをsetするためのページを作ってアップします。
ページに必要な条件は以下の3つ。
- ・除外したいドメイン上にアップする
- ・Analyticsのトラックタグを記載する
- ・bodyタグを下記に
アップして動作確認できたコードです。UAは自分のものを設定してください。
<head>
<title>No Report Cookie Setter</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex,nofollow">
</head>
<body onLoad="javascript:_gaq.push(['_setVar', 'test_value']);">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>
onloadはもちろんimgタグでも動きます。WAFを使っている場合、レイアウトテンプレをカットするのがちょっと手間で、bodyタグは面倒だったりします。
※念のためですが、bodyタグを変更するのは、Cookieセット用のページのみです。テンプレートに突っ込んで、サイト全体に適用しないようにします。
Analytics設定でフィルタを作成する
- フィルタ名 : 任意
- フィルタの種類 : カスタム フィルタ→ 除外
- フィルタ フィールド : ユーザー定義
- フィルタ パターン : さっきの文字列(例だとtest_value)
- 大文字と小文字を区別 : いいえ
うまくいかない場合
Cookieを見る
Chromeの場合
右クリック→要素の検証→Resources→Cookies→サイトドメイン で確認。
Name : __utmv
Value : xxxxxxxxx(数字).test_value
みたいなのがあればCookieは正しく設定されています。
これでフィルタが間違っているのか、ページのコードが間違っているのかあたりをつけます。
リアルタイムだと除外されない
Analyticsのベータ機能リアルタイムでは、Cookieとフィルタを正しく設定しても除外されていないので注意。当日分のコンテンツあたりで確認すると良いのでは。
トラックコード内で設定する方法
やっていることは同じですが、一応別の記載方法も
var _gaq = _gaq || [];
_gaq.push(['_setVar', 'test_value']);
_gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
_gaq.push(['_trackPageview']);
// etc...
</script>
CakePHP2.1をgit push一発でデプロイ
やはりデプロイは自動化しなければまずいということで。全て手で書き換え+ftpでアップロード状態からgit push一発で完了させるようにしました。ディレクトリの配置や環境は前記事準拠です。
CakePHP2.1をさくらのレンタルサーバー+マルチドメイン使用でデプロイ
前提
Gitでソースのバージョン管理をしている
コードで環境の差分を吸収
開発環境と本番環境で設定が異なる部分を、全てコードで吸収します。
僕の場合書き換えたのは以下の4ファイルです。
基本方針は、IPを見て場合分けです。
bootstrapに定義したURL定数と、coreのdebug設定をこんな感じで書き換え
databaseはコンストラクタを定義。設定の配列$devと$prodを作って$defaultに割り当て
if (env('SERVER_ADDR') !== '127.0.0.1') {
$this->default = $this->prod;
}else {
$this->default = $this->dev;
}
}
indexは env('SERVER_ADDR') が使えず、 $_SERVER["REMOTE_ADDR"] を使ってルート、コアのパスを設定
同一コードで正常に動作することを確かめます。CSSや画像パスの設定が必要な場合もあります。僕はbootstrap内で定数ROOT_URL、ASSETS_URLを切り替えて運用しています。
DBのマイグレーション
CakeDC / migrations
データベースのスキーマ変更が自動で反映されるようにします。スキーマファイル(schema.php)と現在のデータベースを比較し、差分を埋める作成時刻付のマイグレーションファイルを作成。schema_migrationsテーブルでマイグレーションファイルの適用状況を管理し、未適用のものを実行という流れみたいです。
インストール
プラグインフォルダに展開
デプロイ時に一緒に本番サーバーにも入る予定でしたが、他のリポジトリで管理されてるファイルは自動的にignoreされるんですね…僕は.gitフォルダを削除しました。これでpush時に本番にもPluginが設置されます。
開発環境でマイグレーションの準備
まずは開発環境のデータベーススキーマを本番環境で再現。既に本番に作ってあっても大丈夫です。
#schema_migrationsテーブルを作成
$ cake Migrations.migration -p Migrations
#最初のマイグレーションファイルを作成
$ cake Migrations.migration generate
本番環境でのマイグレーションの実行
開発環境で作成したマイグレーションファイルを本番に設置した上で、以下の手順を踏めば本番環境にデータベースを再現できます。
#schema_migrationsテーブルを作成
% cake Migrations.migration -p Migrations
#未適用のマイグレーションファイルを実行
% cake Migrations.migration all
Migration: 1339467948_first_migration
Error: Table "areas" already exists in database.
---------------------------------------------------------------
Do you want to mark the migration as successful?. [y]es or [a]bort. (y/a)
git push をフックにスクリプト実行
大まかには、変更をcommit→リモートリポジトリにpush→pushをフックにスクリプトが実行され本番環境にpull+追加処理でデプロイ完了という流れです。
さくらレンタルサーバーにgitを導入
リモートリポジトリの追加
まずは本番サーバーにログインしリモートリポジトリを作成
#リポジトリ用のディレクトリ作成
% mkdir /home/user/repos/myapp.git
#bareリポジトリ(作業ディレクトリをもたないリポジトリ)作成
% cd myapp.git
% git init --bare
続いて開発環境のリポジトリに今作成したリモートリポジトリを登録
#既存のリポジトリにリモートリポジトリとして登録
$ git remote add origin user@user.sakura.ne.jp:/home/user/repos/myapp.git
#pushで変更を反映
$ git push origin master
フックスクリプトの作成
gitはリポジトリへの行動をフックにスクリプトを実行する機能を持っています。
.git/hooks内のファイルに記載し、ファイル名から.sampleを取り除けば実行されます。自分で作成する場合はスクリプトに実行権限を与える必要があります。
今回はpushをフックにしたいのでpost-updateを使用
#リモートリポジトリから本番環境への展開
(cd /home/user/myapp(app); git --git-dir=.git pull)
#webroot内のファイルの転送
(cp -r /home/user/myapp(app)/myapp(webroot)/* /home/user/www/myapp(webroot)/)
#マイグレーションの実行
(cd /home/user/myapp; cake Migrations.migration all)
リモートリポジトリから本番環境への展開
myappディレクトリを置きたい場所に、先ほどのリモートリポジトリからclone
webroot内のファイルを転送
今回のサーバー環境では、appとwebrootの位置関係が変わっています。元のリポジトリと構造が違うので、pullした後app/webroot内のファイルを公開フォルダ上にコピーすることにしました。
マイグレーションの実行
未実行のマイグレーションファイルがあれば実行してくれます。
振り返ると結構色々やったなと。今はかなりプロダクトに集中したいのですが、デプロイ自動化の恩恵は相当大きいので、やってよかったと思います。今回はサーバー1台の運用で恩恵が小さいと判断しましたが、時間を見つけてcapistranoも勉強したいところです。
CakePHP2.1をさくらのレンタルサーバー+マルチドメイン使用でデプロイ
ウキウキでリリースのところ、予想外のトラブルに見舞われました…
サーバーはさくらのレンタルサーバースタンダード。Apacheは1.3。ドメインはスタードメインで取得したものを、さくらのマルチドメイン機能で使用。
http:// mydomain.comで、CakePHPのrootに接続するようにします。
マルチドメイン設定
ディレクトリ構造とCakeのindex.php設定
ディレクトリ構造はこんな感じ。wwwがさくらデフォルトのApacheDocumentRootディレクトリです。
/user_name
/lib
/Cake2.1(core)
/myapp(app)
/www
/myapp(webroot)
さくらのマルチドメイン機能では、追加したドメインごとにDocumentRootを設定します。ただしwww以下という制約があり、appを公開フォルダ上に置くのを避けるには、appとwebrootの位置関係を変えざるを得ないです。
myapp(webroot)/index.phpは以下のように変更。
define('ROOT', DS . 'home' . DS . 'user_name');
}
# 変更前 define('APP_DIR', basename(dirname(dirname(__FILE__))));if (!defined('APP_DIR')) {
define('APP_DIR', 'myapp');
}
# コメントを外す
define('CAKE_CORE_INCLUDE_PATH', DS . 'home' . DS . 'user_name' . DS . 'lib' . DS . 'Cake2.1' . DS . 'lib');
この時点でのエラー
ブラウザ : NOT FOUND
Apacheエラーログ : File does not exist
root(http://mydomain.com)だけは正しく表示。Cakeのroutes.phpでrootのアクションを変更すれば、そのアクションは動作する状態に。
.htaccessの設定
制約の範囲と内容が不明瞭なのですが、今回のケースでは、実際のファイルディレクトリ構造とリクエストURIの構造が異なる場合アクセスできないようです。
対処法
myapp(webroot)内に、下記を記載した.htaccessを設置します。しかし.htaccessって体感できるレベルで遅くなりますね…
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
RewriteBase /
</IfModule>
本来CakePHPで解釈されるroot以降の部分を、事前にクエリストリングに書き換えてから渡すようにRewriteRuleを設定したわけです。
RewriteCondは適用条件を指定するもので、!-fは実際に存在するファイル名を除外するという意味です。画像やCSSに書き換えが適用されないようにしています。
.htaccessを設置したが書き方が間違っていた時のエラー
ブラウザ : Internal Server error
Apacheエラーログ : mod_rewrite: maximum number of internal redirects reached. Assuming configuration error. Use 'RewriteOptions MaxRedirects' to increase the limit if neccessary.
なお、RewriteOptions MaxRedirectsを1~15まで設定してみましたが、エラーは解決しませんでした。
検索すれば似た事例が出ますが、古いバージョンの情報だったりCakeを公開ディレクトリ上におく情報が多かったので参考までに。
ちなみに現在は、全て手動で書き換えて上げています。早く自動化しなければ。
Herokuで"No account specified."と言われloginできない
Herokuにログインできない問題の解決についてです。
Herokuにloginできない
https://devcenter.heroku.com/articles/quickstart
ここを見ながら進めていました。大雑把に言うと
- 1, Herokuにsign up
- 2, メールのリンクからactivate
- 3, Heroku Toolbeltをインストール
- 4, login&公開鍵の送信
この流れで使えるようになる予定でした。
この4の段階で、下記エラーが
Enter your Heroku credentials.
Email: MAIL
Password (typing will be hidden):
! No account specified.
!
! Run this command with --account <account name>
!
! You can also add it as a git config attribute with:
! git config heroku.account work
3の段階はHeroku Toolbeltのインストールではなく、gitはhomebrew、foremanとherokuはgemで入れてある、という状況でした。
:
foreman (0.46.0)
:
heroku (2.26.2)
heroku-accountsプラグインによる解決
heroku-accountsプラグインをインストールし、アカウントを作ったところ、loginできました。
Enter your Heroku credentials.
Email: mail
Password (typing will be hidden):
Authentication successful.
手順
プラグインをインストール
heroku-accounts installed
任意のアカウントを作成
Enter your Heroku credentials.
Email: MAIL
Password (typing will be hidden):
Add the following to your ~/.ssh/config
Host heroku.NAME
HostName heroku.com
IdentityFile /PATH/TO/PRIVATE/KEY
IdentitiesOnly yes
Add the followingの部分を記載
作ったアカウントをデフォルトに
アカウントを確認。*印がデフォルトアカウント
* NAME
これでloginすればいけるはずです。僕は公開鍵を送信してからloginしました。
Uploading SSH public key /PATH_TO_KEY/PUBKEY.pub... done
$ heroku login
本来heroku-accountsは複数アカウント管理用のプラグインみたいです。根本解決ではありませんが、一応参考まで。
なお、エラー文言にある--account accountnameをつけてloginやgit configのやり方は、色々な形式で試行錯誤しましたがうまく行きませんでした。
Rails3.2以降、rakeのdb:fixtures:loadでCSVはインポートできない
Railsでfixturesを使ってダミーデータをインポートしたかったのですが、YAMLで大量のデータを作るのは大変そう。で、CSVをインポートしようとすると…
#エラー文
rake aborted!
No such file or directory - / path_to_app /test/fixtures/items.yml
調べてみると、もはやfixturesがCSVをサポートしていないことが判明。
CSV Fixtures are deprecated and support will be removed in Rails 3.2.0.
Ruby on Rails 3.1 Release Notes
CSVをYAMLに変換するなりプラグインなりあるだろうとも思いましたが、素直にMySQLクライアントからインポートしました。Sequel Pro使いやすいです。
ググるとまだCSVもYAMLもいけるよって記事ばかりなのでご注意を。
Apacheは起動しているが、ブラウザでlocalhostが確認できない
脱XAMPP実行時に、ひっかかったことのメモ。
OSXデフォルトのApacheを使うということで、System Preference -> Sharing -> Web Sharing にチェックで起動するはずでしたが…
localhostに接続できない
原因
DocumentRootディレクトリを削除していることによる、httpd.confのsyntax errorでした。
163~168行目の記述は下記でしたが、肝心の~/Webディレクトリを過去に削除していました。
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/Users/RM/Web"
対応
ここでOSXのApache設定ファイル、/private/etc/apache2/httpd.confの更新日が結構最近なことに気づく。そういえば始めたばっかの時にバックアップとらずにいじってました。で、多分httpd.confに問題があるのだろうと推測。まずは使用しているのが/private/etc/apache2/httpd.confで間違いないか確認したい。が、方法はわからないので他に同名ファイルないか確認してよしとする
~/Webディレクトリを作成して完了ですが、403 Forbiddenです。
403 Forbiddenの解決
原因
168行目DocumentRootの設定と195行目
対応
とりあえずForbiddenて言われたらパーミッションだろということで、 ls -l で確認。755で問題なさそう。
次いで/private/var/log/apache2/error_logを見てみます。client denied by server configurationとのこと。
ここらへんの情報でググってみるも、症状は似ていても、解決はVirtualhostがらみとか、user.confがとかで微妙に違う。ちょっと焦りだす。
やむをえずApacheの設定項目の解説を見て、一つ一つ確認することに。
参考 : httpd.conf の設定
ここで原因に気付き、195行目のパスを168行目と一致させる
# This should be changed to whatever you set DocumentRoot to.
#
<Directory "/Users/UserName/Web">
十分に理解していない部分がある不安と、とりあえず行き詰まることなく解決まで持っていけたことへの喜びを同時に味わいました。インフラは早々に誰かにお任せしたいと思っているので、一旦これで良しとします。