OmniAICreator/Qiita-1.07M huggingface dataset:
オブジェクト指向プログラミングの3大要素について

# 参考文献
平澤章 :『[オブジェクト指向でなぜつくるのか](http://amzn.to/1LFXAk9)』 日経BP社, 2004

# オブジェクト指向技術とは
ソフトウェア開発を楽に行う為の総合的な技術

# オブジェクト指向プログラミングの3大要素
* class
* polymorphism
* inheritance (継承)  

***
3つの仕組みは,
重複した無駄なロジックを排除し,
必要な機能を整理整頓する仕組みをプログラムに提供する.
***
# class
分類,種類といった同種のモノの集まり,という意味
classは,サブルーチンと変数をまとめるもの.
関連性の強いサブルーチン(関数)とグローバル変数を一つにまとめて粒度の大きいソフトウェア部品を作る仕組み.  
この仕組みを使うことで,バラバラに存在していたサブルーチンと変数をまとめて整理整頓できる.


classと対になる要素にinstance
instanceは,具体的なもの,実例を意味し,実行時に確保されるメモリ領域のこと.

class = 種類
instance = 具体的なもの
というわけ.  
1つのclassから実行時にたくさんのinstanceを作る仕組みが,
数学の集合論における集合と要素によく似ている.

プログラムが動くときには,定義したclassからinstanceが作られて,それらが相互作用し合いながらソフトウェアとしての機能を実現する.

# polymorphism
色々な形に変わる,と言った意味を持つ言葉で,日本語では,多態性,多層性などと訳されることもある.
類似したclassに対するmessageの送り方を共通にする仕組み,と言える.
相手が具体的にどのclassのinstanceであるか,を意識せずにmessageを送れる仕組み,といっても良い.
polymorphismはmessageを送る側が楽をする為の仕掛け

# inheritance 継承
classの共通点と相違点を体系的に整理する仕組み
inheritanceは,全体集合と部分集合に相当
オブジェクト指向では,
全体集合 = superset
部分集合 = subset
(これは集合論において,superset,subsetと呼ぶの同様)

# オブジェクト指向と現実世界の違い その1
現実世界では,先に具体的なものがあり,それを様々な基準で分類する.
オブジェクト指向の世界では,1種類のclassからinstanceが作られる.
作られたinstanceは複数のclassに帰属することができず,時間が経っても別のclassに所属替えすることができない.
***
オブジェクト指向は,純粋にプログラミング言語の仕組みとして理解する必要がある.
そのためには現実世界と対比する説明を,たとえ話と割り切ることが混乱しないコツ

# 第三章
サブルーチンの独立性を高める方法は,呼び出し側(メインルーチン)とサブルーチンで共有する情報を少なくすること.
ここで共有する情報とは, 変数に格納されるデータを指す.
そして,複数のサブルーチンが共有するこうした変数のことをグローバル変数と呼ぶ.

***
オブジェクト指向には
抽象的な「汎用の整理術」と
地に足のついた「プログラミング技術」
というまったく異なる2つの側面がある.
C#でOSCをする

#前置き
とあるプロジェクトにて
Windows(おそらくC# WPF)でOSC通信をしそうな匂いがしてきまして
ofとかiOSとかではやったことあったのですが、Windows系では今までやったことなかったので
やりかたを調べてみたのでメモ的に書いておきます。

#使わせていただくライブラリ
以下のように、NuGetで「OSC」を検索したら
![Nu-Get.PNG](https://qiita-image-store.s3.amazonaws.com/0/84949/db4b0076-149e-250d-e55b-cd23a74da8ec.png)

最初に出てきた「Rug.Osc」を使わせていただくことにします。

[Rug.osc Bitbucket](https://bitbucket.org/rugcode/rug.osc)

MITライセンスですし。大変ありがたいことです！
実際にまだ使ってないのでいい感じかどうかは検証できてません。

#OSC送信側ソース
送信はこんな感じでかいてみました。(ボタンクリック時にOSC送信)
IPアドレスとかポートはとりあえず決め打ちですが・・・

```csharp:MainWindows.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    // 送信先のIPアドレスを設定
    IPAddress sendAddress = IPAddress.Parse("192.168.0.14");

    // OSCのセンダーをポート12345で作る usingなので破棄はしてくれる
    using (OscSender oscSender = new OscSender(sendAddress, 12345))
    {
        // 接続
        oscSender.Connect();

        // OSC送信
        oscSender.Send(new OscMessage("/testmsg", 1, 2));
    }
}
```

#OSC受信側ソース
受信はこんな感じでかいてみました。
(起動時にレシーバーを準備してTaskで受信待ちを繰り返し処理)

```csharp:MainWindows.xaml.cs
public partial class MainWindow : Window
{
	// OSCのレシーバー
    private OscReceiver m_OscReceiver;
    
    // OSC受信待ちをするタスク
    private Task m_OscReceiveTask = null;

    public MainWindow()
    {
        InitializeComponent();

        // OSCのレシーバーをポート1234で作る
        m_OscReceiver = new OscReceiver(12345);

        // OSCのレシーバーを接続
        m_OscReceiver.Connect();

        // OSC受信用のタスクを生成
        m_OscReceiveTask = new Task(() => OscListenProcess());

        // タスクをスタート
        m_OscReceiveTask.Start();
    }

    /// <summary>
    /// OSC受信をListenする処理
    /// Taskで実行されており、繰り返し受信を確認し
    /// 接続が終了したら処理を終わらせる
    /// </summary>
    private void OscListenProcess()
    {
        try
        {
            // OSCレシーバーが終了されるまで繰り返し処理する
            while (m_OscReceiver.State != OscSocketState.Closed)
            {
                // 受信待ち(メッセージを受信したら処理が帰ってくる)
                OscPacket packet = m_OscReceiver.Receive();

                // 受信したメッセージをコンソールに出力
                Console.WriteLine(packet.ToString());
            }
        }
        catch (Exception ex)
        {
            // 例外処理　発生時はコンソールに出力
            // 　ただし
            //    m_OscReceiver.Receive()で受信待ち状態の時に終了処理(m_OscReceiver.close())をすると
            //    正しい処理でもExceptionnとなるため、接続中かで正しい処理か例外かを判断する
            if (m_OscReceiver.State == OscSocketState.Connected)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    private void Window_Closed(object sender, EventArgs e)
    {
        m_OscReceiver.Close();
    }
}
```

コメントにも書きましたが、レシーバーをクローズ処理すると受信待ちで例外が発生するのですが
Exceptionで区別がつかなかったので、レシーバーが接続中かで判断しています。
これが正しいか分からなかったですが、サンプルもそうなってたのでよしとしました。

#感想
・思ったよりも簡単でした、ライブラリを作ってくれた方に感謝です！
・実際に使ってないので問題ないかとかはテストしないと分からないからやらないといけないですね。
・中身を見させていただいたらSystem.Net.Socketsをつかってました。(当たり前なのですが)
う…ubygems?

最近はgemで何でもかんでも入れてしまうのであまり意識していないかもしれませんが、Webrickなど、標準添付のライブラリの中にも高機能なものがあります。

# なんだこれ？
標準機能を拡張するものや、あると便利なものなど、ライブラリにもいろいろあるのですが、ファイル一覧を何気なく見ていると、気になるファイルがありました。**`ubygems.rb`**…一瞬見間違いかと思いましたが、たしかにuから始まるところに並んでいます。いったい何者なのでしょうか。

# 中身＝ネタばらし
中身を見れば一目瞭然なので、全部転載します。

```rb:ubygems.rb
# This file allows for the running of rubygems with a nice
# command line look-and-feel: ruby -rubygems foo.rb
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++


require 'rubygems'
```
どういうことかと言えば、rubyのコマンドライン実行の際に、`-rxx`というようにすると、`require 'xx'`をしたのと同様に動くというコマンドラインオプションがあって、この`ubygems.rb`があることで、**`-rubygems`**と綺麗に呼び出せる、という寸法です。

もっとも、Ruby 1.9以降ではRubyGemsは自動的に呼び出されるようになったため、`-rubygems`引数を実用する必要はなくなっています。
postNotificationName:object:userInfo:のobjectをreceiverに値を渡すのに使っちゃダメ

`postNotificationName:object:userInfo:`の`object`は任意のオブジェクトじゃなくて`sender object`です！！

`receiver`が`sender`を特定するために使います。

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/#//apple_ref/occ/instm/NSNotificationCenter/postNotificationName:object:userInfo:

`receiver`に値を渡す時は`userInfo`を使いましょう。
ElixirのMapとKeyword listについてまとめた

入門者向けです（自分含む）。Elixirのチュートリアル読み進めつつまとめてます。

## Keyword list
- 特定の条件のtupleのリストはkeyword list として扱われる
    - tupleの要素数が2
    - 1つ目の要素が atom
- listの特徴を受け継いでいるので、長くなればなるほどサイズ取得時や、後方の要素を取得する際のパフォーマンスが落ちる。ElixirのListは個々の要素が値と次の要素のポインタを保持している構造になっているため。

```ex
iex> list = [{:a, 1}, {:b, 2}]
[a: 1, b: 2]

# アクセスするときはキー名を指定できる。
iex> list[:a]
1

# 直接書いても通る
iex> list = [a: 1, b: 2]

# 一つ目の要素がatomでない場合はtupleのlistとして扱われる
iex> list = [{"a", 1}, {"b", 2}]
[{"a", 1}, {"b", 2}]

# 要素数が異なる場合はtupleのlistとして扱われる
iex>list = [{:a, 1}, {:b, 2, 4}]
[{:a, 1}, {:b, 2, 4}]

# キーの重複は許容される
iex> list = [{:a, 1}, {:a, 2}]
[a: 1, a: 2]

# アクセスするとListの先頭から先に見つかった要素が表示される。
iex> list[:a]
1

# 通常のListと同じ操作が使える
iex> list = [{:a, 1}, {:b, 2}]
[a: 1, b: 2]

iex> list ++ [c: 3]
[a: 1, b: 2, c: 3]

iex> [a: 0] ++ list
[a: 0, a: 1, b: 2]
```

# Map
- key -value のデータを扱いたいときはMapを使う。
- %{ } で囲む
- 関数の引数でMapを使ったパターンマッチを使うと便利
- 割と最近導入された仕組みで小さいMapを扱うのに適している。容量の大きなKeyが必要になるデータはHashDict を使ったほうが性能が良いらしい。

```ex
iex> map = %{:a => 1, :b => 2}
%{a: 1, b: 2}

# キー名を指定してアクセスできる
iex> map[:a]
1

# 存在しないキーはnilが返る
iex> map[:c]
nil

# キーのデータ型が統一されていなくても通る
iex> map = %{:a => 1, 2 => :b}
%{2 => :b, :a => 1}

# キーの重複は許可されず、後勝ち
iex> map = %{:a => 1, :a => 2}
%{a: 2}

# valiableをキーに指定することはできない
iex>  key = :a
:a

iex> map = %{key => 1}
** (CompileError) iex:61: illegal use of variable key in map key
    (elixir) src/elixir_translator.erl:344: :elixir_translator.translate_arg/3
    (elixir) src/elixir_map.erl:154: anonymous fn/7 in :elixir_map.translate_map/4
    (stdlib) lists.erl:1352: :lists.mapfoldl/3
    (elixir) src/elixir_map.erl:153: :elixir_map.translate_map/4
    (elixir) src/elixir_translator.erl:17: :elixir_translator.translate/2

# mapにvaliableでアクセスすることはできる
iex> map[key]
1

# mapを更新する。immutableなので更新後の値を再利用したいときは別の変数に束縛しとく。
iex> %{map | :a => 2}
%{2 => :b, :a => 2}

# 更新するときに存在しないキーを指定すると例外
iex> %{map | :c => 3}
** (ArgumentError) argument error
    (stdlib) :maps.update(:c, 3, %{a: 1, b: 2})
    (stdlib) erl_eval.erl:255: anonymous fn/2 in :erl_eval.expr/5
    (stdlib) lists.erl:1261: :lists.foldl/3
```

- パターンマッチ

```ex
iex> map = %{:a => 1, :b => 2, :c => 3}

# 必ずマッチする
iex> %{} = map
%{a: 1, b: 2, c: 3}

# 部分的にマッチする
iex> %{:b => 2} = map
%{a: 1, b: 2, c: 3}

# 値を束縛する
iex> %{:a => a, :b => 2, :c => c} = map
%{a: 1, b: 2, c: 3}
iex> a
1
iex> c
3

# マッチしないと例外
iex> %{:a => 2} = map
** (MatchError) no match of right hand side value: %{a: 1, b: 2, c: 3}
```

# Dicts
- Keyword list と Map は dictionaryが実装されている(behaviourと呼ばれてるらしい)ので Dict moduleのメソッドが使える
[Xcode]Archive結果がOther Itemsに入ってSubmitできない時の対策


CococaPods 0.38.1のバグらしい
http://stackoverflow.com/questions/10715211/cannot-generate-ios-app-archive-in-xcode/31645306#31645306


調べてみるとたしかに。
0.38.2ではなおってるようなので、

## バージョン上げる
```
$ pod --version
0.38.1

$ gem uninstall cocoapods --version '=0.38.1'
Successfully uninstalled cocoapods-0.38.1


$ gem install -v 0.38.2 cocoapods
Successfully installed cocoapods-0.38.2

$ pod --version
0.38.2
```

バージョンあげた後、再度 pod install
いつものiOS Appsに入って、問題なくSubmitできるようになった。

Provisioning Profileまわりを疑って、時間かかった。
ReadyNasの設定

# ReadyNas 設定
##ネットワーク
###イーサネット1
|設定|初期設定値|設定値|
|:-----------|------------:|:------------:|
|速度および全二重の設定|オートネゴシエーション|←|
|MTU|1500|
|IPv4割り当て|下記の値を使用||
|IPv4アドレス|-|192.168.1.*|
|サブネットマスク|-|255.255.255.192|
|デフォルトゲートウェイ|-|192.168.1.1|
|IPv6割り当て|オフ|オフ|

パフォーマンス設定

|設定|初期設定値|設定値|
|:-----------|------------:|:------------:|
|ジャンボフレームを有効にします|OFF|ON|

###イーサネット2
|設定|初期設定値|設定値|
|:-----------|------------:|:------------:|
|速度および全二重の設定|オートネゴシエーション|←|
|MTU|1500|
|IPv4割り当て|下記の値を使用||
|IPv4アドレス|-|192.168.0.3|
|サブネットマスク|-|255.255.255.0|
|デフォルトゲートウェイ|-|192.168.1.1|
|IPv6割り当て|オフ|オフ|

###グローバル設定／ワークグループ

|設定|初期設定値|設定値|
|:-----------|------------:|:------------:|
|ホスト名|-|ReadyNas6Sec|
|ワークグループ|-|NAS|
|DNSネームサーバ1|-|8.8.8.8|
|DNSネームサーバ2|-||
|DNSネームサーバ3|-||
|ドメイン名|-||

###WINS
|設定|初期設定値|設定値|
|:-----------|------------:|:------------:|
|WINSサーバ|-|-|
|WINSサーバとする|OFF|OFF|

###DHCP
|設定|初期設定値|設定値|
|:-----------|------------:|:------------:|
|Enable DHCPv4 Service|OFF|OFF|
|開始IPv4アドレス|-|-|
|終了IPv4アドレス|-|-|
|リース時間|-|-|

##セキュリティ

##サービス
###ファイルサービス
|設定|初期設定値|設定値|
|:-----------|:------------:|:------------:|
|CIFS|ON|ON|
|NFS|OFF(-)|ON(8)|
|AFP|OFF|OFF|
|FTP|OFF|OFF|
|HTTP|OFF|OFF|
|HTTPS|OFF|OFF|
|Rsync|OFF|ON|

###ストリーミングサービス
|設定|初期設定値|設定値|
|:-----------|:------------:|:------------:|
|ReadyDLNA|OFF|OFF|
|iTunesストリーミングサーバ|OFF|OFF|

###ディスカバリーサービス
|設定|初期設定値|設定値|
|:-----------|:------------:|:------------:|
|Bonjourサービス|OFF|OFF|

##ボリューム
###ボリューム設定
####ボリュームの管理
|設定|初期設定値|設定値|
|:-----------|:------------:|:------------:|
|ディスクスクラブとパリティの修正|OFF|ON(毎週日曜10:00)|
|オンラインファイルシステム整合性チェック|OFF|ON(毎週日曜23:00)|

####iSCSI
|設定|初期設定値|設定値|
|:-----------|:------------:|:------------:|
|iSCSIサポート|OFF|ON|

##共有
###共有リスト
###共有の追加

|共有名|CIFS|NFS|HTTP/S|Rsync|詳細設定|
|:------|:-----:|:-----:|:-----:|:-----:|:-----:|
|Books|R/W|無効|無効|R/W|nobody/nogroup|
|Games|R/W|無効|無効|R/W|nobody/nogroup|
|Images|R/W|無効|無効|R/W|nobody/nogroup|
|Pictures|R/W|無効|無効|R/W|nobody/nogroup|
|Public|R/W|無効|無効|R/W|nobody/nogroup|
|media|R/W|無効|無効|R/W|nobody/nogroup|

##バックアップ
##システム
###時計/警告/パフォーマンス/言語/設定のバックアップ/電源
|項目|設定値|
|:------|:-----:|
|タイムゾーン|GMT+09:00|
|NTPサーバ1|ON(time-a.netgear.com)|
|NTPサーバ2|ON(time-c.netgear.com)|
|ディスク書き込みキャッシュを有効にします|ON|
|フルデータジャーナリングを無効にします|ON|
|高速USBディスクの書き込みを有効にします|OFF|
|言語|日本語(UNICODE)|
|ディスクスピンダウンを有効にする|5|
|パワーオンタイマーを有効にする|ON(ON:月09:00/OFF:水23:00)|
|WOL|ON|
AngularJSで<input type="file">のonchangeイベントをハンドリングする

`<input type="file">`にファイルが設定されたタイミングでスコープ内で定義した関数を実行したい時、普通に`ng-change`を要素につけても動かない。

```html
<input type="file" ng-change="parseFile()">
```

これでは動かない。

ちょっと無理やりだけど、こうすれば動く。

```html
<input type="file" onchange="angular.element(this).scope().parseFile(this)">
```

```js
angular.module('App', [])
  .controller('MyCtrl', function($scope) {
    $scope.parseFile = function(fileElement) {
      var file = fileElement.files[0];
      console.log(file);

      $scope.fileType = file.type;
      $scope.fileName = file.name;

      $scope.$apply();
    };
  });
```

あとは`file.type`や`file.name`を調べるなり`FileReader`を使って中身を読むなりご自由に。
なお、このコールバック関数内でモデルオブジェクトを変更した場合は、`$scope.$apply()`を呼ばないと変更が反映されません。

参考: http://stackoverflow.com/questions/17922557/angularjs-how-to-check-for-changes-in-file-input-fields
スクリーンショットを撮影して adb コマンドでMacに転送するまで

以下、Android アプリ開発者なら常識かもしれない。私みたいな初心者向け。

# Android のスクリーンショットの撮り方

端末によっては違うという話も聞いたが、Nexus 6 では `電源` + `音量小` を長押しすることで撮影ができる。成功すればプレビューが表示されるのでそれで確認ができる。保存先はあとで調べて分かったが、`/sdcard/Pictures/Screenshots/` になる。

> https://support.google.com/nexus/answer/2811098?hl=ja

# adb コマンドへのパスを通す

adb コマンドの設定ができていないのであればこれが必要。Android SDK が配置されているディレクトリ、自分の環境は以下であったので、.bash_profile にこれを追記（bash を使っているので）。環境によっては platform-tools が AndroidStudio.app パッケージ内にあったりもする（？）。

```
export PATH=$PATH:~/AndroidStudioSDK/platform-tools
```

反映させる。

```
$ source .bash_profile
```

# adb コマンドでスクリーンショットを Mac に転送

まずは確認。

```
$ adb shell ls /sdcard/Pictures/Screenshots
```
```
Screenshot_20150828-1.png
Screenshot_20150828-2.png
Screenshot_20150828-3.png
```

このディレクトリにスクリーンショットが保存されていることが確認できたので、これを Mac に転送する。

```
$ adb pull /sdcard/Pictures/Screenshots/Screenshot_20150828-1.png
```

カレントディレクトリに png ファイルが転送された。めでたしめでたし。
![](https://qiita-image-store.s3.amazonaws.com/0/3603/67d7b379-27fe-f45a-9768-feda9bb8d9bc.png)
Android M パーミッション対応のメモ

# Google

ユーザーが変更できるパーミッション一覧
https://developer.android.com/preview/features/runtime-permissions.html#permission-groups

PermissionLebel = dangerous に限らないことに注意。
ページ下に normal の一覧もある。これらはマニフェストに記述しておくだけで良い。

# Qiita

- http://qiita.com/Night___/items/e7e6ad75c91cb82f3fd5
- http://qiita.com/STAR_ZERO/items/973c72cdf7813eccc006
NetGear ReadyNASからデータをサルベージ


## 経緯

ファイル共有サーバー(NetGear ReadyNAS RND4000)が唐突に動かなくなりました。
本体見ると、電源ランプすら光らない状況。
電源系の障害だとしたらディスクは無事の可能性が高いと思い、がんばりました。

## 概要

- 物理的には USB-CVIDE2で、HDDと Mac Miniを接続
- OS X上に VirtualBox で Ubuntu を立てて、接続したHDDをマウント
- Ubuntuで Sambaサーバーを立てて、接続したHDDから Sambaの共有フォルダにコピー
- Windowsから必要ファイルをコピー

## 成功した手順

### 物理的な接続

たまたま、これがあったので、話がはやかったです。

http://www.sanwa.co.jp/product/syohin.asp?code=USB-CVIDE2


### Ubuntu にHDDをマウント
Ubuntu は、このへんからisoイメージをダウンロードして入れました。

http://www.ubuntu.com/server

今回入れたのは、Ubuntu Server 14.04 Server です。
また、インストール時のオプションで Sambaサービスを選択しておきました。

USBで接続したHDDは OS Xでは、「セットしたディスクは、このコンピュータで読み取れないディスクでした。」とか言われますが「無視」です。

生ディスクとして、VirtualBoxに割り当て出来るように、仮装ディスクを作成します。

```
sudo VBoxManage internalcommands createrawvmdk -filename rawdisk.vmdk -rawdisk /dev/disk1
```

権限がないと割り当てが出来ないので、権限を変えます。（こんなにいらないかもしれないけど）

```
sudo chown someone rawdisk.vmdk 
sudo chmod 666 rawdisk.vmdk 
sudo chown someone /dev/disk1
sudo chmod 666 /dev/disk1
```

（someoneは VirtualBoxを実行するユーザー）

この、rawdisk.vmdk を Virtual Boxの設定画面で、Ubuntuに割り当てておきます。

### Ubuntu内でLVMをマウント

ここからUbuntuを起動しての作業です。
面倒なので、全部 suで作業しました。
まずは、ドライブが見えてるかどうか確認。こんな感じで見えたらOKです。

```
# lvscan
 ACTIVE         '/dev/c/c' [924.09 GiB] inherit
```

単なる mountだとblock sizeがダメというエラーになるので、ツール入れます。

```
# apt-get install fuseext2
# fuseext2 -o ro /dev/c/c /data
```

/data に入って見に行ってみると、データの中身が見えます。
（2byteファイル名は文字化けしますが）

### Samba立ててコピー

Sambaは Ubuntuのインストール時に入れておいたので、設定してサービス再起動すればOK。
（このへんは大分記憶が薄れてきたので省略大です。）
Sambaの共有設定をした、フォルダに /dataの中身をコピーしました。
そして、WindowsからこのUbuntuの共有フォルダにアクセスして必要ファイルをコピーして終了です。

## 試したけどダメだったこと

### 大人しくメーカーに電話

対応してくれた方は感じが良かったんですが、結果はザンネンな状況でした。

- 保証期間は5年だけど過ぎている
- 保証期間外の有償修理や有償交換はしていない
- 同型のHDDを接続出来る後継の現行製品は無し
- 中古などでも、おそらくもう無いでしょう
- サルベージ業者を紹介なら出来ます


### Windows8.1で Ext2fsd

http://www.ext2fsd.com/

データの入ってる LVMのパーティションが読めないです。
フォーマットが必要って言われるだけでした。
先頭のパーティションはLVM切ってないので内容を読めるんですが、そこはOSが入ってるだけなんですよね。。。

### OS X で、FUSE + fuse-ext2

http://tex-numerics.blogspot.jp/2013/05/read-and-write-ext4-file-system-on-mac.html

やはり、LVMの中身が見えません。

### Debian でマウント

当初、Debian で試したところ、Debian内でHDDを認識するところまではいくのですが、マウント出来ませんでした。
fuseext2 が Debianでは見つからず、諦めました。

### UbuntuのSambaで、マウントしたディレクトリを直接共有

上手くいきませんでした。
/data を共有設定しても見えず。
Samba で共有設定したディレクトリに、シンボリックリンクを置いてもダメ。
このあたりでは相当疲れていたので追求は諦めて、ただただデータコピーすることで対応しました。


## 参考にさせて頂いたサイト

ありがとうございました。大変助かりました！

http://yudoufu.hatenablog.jp/entry/20110605/1307272662

http://moimoitei.blogspot.jp/2009/06/access-readynas-hdd-by-normal-linux-pc.html

https://hirooka.pro/?p=6517
UnityのAssetをVisualStudioでDLL化して使う

# 初めに
* ソースコード方式で提供されているAssetがあります。  
  これは便利なのですが、いろいろな理由によりDLLにしたくなった場合の手順が  
  Mono前提だったり、Export考慮が漏れていたりしたので改めてまとめました。

# 前提
* Unity5.1.1p4 / VisualStudio2013 で DLL 化した時の手順です。
* 各種Asset毎の固有事情もあるので先に[各Asset固有の手順](#%E5%90%84asset%E5%9B%BA%E6%9C%89%E3%81%AE%E6%89%8B%E9%A0%86)に目を通してみてください。

# 手順
## ソリューションを出力する
1. 対象のAssetのみのUnityプロジェクトを作成する
    * 今回対象のUniRxの場合は[github](https://github.com/neuecc/UniRx)からソースを落とした状態です。
1. UnityVS2015が入っているので、2013に入れ替える ( VS2015を使用している人はスキップしてください )
    1. [Visual Studio 2015 Tools for Unity extension](https://visualstudiogallery.msdn.microsoft.com/8d26236e-4a64-4d64-8486-7df95156aba9) をインストールする
        * VS2015がインストールされていなくてもインストールは可能
    1. UnityVS(VS2015用)を削除
    1. UnityVS(VS2013用)を追加
        * Assets - Import Package - Visual Studio 2013 Tools で簡単に追加可能
1. Examples など不要なファイルを消す
1. Editor ディレクトリを削除していく
    * 後述
1. Generate Project Files

## DLLを出力する
1. プロジェクトのプロパティから出力ファイル名を変更する
    * Application - Assembly name が Assembly-CSharp になっているので任意の名前に変更
    * Editorの方も同様に変更
1. Release に設定 ( これは好みかも？ )
1. ビルドする

## プロジェクトにDLLをコピーする
1. DLLが出力されていることを確認する
    * デフォルト設定だと Temp\UnityVS_bin\Release\
1. DLLを導入したいプロジェクトの任意のディレクトリ(Assets以下)にコピーする
    * 依存するdllも同ディレクトリにコピーされているので必要なもののみコピーしてくる
1. UnityをRefresh(デフォルトだとフォーカスすれば自動でRefresh)

# 各Asset固有の手順
## UniRx
* #if UNITY_EDITOR 対策 (**未検証**)
    * UniRx/DllsにあるプロジェクトでDLLを生成するらしい。
        * @neuecc さんご指摘ありがとうございます。

### 手順
1. UnityでUniRxレポジトリのRootディレクトリを開く
    * Library/UnityAssemblies/*.dll をUnityに持ってきてもらう
1. UnityVS.UniRx.sln を開く
    * 少なくともVS2013の場合は以下の対応が必要
        1. NuGetManagerを開いてRestoreする
        1. UniRx.TestsにLibrary/UnityAssemblies/UnityEngine.dllへの参照を追加する
1. ビルドする
1. Dlls/UniRx.Library.Unity/bin/Debug/ にUniRx.dllとUniRx.Unity.dllが出力されているので使う(**未検証**)
    * Releaseビルドだといろいろ参照が足りないって怒られるのでUnityEngine.dllなどを追加する(**未検証**)

## UnityTestTools
* NUnit系のDLLを忘れずにコピーする
    * UnitTesting/Editor/NUnit/Libs/*.dll
    * UnitTesting/NSubstitute/*.dll
* 画像系ファイルがパス指定で読み込まれているようなので、そのままコピー
    * Common/Editor/icons/*.png
    * IntegrationTestsFramework/TestingAssets/*.prefab
    * IntegrationTestsFramework/TestingAssets/*.png
    * IntegrationTestsFramework/TestingAssets/Materials/*.mat

# 課題
* そもそもそこまでする必要ない可能性が浮上(**未確認**)
    * Library/ScriptAssemblies/ にあるAssembly-CSharp*.dllをリネームして使うだけでも十分かもしれない。
Mac でのDocker docker-machineのトラブルまとめ



## 環境

2015年8月28日時点

* Mac OS X: 10.10.5
* Docker: 1.8.1
* VirtualBox: 5.0.3


## トラブル1: インストールがうまくいかない

VirtualBox 5.0.0-5.0.2辺りの不具合で起きるインストールがうまくいかない問題

* 対策 → [MacのDockerでバグ VirtualBox 5.0.x問題 - Qiita](http://qiita.com/hshimo/items/8b1cd3cc4e16faf792ae)
    
        
## トラブル2: default is not running.

以下のメッセージが出る。VMが動作してない。

>default is not running. Please start this with docker-machine start default

対策: VMをスタートさせる

```
docker-machine start default
```

## トラブル3: re-run the `docker-machine env` command.

メッセージ内容

>Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

対策

```
eval $(docker-machine env default)
```

## トラブル4: An error occurred trying to connect

メッセージ内容

```
$ docker run -it ubuntu bash
An error occurred trying to connect: Post https://192.168.99.101:2376/v1.20/containers/create: dial tcp 192.168.99.101:2376: i/o timeout
```

多分、VMが開始されてないか、環境設定されてないか。

参考: [problem with docker - Ask Ubuntu](http://askubuntu.com/questions/615394/problem-with-docker)

うまくいくと以下のように表示される

```
$ docker run -it ubuntu:14.04 /bin/bash
Unable to find image 'ubuntu:14.04' locally
14.04: Pulling from library/ubuntu
d3a1f33e8a5a: Pull complete
c22013c84729: Pull complete
d74508fb6632: Pull complete
91e54dfb1179: Already exists
library/ubuntu:14.04: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:7a846cdca616c384ac1c5e3a91d0ea22c89
```

## トラブル5: config.json: no such file or directory

メッセージ

```
$ docker-machine status
unable to load host: open /Users/user/.docker/machine/machines/config.json: no such file or directory
```

対策: VM名を指定する

```
$ docker-machine status default
```


## 参考

* [Docker Toolbox for Mac OS X | harasou.github.io](http://harasou.github.io/2015/08/15/Docker-Toolbox/)
* [docker-machine - boot2docker コマンドとサヨナラする - Qiita](http://qiita.com/voluntas/items/dfc73e911be3fafeb954)
* [MacOSX - macにdocker toolboxをインストールする - Qiita](http://qiita.com/imtnd/items/8f0db6e938d55dfd4794)
* [boot2dockerからdocker-machineに変えた話 - Qiita](http://qiita.com/kohey18/items/b7e48ad70f97680041e5)
* [Docker Toolbox使ってみたけど、エラーでちょっとハマった話 - 継続的ブログ](http://akiza-cb.hatenablog.com/entry/2015/08/23/162414)
* [Macにdocker 1.8をインストールしてdocker run hello-worldまで - Qiita](http://qiita.com/salesone/items/84046a72b8472a18043f)
StatusBarとNavigationBarを消してFullScreenにする方法(出す方法付き)


`decorView.setSystemUiVisibility()`メソッドにフラグをセットする方法です。※APIレベル14以上

```
private void hideStatusAndNavigationBar() {
	View decorView = getWindow().getDecorView();
	int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION || View.SYSTEM_UI_FLAG_FULLSCREEN;
	decorView.setSystemUiVisibility(uiOptions);
	isFullScreen = true;
}

private void showStatusAndNavigationBar() {
    View decorView = getWindow().getDecorView();
    int mask = ~(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION || View.SYSTEM_UI_FLAG_FULLSCREEN);
    int uiOptions = decorView.getSystemUiVisibility() && mask;
    decorView.setSystemUiVisibility(uiOptions);
    isFullScreen = false;
}
```
c++ builder > ヘッダinclude重複の回避案


##状況

以下の3つのフォームがある
1. FormOpen (UnitOpen.cpp)
2. Form1 (Unit1.cpp)
3. Form2 (Unit2.cpp)

FormOpenからはForm1とForm2のいずれかを開くことができるようにする。
FormOpen自体はForm1かForm2を開く処理のみ実装する。フォームセレクタ。

##問題点

- UnitOpen.cpp
  - `#include <Unit1.h>` >> extra1.hがincludeされる
  - `#include <Unit2.h>` >> extra2.hがincludeされる
- Unit1.h
  - `#include "extra1.h"`
- Unit2.h
  - `#include "extra2.h"`

以下のようなファイルがある場合、UnitOpen.cppにてCOLOR_REDなどの重複が起きる。
ただし、extra1.hとextra2.hはそれぞれ2つのプロジェクト(C言語で実装)でも使われていて変更ができないとする。

```extra1.h
#ifndef _EXTRA1_H
#define _EXTRA1_H

enum COLOR_e {
	COLOR_RED,
	COLOR_BLUE,
	COLOR_GREEN
};

#endif
```

```extra2.h
#ifndef _EXTRA2_H
#define _EXTRA2_H

enum COLOR_e {
	COLOR_RED,
	COLOR_BLUE,
	COLOR_GREEN
};

#endif
```

##対応

以下のような方法を思いついた。
UnitOpen自体で他のフォームを開く以外の様々なことをしない限りはいいだろうか。
UnitOpenでextra1.hやextra2.h内の定義を使って処理をする場合は問題が出る。

- UnitOpen.cpp
  - `#include <Unit1.h>` >> wrap_extra1.hがincludeされる
  - `#include <Unit2.h>` >> wrap_extra2.hがincludeされる
- Unit1.h
  - `#include "wrap_extra1.h"`
- Unit2.h
  - `#include "wrap_extra2.h"`

```wrap_extra1.h
#ifndef _WRAP_EXTRA_H
#define _WRAP_EXTRA_H

#include "extra1.h"

#endif
```

```wrap_extra2.h
#ifndef _WRAP_EXTRA_H
#define _WRAP_EXTRA_H

#include "extra2.h"

#endif
```
nginxでKibanaにBasic認証をかける

## Kibanaへのアクセスを制限したい

Kibanaは分析・可視化ツールということで社内での運用が基本らしく、認証やセキュリティ対策らしきものは今のところ実装されていない。
待望の[認証機能](https://github.com/elastic/kibana/issues/3904)が 4.2.0 に実装されるかな？と思って期待していたけど、しれっと 4.3.0 にラベルが付け替えられていた。

![Screen Shot 2015-08-28 at 17.18.31.png](https://qiita-image-store.s3.amazonaws.com/0/69860/38b85c25-b230-63af-838d-eaaad2d87d07.png)

というわけでひとまずはnginxでリバースプロキシしてBasic認証を有効にしてみる。

## 環境

* AWS EC2 + ELB
* Ubuntu Server 14.04.2 64bit
* nginx 1.9.0
* Kibana 4.1.1

## 構成

ELBでSSLターミネーションしてHTTPでリクエストを送り込む。

```
Browser ==(HTTP/HTTPS)==> ELB ==(HTTP)==> EC2(nginx)
```

## nginxの設定

`.htpasswd`ファイルはコマンドラインツールで生成してもいいけど、面倒であれば [Htpasswd Generator](http://www.htaccesstools.com/htpasswd-generator/) とかで作ると楽です。
管理しやすくするためにkibana用の設定は別ファイルに記述して、それをnginxの設定ファイルから読み込む。

```nginx.conf
http {
  # ...

  include /path/to/kibana.conf;

  # ...
}
```

```kibana.conf
upstream kibana {
  server 127.0.0.1:5601 fail_timeout=0;
}

server {
  listen 80;
  server_name kibana.example.com;

  location / {
    auth_basic "Restricted";
    auth_basic_user_file /path/to/.htpasswd;
    proxy_pass http://kibana;
  }
}
```

## 再起動して完了

でもこれ、HTTPSを強制しないと片手落ちですね。
`X-Forwarded-Proto`とかを見てリダイレクトかけたほうがいいです。
PHPでCSVファイルから特定の情報を抽出し、新しいCSVファイルを作成する。

# 背景
- とあるCSVファイルから特定のレコードの特定の項目だけ抽出する必要が出てきたので作成したスクリプト
- perlとかの方が向いているかも知れないがperlは使ったことがないのでとりあえず実行環境ができているPHPで実装
- つーか自分があとで使う用のテンプレ

# 環境
- Redhat Enterprise Linux 6.5
- PHP5.3

# ソース

```php
<?php
/**
 * ※ 適当にプログラムの説明を書く※
 * 
 * Usage:
 * # php -f $filename [ENTER]
 */

$inFile     = 'hoge.csv';   // 抽出元ファイル
$outFile    = 'fuga.csv';   // 結果ファイル

// ファイルポインタ取得
$inFp   = fopen($inFile, 'rb');
$outFp  = fopen($outFile, 'w');

// ファイル読込み
while ($line = fgets($inFp)) {

    // 入力ファイルのCSVを配列に変換
    $inLineArray    = explode(',', $line);

    // 抽出条件
    if ( 
        // ※ 抽出条件を記載 ※
    ) {

        // 出力ファイルのフォーマットに変換（例）
        $outLineArray   = array(
            0 => $inLineArray[0],
            1 => $inLineArray[0],
            2 => $inLineArray[2],
            3 => $inLineArray[3],
            4 => $inLineArray[6], 
            5 => $inLineArray[9],
            6 => $inLineArray[16],
            7 => $inLineArray[54],
            8 => $inLineArray[55],
        );

        // ファイル出力
        fputs($outFp, implode(",", $outLineArray) . "\r\n");
    }
}

// ファイルポインタ解放
fclose($inFp);
fclose($outFp);

// コンソールに終わったことを知らせる。
echo "done. \n";

```

# スクリプトの実行

```
php -f $filename
```
homebrew-caskでMacのセットアップをざっくり自動化する


環境整備はできるだけさくっと終わらせたい！
やってみたら意外といい感じだったので、軽く済ませたい人向けに共有します。

## xcodeインストール

AppStoreから。
インストールしたら一度起動してライセンスの同意をしておく。

## homebrewインストール

とりあえずこの順番に叩けばOK

```Bash
xcode-select --install
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew doctor
brew update
```

続いてCaskのインストール

```Bash
brew install caskroom/cask/brew-cask
```


## 準備ができたらbrew cask install

あとはインストールしていくだけ。
[Homebrew Cask](http://caskroom.io/search)で探せるので、ここから探しましょう。
一般的なものは大体揃ってます。

僕はshellを作ってインストールしました。
　（といってもcaskroomeをコピペしただけ）
組織やチーム単位で必須なものは共有できるようにしておくといいかも。

```Bash:install.sh
brew cask install google-chrome
brew cask install firefox
brew cask install alfred
brew cask install vagrant
brew cask install virtualbox
brew cask install sublime-text
brew cask install atom
brew cask install mysqlworkbench
brew cask install skitch
brew cask install evernote
brew cask install google-japanese-ime
brew cask install karabiner
brew cask install seil
brew cask install hipchat
brew cask install kobito
```

## ちなみにアップデートは

```Bash
brew update
```

もしくは

```Bash
brew cask update
```


# 注意点・その他

- AppStore経由で入れるのと少し違うケースが有る
	- アプリのバージョンがAppStoreより古かったり新しかったり
- google-japanese-imeはシステム設定しないと動かなかった
- ナウいやり方ではないかもしれない

今のところ全く問題なく動いていますが、この辺りが気になる人はやめておいたほうがいいかもしれません。


# Windowsではchocolatey

という、似たようなものがあります。

https://chocolatey.org/

`choco install [package]`とやるとインストールできるので、同じように使えます。


# 参考情報

- [Mac の開発環境構築を自動化する (2015 年初旬編)](http://t-wada.hatenablog.jp/entry/mac-provisioning-by-ansible)
- [みんなhomebrew-caskって知ってるか？](http://qiita.com/ryurock/items/1432578d364985f6cb06)
SAStruts Seasar2でのログインチェック


## 目的
ログインしていないユーザーに、WEBサイトを見られないようにする。

## 行ったこと
アクセスをされた際に、ログイン情報がセッションに入っていない場合、
welcomeページにリダイレクトをする。

## ソースコード

###インターセプターの実装

```LoginConfirmInterceptor.java
public class LoginConfirmInterceptor extends AbstractInterceptor {
    private static final long serialVersionUID = 1L;

    // ===================================================================================
    //          When you inherit the AbstractInterceptor, this methods must be implemented
    //                                                                            ========
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // Failure to meet both conditions , skip to the Login page.
        return (!isExecuteMethod(invocation) || isLoggedIn()) ? invocation.proceed() : "/飛ばしたいアクション/";
    }

    /**
     * Whether or not with a Execute to the executed Action.
     * 
     * @param invocation
     * @return If with annotation true
     */
    private boolean isExecuteMethod(MethodInvocation invocation) {
        return invocation.getMethod().isAnnotationPresent(Execute.class);
    }

    /**
     * There is Dto on the session , and the userID in Dto
     * 
     * @return if satisfies both the above conditions true
     */
    private boolean isLoggedIn() {
        UserDto userDto = (UserDto) RequestUtil.getRequest().getSession().getAttribute("userDto");
        return (userDto != null && userDto.userId != null);
    }
}

```

###設定の変更
- 処理対象にするAction
- 処理対象にしないAction
を設定する。

```customizer.dicon
<initMethod name="addCustomizer">
	<arg>
		<component class="org.seasar.framework.container.customizer.AspectCustomizer">
			<property name="interceptorName">"loginConfirmInterceptor"</property>
	
			<!-- 処理の対象外ににしたいAction -->
			<initMethod name="addIgnoreClassPattern">
			<arg>"パッケージ名"</arg>
				<arg>"Action名"</arg>
			</initMethod>
			<initMethod name="addIgnoreClassPattern">
				<arg>"パッケージ名"</arg>
				<arg>"Action名"</arg>
			</initMethod>
			<initMethod name="addIgnoreClassPattern">
				<arg>"パッケージ名"</arg>
				<arg>"Action名"</arg>
			</initMethod>
	
			<!-- 対象にしたいクラス -->
			<initMethod name="addClassPattern">
				<arg>"パッケージ名"</arg>
				<arg>"クラス名"</arg>
			</initMethod>
		</component>
	</arg>
</initMethod>

```
CSS3アニメーションのイベントを取得する

## アニメーション開始
```js
var selector = document.querySelector("#example");
selector.addEventListener("animationstart",function(e){
    // animation start
});
```

## アニメーション中
```js
var selector = document.querySelector("#example");
selector.addEventListener("animationiteration",function(e){
    // animation iteration (step)
});
```

## アニメーション終了
```js
var selector = document.querySelector("#example");
selector.addEventListener("animationend",function(e){
    // animation end
});
```

## トランジション開始
```js
var selector = document.querySelector("#example");
selector.addEventListener("transitionstart",function(e){
    // transition start
});
```

## トランジション中(ない？？これが一番欲しい)
```js
// var selector = document.querySelector("#example");
// selector.addEventListener("transitioniteration",function(e)// {
//     // transition iteration (step)
// });
```

## トランジション終了
```js
var selector = document.querySelector("#example");
selector.addEventListener("transitionend",function(e){
    // transition end
});
```

## 参考
http://wilsonpage.co.uk/animation-iteration-event/

## 注意
webkitとかベンダープリフィックスが必要みたい
イベント名が違うので注意
ルートフォルダの異なるプロジェクト/moduleをimportせずに参照する


# 1 現状

svn+eclipseで,こんな構成で管理していたとします。

branch_MyLibs
+AndroidLibA
+JavaLibB

branch_MyApp1
+AndroidApp1(AndroidLibA/JavLibBを参照)

branch_MyApp2
+AndroidApp2(AndroidLibA/JavLibBを参照)

eclipseであれば、workspaceを作成してそれぞれをimportしていけばいいですが、AndroidStudioでimport Moduleをすると、ライブラリプロジェクトそのものがコピーされてきてしまいます。

コピーされてきてしまうと、AndroidApp1のJavaLibBのソースコードを変更しても、当然ながら、AndroidApp2のJavaLibBは変わりません。
これでは意味が無いので、なんとかただ「参照」する方法がないか、探しました。

結果、出来たのでその方法を。

# 2 前提
AndroidStudio 1.3を使用。
それぞれのプロジェクトはAndroidStudio化しているものとする。

以下サンプル。

branch_MyLibs_AndroidStudio
+AndroidLibA
+JavaLibB

branch_MyApp1_AndroidStudio
+AndroidApp1

簡単な方法としては、いったんAndroidApp1をimportしてAndroidSudioプロジェクトに変更させて、出来たライブラリプロジェクトなどを、上記プロジェクト構成になるよう移動させることかな。
移動させた後はいったんビルドが通らなくなるがそのままでOK.（移動前はビルド通ることを確認してね)

# 3 手順

## (1) settings.gradleを書き換える

```settings.gradle
include ':AndroidLibA'
include ':JavaLibB'

project(':AndroidLibA').projectDir = new File('../branch_MyLibs_AndroidStudio/AndroidLibA')
project(':JavaLibB').projectDir =new File('../branch_MyLibs_AndroidStudio/JavaLibB')
```

相対パスは実際のパスに合わせて下さい。

## (2) build.gradleのdependenciesを書き換える

```build.gradle(app)
dependencies {
    compile project(':AndroidLibA')
    compile project(':JavaLibB')
}

```

以上でOK。
Javaによる入力された文字のエスケープ


## 目的
テキストエリアから入力された文字列を、
適切な処理をして問題なくDBに格納をする。

## 実装のために考えたこと
- javascriptのスクリプトタグのエスケープ
- サロゲートペアの文字列の文字数カウントの変更


## ソースコード

###スクリプトタグのエスケープ処理

```java
public static String removeTag(String inputedText) {
	String text = inputedText;
	if (text != null) {
		text = text.replaceAll("<", "&lt;");
		text = text.replaceAll(">", "&gt;");
	}
	return text;
}
```

###サロゲートペアの文字列チェックの変更
サロゲートペアの文字列も1文字として扱いたいため。

```java
public static void hasCorrectTextLength(String tweetText) {
	BreakIterator bi = BreakIterator.getCharacterInstance();
	bi.setText(tweetText);
	int textCount = 0;
	while (bi.next() != BreakIterator.DONE) {
		textCount++;
	}
	if (textCount > 140) {
		throw new ActionMessagesException("ツイートの長さが最大値(140)を超えています。", false);
	}
}
```

## 改善点
```java
BreakIterator
```
はほとんど見たことがないとの評価を受けた。
実装をする際には、一度どういったメソッドがはいっているのか調べておいた方がいいかもしれない。
AWS 使い方メモ


# 概要
AWS 使い方メモ的な。

# 作業手順
## なにはともあれアカウント取得
AWSアカウントがないと何も始まりません。
作成しましょう。

* https://aws.amazon.com/jp/
* サインアップからアカウント作成できます
* サインアップ後の画面は下記(変わったりすると思うので大体こんな感じ)
* (この後の手順で EC2 を選択、VPC を選択と出てくればまずは下記画面を思い出してください)

![aws_login.png](https://qiita-image-store.s3.amazonaws.com/0/18359/9769072d-8558-5c35-b556-8dcb49ae40cb.png "aws_login.png")


## VPCの作成
1. ログイン後画面でVPCを選択
2. 画面左側のメニューからVPCを選択
3. 画面上側のVPCの作成を選択
4. 下記のように入力BOXを埋めます
	* ネームタグは任意
	* CIDRも任意(ただし/16以内)
![vpc_cidr.png](https://qiita-image-store.s3.amazonaws.com/0/18359/cdf242f0-8f8a-cdde-eda5-3a7a96591561.png "vpc_cidr.png")

* 最後に作成ボタンを押します
	* VPC作成完了です

## ゲートウェイのアタッチ
AWS では VPC にゲートウェイをアタッチする作業が必要となります。
この作業を行わなければ、後ほど行う ElasticIP の付与ができません。
簡単なので言葉だけで。

1. 画面左側のインターネットゲートウェイを選択
2. 画面上側のインターネットゲートウェイの作成を選択
3. 任意のタグ名を入力して作成
4. 画面上側の VPCにアタッチ を選択

以上で完了です。

## サブネットの作成
先ほど作成したVPC内にサブネットを作成します。最初は混乱するかもしれませんが、慣れればなんてことはないです。とりあえず作成してみましょう。

1. 画面左側のメニューからサブネットを選択
2. 画面上側のサブネットの作成を選択
3. 下記のように入力BOXを埋めます
	* ネームタグは任意
	* VPCは先ほど作成したものを選択
	* AZ(アベイラビリティゾーン)は ap-southeast-1a
		* (訳あってシンガポールリージョンで今回は作成しています)
		* AZ はデータセンター単位と捉えていればいいので AZ 冗長化のために2つ作成しておくことをおすすめします
![subnet.png](https://qiita-image-store.s3.amazonaws.com/0/18359/f7bfd294-4a6f-f5c0-0696-8021a856190a.png "subnet.png")

4. 上記で作成後に、AZ を ap-southeast-1b とし、CIDR を 10.0.2.0/24 として作成しておきます(画像省略)

注)サブネットの設定時に public ip が付与されるようにしておくこと
事後であれば、サブネットを選択 → サブネットのアクション → 自己割り当てパブリックIPの変更で変更できます

## セキュリティグループの作成
セキュリティグループの作成を行います。要はどの通信を許可するのかという話です。
既に最初から default VPC security group が存在するので今回はそちらを設定します。必要に応じて default ではなく作成していくシーンもありますが、今回は触れません。

1. 下記画像のように送信元にグループを指定しなければインスタンス同士の通信が許可されないので設定しておきます
	* もし、外部公開を行いたい場合などは TCP:80(www) のインバウンドを許可する必要があります、そのあたりは必要に応じて調整してください
	* オフィス等からのみ接続/閲覧できるようにしたいのであれば、https://www.cman.jp/network/support/go_access.cgi あたりで自身のクライアントPCが使用しているグローバルIPを確認して送信元を /32 で追加すれば良いです
	* アウトバウンドは特に今回は触れません

![security_group_box.png](https://qiita-image-store.s3.amazonaws.com/0/18359/f364953e-122c-4e33-77aa-1ccffb85947e.png "security_group_box.png")

## インスタンスの作成
いよいよインスタンスの作成です。一番最初の各コンポーネントが表示されている画面に戻りましょう。左上のオレンジの正方形を押せば戻ります。

1. EC2 を選択
2. すでにインスタンス作成ボタンが存在すると思うので選択
3. Amazon Linux を選択(特にこだわりが無ければ Amazon Linux で良いかと)
4. t2.micro を選択(t2.micro が最小の単位です)
	* 画面は下記画像となっていると思います
![instance_t1.png](https://qiita-image-store.s3.amazonaws.com/0/18359/7d692bf9-e689-6ed7-6edc-36f805fbac10.png "instance_t1.png")


5. 上記画像の【次の手順：インスタンスの詳細の設定】を選択
6. インスタンスの詳細設定
	* ネットワーク: 先ほど作成した VPC を選択
	* サブネット: 先ほど作成したサブネット/AZ
		* お気づきかも知れませんが、今回はインスタンスを2台作成するのでサブネット/AZを別々にします
	* 自動割り当てパブリックIP: サブネット設定を使用(有効)を選択
		* これでパブリックIPが起動時に付与されます
		* 参考画像は下記
	* 入力が完了していれば、【次の手順：ストレージの追加】を選択
![instance_az.png](https://qiita-image-store.s3.amazonaws.com/0/18359/1cda3c1e-f585-a483-1abc-38960ae9f959.png "instance_az.png")


7. ストレージの追加は今回行わないのでそのまま次へ
8. タグも同様なのでそのまま次へ
9. セキュリティグループの設定
	* 既存のセキュリティグループを選択する を選択し、default VPC security group が選択されていることを確認して【確認と作成】を選択
10. 最後に設定内容が表示されるので一通り確認して問題なければ作成を選択
11. 同様に サブネット/AZ を変えてもう1台作成しておきます

# さいごに
インスタンスの作成まで完了です。
今回はパブリックIPの付与としたため ElasticIP は使いませんでしたが、IPを固定したい場合は ElasticIP を使用すると良いです。
ELB も今回は使用しませんでした。負荷分散を行いたい際は ELB も使うと良いです。
(キャプチャ容量的に画像に限界があり文字ばかりになってしまった...)
SSHでのログインにアカウントロックをかけたい


CentOsはデフォルトでは，sshの履歴(?)を監視するだけのはずなので，ログイン失敗回数を数えて，そのアカウントが定めた失敗回数に達したらログインできないようにした．

## CentOsのバージョン
6.4

## PAMによる認証を許可する
[pam_tally2 で一定回数ログインに失敗したアカウントをロックする](http://hogem.hatenablog.com/entry/20121107/1352297631)を参考にさせていただきました．

自分は研究室のサーバであらかじめ，PAMでのssh認証がyesになっていたのでPAMに絞ってしらべました．

とりあえずPAMを使いたい場合はまず，```/etc/ssh/sshd_config``` で UsePAMをYesにすること

```bash:sshd_config
・
・
#UsePAM no
UsePAM yes
・
・
```

## pam_tally2を使ってアカウントロックする
```/etc/pam.d/password-auth``` を編集する．

```bash:password-auth
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      pam_env.so
#この下1行追記
auth        required      pam_tally2.so deny=5
#
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 500 quiet
auth        required      pam_deny.so
```

この2行目の```deny```で定義した値とログイン失敗回数が一致したらアカウントがロックされる．

4行目は常にログイン失敗時にログを残すというもので，もはや不要かとも思ったが，試す勇気もなかったのでそのまま残した．

### 試しに失敗してみる
ログインに失敗した回数は ```/var/log/tallylog```を見ればわかるのだが，これはバイナリファイルであるため，```pam_tally2``` コマンドを使う．

```
$ pam_tally2 -u locktestusername
Login           Failures Latest failure     From
locktestusername      1      08/28/15 19:43:45  xxx.xxx.xxx.xxx

```

記録された．

勇気をだして5回失敗してみたら，次からちゃんとしたパスワードを打ってもpermission deniedのエラーになってログインできなくなってた

### ロックを解除する
ロック解除も```pam_tally2``` コマンドを使う

```bash:
$ pam_tally2 -u locktestusername --reset
```

確認

```bash:
$ pam_tally2 -u locktestusername
Login           Failures Latest failure     From
locktestusername      0      
```

ちゃんと0になった

## 感想
今回はアカウントをベースにしてロックをかけた．
けども，もしIDが漏洩した場合，ログインを失敗しまくってアカウントをロックさせるということが可能になってしまうため，ipベースのロックも調べたい．

ただ，他人のIDを取得し，サービスや情報にアクセスするのが目的の攻撃はこれで十分防げる(?)のかな．
Java言語でのメールアドレスのチェック


## 行いたかったこと
サインアップに、メールアドレスが正しい形となっているかの確認

## 実装
```java
String mailAddress;
String mailFormat = "^[a-zA-Z0-9!#$%&'_`/=~\\*\\+\\-\\?\\^\\{\\|\\}]+(\\.[a-zA-Z0-9!#$%&'_`/=~\\*\\+\\-\\?\\^\\{\\|\\}]+)*+(.*)@[a-zA-Z0-9][a-zA-Z0-9\\-]*(\\.[a-zA-Z0-9\\-]+)+$";

if (!mailAddress.matches(mailFormat)) {
	return false;
}
return true;
```

## 改善点
docomoの@の直前に.を入力できるメールアドレスの場合は、
正規表現にて弾かれてしまうので、
そこに対応をした場合は別途別の正規表現を書く必要がある。
正規表現を使ったTwitterに似たハッシュタグ機能の実装


環境 Java

## 行いたかったこと
Twitterのようにツイート内容に「#」があった場合、
ハッシュタグとして認識をして、
ハッシュタグごとのタイムラインを表示できるようにする。

## 実装の考え
- 正規表現で、ハッシュタグにあたる文字列をリストに挿入をする。
- 文字列からハッシュタグを削除する
- タイムラインを表示するときに、ハッシュタグを文字列の後ろにいれ表示をする。

## ソースコード

```java
String text = "文字列";
String regex = "#(w*[一-龠_ぁ-ん_ァ-ヴーａ-ｚＡ-Ｚa-zA-Z0-9]+|[a-zA-Z0-9_]+|[a-zA-Z0-9_]w*)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
List<String> hashtagList = new ArrayList<String>();
while (matcher.find()) {
	hashtagList(matcher.group());
}
```

```java
String text = "文字列";
String regex = "#(w*[一-龠_ぁ-ん_ァ-ヴーａ-ｚＡ-Ｚa-zA-Z0-9]+|[a-zA-Z0-9_]+|[a-zA-Z0-9_]w*)";
String replacedText = text.replaceAll(regex, "");

return replacedText;
```

## 問題点
のちにハッシュタグを挿入すると、
文章中のハッシュタグの位置が文章の最後に変わってしまう。
本文中の文字列でマッチした場合、htmlタグを挿入するなどして、
より本家に近い実装をする方法を考えると良いと思う。
OpenCV 2.4.9 の iOS 用ビルドがうまくいかなくなったら

# はじめに

OpenCV 2.4.9 を iOS で使うときに自分で framework を作成することがある.
しかし、

```
python opencv/platform/ios/build_framework.py ios
```

が最近になって上手くいかない.

# 原因

深くは記載しないけど clang が error を吐いて邪魔していた.

# 解決策

opencv を clone して 2.4.9 (2.4.9.1) のブランチに移動して、
下のコミットを cherry-pick すると解決する.

[Fix tautologies in calibfilter.cpp which cause a build failure when u… · Itseez/opencv@35f96d6](https://github.com/Itseez/opencv/commit/35f96d6da76099d80180439c857a4abe5cb17966)

# おわりに

すべての人に関係のある現象かどうかはわからないが一応メモとして書いておく.
2.4.9.1 より上のバージョンを使うとリンカーのエラーがでて面倒であった.

最近だと、[OpenCV on CocoaPods.org](https://cocoapods.org/pods/OpenCV) があるのでこちらを使うと楽かもしれない.

```
pod 'OpenCV'
```

# 参考

- [osx yosemite - Build opencv 2.4.10 on Mac 10.10.3 failed - Stack Overflow](http://stackoverflow.com/questions/29724408/build-opencv-2-4-10-on-mac-10-10-3-failed)
成果の見えにくい仕事で成果をコンスタントに上げるためのTips

色んなプロジェクトを経験して意識するようになったことなど。 

# １　目的とアウトプット（成果物）を意識すること
企画やディレクションというものは数字に表すのが難しいし、また善し悪しの評価もしにくい。
とくにディレクションは触媒みたいなもので、ディレクション自体には成果物が無いことがほとんど。
（開発で例えるならコードの美しさとか、そういう感覚に近いのでは）

なので、どの仕事をする際にも、最終的なアウトプットを常に意識するようにしていた。

## 最終的なアウトプットからイメージする
機能の開発であれば、その機能を使うユーザーと、機能を使うユーザーの窓口になる営業を意識する。

デザイン案件であれば、最終的にどういうものをお客様に届けたいのか、
そのアウトプットをよりよく、より早く出すために、デザイナーにどうやって伝えたらいいか。

## よいアウトプット＝目的をより高い精度でクリアしたアウトプット
アウトプットというフワっとしたワードには色んな要素が含まれているが、
何よりも、よいアウトプット＝目的をより高い精度でクリアしたアウトプットと言える。

## アウトプットを軸に沿って評価する
で、目的をより高い精度でクリアしたアウトプットっていうとざっくりだし幅が広すぎるので、
例えばこういった軸でアウトプットを見て、評価する。

* PV/UUの高さ
* 開発コストの低さ
* 開発スケジュールの短さ
* 開発効率の良さ
* 品質
* 次の開発のしやすさ（技術的負債が少ない、ドキュメントが揃っているなど）
* そのアウトプット制作に関わったチームやメンバーの満足度、成長度

## アウトプットは目的のためにある
繰り返しになるが、目的のためにアウトプットがあって、
目的を達成できたかどうかがアウトプットの一番の評価。
アウトプットとセットで「何のためにそれをやるの？」という目的は常に意識する。

# ２　良いフィードバックをすること
一度失敗したので、その後勉強して意識するようにした。

## プラスのフィードバックをする
スイカを割るときに「そっちじゃない！あ～～そっちでもない！」ばかり言うと、「じゃーどっちに行けばいいんだよ！」ってなる。
「そっちじゃないよ」にプラスして**「あっ今の方向あってる！そっちそっち！」**と言われるとスイカにより近づくように、
出来なかったことだけじゃなくて、出来たことや良かったことをフィードバックする。
なにが出来たかが分かれば、再生産性が高まる。
 
## 批判だけで終わらせない
最終的なアウトプットのためには、批判＋提案（対案）をするのがベターかなと思う。その方が話が早いし、発展しやすい。
 
## 指示やフィードバックは明確に、分かりやすく、受け取りやすく
相手にとって分かりやすい形でフィードバックしないと意味が無い。
「100万円のダイヤを贈ったのに全然喜ばれなかった」のパターンと同じ様に、
たとえとってもタメになる金言でも、相手が喜んで受け入れてくれないとまったく意味がない。
フィードバックの目的は、相手がよりよくなること。
相手をよく観察して、相手がよりよくなるために一番効果的なフィードバックを心がける。

## 理由を必ず添える、前提条件を話す、道筋を与える
有名な例だが、こんな２つのパターンで指示を出されたとしよう。

* 「穴を掘ってください。あっ、埋めてください。次ここ掘ってください。あっやっぱりそこも埋めて。次ここ掘ってください。…」
* 「最近金塊があちこちで見つかっているので、私たちも金塊探しをしたいと思います。このどこかに金塊が埋まっているという情報があったので、ここからそこまで、順に穴を掘って、何もなければ埋めて次、と繰り返してください。

上の二つのうち、どちらが言われてウンザリするかは明確。

**なぜそれをしなければならないか。しなければならなくなった背景はなにか。どこがゴールか。**
それらが見えないと、言われる方はとてもイライラしてくる。
最初に言うだけでイライラしなくなるので、特にキックオフのときに気を付ける。

# ３　開き直ること、スタートはゼロから評価すること
世の中は広いので、上を見たらキリがないし、また下を見てもキリがない。
自分も相手も、評価のスタートはゼロから始める。

凄腕のエンジニアでも、プラス100とかからはじめずに、ゼロから評価しはじめる。
まったく仕事の出来ない新人でも、マイナスからスタートしたくなるのは分かるが、ゼロから評価しはじめる。

## 自分にも相手にもヘンな期待は低く
もちろん、信頼という意味での期待は高く持っておいて良いが、
期待を裏切ったからマイナスにするような期待なら、あまり持たないようにする。

これは自分に対しても一緒。

人と比べて出来ないことに落ち込んだり、人と比べてデキることに奢ったりするのはけっこうしんどい。
「今ぜんぜんできないけど、それが何か？」「今すっごいできてるけど、それが何か？」
ゼロからはじめれば、出来ていても出来ていなくてもこうやって開き直れる。

## 常に前より少し良く、少し良く、して評価を高められるようにする
比べるのは以前の仕事、以前の自分。

**ただし、これと成果物の評価は別にすること。**
人についてはあくまでゼロベースだが、成果物は仕事なので、ゼロベースではない。
ボーダーラインをクリアしなければ仕事をしたとは言えない。ぐらいの厳しさは持っておきたい。

一定のラインをクリアしていない成果物は、前と比べて良くなったかどうかなどどうでもいい。

お金払って買ったら、買ったのがボタン一つついてないカッターシャツ
「でもね～以前より洋服っぽくなったんですよぉ～」なんて言われたらガチギレである。
シャツの体をまず成してからより良くする。


## “仕事ができない自分”と、“今仕事ができていないこと”を区別する
このニュアンスは難しいかもしれないが、
「仕事ができない人」と「今、その仕事が出来ていないこと」はまったくの別物。

仕事をする方法は一つじゃないので、「今出来ていない仕事」を解決することにフォーカス出来れば、
仕事が出来ない自分ではなく、仕事が出来る誰かに依頼することで「今出来ていない仕事→今出来た仕事！」に変えられる。 

「仕事ができない自分」に悩むのではなく、「今仕事が出来ていないこと」に悩むべし。
だから、仕事が出来ない自分であってもいい、と開き直る。
MacからSSHしてロケールのエラーが出た時の対処

##事象
SSHで本番環境にログイン後、capistranoでデプロイ中に、以下のようなエラーになった。

```
ArgumentError: invalid byte sequence in US-ASCII
　（中略）
error: invalid byte sequence in US-ASCII
```

## 原因
http://yano3.hatenablog.jp/entry/2012/11/25/234244
私の場合は、こちらに書いてあることが、まんまソレでした。
SSH側でenvを確認して、こんな感じだったらおそらくビンゴ。

```
$ env | grep -e LANG -e LC_CTYPE
LANG=en_US.UTF-8
LC_CTYPE=UTF-8
```

とりあえずの対処として、SSH先のLC_CTYPEを、例えばLANGと同じにしておくなど。でも再ログインすると元通りになってしまう。

```
export LC_CTYPE=en_US.UTF-8
```

原因が上記サイトに書かれているので引用します。

> - Mac の Terminal.app の Settings > Advanced > Set locale environment variables on startup がオンになっていると、 Mac 側で ```LC_CTYPE=UTF-8``` が設定される。
- Mac の ```/etc/ssh_config``` で ```SendEnv LANG LC_*``` になっているので、 ```LC_CTYPE``` が ssh サーバに送信される。
- Ubuntu の ```/etc/ssh/sshd_config``` で ```AcceptEnv LANG LC_*``` になっているので、 Mac からの ```LC_CTYPE``` が Ubuntu に渡される。
- ```UTF-8``` というロケールはない (正しくは ```en_US.UTF-8``` とか ```ja_JP.UTF-8```) ので怒られる。

なるほど。ターミナルめ…

## 対処法

~~一番の原因であるターミナルの設定を変更しませう。~~
※ターミナルの設定を以下のようにすると、コンソール上で日本語が入力出来なくなってしまった。チェックは外さない方が良いみたい。`/etc/ssh_conf`の設定のみ無効にしておく。

![terminal.png](https://qiita-image-store.s3.amazonaws.com/0/52142/cf0238e4-eaad-33ec-2264-1925560c6ca2.png)

併せて、```etc/ssh_config``` の```SendEnv``` も念のため無効にしておく

```:/etc/ssh_config
 Host *
 #   SendEnv LANG LC_*
```

## ポエム
ロケールの設定って大変ややこしい。そしてローカライズを考えるたびに、USの勝ち組っぷりに嫉妬する。
git で誤ったコミットをpushしてしまいコミットだけを破棄してしまってエラーが起きた時の対処法

タイトルどおりの状況になったので開発に戻るために対処する。自分は

①git で誤ったコミットをpushしてしまい。コミットだけを破棄してしまった!
 =>②それにきづかないまま期待するコミットをpushする
  => ③pushできないとエラーがでる
   =>④pushできない時のエラーはPULLをすることで対処できることが多くあるのでpullをする 
    =>⑤pullでエラーがでる！！！！！

となってしまったのでまずは⑤から解決していく。

## 第一関門. pullエラーを対処する(上記⑤の部分)
エラーが次のように表示された。

```error:error内容
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree pull origin add_user_system001 

From https://github.com/MoltndarKen/protospace

 * branch            add_user_system001 -> FETCH_HEAD

error: Your local changes to the following files would be overwritten by merge:

Gemfile

Gemfile.lock

Please, commit your changes or stash them before you can merge.

Aborting

Updating 0c17d3a..e74b9c0

Completed with errors, see above
```

上のエラーの次の記述、

```
error: Your local changes to the following files would be overwritten by merge:

Gemfile

Gemfile.lock

```

この部分に対してエラーを起こしていたらしい。そのファイルの中身がどっかいかないように(怖いので。。)メモにコピペしておいてrails project内の`Gemfile`,`Gemfile.lock`を削除。そして`pull`を実行して `無事にpullできた。`

# 第２関門. 間違ったコミットによるpushをなかったことにする

その後pushもできたが、自分の期待通りの内容に反映されなかったのであやまったpushを消すことにした。

```terminal:ターミナル
& git log

commit 760456bae63c287f883e8d413aa1c7a2e1d6fc60
Author: hoge_hogetan <nezumi@nezumizumizumi-no-MacBook-Pro.local>
Date:   Fri Aug 28 14:18:30 2015 +0900

    # WHAT
    this is mistaked change, then , I' reset this commit
                        .
                        .
                        .
#ズラ～っと履歴が表示される。あんまり長いと:が出てくるのでqを押して脱出。

```

この自分の場合は上のように表示されているので`commit`の右にある番号をコピーして次のように実行する。（人によって違うので注意。なので'git log'をして自分のあやまってpushしてしまったコミットを探してください。）

```terminal:ターミナル
$ git revert 自分の間違って反映したcommitID
```

つまり自分のコミットIDは上記のgit logよりわかるので次のように入力する

```
& git revert 760456bae63c287f883e8d413aa1c7a2e1d6fc60
```

すると変更が生まれるのでこれをcommitしてpushするとやっとこさ誤ったpushの反映を消せる。へまをあまりしてない人は `git log` と `git revert`だけで目標達成できるかも。。。



# 参考url
第1の関門-まずはPULLできない状態をなんとかする

git pullしたときにerror: The following untracked working tree files would be overwritten by merge とエラーがでる解決方法
http://qiita.com/pugiemonn/items/ef595c49eedd4f991a1e

第２の関門を突破させてくれたもの
[リモートにプッシュしたコミットを取り消す](http://qiita.com/kkyouhei/items/f7588566cba0364ea832)

# 教訓
やばいのは(鼻からコミットをなかったことにするものコミットなど)コミットと同時にpushなんてしたりしない。

# その後のこれを書いた人は。。
結局その後は白紙に戻ったから変更点前から地道に作業をやり直した。もっといい方法があったかもしれないがいまはこれしかないで候。
Gradleスクリプトメモ


build.gradleにタスクスクリプトを書くときに覚えておきたいメモ。

# ビルドタイプ名

variant.buildType.name

# productFlavor名

variant.flavorName

# version

variant.versionCode
variant.versionName

# 文字列置換

文字列.replaceAll(/検索文字/, "置換文字")
文字列.replaceFirst(/検索文字/, "置換文字")

# タイムスタンプ

new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())

# 自作外部スクリプト等の適用

apply from:'(相対パスなど。URLでも可)'

例:自作タスクをいろんなプロジェクトで使い回せるように別ファイルにする

```groovy:my.gradle
def myTask(){
...(略)...
}

android {
   
    applicationVariants.all { variant ->
      myTask()
    }
}
```

```groovy:build.gradle(app)
apply plugin: 'com.android.application'
apply from: 'scripts/my.gradle'

android{
...(略)...
}

```
リモートシャットダウンするスクリプトを動作させるための設定

# 概要
UPSからシャットダウンの通知を受けてから、
Ubuntuをシャットダウンさせるスクリプトを動作させるためにしたこと。
(Windows、CentOSはUPS付属のツールでシャットダウンできるため省略)

# SSHの認証方法
Ubuntuにはすでにパスワードによる認証でSSH接続できるように設定済みであった。
プロンプトなしでSSH経由のアクセスが必要なために、公開鍵と秘密鍵を使用した認証に変更する。

## 公開鍵と秘密鍵の作成
プロンプトを表示させないためパスフレーズは入力せずに作成する。([SSHでリモートホストに接続する前にやっておくと便利なことは？ ssh-keygenコマンド](http://www.atmarkit.co.jp/ait/articles/1503/20/news007.html))

```bash
$ ssh-keygen -t rsa
```

`~/.ssh/id-rsa.pub`に公開鍵が作成される。

## SSHサーバに公開鍵を登録
公開鍵をUbuntuにコピーする。

```bash
$ scp ~/.ssh/id-rsa.pub remoteuser@192.168.XXX.XXX:/home/.ssh/authorized_keys
```

> 注意：上記SSHサーバはauthorized_keysが存在しなかったため、公開鍵ファイルを直接、authorized_keysとしている。すでに存在している場合は、一旦別名で保存し、catコマンドなどで追加すること。

# パスワード不要でシャットダウンできるように設定
プロンプトなしでSSH接続できるようになっても、shutdownコマンド実行時にroot権限が必要になるため、このままではプロンプトでパスワードを問われてしまう。

## /etc/sudoers編集
shutdownコマンドのみパスワード不要で実行できるようにsudoersを編集する。
sudoersの編集にはvisudoコマンドを使用する。
([Ubuntu Forums Thread: Sending single command via SSH for shutdown](http://ubuntuforums.org/showthread.php?t=845734))

```bash
$ ssh remoteuser@192.168.XXX.XXX #=> シャットダウン対象のUbuntuにログイン
$ sudo visudo
```

以下の行を追加
```
remoteuser ALL=NOPASSWD: /sbin/shutdown
```

```bash
$ exit #=> シャットダウン対象のUbuntuからログアウト
```

# シャットダウンスクリプトの作成
```bash
#!/bin/bash
ssh remoteuser@192.168.XXX.XXX "sudo shutdown -P now"
```

上記ファイルに実行権限を設定する。

```bash
$ chmod 764 shutdown_script.sh
```

UPSの通知を受けて実行するスクリプトとして、上記ファイルを指定する。
シェルスクリプトで普通に実行した時と curl | sh した時とで挙動を変える

以下に示すような方法で実現できます。

```sh:test.sh
#!/bin/sh

if [ "${0##*/}" = "test.sh" ] ; then
  # 普通に実行されたとき
else
  # curl | sh されたとき
fi
```

もしくは

```sh:test.sh
if [ $(basename "$0") = "test.sh" ] ; then
  # 普通に実行されたとき
else
  # curl | sh されたとき
fi
```
[memo] ftp の put は current directory の file しか扱えない

http://www.linuxquestions.org/questions/linux-newbie-8/ftp-error-553-could-not-create-file-4175446865/ のとおり。

```
ftp> put /foo/bar/file.ext
```

は失敗するので、

```
$ cd /foo/bar
$ ftp server.net
ftp> put file.ext
```

とするのが正しい。