2012年4月3日火曜日

zshでnaveを使うと"no such option: rcfile"が出る

どうも、俺@仕事中です。
nodeのバージョン管理をnaveを使って優雅に使いこなそうとして

$ ./nave.sh use stable
とかカッコ付けてやると

$ Already installed: 0.6.14
using 0.6.14
/bin/zsh: no such option: rcfile
とか出て「マジでか!?」ってなる人へ。

nave use latest: zsh no such option rcfile - Linux LABS
にあるように実行ユーザのシェルをbashに変えちゃうという方法もありますが。

nave.shを見てみると
$ vim nave.sh

-------------------------------
408: "$SHELL" --rcfile "$NAVE_DIR/naverc"
〜(中略)〜
464: "$SHELL" --rcfile "$NAVE_DIR/naverc"
と2ヶ所rcfileオプションを使ってる場所があります。
そもそもrcfileオプションはbashで使えるオプションで、コマンドラインでシェルを使う場合に設定ファイルとして読み込むファイルを指定できるオプションです。
つまり上記のnave.shでは

 bash --rcfile ~/.nave/naverc
のように"~/.nave/naverc"を読み込んで対話型bashを使う、というようにプログラムされているのですが、
実行ユーザのシェルがbash以外だと$SHELLがzshなりtcshなりに展開されて、意図しない動きになっちゃう訳です。

僕が普段使うzshは--rcfileというオプションが使えません。
基本的にログイン時は

$ZDOTDIR/.zshenv $ZDOTDIR/.zprofile $ZDOTDIR/.zshrc $ZDOTDIR/.zlogin
これらのファイルが読み込まれるのですが、全部が全部ログイン時に読み込まれるわけではなく、詳しくは
zsh - watallica metallicus
を参照のこと。

今回は .zshrc に設定することにします。
# 以下の方法は正しい動作を保証するものではありません。
# とりあえず動くように設定していますので、安定性を重視する場合は実行ユーザのログインシェルをbashにしておき、配布されたソースプログラムは変更しない事をお勧めします。

という訳で、書き換えちゃいましょう。
$ vim nave.sh

-------------------------
# nave_use () 内
397: else
398:   hash -r
399:   NAVELVL=$lvl NAME="$version" ¥
400:     NAVEPATH="$bin" ¥
401:     NAVEVERSION="$version" ¥
402:     NAVENAME="$version" ¥
403:     npm_config_binroot="$bin" npm_config_root="$lib" ¥
404:     npm_config_manroot="$man" ¥
405:     npm_config_prefix="$prefix" ¥
406:     NODE_PATH="$lib" ¥
407:     NAVE_LOGIN="1" ¥
408:    "$SHELL"
409: #"$SHELL" --rcfile "$NAVE_DIR/naverc"

コレでよしと。

次にnave用のzshが起動されたときの処理を.zshrcに書きます。
$ vim ~/.zshrc
------------------------------------
# 追加
if [ "$NAVE_LOGIN" = "1" ]; then
    export PATH=$NAVEPATH:$PATH
fi


これで準備完了です。
あとは優雅に

$ nave.sh use stable
と打つべし。


以上でぇぇぇえぇぇす。





gccのバージョンを確認する方法

どうも、俺@昼休みです。

インストールされているgccのバージョンを確認したい場合は

$ gcc -dumpversion
3.4.5
で確認できます。
ちなみにv3.4.5は非常に古いバージョンですが、僕の開発サーバではこのバージョンでgcc使ってます。


以上でぇぇぇぇぇえす。

2012年3月23日金曜日

CGRect、CGSize、CGPointについて

どうも、俺@絶賛開発中です。
今日は(も)Objective-Cについてです。最近はアプリ(iOS/Android)関連の仕事が多いですね。

Objective-Cで開発してるとよくCGRectやCGPoint、CGSizeなどといったクラス(構造体)を使います。
これについてメモメモ。
ゲームアプリなど座標を細かく管理する開発では必須の知識です。

■CGRect
オブジェクトの座標とサイズを管理します。
// 座標(100, 100)の位置に横50 x 縦50のサイズを表すCGRect
CGRect rect = CGRectMake(100, 100, 50, 50);


■CGPoint
オブジェクトの座標を管理します。
//座標(200, 100)の位置を表すCGPoint
CGPoint point = CGPointMake(200, 100);


■CGSize
オブジェクトのサイズを管理します。
// 横200 x 縦100のサイズを表すCGSize
CGSize size = CGSizeMake(200, 100);


またこれらをコンソール上にログ出力する場合は、

CGRect rect = CGRectMake(0, 0, 30, 30);
NSLog(@"%@", rect);
のようにしても出力されません。

座標情報やサイズをログ出力させるには、
NSStringFromCGRect()
NSStringFromCGPoint()
NSStringFromCGSize()
これらを使います。

CGPoint point = CGPointMake(100, 200);
NSLog(@"%@", NSStringFromPoint(point));


以上でぇぇぇえぇす。

2012年3月13日火曜日

NSStringのstringByAppendingPathComponent注意

どうも、俺@仕事中です。
Objective-Cでゲームとか開発してると、ユーザのちょっとしたデータをファイルに保存したりしますよね。

その時のコードでエラー起こしてしまったので、対処法をメモ。

間違いソースがこれです。

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex: 0];
self.filePath = [directory stringByAppendingPathComponent: @"hoge.plist"];
self.filePathは保存するファイルのパスを格納するNSStringなクラス変数です。

これだとstringByAppendingPathComponentメソッドは結果をautoreleaseしている(と思う)ので、
ココの処理を抜けた時点でself.filePathはリリースされてしまう(はず)。
別のメソッドでself.filePathを使おうとしても、リリースされたオブジェクトにアクセスしようとしてEXC_BAD_ACCESSになっちゃう。


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex: 0];
self.filePath = [[NSString alloc] initWithString: [directory stringByAppendingPathComponent: @"hoge.plist"]];
にしてやれば、self.filePathを自身のdeallocメソッド内でreleaseすることが出来る!


以上でぇぇえぇす。

2012年3月6日火曜日

Autoingestion.classを使うとjavax.net.ssl.SSLHandshakeExceptionが出ちゃう

どうも、俺@残業中です。

iPhoneアプリの販売データを取得するため、AppleはAutoingestion.classなるものを用意してくれてます。
iTunesConnectのSales and TrendsにあるデータをTSVデータとしてDLできます。
わざわざHTMLをスクレイピングしなくて良いですね!
ドキュメントはココ
とても分かりやすい参考サイトは iTunesConnectからアプリダウンロード数レポートを自動取得する方法 - zaru blog がとても分かりやすいです!

ところが、僕の開発環境だと、このプログラムを実行させるとタイトルの通り

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
になっちゃいます。ほとんどの人は関係ないと思いますが。。
今日はその解決法をばめもめも。

javaのkeytoolというコマンドを使って、証明書をインポートすれば良いそうです。
あまりjavaには明るくない俺なりに調べてみたのですが、
どうやら[SSLHandshakeException]信頼できない証明書のサイトと無理矢理接続する方法にあるように、
Javaで信頼できないSSL証明書を使ってHTTPコネクションを貼ろうとした場合に出る例外のようです。
AppleからのAutoingestion.classがどういう実装になっているのか調べてみれば分かるかもしれませんが、
とりあえず今回は解決優先ということで、「Sales And Trends」データを取得しにいくサーバへSSL通信するときの証明書が怪しいのでは?という仮説を立てて対応することにしました。

つまり、接続先の証明書をkeytoolを使ってインポートすれば良いのです。
証明書はhttps://itunesconnect.apple.comのものだと思います。
つまり、Autoingestion.classはitunesconnect.apple.comへ接続しにいっているはず。
(多分。。。tcpdumpとかでパケットを監視してないので嘘だったらごめんなさい。今度調べます。)

なので、FireFox(僕Mac版FireFox使ってます)とかで上記URLを叩き、
アドレスバーの左側(緑色になっているはず)をクリック>詳細を表示>「セキュリティ」タブ>証明書を表示...>「詳細」タブ>書き出す...
の操作を行えば証明書を取得できます。

この証明書ファイルを、開発サーバのjavaへ組み込みます。

$ keytool -import -keystore /usr/local/jdk1.6.0_16/jre/lib/security/cacerts -storepass changeit -file /path/to/証明書ファイル
これでOK。
-keystore は俺の環境での値を書きましたが、環境に合わせて書き換えて下さい。
-storepass はデフォルトでchangeitです。
-file は先程FireFoxから取得した証明書ファイルへのパスです。
何とこれでサーバのjava(/path/to/jdk/jre/lib/security/cacerts)に証明書データがインポートされ、
「信頼できる証明書」として扱われます。
オレオレ証明書を作成した場合などで使えますね!

keytoolについてはJava/keytool - 備忘録に詳しく書かれています。


これでAutoingestion.classを使えば、悩み解決されます!

$ java -cp . Autoingestion username password vendorid Sales Daily Summary `date +%Y%m%d -d "2 days ago"`

.gzファイルがDLされます!

以上でぇぇぇえぇす。