かってぃのブログ

喫茶店を遊牧しながら勉強したり開発したりする大学院生のブログです。

katty0324

MacにWEBの開発環境整えた。結構めんどくさかった。(よく分からないこと多い)

on 2011-10-25 03:52:39

webから

Macで開発できるようにします。

今までWindowsとxampp環境でゴリゴリ開発してましたが、しばらくMac一本で行くことになりそうなので、Macの方にもWEBの開発環境を作りました。非常に個人的な内容が含まれてて、これからMacに環境構築するには冗長な部分があります。

Apacheの起動

システム環境設定 > 共有 > WEB共有 > ON

これだけ。ブラウザで http://localhost/ を開けばIt Worksが見えて、もうWEBサーバが動いてることが分かります。

バーチャルホストの設定

# テキトーなところにWeb用のディレクトリを作る。
cd
mkdir Web
cd Web
mkdir project
cd project

# どっかからソースコードをダウンロードしてくる。
git clone ssh://example.com/var/repos/www .

# hostsファイルの設定
sudo vim /private/etc/hosts

127.0.0.1       project.localhost

# バーチャルホストの設定
sudo cp /private/etc/apache2/original/extra/httpd-vhosts.conf /private/etc/apache2/extra/httpd-vhosts.conf
sudo vim /private/etc/apache2/extra/httpd-vhosts.conf

<VirtualHost *:80>
    DocumentRoot "/Users/username/Web/project"
    ServerName
project.localhost
    ServerAlias
project.localhost
    ErrorLog "/private/var/log/apache2/project.localhost-error_log"
    CustomLog "/private/var/log/apache2/
project.localhost-access_log" common
    <Directory "
/Users/username/Web/project">
         order deny,allow
         allow from All
    </Directory>
</VirtualHost>

# Apacheの設定(2行のコメントアウト外すだけ)
sudo vim /etc/apache2/httd.conf

LoadModule php5_module        libexec/apache2/libphp5.so
Include /private/etc/apache2/extra/httpd-vhosts.conf

# Apacheの再起動
sudo /usr/sbin/apachectl restart

これでPHPが動くようになるはず。PHPはMac OSに標準で入っているのでインストールする必要なしで、WEBサーバから使えるようにすればOK!

http://project.localhost/ を開くと、~/Web/projectの中に配置したページが表示されます。

Aptana Studio 3のインストール

愛するAptanaをインストールします。Windowsの時と同じ環境で開発できるのはありがたい。パーフェクトとは思いませんが使いやすい統合開発環境だと思います。

Aptana Studio 3

http://www.aptana.com/

MySQLのインストール

http://www.mysql.com/

MySQLのサイトからダウンロードします。Mac OS X ver. 10.6 (x86, 64-bit), DMGというやつをダウンロードしました。

展開したら、3つのプログラムを順番に実行していきます。これでMySQLサーバ起動完了。

mysql-5.5.17-osx10.6-x86_64.pkg
MySQLStartupItem.pkg
MySQL.prefPane

(参考)Mac OS XにMySQLをインストールしよう

PHPからMySQLに接続

# データベースにテスト用のデータをインポート
scp example.com:/home/username/mysqldump.sql .
/usr/local/mysql/bin/mysql -u user < mysqldump.sql

# PHPからMySQLに接続できるようにする
sudo cp /etc/php.ini.default /etc/php.ini
sudo chmod +w /etc/php.ini
sudo vim /etc/php.ini

mysql.default_socket = /private/tmp/mysql.sock

# mysql.sockの位置が分からなかった場合
sudo find / -name mysql.sock -print

# Apacheの再起動
sudo /usr/sbin/apachectl restart

MySQLサーバは立ち上がってるんですが、PHPから接続できなくて、「アレ?」となりますが、php.iniの設定を1行書き換えると接続できるようになります。

(参考)Mac OS X LeopardでPHPからMySQLに接続する

by katty0324 on 2011-10-25 04:32:30

コメント(0)

katty0324

MySQLのレプリケーションできたー。少しずつサーバ1台態勢から脱却できるように頑張ろう。 http://t.co/6K1v6taM

on 2011-10-18 02:18:27

webから

はじめに

MySQLのレプリケーションに挑戦してみたのでその記録です。

レプリケーションって何?

「レプリカ」を作ること、データベースサーバの複製を作ることです。

WEBサイトへのアクセスが増えて1台のデータベースサーバでさばききれなくなった場合などに使います。1台でさばけないなら2台にすればいいんですが、2台のデータベースサーバが同じデータをもつようにしてやらねばなりません。

その一つの方法がレプリケーションです。

1台目をマスター、2台目をスレーブとして、主従関係をもたせます。データベースへの更新処理はマスターに対してのみ行なって、マスターには常に最新のデータがあることを保証します。マスターに対する更新処理のログを残しておき、それを定期的にスレーブにも実行します。

そうするとマスターに対して少し遅れをとるものの、スレーブもマスターと同じ内容にすることができます。

そもそも「1台のデータベースサーバで十分です。」という状況ではレプリケーションは必要ありません。データベースサーバを増やしたくなるのは、性能を上げたいとか、システムがダウンしないように予備を用意しておきたいとか、そういう場合です。(アクセスの少ないサイトを、落ちたら諦めようというスタンスで運営していた場合必要ないと思います。)

レプリケーションで何をしたの?

MySQLのバックアップを定期的に取りたいと思いました。mysqldumpというコマンドを使えば、データベースの内容をテキストに落としこんでくれます。

mysqldump --all-databases --opt -u user -ppassword > mysqldump.sql

--optのオプションについて。mysqldumpの実行中にデータベースの中身が書き変わってしまうと、データに不整合が生じる危険性があるので、mysqldumpの実行中はデータベースの書き込みをロックしています。

しかし、書き込みがロックされている間にWEBサイトにアクセスしてくれた人は、ロックが解除されるまでアクセスができないという状態になります。(更新系クエリがなければアクセスできます)

そこで、レプリケーションを組んで、スレーブ側でmysqldumpを実行すれば良いんじゃないかと思いました。

マスター側だけでWEBサイトが動いている状況では、スレーブをロックしてもサイトには影響を及ぼしません。スレーブにはレプリケーションによってマスター側と同じものがコピーされているはずなので、これをmysqldumpすれば良いという寸法です。(そもそもレプリケーションが正しく行われないかもしれない・・・という心配がありますが、とりあえず無視しておきます。)

設定の仕方

以下のページを見ながらやっただけなので、こちらを見たほうが分かりやすいと思います。

MySQL レプリケーションのセットアップ手順

http://wadslab.net/wiki/index.php?MySQL%20%A5%EC%A5%D7%A5%EA%A5%B1%A1%BC%A5%B7%A5%E7%A5%F3%A4%CE%A5%BB%A5%C3%A5%C8%A5%A2%A5%C3%A5%D7%BC%EA%BD%E7

設定は、マスターサーバと、スレーブサーバを行ったりきたりします。

どちらもさくらVPSを使っていて、マスターはサービス用にそこそこ良いやつ、スレーブは前に契約して余っていた一番安いやつです。

作業ログ

緑色はmysql内やvim内で入力する内容。赤色は適宜書き換えるところです。マスターのIPが49.212.yyy.yyyで、スレーブのIPが49.212.xxx.xxxとしています。

# master
yum update -y mysql

# slave
yum update -y mysql

#master
mysql -u username -p

grant replication slave on *.* to 'repl'@'49.212.xxx.xxx' identified by 'password';
quit

sudo vim /etc/my.cnf

log-bin=mysql-bin
server-id=1001

sudo /etc/init.d/mysqld restart

# slave
sudo vim /etc/my.cnf

server-id=1002

sudo /etc/init.d/mysqld restart

# master
mysql -u username -p

flush tables with read lock;
show master status
# FileとPositionを控えておく

# master(別のターミナルから)
mysqldump -u username -p database --lock-all-tables > dbdump.db

# mster(元のターミナルから)
unlock tables;
scp ./dbdump.db 49.212.xxx.xxx:~/dbdump.db

# slave
mysql -u username -p database < dbdump.db
mysql -u
username -p

# 先ほど控えたFileとPositionをここで使う
change master to master_host = '49.212.yyy.yyy', master_user='repl', master_password='password', master_log_file='mysql-bin.000001', master_log_pos=9201;
start slave;

バックアップの取り方

レプリケーションと関係ないですが、目的が自動バックアップをとるところだったので、そのあたりも書いておきます。mysqldumpを実行するシェルスクリプトをcronで定期的に実行させてやるだけです。

cd /home/user
mkdir bak
vim bak_mysql.sh

file="/home/user/bak/mysqldump-"`date '+%Y%m%d%H%M'`".sql"
mysqldump --all-databases --opt -u user -ppassword  > $file

chmod 755 bak_mysql.sh
crontab -e

0 1 */1 * * cd /home/user;/bin/bash /home/user/bak_mysql.sh

おわりに

サーバ2台使うならスレーブ側にも読み込み系処理をさせたら良いではないかとか、バックアップとるだけなら他に方法がとか、セキュリティ的にとか、気づいたことがあればどうか突っ込んでください。

by katty0324 on 2011-10-20 03:18:35

コメント(0)

katty0324

iPhoneアプリがメモリ不足で落ちる理由は「メモリが足りない → OSによってビュー強制終了 → 強制終了ビューのオブジェクトにアクセス → 応答不可 → アプリ強制終了」か?

on 2011-08-30 10:28:20

webから

iPhoneアプリは良く落ちる。

ランキングで上位に入ったり、話題になったりしているアプリでも落ちる時は落ちる。
なぜ落ちるか?

原因のほとんどは、

解放済みのオブジェクトにメッセージを送ってしまうこと

だと思います。


メモリ不足で落ちる?

「メモリ不足で落ちる」という言葉も良く使いますが、本質的には

  1. メモリが不足する
  2. 自動的にオブジェクトが解放される
  3. 解放されたオブジェクトにメッセージが送られる
  4. エラー

という流れで生じるものだと思います。

だから、この問題の解決策は、ふたつ。

  1. メモリを無駄に使わない(メモリリークを無くす)
  2. メモリ不足などによって解放されたオブジェクトにメッセージが送られないようにする

そのために気をつけるべきことなどを以下に列挙します。


alloc initしたら参照カウントが増えるので、かならずreleaseする。

非常に基本的なことですが、確保したものは解放します。

NSString *string = [[NSString alloc] initWithString:@"test"];
// ...処理...
[string release];


クラスメソッドで初期化した場合はreleaseしない。

次の例のようにクラスメソッドで初期化する場合があります。

この場合、autoreleaseの状態、つまり後ほど自動でreleaseが送られることになっているため、自分ではreleaseしません。

NSString *string = [NSString stringWithString:@"test"];
// ...処理...


CF〜Create()で作られたオブジェクトはCFRelease()で開放する。

CF〜Create()という関数で作られたオブジェクトも必ず解放する必要があります。

CFDataRef dataref = CFDataCreate(NULL, buffer, CFDataGetLength(data));
// ...処理...
CFRelease(dataref);


viewDidUnloadはいつ呼ばれる?

viewDidUnloadというメソッド名を見ると、まるでビューが閉じる時に呼ばれそうなものですが、これは勘違い。

一度も呼ばれることなくビューが開いて閉じることも多々あります。


ではいつ呼ばれるかといえば、低メモリ状態になった時です。

低メモリ時、最前面で表示されているもの以外のビューコントローラにはviewDidUnloadが呼ばれます。


viewDidLoadで確保した変数はviewDidUnloadでreleaseする。

viewDidUnloadされたビューコントローラは、画面が空っぽになってしまいます。

まだ使っている最中のビューコントローラが空になっても、問題がないのは、次に表示されるときに再びviewDidLoadが呼ばれて画面を作り直すためです。

もし、1回目のviewDidLoadで確保したオブジェクトをviewDidUnloadで解放していないと、2回目のviewDidLoadをするときにメモリリークを起こします。

だから、viewDidLoadで確保したオブジェクトはviewDidUnloadで解放します。


initとviewDidLoadで確保したメモリはdeallocでreleaseする。

上でも書いたように処理が終わってビューコントローラが閉じる時には、viewDidLoadは呼ばれません。

deallocだけが呼ばれます。

したがって、initで確保したオブジェクトはもちろん、viewDidLoadで確保したものも解放する必要があります。


didReceiveMemoryWarningでオブジェクトを解放する時はnilを代入する。

低メモリ状態になると、確保されている全てのビューコントローラにdidRecieveMemoryWarningが呼ばれます。

viewDidUnloadは、ビューコントローラが閉じた状態になると、もう呼ばれません。

しかし、didReceiveMemoryWarningはメモリが足りなくなるたびに何度でも呼ばれます。


ここで注意しなければならないことは、1回目のdidReceiveMemoryWarningで解放されたオブジェクトに、2回目のdidReceiveMemoryWarningで再びreleaseが送られるとクラッシュします。

そこで、didReceiveMemoryWarning内で解放したオブジェクトにはnilを代入して、二度目の解放処理が行われないようにします。

(nilはreleaseを受け取ってもクラッシュしないためです)


というかオブジェクトを解放する時はnilを代入する。

解放後にメッセージが送られる可能性があるオブジェクトを解放する時は、releaseだけでなくnilの代入が必要です。

そうでない場合でも、nilを代入して悪いことはないです。

[obj release];
obj = nil;


プロパティとして定義されているものは、nilを代入して解放する。

プロパティとして定義されている変数はセッターにreleaseの処理が含まれているので、nilを代入するだけで済みます。

self.obj = nil;

この解放手段は、プロパティがassignかretainかcopyか考える必要がなくて一石二鳥です。

http://iphone-dev.g.hatena.ne.jp/tokorom/20100314/1268591111


ただし、次のように書いてしまうとセッターが働かず解放できないので注意。

obj = nil


マルチスレッドの場合は、全てのスレッドでNSAutoreleasePoolを作成する。

NSAutoreleasePoolはスレッド内でのみ有効なので、新たにスレッドを立てる場合はNSAutoreleasePoolを作成する必要があります。


ループ内など大量のオブジェクトを確保するところでは、局所的にNSAutoreleasePoolを作成する。

ループ内でオブジェクトを確保するような処理では、大量のメモリを消費するので、NSAutoreleasePoolを局所的に作成するなどして、ループが1周するたびにメモリを解放するようにしてやります。


UIScrollViewでaddSubviewをする場合は、画面外に出たviewをremoveFromSuperviewする。

UITableViewでは画面外に出たセルを自動的に再利用する機構がありますが、UIScrollViewにはありません。

したがって、そのような機構を自作するなどして画面外に出たviewを閉じることでメモリ使用量を削減します。


メモリ使用量の取得方法

プロファイラなどを使えば見えるが、プログラム中で値として取得したい場合

http://d.hatena.ne.jp/kimada/20090405/1238914098#20090405f1


メモリリークを調べる。

Xcode4をRunではなくAnalyzeで実行することで、本質的にメモリリークになる部分を全て指摘してくれます。便利。

これを全てつぶしても、動的に生じるメモリリークは残るので、更にProfileで実行してメモリリークをプロファイルします。

これでひとつずつ確認して原因を潰していく作業が待っています。


メモリ警告シミュレーションの仕方

iOSシミュレータのメニューから、メモリ警告シミュレーションを実行できる。

これでメモリ不足の警告を出し、つまり背面のビューコントローラをUnloadしたりして、メモリリークが起きたり、解放されたオブジェクトにメッセージが送られるようなプログラムになっていないかを確認します。


おわりに

以上で終わりです。

勉強しながらまとめたものですので、もし誤っているところがありましたら、お知らせください。


参考URL

http://konton.ninpou.jp/program/cocoa/memory.html
http://iphone-dev.g.hatena.ne.jp/tokorom/20100314/1268591111
http://hamasyou.com/blog/archives/000384
http://labs.torques.jp/2010/11/07/1495/
http://safx-dev.blogspot.com/2010/10/viewcontroller.html
http://d.hatena.ne.jp/sakusan_net/20110226/1298727973
http://journal.mycom.co.jp/column/objc/104/index.html
http://hamasyou.com/blog/archives/000383
http://d.hatena.ne.jp/glass-_-onion/20110218/1297963007
http://cocoadays.blogspot.com/2010/10/nsautoreleasepool.html

by katty0324 on 2011-09-05 23:36:05

コメント(0)