2016年2月14日日曜日

Goでクロスコンパイルを実行する

Go 1.5からはクロスコンパイルが簡単に実行できるようになっている。

github公開用としてコードを書く場合
$ cd $GOPATH
$ mkdir -p src/github.com/hogeuser/fugarepo
$ cd src/github.com/hogeuser/fugarepo

ローカルマシン専用にコードを書く場合
$ cd $GOPATH
$ mkdir src/foohost.local
$ cd src/foohost.local

hello.go
package main

import "fmt"
import "runtime"

func main() {
        fmt.Printf("hello, %s/%s\n", runtime.GOOS, runtime.GOARCH)
}


OS X用にビルドして実行する場合
$ go build -o hello hello.go 
$ ./hello
hello, darwin/amd64

Windows用にビルドする場合
$ GOOS=windows GOARCH=amd64 go build -o hello.exe hello.go

Raspberry Pi 2用にビルドする場合
$ GOOS=linux GOARCH=arm GOARM=7 go build -o hello hello.go


[参考URL]
Go1.5はクロスコンパイルがより簡単 | SOTA
GoArm
Cross compile with Go 1.5 for Raspberry Pi

2016年2月13日土曜日

Goをインストールする

homebrewを使ってGoをインストールする。
$ brew update && brew install go

環境変数としてGOPATH、GOROOTを設定した上でPATHを通す。
GOPATH配下はbin、pkg、srcのディレクトリで構成されることが想定されている。GOROOTについてはGoツールのパスを指定しておく。
$ mkdir ~/golang
$ echo 'export GOPATH=$HOME/golang' >> ~/.bashrc
$ echo 'export GOROOT=/usr/local/opt/go/libexec' >> ~/.bashrc
$ echo 'export PATH=$GOPATH/bin:$PATH' >> ~/.bashrc
$ echo 'export PATH=$GOROOT/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc

使用可能なコマンドを確認する。
$ go help

インストールされたGoのバージョンを確認する。
$ go version
go version go1.5.3 darwin/amd64

Goの環境情報を確認する。
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/hogeuser/golang"
GORACE=""
GOROOT="/usr/local/opt/go/libexec"
GOTOOLDIR="/usr/local/opt/go/libexec/pkg/tool/darwin_amd64"
GO15VENDOREXPERIMENT=""
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
CXX="clang++"
CGO_ENABLED="1"

入力補完用にgocodeをインストールする。
$ go get -u github.com/nsf/gocode


現時点でのhomebrew Formulaを確認する限り、godocとvetはデフォルトでインストールされるようだが、別途インストールする必要がある場合は下記の通り実行する。

godocのインストール
$ go get golang.org/x/tools/cmd/godoc

vetのインストール(先にMercurialをインストールしておく必要がある)
$ brew install mercurial
$ hg version
Mercurial Distributed SCM (version 3.6.1)
(see https://mercurial-scm.org for more information)

Copyright (C) 2005-2015 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ go get golang.org/x/tools/cmd/vet


[参考URL]
How to Write Go Code - The Go Programming Language
Goのコマンド
これからGoを始める人のためのTips集

2016年2月5日金曜日

Pythonバージョン管理ツールを導入する

Pythonバージョン管理ツールであるpyenvを導入する。pyenvプロジェクトはrbenv及びruby-buildからフォークされ、Python用にモディファイされたプロジェクトである。そのため、導入方法はほぼRubyの場合と同様(参考:Rubyバージョン管理ツールを導入する)。

pyenvをインストールしてPATH設定する。
$ brew update
$ brew install pyenv

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ exec $SHELL -l

pyenvのバージョンを確認する。
$ pyenv -v
pyenv 20160202

インストール可能なPythonのバージョンを確認する。
$ pyenv install -l

2.7.10をインストールする。
$ pyenv install 2.7.10
$ pyenv rehash

3.5.0をインストールする。
$ pyenv install 3.5.0
$ pyenv rehash

インストールされているPythonのバージョンを確認する。
$ pyenv versions
* system (set by /Users/hogeuser/.pyenv/version)
  2.7.10
  3.5.0

使用するPythonのバージョンを切り替える。
$ pyenv global 2.7.10
$ pyenv versions
  system
* 2.7.10 (set by /Users/hogeuser/.pyenv/version)
  3.5.0

使用中のPythonのバージョンを確認する。
$ pyenv version
2.7.10 (set by /Users/hogeuser/.pyenv/version)
$ python --version
Python 2.7.10

2015年5月23日土曜日

GCDについて情報整理する

歴史的なことも含めてGCDに関する情報を整理しておく。


GCDの歴史

  • Mac OS X 10.6(Snow Leopard)以降、iOS 4.0以降で利用可能
  • OS X 10.8(Mountain Lion)、iOS 6.0以降では、GCDオブジェクト(Dispatch Queue)もARCの管轄下に入るようになった(実際にはGCDだけでなくXPCも)
  • OS X 10.10(Yosemite)、iOS8.0 からQoS(Quality of Service)の概念が導入された


ディスパッチキューの利用


ディスパッチキューの利用には大きく分けて2つの方法がある

  1. dispatch_queue_create関数を使ってディスパッチキューを自分で生成する
  2. システムが標準で提供しているディスパッチキューを取得する

1. dispatch_queue_create関数を使ってディスパッチキューを自分で生成する

  • 開発者はシリアルキューとコンカレントキューを生成できる
  • コンカレントキューを自分で生成するケースは稀
  • OS X v10.7、iOS 4.3以降から第2引数にNULL以外を指定できるようになった

1.1. シリアルキューを生成する場合
dispatch_queue_t mySerialDispatchQueue 
= dispatch_queue_create("com.example.MySerialDispatchQueue", DISPATCH_QUEUE_SERIAL);
// または、下記の通り、第2引数にNULLを指定してもよい。
// ただし、個人的には明示的に定数指定している上記の書き方の方がいいと思う。
//dispatch_queue_t mySerialDispatchQueue 
//= dispatch_queue_create("com.example.MySerialDispatchQueue", NULL);

1.2. コンカレントキューを生成する場合
dispatch_queue_t myConcurrentDispatchQueue 
= dispatch_queue_create("com.example.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);


2. システムが標準で提供しているディスパッチキューを取得する

  • システムが標準で提供しているディスパッチキューは2種類ある(Main Dispatch QueueとGlobal Dispatch Queue)
  • アプリのどこからでも利用できる

2.1. Main Dispatch Queue
  • メインスレッドで実行されるシリアルキュー(メインスレッドは1つしかないため)
  • 実際にはメインスレッドで実行されるデフォルトのRunLoopで処理される
  • Main queue is access queue for UI
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();

2.2. Global Dispatch Queue
  • コンカレントキュー
  • 実行優先度別に4種類(従来方式)または5種類(QoS方式)ある
  • 2015年5月現在においてバックワードコンパチを考慮(例えばiOS7.xをサポート)する場合は必然的に従来方式を採用することになる
// OS X 10.10(Yosemite)、iOS8.0以前でも以降でも利用できる
// 第2引数は0固定

dispatch_queue_t globalDispatchQueuePriorityHigh 
= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

dispatch_queue_t globalDispatchQueuePriorityDefault 
= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_queue_t globalDispatchQueuePriorityLow 
= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

dispatch_queue_t globalDispatchQueuePriorityBackground 
= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

// OS X 10.10(Yosemite)、iOS8.0以降でしか利用できない
// 第2引数は0固定

// 基本的にはQoSに関する明確な意思を決めて
// QOS_CLASS_DEFAULT以外を選択するのが良さげ。
// また、QOS_CLASS_DEFAULTについては下記の通り。
// Ordered between UI and non-UI QoS
// Not intented as a work classification

dispatch_queue_t globalDispatchQueueQosInteractive 
= dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0);

dispatch_queue_t globalDispatchQueueQosInitiated 
= dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);

dispatch_queue_t globalDispatchQueueQosDefault 
= dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);

dispatch_queue_t globalDispatchQueueQosUtility 
= dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);

dispatch_queue_t globalDispatchQueueQosBackground 
= dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0);



コード例


ワーカスレッドがシリアルの場合
dispatch_queue_t mySerialDispatchQueue 
= dispatch_queue_create("com.example.MySerialDispatchQueue", DISPATCH_QUEUE_SERIAL);
    
dispatch_async(mySerialDispatchQueue, ^{
    // ワーカスレッド(シリアル)
    // 重い処理をここに書く
    
    dispatch_async(dispatch_get_main_queue(), ^{
        // メインスレッド(シリアル)
        // UI処理をここに書く
    });
    
});

ワーカスレッドがコンカレントの場合
//dispatch_queue_t globalDispatchQueuePriorityDefault 
//= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(globalDispatchQueuePriorityDefault, ^{
    // ワーカスレッド(コンカレント)
    // 「コンカレント実行されても問題ない」重い処理をここに書く
    
    dispatch_async(dispatch_get_main_queue(), ^{
        // メインスレッド(シリアル)
        // UI処理をここに書く
    });
    
});

2015年5月17日日曜日

CocoaPodsを使ってAFNetworkingを導入する

導入対象プロジェクト(今回の場合はPodsSample.xcodeproj)は閉じておく。
プロジェクトファイルがあるディレクトリまで移動後、Podfileを生成する。
$ cd /path/to/PodsSample
$ pod init

Podfileを編集する。
$ open -a Xcode Podfile

Podfile
# Uncomment this line to define a global platform for your project
# platform :ios, '6.0'
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

target 'PodsSample' do
  pod 'AFNetworking', '~>2.5.3'
end

target 'PodsSampleTests' do

end


Podfileを保存して閉じた後、pod installを実行する。
$ rm Podfile.lock
$ pod install --verbose

以降は常にプロジェクトではなく、ワークスペースを開いて使う。
$ ls -l
(下記は抜粋表示)
Podfile
Podfile.lock
Pods
PodsSample
PodsSample.xcodeproj
PodsSample.xcworkspace
PodsSampleTests

$ open PodsSample.xcworkspace


CocoaPods管理のライブラリを更新する際は下記を実行する。
$ pod update


2015年5月16日土曜日

CocoaPodsをインストールする

使用中のRuby及びgemのバージョンを確認する。
$ rbenv version
2.2.0 (set by /Users/hogeuser/.rbenv/version)
$ gem -v
2.4.7

CocoaPodsをインストールする。
$ gem install cocoapods
$ rbenv rehash
$ pod setup --verbose


補足


「gem install cocoapods」により"追加で"インストールされたgem
activesupport (4.2.1)

claide (0.8.1)
cocoapods (0.37.1)
cocoapods-core (0.37.1)
cocoapods-downloader (0.9.0)
cocoapods-plugins (0.4.2)
cocoapods-trunk (0.6.0)
cocoapods-try (0.4.4)
colored (1.2)
escape (0.0.4)
fuzzy_match (2.0.4)
i18n (0.7.0)

molinillo (0.2.3)
nap (0.8.0)
netrc (0.7.8)

thread_safe (0.3.5)
tzinfo (1.2.2)
xcodeproj (0.24.1)

インストールするCocoaPodsのバージョンを指定する場合(RubyGemsの仕様通り)
$ gem install cocoapods --version "=0.36.4"

「pod setup」ではそれなりに時間がかかるので根気よく待つ。

2015年4月29日水曜日

32bit EFIブートファイルを作成する

WindowsタブレットPC等で採用されているCPU(Intel Atom: xx Trail)は基本的に32bitアーキテクチャであり、最近は例外なくファームウェアとしてUEFIが採用されていることから、この類のものにLinuxをインストールしたい場合は、別途32bit版(U)EFIファイルを用意する必要がある。

環境
  • Ubuntu Server 14.04.2 LTS x64

作業ディレクトリを作成
$ mkdir ~/tmpwork
$ cd ~/tmpwork

必要なパッケージをインストール
$ sudo apt-get update -y
$ sudo apt-get install -y git build-essential
$ sudo apt-get install -y bison libopts25 libselinux1-dev autogen m4 autoconf help2man libopts25-dev flex libfont-freetype-perl automake autotools-dev libfreetype6-dev texinfo

GRUB 2のソースを落としてきてmake
$ git clone git://git.savannah.gnu.org/grub.git
$ cd grub
$ ./autogen.sh
$ ./configure --with-platform=efi --target=i386 --program-prefix=''
$ make

EFIファイルを作成
$ cd grub-core
$ sudo ../grub-mkimage -d . -o bootia32.efi -O i386-efi -p /boot/grub ntfs hfs appleldr boot cat efi_gop efi_uga elf fat hfsplus iso9660 linux keylayouts memdisk minicmd part_apple ext2 extcmd xfs xnu part_bsd part_gpt search search_fs_file chain btrfs loadbios loadenv lvm minix minix2 reiserfs memrw mmap msdospart scsi loopback normal configfile gzio all_video efi_gop efi_uga gfxterm gettext echo boot chain eval

作成したEFIファイルを作業ディレクトリ直下にコピーしておく
$ cp bootia32.efi ~/tmpwork


[参考URL]
Instructions to install Ubuntu 14.10 on ASUS EeeBook X205TA
UEFIBooting - Community Help Wiki

2015年4月26日日曜日

Ubuntu ServerインストーラをUSBメモリに書き込む

環境
  • Ubuntu Server 14.04.2 LTS x64

isoイメージファイルをダウンロード
$ wget http://releases.ubuntu.com/14.04/ubuntu-14.04.2-server-amd64.iso
$ md5 ubuntu-14.04.2-server-amd64.iso 
MD5 (ubuntu-14.04.2-server-amd64.iso) = 83aabd8dcf1e8f469f3c72fff2375195

isoファイルからimgファイルに変換
$ hdiutil convert -format UDRW -o ubuntu-14.04.2-server-amd64.img ubuntu-14.04.2-server-amd64.iso
$ mv ubuntu-14.04.2-server-amd64.img.dmg ubuntu-14.04.2-server-amd64.img

USBメモリを接続してディスク番号を確認
$ diskutil list
$ df -h

USBメモリをアンマウントした上で、rawデバイス指定でimgファイルを書き込む
(下記はディスク番号が「2」の場合)
$ sudo diskutil unmountDisk /dev/disk2
$ sudo dd bs=1m if=ubuntu-14.04.2-server-amd64.img of=/dev/rdisk2
$ sudo diskutil eject /dev/disk2


[参考URL]
How to create a bootable USB stick on OS X | Ubuntu

2015年3月7日土曜日

Javaの設定を行う

現在インストールされているJDKを確認する(私の環境ではJDK6、7、8がインストール済み)。
$ /usr/libexec/java_home -V

JDK7をJAVA_HOMEとして設定する。
$ vim ~/.bashrc
$ less ~/.bashrc
(関連箇所を抜粋)
export JAVA_HOME=`/usr/libexec/java_home -v 1.7`

必要に応じてJavaVMのオプションを設定する。例えば下記の通り。
$ vim ~/.bashrc
$ less ~/.bashrc
(関連箇所を抜粋)
export JAVA_OPTS="-Dfile.encoding=UTF-8"
# または
#export JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"

最後に~/.bashrcを再読み込み
$ source ~/.bashrc

2014年12月30日火曜日

プロキシ環境下でApache Subversionを使う

設定ファイル


~/.subversion/servers


グループ毎に個別指定する場合


アクセスするリポジトリが固定している場合はgroupsセクションで設定するのが望ましい
$ cat ~/.subversion/servers
(関連箇所のみ抜粋)
[groups]
targetgroup1 = somerepository.example.org

[targetgroup1]
http-proxy-host = proxy.example.com
http-proxy-port = 8080
http-proxy-username = foo.bar@example.com
http-proxy-password = hogepass


まとめて指定する場合


外部リポジトリにしかアクセスしない場合等はglobalセクションで一括設定すると楽
$ cat ~/.subversion/servers
(関連箇所のみ抜粋)
[global]
http-proxy-exceptions = *.internal.example.com, *.internal.example.net
http-proxy-host = proxy.example.com
http-proxy-port = 8080
http-proxy-username = foo.bar@example.com
http-proxy-password = hogepass

2014年11月26日水曜日

NSURLSessionを使ってHTTPリクエストする(Swift)

SwiftでNSURLSessionDataTaskを使って、HTTP-GET、JSONデータをHTTP-POSTする。

環境
  • Xcode 6.1
  • iOS 8.1
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    // HTTP-GET
    @IBAction func getAsync(sender: AnyObject) {
        
        // create the url-request
        let urlString = "http://httpbin.org/get"
        var request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
        
        // set the method(HTTP-GET)
        request.HTTPMethod = "GET"
        
        // use NSURLSessionDataTask
        var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { data, response, error in
            if (error == nil) {
                var result = NSString(data: data, encoding: NSUTF8StringEncoding)!
                println(result)
            } else {
                println(error)
            }
        })
        task.resume()
        
    }


    // HTTP-POST
    @IBAction func postAsync(sender: AnyObject) {
        
        // create the url-request
        let urlString = "http://httpbin.org/post"
        var request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
        
        // set the method(HTTP-POST)
        request.HTTPMethod = "POST"
        // set the header(s)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        
        // set the request-body(JSON)
        var params: [String: AnyObject] = [
            "foo": "bar",
            "baz": [
                "a": 1,
                "b": 20,
                "c": 300
            ]
        ]
        request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: nil)
        
        // use NSURLSessionDataTask
        var task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error in
            if (error == nil) {
                var result = NSString(data: data, encoding: NSUTF8StringEncoding)!
                println(result)
            } else {
                println(error)
            }
        })
        task.resume()
        
    }
        
}

2014年10月5日日曜日

即時関数を使ってグローバル汚染を最小にする


関数単位でスコープが決まる性質を利用する。

  • 即時関数を使ってローカルスコープ化することにより、グローバル汚染を防ぐ。
  • strictモードでは関数内のthisがundefinedになるため、callメソッドを使用する。
  • 関数前の「;」はファイル連結時に不具合が出ないようにするための予防策。
<!DOCTYPE html>
<html>
<head lang="ja">
  <meta charset="UTF-8">
  <title>即時関数によるスコープ閉じ込め</title>
</head>
<body>
  <ul>
    <li id="first">1行目</li>
    <li id="second">2行目</li>
    <li id="third">3行目</li>
  <ul>
  <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
  <script src="./js/app.js"></script>
</body>
</html>
;(function ($) {
  'use strict';

  alert('outside ready method: this = ' + this);
  alert('outside ready method: $ = ' + $);
  alert('outside ready method: _.VERSION = ' + _.VERSION);

  $(function () {
    alert('inside ready method: this = ' + this);
    alert('inside ready method: $ = ' + $);
    alert('inside ready method: _.VERSION = ' + _.VERSION);
    $('#third').css('color', 'red');
  });

  alert('this = ' + this);
  alert('$ = ' + $);
  alert(_.VERSION);

}).call(this, jQuery);
//}.bind(this)(jQuery));

[参考URL]
知ってて当然?初級者のためのJavaScriptで使う即時関数(function(){...})()の全て - 三等兵
callで関数を即時実行すると何が嬉しいのか(と、ちょっとおまけ) - ただぱそこんしてるだけ
便利なjavascriptテクニック集 - Thujikun blog
"use strict" - blog.niw.at

2014年8月16日土曜日

NSURLSessionを使ってHTTPリクエストする

NSURLSessionDataTaskを使って、HTTP-GET、JSONデータをHTTP-POSTする。

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UITextField *requestUrl;
@property (weak, nonatomic) IBOutlet UITextField *requestBody;
@property (weak, nonatomic) IBOutlet UITextView *requestResult;
- (IBAction)getAsync:(id)sender;
- (IBAction)postAsync:(id)sender;

@end
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

// HTTP-GET
- (IBAction)getAsync:(id)sender {
    NSLog(@"%s", __func__);
    
    // create the url-request
    NSURL *url = [NSURL URLWithString:self.requestUrl.text];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    // set the method(HTTP-GET)
    [request setHTTPMethod:@"GET"];
    
    // use NSURLSessionDataTask
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        if (!error) {
            NSHTTPURLResponse *httpRes = (NSHTTPURLResponse *)response;
            NSLog(@"statusCode: %ld", (long)httpRes.statusCode);
            NSLog(@"allHeaderFields: %@", httpRes.allHeaderFields);
            
            NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"result: %@", result);
            
            dispatch_async(dispatch_get_main_queue(), ^{
                self.requestResult.text = result;
            });
            
        } else {
            NSLog(@"error: %@", [error localizedDescription]);
        }
        
    }];
    
    [task resume];
}

// HTTP-POST
- (IBAction)postAsync:(id)sender {
    NSLog(@"%s", __func__);
    
    // create the url-request
    NSURL *url = [NSURL URLWithString:self.requestUrl.text];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    // set the headers(s)
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
    // set the method(HTTP-POST)
    [request setHTTPMethod:@"POST"];

    // set the request-body
    NSString *reqBody = self.requestBody.text;
    NSLog(@"%@", reqBody);

    [request setHTTPBody:[reqBody dataUsingEncoding:NSUTF8StringEncoding]];
    
    // use NSURLSessionDataTask
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        if (!error) {
            NSHTTPURLResponse *httpRes = (NSHTTPURLResponse *)response;
            NSLog(@"statusCode: %ld", (long)httpRes.statusCode);
            NSLog(@"allHeaderFields: %@", httpRes.allHeaderFields);
            
            NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"result: %@", result);
            
            dispatch_async(dispatch_get_main_queue(), ^{
                self.requestResult.text = result;
            });
            
        } else {
            NSLog(@"error: %@", [error localizedDescription]);
        }
        
    }];
    
    [task resume];
}

@end

2014年7月25日金曜日

WICの機能や無線LANの状態を確認する

Raspberry Piに無線LAN USBアダプタ(WLI-UC-GNM)を接続

$ lsusb
(関連箇所のみ抜粋)
Bus 001 Device 004: ID 0411:01a2 BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070]

$ lsmod
Module                  Size  Used by
(関連箇所のみ抜粋)
rt2800usb              17279  0 
rt2800lib              80619  1 rt2800usb
rt2x00usb              11669  1 rt2800usb
rt2x00lib              44799  3 rt2x00usb,rt2800lib,rt2800usb
mac80211              329373  3 rt2x00lib,rt2x00usb,rt2800lib
cfg80211              211002  2 mac80211,rt2x00lib
rfkill                 19567  2 cfg80211
-->
cfg80211、mac80211の記述からnl80211でカバーできそう

iwのインストール
$ sudo apt-get install iw

サポート機能の確認
$ iw list
Wiphy phy0
(関連箇所のみ抜粋)
 Supported Ciphers:
  * WEP40 (00-0f-ac:1)
  * WEP104 (00-0f-ac:5)
  * TKIP (00-0f-ac:2)
  * CCMP (00-0f-ac:4)
 Available Antennas: TX 0 RX 0
 Supported interface modes:
   * IBSS
   * managed
   * AP
   * AP/VLAN
   * WDS
   * monitor
   * mesh point
 software interface modes (can always be added):
   * AP/VLAN
   * monitor
 valid interface combinations:
   * #{ AP, mesh point } <= 8,
     total <= 8, #channels <= 1
-->
IBSS: アドホック
managed: クライアント
AP: アクセスポイント
VLAN: 無線VLAN
monitor: 無線LANネットワーク検出

無線LANのスキャン
$ sudo iw dev wlan0 scan

iwconfigはまだ使えるようだが、これはそのうちdeprecatedされるかもしれない
$ sudo ifdown wlan0
$ iwconfig
(関連箇所のみ抜粋)
wlan0     IEEE 802.11bgn  ESSID:off/any  
          Mode:Managed  Access Point: Not-Associated   Tx-Power=20 dBm   
          Retry  long limit:7   RTS thr:off   Fragment thr:off
          Power Management:on

$ sudo ifup wlan0
$ iwconfig
(関連箇所のみ抜粋)
wlan0     IEEE 802.11bgn  ESSID:"RaspiSSID"  
          Mode:Managed  Frequency:2.462 GHz  Access Point: 01:23:45:67:89:AB   
          Bit Rate=6.5 Mb/s   Tx-Power=20 dBm   
          Retry  long limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          Link Quality=70/70  Signal level=-39 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0


[参考URL]
cfg80211 - Linux Wireless
mac80211 - Linux Wireless
nl80211 - Linux Wireless
hostapd を使用した簡単な方法で WiFi に強力な暗号化を実装する

2014年7月21日月曜日

Raspberry Piのネットワークを設定する

有線LAN


有線LAN用固定IPの設定
$ sudo cp /etc/network/interfaces{,.orig}
$ sudo vim /etc/network/interfaces

/etc/network/interfaces
auto lo
iface lo inet loopback

iface eth0 inet static
address 192.168.21.41
netmask 255.255.255.0
gateway 192.168.21.1

該当IFの無効・有効化
$ sudo ifdown eth0 && sudo ifup eth0


無線LAN


無線LANクライアントの設定
$ sudo cp /etc/wpa_supplicant/wpa_supplicant.conf{,.orig}
$ wpa_passphrase "RaspiSSID" "RaspiSSIDPW" | sudo tee -a /etc/wpa_supplicant/wpa_supplicant.conf
network={
        ssid="RaspiSSID"
        #psk="RaspiSSIDPW"
        psk=d721085129ab22a68036c3c5cf7d28dab5f9b3de93a8866fe6626d59e811b7f7
}

$ sudo vim /etc/wpa_supplicant/wpa_supplicant.conf

/etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
        ssid="RaspiSSID"
        scan_ssid=0           # スキャン方法(0:パッシブ、1:アクティブ)
        priority=0            # 値が大きいほど優先度が高い(デフォルトは0)
        proto=RSN             # WPA2はRSNの別名
        key_mgmt=WPA-PSK
        pairwise=TKIP CCMP
        group=CCMP
        psk=d721085129ab22a68036c3c5cf7d28dab5f9b3de93a8866fe6626d59e811b7f7
        id_str="RaspiConf"    # 識別名
}

無線LAN用固定IPの設定
$ sudo cp /etc/network/interfaces{,.orig}
$ sudo vim /etc/network/interfaces

/etc/network/interfaces
auto lo
iface lo inet loopback

iface eth0 inet static
address 192.168.21.41
netmask 255.255.255.0
gateway 192.168.21.1

allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

iface RaspiConf inet static
address 192.168.21.42
netmask 255.255.255.0
gateway 192.168.21.1

該当IFの無効・有効化
$ sudo ifdown wlan0 && sudo ifup wlan0


リゾルバの設定


$ sudo vim /etc/resolv.conf
$ cat /etc/resolv.conf
nameserver 192.168.21.1
nameserver 192.168.22.1
search example.com example.jp


ホスト名の設定


$ sudo vim /etc/hostname
$ cat /etc/hostname
raspi

$ sudo vim /etc/hosts
$ cat /etc/hosts
127.0.0.1      localhost.localdomain   localhost
127.0.1.1      raspi.example.com       raspi
192.168.11.41  raspi.example.com       raspi
192.168.11.42  raspi.example.com       raspi


再起動


$ sudo shutdown -r now


[参考URL]
How-To: WiFi roaming with wpa-supplicant | Debuntu
wpa_supplicant.conf(5)
Gentoo Linux ドキュメント -- 無線ネットワーク

2014年7月18日金曜日

Raspberry Piをバックアップ・リストアする

バックアップ


バックアップ元であるSDカードのディスク番号を確認してからバックアップを実行。
$ diskutil list
(関係箇所のみ抜粋)
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *15.9 GB    disk1
   1:             Windows_FAT_32 boot                    58.7 MB    disk1s1
   2:                      Linux                         15.9 GB    disk1s2

$ df -h
Filesystem                          Size   Used  Avail Capacity  iused    ifree %iused  Mounted on
(関係箇所のみ抜粋)
/dev/disk1s1                        56Mi  9.5Mi   46Mi    17%      512        0  100%   /Volumes/boot

$ sudo dd bs=1m if=/dev/rdisk1 of=./raspi_YYYYMMDD.img

gzip圧縮してバックアップする際は
$ sudo dd bs=1m if=/dev/rdisk1 | gzip > ./raspi_YYYYMMDD.gz


リストア


リストア先であるSDカードのディスク番号を確認、アンマウントしてからリストアを実行(過去の内容と同様)。
$ diskutil list
(関係箇所のみ抜粋)
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *15.9 GB    disk1
   1:                 DOS_FAT_32 UNTITLED                15.9 GB    disk1s1

$ df -h
Filesystem                          Size   Used  Avail Capacity  iused    ifree %iused  Mounted on
(関係箇所のみ抜粋)
/dev/disk1s1                        15Gi  2.5Mi   15Gi     1%        0        0  100%   /Volumes/UNTITLED

$ sudo diskutil unmount /dev/disk1s1
$ sudo dd bs=1m if=./raspi_YYYYMMDD.img of=/dev/rdisk1
$ sudo diskutil eject /dev/rdisk1

gzip圧縮したファイルからリストアする際は
$ sudo diskutil unmount /dev/disk1s1
$ gzip -dc ./raspi_YYYYMMDD.gz | sudo dd bs=1m of=/dev/rdisk1
$ sudo diskutil eject /dev/rdisk1


[参考URL]
Back-up a Raspberry Pi SD card using a Mac | TechTonic

2014年7月16日水曜日

Raspberry Piの初期設定を行う

apt-getの実行


$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo shutdown -r now


raspi-configの実行


$ sudo raspi-config

1 Expand Filesystem
    rootfs(ext4フォーマット)を拡張する。
    再起動後に拡張rootfsが有効になる。

2 Change User Password
    「$ sudo passwd pi」が実行される。
    ユーザpiのパスワードを変更する。

4 Internationalisation Options
  • Change Locale
  • 「$ sudo dpkg-reconfigure locales」が実行される。
    「en_US.UTF-8 UTF-8」のみをチェックする。
    「Default local for the system environment」については「en_US.UTF-8」を選択する。
    設定反映のために、一旦ログアウトしてから再度ログインする。

  • Change Timezone
  • 「$ sudo dpkg-reconfigure tzdata」が実行される。
    「Asia -> Tokyo」と選択する。

  • Change Keyboard Layout
  • 「Generic 105-key (Intl) PC -> Other -> Japanese -> Japanese - Japanese (OADG 109A) -> The default for the keyboard layout -> No compose key -> Yes」と選択する。
    最後のYesは「Use Control+Alt+Backspace to terminate the X server?」に関する選択。


追加のロケール設定


$ sudo vi /etc/default/locale
$ cat /etc/default/locale 
#  File generated by update-locale
LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8
LANGUAGE=en_US.UTF-8
設定反映のために、一旦ログアウトしてから再度ログインする。


HDMI出力の固定化


$ sudo vi /boot/config.txt
(関連箇所のみ抜粋)
hdmi_force_hotplug=1
framebuffer_width=1920
framebuffer_height=1080

$ sudo shutdown -r now


[参考URL]
“Americanizing” the Raspberry Pi | Rohan Kapoor
Fix locale problems in Raspbian | Programming and Technology

2014年7月14日月曜日

Raspberry Piで使うSDカードをセットアップする

OSイメージ(Raspbian)の準備


本家からOSイメージをダウンロードしようとすると時間がかかるので、JAISTのミラーサイトからダウンロードする。
$ wget http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/raspbian-2014-06-22/2014-06-20-wheezy-raspbian.zip

$ openssl sha1 2014-06-20-wheezy-raspbian.zip
SHA1(2014-06-20-wheezy-raspbian.zip)= b020908e3cba472a24f7a17498008eb69d86d1cb

$ unzip 2014-06-20-wheezy-raspbian.zip


ディスク番号の確認


SDカードを接続してディスク番号を確認する。
$ diskutil list
(関係箇所のみ抜粋)
/dev/disk1
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *15.9 GB    disk1
   1:                 DOS_FAT_32 UNTITLED                15.9 GB    disk1s1

$ df -h
Filesystem                          Size   Used  Avail Capacity  iused    ifree %iused  Mounted on
(関係箇所のみ抜粋)
/dev/disk1s1                        15Gi  2.5Mi   15Gi     1%        0        0  100%   /Volumes/UNTITLED


OSイメージの書き込み


SDカードをアンマウントした上で、rawデバイス指定で書き込みを実行する(アンマウント実行後は、書き込みが完了するまでSDカードを取り外さないこと)。
なお、ddコマンド実行中にControl-Tを押下すると書き込み進捗状況を確認できる。
$ sudo diskutil unmount /dev/disk1s1
$ sudo dd bs=1m if=2014-06-20-wheezy-raspbian.img of=/dev/rdisk1
$ sudo diskutil eject /dev/rdisk1


[参考URL]
Raspberry Pi Documentation
RPi Easy SD Card Setup - eLinux.org

2014年6月14日土曜日

プロキシ環境下でChef Soloをインストールする

環境
  • Ubuntu Server 12.04 LTS x64

apt-get用にプロキシ設定を追加
$ sudo vi /etc/apt/apt.conf
$ cat /etc/apt/apt.conf
(関係箇所のみ抜粋)
Acquire::http::Proxy "http://proxy.example.com:8080";
Acquire::https::Proxy "http://proxy.example.com:8080";
Acquire::ftp::Proxy "http://proxy.example.com:8080";

vim、curlのインストール
$ sudo apt-get update -y
$ sudo apt-get install -y vim curl

プロキシ用の環境変数を追加
$ vim ~/.bashrc
$ cat ~/.bashrc
(関係箇所のみ抜粋)
export http_proxy="http://proxy.example.com:8080"
export https_proxy="http://proxy.example.com:8080"
export ftp_proxy="http://proxy.example.com:8080"

$ source ~/.bashrc


wget用にプロキシ設定を追加(後で実行するオムニバスインストーラスクリプト内でwgetが実行されるため)
$ sudo vim /etc/wgetrc

/etc/wgetrc(関係箇所のみ抜粋)
# You can set the default proxies for Wget to use for http, https, and ftp.
# They will override the value in the environment.
https_proxy = http://proxy.example.com:8080
http_proxy = http://proxy.example.com:8080
ftp_proxy = http://proxy.example.com:8080

# If you do not want to use proxy at all, set this to off.
use_proxy = on


オムニバスインストーラを使ってChefをインストール
$ curl -L https://www.opscode.com/chef/install.sh | sudo bash

Chef Soloのバージョン確認
$ chef-solo -v


補足

wgetについて個別にプロキシ設定しない場合は、sudoコマンドにEオプションをつけることにより、ログインアカウントの環境変数を引き継いでインストールスクリプトを実行する。

$ curl -L https://www.opscode.com/chef/install.sh | sudo -E bash


[参考URL]
The little, that can make a difference...: Unable to add ppa behind proxy

2014年5月17日土曜日

RubyGemsをアップデートする

RubyGemsをアップデートする。rubygems-updateパッケージがない場合は自動的にインストールされる。
$ gem update --system
$ gem -v
2.2.2

なお、rubygems-updateパッケージを直接利用する場合は下記を実行すればOKのハズだが、私は使っていない。
$ update_rubygems 
$ gem -v
2.2.2

基本的にBundler(Gemfile)で各gemを管理しているので、Bundlerもアップデートする。
$ gem update bundler
$ bundle -v
Bundler version 1.6.2


必要に応じて下記も実行する。

Bundler管理のgemの更新
$ bundle update

Bundler管理の古いgemの削除
$ bundle clean