PHPからAWS(EC2)のAPIを叩いてみたので書いてみる。
AWSの公式SDKがあるけど勉強がてらやってみた。
仕様は、
http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/
に書いてある。
準備
- アクセスキーID
- シークレットアクセスキー
すでに発行しているならばそれでもOK
Endpointを決める
http://docs.amazonwebservices.com/general/latest/gr/index.html?rande.html#ec2_region
東京リージョンの場合はec2.ap-northeast-1.amazonaws.com
叩くAPI(Action)を決める
インスタンスを起動したい!とかタグを打ちたい!とか。
http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?OperationList-query.html
今回は、インスタンス一覧取得(DescribeInstances)を選択したみる。
Action固有のパラメータを決める
DescribeInstancesはパラメータなしでも叩ける。
今回は、マイクロインスタンスで絞ってみる。
| Key | Value |
|---|---|
| Filter.1.Name | instance-type |
| Filter.1.Value.1 | t1.micro |
必須パラメータを追加
http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?Query-Common-Parameters.html
| Key | Value |
|---|---|
| Action | アクション名(今回は、DescribeInstances) |
| Version | APIのバージョン(今回は、2011-11-01) |
| AWSAccessKeyId | アクセスキーID |
| Timestamp | YYYY-MM-DDThh:mm:ssZ(date(‘c’)で取得できる) |
| Signature | 後述する方法で生成 |
| SignatureMethod | HmacSHA256 or HMacSHA1 |
| SignatureVersion | 2 |
これに、Action固有のパラメータを足したものが最終的に送るパラメータ。
オープンソーシャルなAPIも似たような方法で署名してた気がする。
手順は、
- 各Keyを元にソート(ksort)
- Key,ValueをURLEncode(RFC 3986)して&で連結
- 署名に使う文字列を生成(HTTPメソッド名+EndPoint+path+連結したパラメータ)
- 上記文字列とシークレットアクセスキーを使ってハッシュ生成(HMAC-SHA256 or HMAC-SHA1)
- base64エンコード
コードにすると以下のような感じ。
(HTTPメソッドとかベタ書きだけど…)
<?php
class Signer
{
function sign($params, $secretAccessKey)
{
$params = $this->sortByKey($params);
$string = $this->buildCanonicalString($params);
$stringToSign = $this->buildStringToSign($string);
$signature = base64_encode($this->hash($stringToSign, $secretAccessKey));
return $signature;
}
private function sortByKey($params)
{
ksort($params);
return $params;
}
private function buildCanonicalString($params)
{
$strings = array();
foreach ($params as $key => $value) {
$strings[] = $this->urlencode($key) . '=' . $this->urlencode($value);
}
return implode('&', $strings);
}
private function buildStringToSign($string)
{
$stringToSign = "GET\n"
. "ec2.ap-northeast-1.amazonaws.com\n"
. "/\n"
. $string;
return $stringToSign;
}
private function hash($stringToSign, $secretAccessKey)
{
return hash_hmac('sha256', $stringToSign, $secretAccessKey, true);
}
// PHP 5.2.X系はチルダもエンコードするので元に戻す
private function urlencode($value)
{
return str_replace('%7E', '~', rawurlencode($value));
}
}
※PHP5.2系の環境はなかったので、PHP5.3でしか動作確認していない。
HTTPリクエスト送信
結果はXMLとして帰ってくるので、これもまたお好きなように。
まとめ
Signature生成/Httpリクエスト送信/EndPoint/ハッシュアルゴリズム
辺りを分離したクラスを作れば立派な簡易クライアントの出来上がり!
それは、また時間のある時にでも…。
Objective-Cのシングルトンは以前書いたけど、
dispatch_onceを使うとより簡単に書けるのでメモ。
Singleton.h
#import <Foundation/Foundation.h> @interface Singleton : NSObject + (Singleton *)instance; @end
Singleton.m
#import "Singleton.h"
@implementation Singleton
+ (Singleton *)instance {
static Singleton *instance_ = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
instance_ = [[self alloc] init];
});
return instance_;
}
@end
fullScreenImageメソッドで取得できる画像がちょっとおかしい。
initWithCGImage:scale:orientation:
でUIImage作って表示させると右に90度回転してる。
iOS4だとこの問題は起きない。
initWithCGImage
にすると、ちゃんと表示される。
でも、今度はiOS4系だと回転している。
iTunesで同期した画像はiOS5でもこの問題は起きない。
クラスリファレンスみるとiOS5で修正が入ったぽいが…。
まぁ、iOS4とiOS5の時で使い分ければいいんだけど何か釈然としない…。
目次
前職ではこんな感じにしていたなぁというネタ。
下書き状態で残っていてもったいなかったので公開。
ディレクトリ構成
$CAP_HOME
- Capfile => config配下のXXX.rbをloadする
- config
- deploy.rb
- deploy
- production.rb => 本番用環境情報
- test.rb => テスト用環境情報
- XXX.rb => 各種レシピ
deploy.rbは以下の通り。
require 'capistrano/ext/multistage' set :default_run_options, :max_hosts => 20 set :user, 'cap' ssh_options[:keys] = '/home/user/.ssh/id_rsa'
- 同時20サーバで実行
- 実行ユーザはcap
- sshの秘密鍵は /home/user/.ssh/id_rsa
環境設定
server 'srv1.example.com', :web server 'srv2.example.com', :web server 'srv3.example.com', :web, :ap server 'db1.example.com', :db server 'db2.example.com', :db
みたいな形で、1サーバずつロールを設定。
レシピ
namespace :group do
task :task1, :roles => :web do
ここでごにょごにょする
end
task :task2, :roles => :db do
ここでごにょごにょする
end
end
といった形。
$ cap production group:task1
とか
$ cap test group:task1
のように呼び出す。
引数を受け取る
例えば、Capistrano実行サーバにあるファイルを各サーバへscpしたい時は、
namespace :fileup do
task :upload_txt, :roles => :web do
upload filename, '/tmp', :via => :scp
end
end
というレシピを書いて、
$ cap test -S filename=/tmp/text.txt fileup:upload_txt
と呼び出す。
シェルスクリプトからCapistranoを呼ぶ
そんな時の例。
#!/bin/sh CAP_HOME="/home/user/cap" CAP="/usr/local/bin/ruby /usr/local/bin/cap" cd $CAP_HOME $CAP production group:task1
目次
構成
- ドメインはexample.com
- 同一サーバ内
- 画像, CSS, JavaScriptはリバースプロキシ側で担当
- それ以外はAPサーバ
| サーバ | ポート | インストール先 |
|---|---|---|
| リバースプロキシ | 80 | /usr/local/apache_proxy |
| APサーバ | 20080 | /usr/local/apache |
インストール【APサーバ】
アクセスしてきたユーザのIPをAPサーバ側へ渡すモジュール。
IPベースでアクセス制限をかける場合とかに必要になる。
下記のサイトからダウンロードする。
http://www.openinfo.co.uk/apache/index.html
# cd /usr/local/src # tar -zxvf extract_forwarded-2.0.2.tar.gz # cd extract_forwarded/ # /usr/local/apache/bin/apxs -c -i -a mod_extract_forwarded.c
インストール【リバースプロキシ】
# cd /usr/local/src # tar zxf httpd-2.2.14.tar.gz # cd httpd-2.2.14 # ./configure --prefix=/usr/local/apache_proxy \ --with-mpm=worker \ --enable-mods-shared=all \ --enable-proxy \ --enable-cache \ --enable-mem-cache \ --enable-disk-cache \ --with-suexec-caller=www \ --with-expat=builtin # make # make install
設定【リバースプロキシ】
ServerRoot "/usr/local/apache_proxy"
Listen 80
User www
Group www
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule dir_module modules/mod_dir.so
<IfModule worker.c>
StartServers 2
ServerLimit 16
ThreadLimit 64
MaxClients 512
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 32
MaxRequestsPerChild 0
</IfModule>
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
ServerAdmin admin@example.com
DocumentRoot "/usr/local/apache_proxy/htdocs"
ErrorLog "logs/error_log"
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
CustomLog "logs/access_log" common
DirectoryIndex index.html
Include conf/extra/httpd-vhosts.conf
NameVirtualHost * <VirtualHost *> ServerName example.com SetEnvIfNoCase Request_URI "^/(img|css|js)" nolog SetEnvIfNoCase Request_URI "^/favicon.ico" nolog DocumentRoot /var/www/html RewriteEngine On RewriteRule ^/(img|css|js)/ - [L] RewriteRule ^/(.*) http://localhost:20080/$1 [P,L,QSA] ProxyRequests Off ProxyPreserveHost On ProxyPassReverse / http://localhost:20080/ </VirtualHost>
設定【APサーバ】
#Listen 80 Listen 20080 #KeepAlive On KeepAlive Off LoadModule extract_forwarded_module modules/mod_extract_forwarded.so MEForder refuse,accept MEFrefuse all MEFaccept 192.0.2.1 MEFaccept 127.0.0.1
192.0.2.1の部分は、リバースプロキシのグローバルIPに置き換える。
再起動
本日、7月1日よりミツバチワークスという会社で働く事となりました。
デコログというブログサービスを運営してます。
65億PVという国内のブログではトップレベルの規模のサービスです。
アーキテクチャや負荷との戦いなど得る物が多そうだなぁと感じてます。
とても刺激的な人達と働けそうでワクワクしてます!
でも、俺はそのデコログすら超えるようなサービスをいつか作ってやる!と思ってます!
そんなこんなで、これからもWEBの業界で頑張っていきまーす。
色々と頂いたのでご報告とお礼を兼ねてのエントリ。
ScanSnap S1100
FUJITSU ScanSnap S1100 FI-S1100

富士通 2010-11-22
売り上げランキング : 255
↑を頂きました。
ひとまず、家にあった
- 名刺
- 給与明細
- 源泉徴収票
- 取説
などを、スキャンしてEvernoteへ送りました。
使い心地はとてもいいです!楽しくスイスイスキャンできます。
Windows Vista マシンよりMacBook Proからやった方が早く取り込めました。
Windowsマシンの方がCPUとかHDDいいはずなのに…。
紙の書類をPDF化して保存しておけるのはとても助かります。
文字列をコピー出来ることに今更感動しました(笑)
- ノートはルーズリーフにする
- 書いたらすぐにスキャンしておく
- 頂いた名刺もPDFにして取り込む
- レシートなどは取り込むか悩み中
- 本の裁断はまだしない
という感じで、運用していくつもりです。
図書カード1万円分
4冊本を買いました。
うち2冊は子供用なので省略。
残りの2冊は以下の通り。共に今後の仕事に役に立ちそうなものと判断して買いました。
ウェブオペレーション ―サイト運用管理の実践テクニック
John Allspaw

レガシーコード改善ガイド (Object Oriented SELECTION)
マイケル・C・フェザーズ ウルシステムズ株式会社

Webサイトの運用に関して書かれている本。
実は、この辺りは今までの経験でなんとなーくやっていた範囲。
ちょっとモヤモヤした感じではあった。
この分野を体系だてて進められたらいいなぁという期待を込めて購入。
これは、色々な方面より鉄板だとお墨付きの本。
「テストのないコード=レガシーコード」
こいつとの戦いは次の会社でも起こると思っている。
それに備えて学びたいなぁと思ったので購入。
iTunes Card 1500円分
iPad2とかを買った時に、アプリを買うかもしれないです。
寄せ書き
みんなの印象が割と一致していたのは面白かったです。
そういう意味ではきっと裏表のない人間なんですよ。俺は(笑)
まとめ
しっかりと自分に投資してさせて頂きました。
Redmine 1.1.3をインストールした時のまとめ。
色々とバージョン指定が多いので大変だった…。
前提条件
- MySQLはすでに構築済み
- example.comというドメインでアクセス
- nginxというユーザで実行
以下、
# は rootユーザ $ は nginxユーザ
として記述。
nginxのインストール
実行用ユーザ作成
# useradd nginx
作業が楽なので一旦nginxユーザはログイン可能にしておく。
全部終わったら、nologinに切り替える。
インストール
# yum install gcc openssl-devel pcre-devel zlib-devel mysql-devel
# cd /usr/local/src # wget http://nginx.org/download/nginx-1.0.4.tar.gz # tar -zxvf nginx-1.0.4.tar.gz # cd nginx-1.0.4 # mkdir -p /usr/local/nginx-1.0.4 # ./configure --prefix=/usr/local/nginx-1.0.4 --user=nginx --group=nginx # make # make install # chown -R nginx:nginx /usr/local/nginx-1.0.4 # ln -fns /usr/local/nginx-1.0.4 /usr/local/nginx
起動テスト
# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ブラウザからアクセスしてみて、
と出ていればひとまずOK。
nginxを止める。
# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf -s stop
rvmのインストール
gitインストール
開発する時に使うし、rvmインストールも楽になるのでgitを入れてしまう。
# cd /usr/local/src # wget http://kernel.org/pub/software/scm/git/git-1.7.5.4.tar.bz2 # tar -jxvf git-1.7.5.4.tar.bz2 # cd git-1.7.5.4.tar.bz2 # ./configure # make # make install
rvmインストール
# su - nginx $ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm) $ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile $ source ~/.bash_profile $ rvm -v rvm 1.6.18 by Wayne E. Seguin (wayneeseguin@gmail.com) [https://rvm.beginrescueend.com/]
rails環境構築
Redmineはrails3では動かないみたいなので、rails2の環境を作る。
色んなサイトを見ると結構バージョンも低めでないといけないみたい。
ruby 1.8.7のインストール
$ rvm install 1.8.7 $ rvm use 1.8.7 --default
RubyGems 1.4.2のインストール
$ rvm rubygems 1.4.2 $ gem -v 1.4.2
※Errorという文字が見えたが動いているみたいなので先に進んでしまう。
rails2のインストール
$ gem install rails -v=2.3.11
unicornのインストール
$ gem install unicorn
Redmineの構築
必要なGEMの導入
$ gem install rack -v=1.0.1 $ gem uninstall rack
1.0.1以外のrackを削除
$ gem install i18n -v=0.4.2 $ gem install mysql
Redmineの設置
$ cd /home/nginx $ wget http://rubyforge.org/frs/download.php/74722/redmine-1.1.3.tar.gz $ tar -zxvf redmine-1.1.3.tar.gz $ ln -fns /home/nginx/redmine-1.1.3 /home/nginx/redmine
設定
$ cd /home/nginx/redmine/config $ cp -p database.yml.example database.yml $ cp -p email.yml.example email.yml
DB設定やメール設定は環境に合わせて変更。
公式ページに設定例は書いてある。
http://blog.redmine.jp/articles/redmine-1_1-installation_centos/
その後、rake
$ rake generate_session_store $ rake db:migrate RAILS_ENV=production
unicorn起動
$ unicorn_rails -c config/unicorn.rb -E production -D
各種設定
nginx設定
# vim /usr/local/nginx/conf/nginx.conf
http {
…
include /usr/local/nginx/conf.d/*.conf;
}
# mkdir -p /usr/local/nginx/conf.d
# vim /usr/local/nginx/conf.d/redmine.conf
upstream unicorn {
server unix:/tmp/.unicorn.sock;
}
server {
listen 80;
server_name example.com;
root /home/nginx/redmine/public;
access_log logs/example.com.access_log;
error_log logs/example.com.error_log;
location / {
if (-f $request_filename) { break; }
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://unicorn;
}
}
# chown -R nginx:nginx /usr/local/nginx/conf.d
Redmine向けunicorn設定
worker_processes 2
listen '/tmp/.unicorn.sock'
stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
preload_app true
before_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
old_pid = "#{ server.config[:pid] }.oldbin"
unless old_pid == server.pid
begin
Process.kill :QUIT, File.read(old_pid).to_i
rescue Errno::ENOENT, Errno::ESRCH
end
end
end
after_fork do |server, worker|
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end
nginx起動&確認
# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
その後、http://example.com にアクセスして動いていれば終わり。
動いていない場合は、
にログファイルができるので確認してみましょう。
辞めようと思った時に自分の気持ちを落ち着かせる為に自分が実践した事の振り返り。
とある人に書いて欲しいと言われたので書くことに。
退職を助長する意味合いは全くありません!
勘違いすんなよ!!
いいか!絶対だぞ!
では、スタート!
辞める事で自分に生じるメリットを考える
ネガティブな気持ちでぶつかっても互いに嫌な気持ちになるだけ。
だから、ポジティブな気持ちで心を満たそう!
- 〇〇ができる!
- 年収が上がる!
嫌いなあの人とお別れできる!
などなど。
でも、口に出して良い事と悪い事は整理しておこうね!(笑)
不要な書類をシュレッダーにかける
- 身辺整理が進むと勇気が出る
- 退職日当日に慌てないで済む
結構、高い確率でシュレッダーをオーバーヒートさせてます。 - あれ!?あの人もしかして辞めるのか…と匂わせる事ができる(笑)
行動を変える事で意識を変えようという意味合いで実施しました。
あと、
もしっかりとシュレッダーにかけましょうね。
10枚くらいを並べて手動でかけるとサクサク進んで楽しいです(笑)
誰かに話してみる
もしかしたら、いいアドバイスがもらえるかもしれません。
(このタイミングだと〇〇だと思うよとか)
まとめ
退職は(疎まれていなければ…)会社側に迷惑をかける事になります。
せめてできる事は、
- しっかりと引継ぎを行なう
- 残った人達の為にできる事をする
- 明るく立ち去る
だと思いました。
その為にも、自分を奮い立たせて下さいね!
結構前に書いて下書きで眠ってた…。
せっかくなので、公開。
PHP, Ruby, Pythonの比較。
PHPで(個人的に)良く使う関数は他の言語ではどうすればいいんだろう?
という趣旨のエントリー。
ちょこちょこっとググったモノを使っているので、もっといいやり方をご存知の方は教えて下さい。
GET
<?php $url = 'http://google.co.jp'; $string = file_get_contents($url); echo $string;
require 'open-uri'
url = 'http://google.co.jp'
results = ''open(url) {|f| results = f.read}
puts results
import urllib url = 'http://google.co.jp' d = urllib.urlopen(url) results = d.read() d.close() print results
URL encode/decode
<?php $url = 'http://example.com/'; echo urlencode($url)."\n"; echo urldecode(urlencode($url))."\n";
require 'cgi' url = 'http://example.com/' puts CGI::escape(url) puts CGI::unescape(CGI::escape(url))
import urllib url = 'http://example.com/' print urllib.quote(url, '') print urllib.unquote(urllib.quote(url, ''))
HTMLのescape/unescape
<?php $html = <<<EOD <html> <body> body </body> </html> EOD; echo htmlspecialchars($html); echo htmlspecialchars_decode(htmlspecialchars($html));
require 'cgi' html = <<EOD <html> <body> body </body> </html> EOD puts CGI.escapeHTML(html) puts CGI.unescapeHTML(CGI.escapeHTML(html))
from xml.sax.saxutils import * html = """ <html> <body> body </body> </html> """ print escape(html) print unescape(escape(html))

最新コメント