OmniAICreator/Qiita-1.07M huggingface dataset:
UiPathでRPAを実践してみる(8) ～Invokeを上手く使う～

# 始めに
UiPathで様々な処理を作っていくと、同じような処理を他の場所でも使いたくなるようなことが有ります。
他にも、Mainの処理が大きくなりすぎるとテストを行う際に、結構、面倒くさくなったりします。
(前の処理の完了を待たなければいけないので、何度も流していると時間が無駄だったりします)
# 処理を切り出してみよう
というわけで、前述の処理をもっと小さい単位で切り出してみましょう。
## この対応を行う事によるメリット
1. 繰り返しの処理で、同じ処理を自分自身で書かなくてよくなります。もちろん、修正も1か所で済みますので保守性も向上します。
2. 切り出した処理単体で、実行が出来るのでプログラムの見通しが良くなります。
3. テストがしやすくなり、バグの発見が容易になります。

## 実際にどうやってやるのか？
まずはサンプルでフローチャートを作ってみましょう。
### 全体図
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/d1958c20-c53a-9f1e-630e-67b4503fa4ce.png)

### 内部のフローチャート
メモ帳を開いて、上位のフローチャートより受け取ったMessageを転記する。
![キャプチャ1.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/2ecf4399-ce12-9b1d-b486-a32c6e6fe4f3.png)

---

![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/4975052f-42a3-ea58-9258-4fb1668fa144.png)

もちろん、この程度の複雑さであればこれでも良いかもしれませんが…
折角なので分割しましょう
### フローチャートを別ファイルにする
右クリック→Extract as Workflowを選択します。
![キャプチャ3.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/5061b4ac-0785-70d6-1a1f-0c5cda965d04.png)
保存する名前の入力を求められるので適当に入れて、createを選択
![キャプチャ4.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/5a77327a-e89e-436f-e65f-3a563ce5d2ea.png)
これで別ファイルとしてworkflowが出来ました！
![キャプチャ5.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/c74a38b7-8c23-ba55-327c-19f01c322638.png)

さて、messageが存在しないのでエラーになっています。これは、上流のフローチャートより値を受け取りたいので引数として受け取れるようにしましょう。
Argumentsを選択して、Messageという名称で引数を作ります。Directionは、入力を表す「In」を選択します。もちろん、後続処理に値を渡す「Out」や両方できる「In/Out」もあります。デフォルト値には、「初期値」を入れておきます。
![キャプチャ6.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/9dc33bee-c63e-0fb8-62d1-b7a8acbda855.png)

これで、上記のエラーメッセージは消えたはずです。さて、openNotepadを実行してみましょう。このWorkflowを開いた状態で実行キーを押すだけです。
![キャプチャ7.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/8ece4da4-8374-4ddb-85fe-8f83628b14be.png)
問題なく、この処理だけが実行されました。(2回目の処理は流れないはずです。)これが上記のメリット2で上げた「切り出した処理単体で、実行が出来る」という事になります。

###上流のフローから値を渡す
さて、切り出した処理単体でうまく動かせたので呼び出し元のフローも変更しましょう。
Extract as Workflowとした処理がInvokeに変わっています。
![キャプチャ8.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/cd67082a-82b1-097e-0f06-34c92559943f.png)
このInvokeの処理をダブルクリックで開くと下記の画面になります。引数を編集できる機能があります。まずは、「Import Arguments」で、必要となる引数を自動でインポートしましょう。
![キャプチャ9.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/81985f5d-f683-9219-a8ef-43c51a7cc973.png)
下記の画面が表示されます。Name,Direction,Typeについては自動で入力されています。Valueに、こちらから渡したいmessageという変数を指定しましょう。
![キャプチャ10.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/632935e0-e8d2-60d9-68bb-994eb592ef26.png)

この状態を全て保存して処理を実行すると、2つのメモ帳が立ち上がり、大元のWorkflowの変数に格納していた「hogehoge」という言葉がメモ帳に記入されることを確認できたかと思います。「初期値」という言葉にはならないはずです。

これで、処理の一部を外だしすることが出来ました。
後は、「上と同じフロー」としていた部分もInvokeにしてあげればOKです。
![キャプチャ11.PNG](https://qiita-image-store.s3.amazonaws.com/0/154110/32fc79a1-87c8-bde1-7736-e8ffc02e0ec3.png)

この例は、非常に簡単な物でしたが、例えば「メモ帳を別のエディタに変えたい」という対応も、一か所で修正が出来るようになります。
もちろんInvokeしたWorkflowでさらにInvokeという事も可能です。(あまり階層が深くなりすぎるのも大変ですが…)
保守性の高いプログラムを行う上では必須の知識かと思っていますので、設計の際に参考にしてみてはいかがでしょうか。
kubernetes 1.7で導入された hostAliasesを試してみる

# 前書き
Kubernetes1.7でhostAliasesが導入された
https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#downloads-for-v170
今回hostAliasesを検証してみたので検証結果を示す。
なお、GKE上で動作検証を行っている。

# hostAliasesとは
https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/#adding-additional-entries-with-hostaliases

pod levelで/etc/hostsを上書き出来る機能。

# use-case
- 例えばMySQLはGCEで運用したいという場合でかつドメインでアクセスしたい場合
  - インスタンスのIPが192.168.2.4 ドメインがdb.example.jpとした場合、
  - 基本的にdbのドメインはDNS登録したくない。hostsで登録したい
- 社内専用システム等ドメインを登録したくないサービスにアクセスしたい場合
    - 社内専用の認証システムが 192.168.27 oauth.example.jpの場合
    - これもhostsで解決したい


などが考えられる。

# 設定
今回はkubernetes-guestbookに設定を追加してみる

https://github.com/kubernetes/kubernetes/blob/master/examples/guestbook/frontend-deployment.yaml

spec.template.spec.hostAliasesとして追加することになる

frontend-deployment.yamlを一部抜粋

```
 template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google-samples/gb-frontend:v4
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 80
      hostAliases:
      - hostnames:
        - mydb1.jp
        ip: 192.168.0.3
      - hostnames:
        - mydb2.jp
        ip: 192.168.0.4

```

hostnamesにドメインとipをセットで書く

# 確認
今回はpodにexec して /etc/hostsを確認してみる

```
kubectl get pods
kubectl exec -it frontend-......-.... bash -

```


```
# cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
fe00::0	ip6-mcastprefix
fe00::1	ip6-allnodes
fe00::2	ip6-allrouters
10.32.0.13	frontend-2019487900-ctsm6
192.168.0.3	mydb1.jp
192.168.0.4	mydb2.jp
```

とyamlで指定した hostsが追加されていることがわかる。

# 同一IPで複数hostがある場合
https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/
のマニュアルの用に、 1IPに対して複数hostsを並べればいい。
PHPサーバ変数 ($_SERVER) の出力コードサンプル

PHPのサーバ変数を出力するコード、デバッグでよく利用するのでメモしておきます。

```php:sample.php
<?php
echo '<pre>', json_encode($_SERVER, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
```
Python3でコンパイルが必要なパッケージをpipでインストール[Windows]

例えばpycryptoというパッケージはWindowsで使用する場合、コンパイルが必要ですので普通に`pip install pycrypto`と入力してもエラーが返ってきます。
そこで、Visual Studio Build Toolを使ってコンパイルをした上でインストール作業を行います。
Visual Studio Build Toolのインストールにある程度容量が必要ですが、作業自体は非常に簡単です。

- Windows 10
- Anaconda インストール済み

## 仮想環境を構築

試しに動作させるだけなので、仮想環境を一時的に作成して使用します。
コマンドプロンプトで管理者として実行します。

```commandline
# 仮想環境を構築
# conda create -n 仮想環境の名前 python=3.5.3
conda create -n wxenv python=3.5.3
# Anacondaのセットで作成する場合
# conda create -n wxenv python=3.5.3 anaconda
# 作った環境を確認するときは
# conda info -e
# conda list -n wxenv
# 作った仮想環境を削除する時は
# conda remove -n wxenv --all
```

## コンパイラのインストール

> 参考
> https://stackoverflow.com/questions/41724445/python-pip-on-windows-command-cl-exe-failed

下記URLからVisual C++ 2015 Build Toolsをダウンロードし、
インストーラのオプションで「カスタム」を選択、
windows 10 sdkのみをチェックしてインストール
> http://landinghub.visualstudio.com/visual-cpp-build-tools

<img width="496" alt="スクリーンショット 2017-07-27 12.28.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/cc964961-4041-c6c0-1116-7f75450c1b3f.png">

<img width="464" alt="スクリーンショット 2017-07-27 12.32.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/2050af42-80c2-8b38-1f53-0bc9e54d1aa3.png">

<img width="462" alt="スクリーンショット 2017-07-27 12.33.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/c8304545-ab7c-b6f3-c61e-4e8c6f7d9123.png">

インストールが完了後、追加された
Visual C++ 2015 x86 x64 Cross Build Tools Command Prompt
を「管理者として実行」で起動する。
※注意：同じような名前で
Visual C++ 2015 x64 x86 Cross Build Tools Command Prompt
があります。うまく通らない時はこちらで実行してみてください。

ちなみにこのツール群は、
C:\Program Files (x86)\Microsoft Visual C++ Build Tools
のディレクトリにあるはずです。

```commandline
# Visual C++ 2015 x86 x64 Cross Build Tools Command Prompt
# で実行

# 仮想環境へ移行
# activate 仮想環境の名前
activate wxenv
# パッケージのインストール
# pip install パッケージ名
pip install pycrypto
```
<img width="500" alt="スクリーンショット 2017-07-27 17.14.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/76058/5e328039-48e6-53c0-ac41-05d44e018528.png">
Dockerfileで、質問を受けずにrootで`composer install`する

## やること

パッケージによって出る`[Y,n]`で処理が止まらないようにする。

```bash
# みたいな
Set Folder Permissions ? (Default to Y) [Y,n]? 
```

あと、rootユーザーだとこんな警告が出るのでそれを出ないようにする。

```bash
Do not run Composer as root/super user! See https://getcomposer.org/root for details
```

## `RUN composer install`より前に環境変数を設定

使うのは２つ。

```docker
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_NO_INTERACTION 1

# RUN composer install
```

### `COMPOSER_ALLOW_SUPERUSER`

`1`を設定するとrootでのインストールを許可できる。

### `COMPOSER_NO_INTERACTION`

`1`を設定すると何も聞いてこないくなる。
bootstrap-select のプルダウンの矢印を文字（▼）にする方法


## 概要
bootstrap-select を使ってて、プルダウン横の矢印が小さすぎるので、自分でサイズを指定したい、できたら font-size 指定したいなーと思ったので、やってみた。  

## 環境
|項目名|バージョン|
|---|---|
|bootstrap-select.js|v1.2.2|
|Chrome|v59.0.3071.115 |

## やりかた
CSSをいじるだけ。
dropup は使ってないので、無視しています。  

```css:css
/* デフォルトの矢印を非表示にする */
.bootstrap-select.btn-group .dropdown-toggle .caret {
    display: none;
}
/* プルダウンの右端に▼を挿入する */
.bootstrap-select.btn-group .btn .filter-option:after {
    content: '▼';
    font-size: 20px;
    float: right;
}
```
RxSwiftのshare*の早見表

# はじめに
RxSwiftの3.5.0から`share(replay:scope:)`が追加されました。
3.5.0未満の`share()`、`shareReplay(_:)`、`shareReplayLatestWhileConnected()`にどう対応しているのか書いていきます。

## .share()
```swift
.share(scope: .forever)
```

## .shareReplay(1)
```swift
.share(replay: 1, scope: .forever)
```

## .shareReplayLatestWhileConnected()
```swift
.share(replay: 1, scope: .whileConnected)
```


## 参考

[RxSwift 3.5.0 Release Note](https://github.com/ReactiveX/RxSwift/releases/tag/3.5.0)

```swift:RxSwift/Observables/ShareReplayScope.swift
public func share(replay: Int = 0, scope: SubjectLifetimeScope)
        -> Observable<E> {
    switch scope {
    case .forever:
        switch replay {
        case 0: return self.multicast(PublishSubject()).refCount()
        default: return shareReplay(replay)
        }
    case .whileConnected:
        switch replay {
        case 0: return ShareWhileConnected(source: self.asObservable())
        case 1: return ShareReplay1WhileConnected(source: self.asObservable())
        default: return self.multicast(makeSubject: { ReplaySubject.create(bufferSize: replay) }).refCount()
        }
    }
}
```

# 追記

## .share()

```swift:RxSwift/Observables/Multicast.swift
public func publish() -> ConnectableObservable<E> {
    return self.multicast(PublishSubject())
}

public func share() -> Observable<E> {
    return self.publish().refCount()
}
```

## .shareReplayLatestWhileConnected()

```swift:RxSwift/Observables/ShareReplayScope.swift
public func shareReplayLatestWhileConnected() -> Observable<E> {
    return ShareReplay1WhileConnected(source: self.asObservable())
}
```
通知の許可を要求する際のoptions引数について (User Notifications framework)


## 内容
- `requestAuthorization(options:completionHandler:)`のoptions引数にUNAuthorizationOptions型の配列を渡すとコンパイルエラーが出る
- エラー内容:`Cannot convert value of type '[UNAuthorizationOptions]' to expected argument type 'UNAuthorizationOptions'` 
- 以下のような形で解決できたのでメモ

## 環境
- Xcode: 8.3.3
- Swift: 3.1

## 通知許可を処理するクラス

```Swift:MyNotifications.swift
import Foundation
import UserNotifications

class MyNotifications: NSObject {
	/// 通知の許可ダイアログを表示させる
	///
	/// - Parameter options: 通知の種類
	class func requestAuthorization(withOptions options: UNAuthorizationOptions...) {
	    var optionSet: UNAuthorizationOptions = []
	    for option in options {
	        optionSet.insert(option)
	    }

	    UNUserNotificationCenter.current().requestAuthorization(options: optionSet) { (granted, error) in
	        if error != nil {
	        	print("エラー")
	        	return
 	       }
        
	        if granted {
	        	print("通知許可")
	        } else {
	        	print("通知拒否")
	        }
	    }
	}
}
```


## AppDelegate等で呼び出す

```Swift:AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // アラート、バッジ、サウンドの許可を要求する
        MyNotifications.requestAuthorization(withOptions: .alert, .badge, .sound)
        
        return true
    }

}
```
たくさんの連番のディレクトリがある時，次のディレクトリに移動するコマンド

## 背景

連番のディレクトリがあり，順番にディレクトリを移動して処理しなければならない場合がある．
その処理が定型的なものであれば，シェルスクリプトで対応できるが，各ディレクトリ内で，人手で処理しなければならない場合もある．
その場合，ディレトリの数が多ければ次のディレクトリがよくわからなくなる．
じゃあ，次のディレクトリに移動するコマンドを作れば良いと思って，作ってみた．

## 改善版

### getnextdir

以前のやり方だと，```.bash_profile```に結構な量のスクリプトがあったので，それを別のシェルスクリプトに追い出した．
下のスクリプトをパスの通ったところに保存する．

```bash:getnextdir
#! /bin/sh

cwd=$(pwd)
current="../${cwd##*/}"

previous=FALSE

while getopts p OPT
do
  case $OPT in
    "p" ) previous=TRUE ;;
  esac
done

next=0
nextdir=$current

for i in $(find .. -maxdepth 1 -mindepth 1 -type d | sort)
do
    if [ $previous = TRUE ]; then
        if [ "$current" = "$i" ]; then
            break
        fi
        nextdir=$i
    else
        if [ $next -eq 0 ]; then
            if [ "$current" = "$i" ] ; then
                next=1
            fi
        elif [ $next -eq 1 ]; then
            nextdir=$i
            break
        fi
    fi
done

if [ "$nextdir" = "$current" ] ; then
    echo $current/..
    exit 1
else
    echo $nextdir
    exit 0
fi
```

### .bash_profile

次に，```.bash_profile```に下のスクリプトを追加する．

```bash:.bash_profile
nextdir(){
    next=$(getnextdir)
    if [ $? -eq 0 ]; then
        cd $next
    else
        echo "Done"
        cd $next
    fi
    pwd
}

prevdir(){
    next=$(getnextdir -p)
    if [ $? -eq 0 ]; then
        cd $next
    else
        echo "Done"
        cd $next
    fi
    pwd
}
```

### 注意点

* シェルスクリプトとして作成しようとしても実現できません．
    * 別のシェル環境内で移動し，そのシェルスクリプトが終了すると元の環境（元のディレクトリのまま）に戻ります．
    * 実現方法を探していると， ```source``` （```.```）を使ってスクリプトを読み込めという記述が散見されるものの，目的が違うのでここでは採用していません．

### 参考サイト

* シェルスクリプトでの引数の処理: http://shellscript.sunone.me/parameter.html

## 以前のバージョン

### 次のディレクトリに移動する

たくさんの連番のディレクトリがあり，一つずつ中に移動して確認して，次のディレクトリに移動して．．．と繰り返していると，次のディレクトリが何かがわからなくなってくる．
次のディレクトリに移動するコマンドがあれば良いと思い，作ってみた．

```bash:.bash_profile
nextdir () {
    cwd=$(pwd)
    current="../${cwd##*/}"

    next=0
    nextdir=$current
    for i in $(find .. -maxdepth 1 -mindepth 1 -type d)
    do
        if [ $next -eq 0 ]; then
            if [ "$current" = "$i" ] ; then
                next=1
            fi
        elif [ $next -eq 1 ]; then
            nextdir=$i
            break
        fi
    done
    if [ "$nextdir" = "$current" ] ; then
        echo "Done"
        cd ..
    else
        cd $nextdir
    fi
    pwd
}
```

この関数を```~/.bash_profile```や```~/.bashrc```に保存して次のコマンドを入力すると```nextdir```コマンドが有効になる．

```shell-session
$ . ~/.bash_profile
```

### 前のディレクトリに移動する．

同様に次のようにすることで，前のディレクトリに移動するコマンドも実現可能．

```bash:.bash_profile
prevdir () {
    cwd=$(pwd)
    current="../${cwd##*/}"

    prev=0
    prevdir=$current
    for i in $(find .. -maxdepth 1 -mindepth 1 -type d)
    do
        if [ "$current" = "$i" ] ; then
            break
        fi
        prevdir=$i
    done
    if [ "$prevdir" = "$current" ] ; then
        echo "Done"
        cd ..
    else
        cd $prevdir
    fi
    pwd
}
```
ハイブリッドアプリとは? 

# はじめに
ハイブリッドアプリの解説記事はよく見かけますが、そもそもどのような仕組みで、何故動いているのかよくわからなかったため、ハイブリッドアプリの仕組みやCordovaなどのフレームワークが何をしているかに関しての備忘録になります。

私みたいな**「ハイブリッドアプリってあれでしょ。Webとネイティブアプリが組み合わさったものでJSとかでアプリ作れちゃうあれでしょ!?」**という方が読めば、更に理解を深められるかもしれません。

※ハイブリッドアプリの概要や仕組みに関しての記事のため、開発方法やコードは書いておりません。

# ハイブリッドアプリとは?
HTML5、CSS、JavaScriptなどのWeb技術で開発しており、且つカメラやGPSなどのデバイスのネイティブ機能を利用しているアプリのこと。
ブラウザ上で動作するWebアプリとは異なり、Android OSやiOSに標準で組み込まれているWebView上で動作する。
Cordova（ハイブリッドアプリ開発に必要な機能、仕組みを提供しているフレームワーク）などがJavaScriptでネイティブ機能を利用できるAPIを提供している。

# ハイブリッドアプリの仕組み（どのような仕組みでWeb技術でネイティブ機能を利用しているのか）
以下は代表的なハイブリッドアプリ開発フレームワークである、Cordova（コルドバ）を利用したハイブリッドアプリの仕組みのイメージ図

![hybrid_application (6) (2) (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/69667/728cb5dd-8870-2cfb-1939-d0aec60462c6.jpeg)

CordovaがWebアプリ（Web技術で開発したブラウザ上で動作するアプリ）をWebView上で実行し、デバイス上のネイティブ機能（カメラ、GPSなど）の呼び出しをするためのインターフェイスを提供している。
そのため、Web技術でネイティブ機能を利用できる。

## CordovaがWebアプリをWebView上で実行
Webアプリ（HTML/CSS/JavaScriptで開発したブラウザ上で動くアプリ）をWebView上で実行（レンダリングやJavaScriptを実行）する。

### WebViewとは
Android OSやiOSに標準で組み込まれているソフトウェア（ネイティブコンポーネント）のこと。Webページを読み込んで表示する機能を提供する。Webページ表示の機能を独自で開発・実装しなくても、WebViewを利用すればWebページを表示する機能をアプリに組み込むことができる。

## CordovaがJavaScriptでネイティブ機能を呼び出せるインターフェイスを提供
WebView上で実行したJavaScriptにネイティブ機能を利用する処理があれば、インターフェースを介してネイティブ機能を呼び出す。

例えば、カメラで写真を撮影する機能を実行したい場合、JavaScriptで以下のように書く。

```JavaScript
navigator.camera.getPicture(cameraSuccess, cameraError, cameraOptions);
```

上記のような処理を実行すれば、Cordovaがネイティブコードによって対応する機能を実行してくれる（CordovaがiOSやAndroidに応じた機能を実行してくれる）。

# Cordovaをベースにしたフレームワークやプラットフォーム
ハイブリッドアプリ開発フレームワークやプラットフォームは多数存在するが、Cordovaをベースにしたものが多いらしい。

- [Adobe PhoneGap（Cordovaと大体同じものという認識で問題ないらしい）](https://phonegap.com/)
- [Ionic（UIフレームワーク）](https://ionicframework.com/)
- [Onsen UI（UIフレームワーク）](https://onsen.io/)
- [Monaca（開発プラットフォーム）](https://ja.monaca.io/)

# ハイブリッドアプリの特徴やメリット・デメリット
色々な記事で書かれているが、一応記載しておく。

## ハイブリッドアプリの特徴やメリット（ネイティブアプリと比べて強い点）
- クロスプラットフォーム（1つのコードでiOS、Androidで動作する）
- iOS、Androidを同時に開発できるため、ネイティブアプリと比べて開発コストは非常に小さくなる
- Web技術でアプリを開発できる（Web開発経験がある人ならアプリを開発できる）
- UIの構築にhtml5、css3を利用できるため、ネイティブアプリと比べて自由度が高い

など、開発コストが魅力に挙げられることが多い。

## ハイブリッドアプリのデメリット（ネイティブアプリと比べて弱い点）
- 動作が遅い。
- 複雑、またはマイナーなネイティブ機能を利用することは難しい（または利用できない）。

### 動作が遅い
昔は動作スピードにかなり差があったらしいが、最近はゲームのようなゴリゴリ動くものでなければネイティブアプリと遜色ないらしい。
しかし、それは新しめのOSの場合であり、Android 4.4以前はかなりパフォーマンスが悪いため、古いAndroidもサポートするならネイティブ開発の方が良いらしい。

### 複雑、またはマイナーなネイティブ機能を利用することは難しい（または利用できない）
Cordovaなどのフレームワークが、ネイティブ機能を利用できるようにするプラグインを提供しているかどうか次第らしい。
プラグインの多くは個人開発のものなので、欲しいプラグインがなかったら自分で開発するという手段もある。

# 終わり
ハイブリッドアプリの説明を見ると

- 「Webアプリとネイティブアプリを組み合わせたようなアプリ」
- 「Webアプリとネイティブアプリの良いとこどりをしたアプリ」

など、Webとネイティブの組み合わせを強調していることが多いですが、説明が抽象的すぎる（どこがWebでどこがネィティブなのか）ため

**「ネイティブアプリと（ほぼ）同様の機能をもった、HTML、CSS、JavaScriptで開発したクロスプラットフォームのアプリ」**

と説明した方が個人的にはわかりやすいと思いました。
MAMP環境でWP-CLIを導入


# はじめに
WP-CLIとは、コマンドラインからWordPressを操作するためのツールです。ブラウザを起動する必要がなく、CUIで様々な操作が可能になります。

MAMPで構築した環境で、WP-CLIを利用開始するまでの流れをまとめます。

# WP-CLIをインストール
HTTP経由でのインストールが可能です。
動作条件は、PHP 5.3.29 以上、WordPress 3.7 以上です。

```
> curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
```

動作確認をしてみます。

```
> php wp-cli.phar --info
```


# パスを通す

コマンドをグローバrに呼び出せるようにしていきます。

```
> chmod +x wp-cli.phar
> sudo vm wp-cli.phr /usr/lobagin/wp

```

シェルファイルに定義を追加していきます。


```.zshrc
# WP-CLIからMAMPのMySQLを呼ぶため
export PATH=/Applications/MAMP/Library/bin:${PATH}

# WP-CLIが使用するMAMPのPHPバージョン
export WP_CLI_PHP=/Applications/MAMP/bin/php/php5.6.10/bin/php
```

# wp-config.phpをMAMP想定に調整
MAMP環境で注意が必要なのはデータベース接続に使用するソケット。これがMAMP内の場所となります。

```wp-config.php
define( 'DB_HOST', 'localhost:/Applications/MAMP/tmp/mysql/mysql.sock' );
```

# WordPressから投稿一覧を取得してみる
設定に問題がなければ、WP-CLIから操作が可能になります。
以下はとりあえず投稿一覧を取得するコマンド。

```
> wp post list
```
RPMのプロキシ設定をコマンドオプションではなくファイルに設定する

rpmをプロキシ環境下で利用するにはコマンドオプションで実行するには

```
rpm --httpproxy proxy_ip --httpport port_num
```

としますがシェルに埋め込まれていてコマンドオプションを付けられないときには`/usr/lib/rpm/macros`の中に設定する場所があるのでコメントを外して

```
#       The port and machine name of an HTTP proxy host.
#
%_httpport port_num
%_httpproxy proxy_ip

```

とする。
パスは環境によって多少ちがうかも。
IBM Bluemix SecureGateway サービスを利用する際にはセキュリティを設定すること

# ご利用は計画的に

IBM Bluemix 上には、Secure Gateway サービスというオンプレミスと `Bluemix` 環境の通信をトンネリングしてオンプレミス側（これはBluemix CF環境以外をしめしています）のリソースをBluemixのCFアプリケーションから利用するためのものです。非常に便利に簡単に利用できるのですが、何も考えずに利用するとセキュリティ上の問題になりますのでここでは注意点を書いておきます。

# 注意点

* Secure Gateway で公開したリソース(クラウドホスト：ポート）は、 **インターネット上にアクセス制限無しで公開される** （ディフォルトの状態）
* リソース（クラウドホスト：ポート）に対して制限を設けるために、「アプリケーションサイドTLS」または「IPテーブル・ルール」を利用して制限を行うこと。
* アプリケーション要件が許すのであれば「アプリケーションTLS」を構成し、利用時のみ有効化することが望ましい。

資料「アプリからのアクセス」必読
* https://console.bluemix.net/docs/services/SecureGateway/sg_023.html#sg_023

なんか、社内のデータベースとか簡単にCFアプリケーションに繋げられます的な説明があるのですが単に設定しただけでは社内のデータベースを外部に公開していることになるってしまうので気をつけましょう＆ドキュメントはよく読みましょう。最近は、Bluemix上のアプリケーションの中にもSecure Gateway が利用可能な物が増えてきました。そういったアプリは上記の「アプリケーションサイドTLS」を自動的に構成して接続してくれるものもありますので利用可能な場合には検討して見るべきでしょう。


# 補足

以下の例は、Secure Gateway Client 上の設定用UIに対しての「宛先」設定になっています。この場合、セキュリティの設定が何もされていないため提供される「クラウドホスト：ポート」に対してインターネット上のどの端末からもアクセスが出来てしまいます。

<img width="1022" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/11540/d41c1a27-23e1-806f-6b99-73f52b8a9301.png">

ここでは、ネットワークセキュリティの「IPテーブルルールを使用して、この宛先のクラウドアクセスを制限します」にチェックを入れて「宛先を更新」します。

<img width="1020" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/11540/e0bf518e-ce9a-ae5d-69e3-a5203c3a98b7.png">

これで「IPアドレス」に送信元IPアドレス（直接アクセスする端末のIPアドレス）を記入しないと通信が許可されない状態になっています。では、実際の場合を考えてみましょう。CFアプリケーションは、実行時にそのアプリケーションが実行するノードが確定します。そのため、一般的なユースケースであるCFアプリケーションからSecure Gateway を経由してなんらかのデータを処理することを考えた場合にはCFアプリケーションのIPアドレスを取得する必要があります。

ドキュメントにもありますが、CFアプリケーション上で環境変数`CF_INSTANCE_IP`に実行ノードのIPアドレスが格納されます。この値を利用して、CFアプリケーションの内部でREST APIを利用して設定を行う必要があります。

```
curl -X PUT "https://sgmanager.ng.bluemix.net/v1/sgconfig/<gateway_id>/destinations/<destination_id>/ipTableRule"
    -H "Authorization: Bearer <security_token>" -H "Content-type:  application/json" -d
    '{"src":"<app_IP>","app":"<app_ID>"}'  -k
```

ドキュメント内で指定されているapiは上記になります。特に変則的な事はありません。 `app_id`はソースポートになりますが指定しないでも設定することは可能です。私はハマっていましたがメソッドが`POST`じゃなくて`PUT`なので気をつけましょう。
Expectでtelnetのログインを自動化する

ssh先でtelnetを使ってログイン必要な環境があったので
expectを使って自動化してみた

```:ssh_telnet.exp
#!/usr/bin/expect

set Prompt "\[#$%>\]"
set SSHUSER "foo"
set SSHPW "hogehoge"
set TELUSER "bar"
set TELPW "fugafuga"
set timeout 5

spawn env LANG=C ssh ${SSHUSER}@ssh-ip

expect {
  "password:" {
    send "${SSHPW}\n"
  }
}

expect {
    -glob "${Prompt}" {
      send "telnet telnet-ip\n"
    }
}

expect {
  "login:" {
    send "${TELUSER}\r"
    exp_continue
  }

  "Password:" {
    send "${TELPW}\r"
    exp_continue
  }

  ">>" {
    interact
    exit 0
  }
}
```

ポイントは telent中のEnterは `\n` ではなく `\r` になる。
(ちょっとハマった)
mysql2で巨大データを扱う場合

Rubyのmysql2で巨大なデータを取り扱いたい場合、Streamingをtrueにすると一度に必要な行だけ取ってこられるようです。

```ruby
result = client.query("SELECT * FROM really_big_Table", :stream => true)
```

https://github.com/brianmario/mysql2#streaming
PHP Manual 読書会(12回目)(クラスとオブジェクト4)

PHPに慣れる為に週1ぐらいで更新していきます。PHP Manualを読んで実験して行きます。

前回:[PHP Manual 読書会(11回目)(クラスとオブジェクト3)](http://qiita.com/amesho/items/a79a2a9e45ed7d9d0a98)

## [コンストラクタとデストラクタ](http://php.net/manual/ja/language.oop5.decon.php)

### コンストラクタ

> PHP 5 では、開発者がクラスのコンストラクタメソッドを宣言することが できます。コンストラクタメソッドを有するクラスは、新たにオブジェクトが 生成される度にこのメソッドをコールします。これにより、 そのオブジェクトを使用する前に必要な初期化を行うことができます。

要注意な点としては、

> 注意: 子クラスがコンストラクタを有している場合、親クラスのコンストラクタが 暗黙の内にコールされることはありません。 親クラスのコンストラクタを実行するには、子クラスのコンストラクタの 中で parent::__construct() をコールすることが 必要です。 子クラスでコンストラクタを定義していない場合は、親クラスのコンストラクタを継承します (ただし、private 宣言されている場合は除く)。 これは、通常のクラスメソッドと同様です。

ここですね。


```php
<?php

class Base {
    function __construct() {
        echo "Yo!\n";
    }
}

class Sub extends Base {
}

$obj = new Sub();
```

結果

```
Yo!
```

これが、`private`に指定された場合は

```php
<?php

class Base {
    private function __construct() {
        echo "Yo!\n";
    }
}

class Sub extends Base {
}

$obj = new Sub();
```

エラーになります。

```
PHP Fatal error:  Uncaught Error: Call to private Base::__construct() from invalid context
```

親クラスのコンストラクタを呼びたい場合は、明示的に呼びます。

```php
<?php

class Base {
    function __construct() {
        echo "Yo!\n";
    }
}

class Sub extends Base {
    function __construct() {
        parent::__construct();
        echo "Yo!\n";
    }
}

$obj = new Sub();
```

```
Yo!
Yo!
```

> 他のメソッドと異なり、親の __construct() と異なるパラメータで __construct() をオーバーライドしても PHP は E_STRICT エラーメッセージを出しません。
> PHP 5.3.3 以降、名前空間つきのクラス名の最後の部分と同じ名前のメソッドは コンストラクタとみなされなくなりました。 名前空間を使っていないクラスは今までと変わりません。


他に注意すべき点は、この場合だとSubというメソッドを追加した場合5.3.3以前はコンストラクタとしてみなされていたが、現在のバージョンでは見なされない。

### デストラクタ

> PHP 5 では、C++ のような他のオブジェクト指向言語に似た概念のデストラクタが 導入されました。デストラクタメソッドは、 特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。

```php
<?php

class Base {
    function __destruct() {
        echo "Yo!\n";
    }
}

class Sub extends Base {
    function __destruct() {
        parent::__destruct();
        echo "Yo!\n";
    }
}

$obj = new Sub();
$obj = NULL;
echo "delete\n";
```

結果

```
Yo!
Yo!
delete
```

気にすべき点としては、

> exit() でスクリプトの実行を止めた場合にもデストラクタはコールされます。 デストラクタの内部で exit() をコールすると、 それ以降のシャットダウンルーチンを実行しません。

このデストラクタ内部で`exit()`をコールすると、それ以降のシャットダウンルーチンが実行されない点。
StackStormをプロキシ下でインストール



stackstormは一撃でインストールできるスクリプトが用意されていますが、プロキシ環境下では途中でこけてしまいました。これを回避するためにいくつかの事前準備が必要だったので事前準備からインストールまでのメモ。


今回プロキシサーバーは

```
http://proxy.server:8080/
```

とします。

今回使用したOSは
CentOS Linux release 7.3.1611 (Core)
です。

# 環境変数のプロキシ設定

以下のコマンドで環境変数を設定します。

```
export http_proxy=http://proxy.server:8080
export https_proxy=http://proxy.server:8080
export HTTP_PROXY=http://proxy.server:8080
export HTTPS_PROXY=http://proxy.server:8080
export NO_PROXY=localhost,127.0.0.1
export no_proxy=localhost,127.0.0.1
```

また`/etc/profile`の最後にも上記コマンドを追記しておきます。

- /etc/profile

```
export http_proxy=http://proxy.server:8080
export https_proxy=http://proxy.server:8080
export HTTP_PROXY=http://proxy.server:8080
export HTTPS_PROXY=http://proxy.server:8080
export NO_PROXY=localhost,127.0.0.1
export no_proxy=localhost,127.0.0.1
```

# curlのプロキシ設定

curlのプロキシ設定は`~/.curlrc`に行います。

```
proxy = http://proxy.server:8080/
```

# rpmのプロキシ設定

`/usr/lib/rpm/macros`の中に設定する場所があるので該当箇所のコメントを外して以下のように設定。

```
#       The port and machine name of an HTTP proxy host.
#
%_httpport 8080
%_httpproxy proxy.server

```

# yumのプロキシ

`/etc/yum.conf`に以下を追記します。

```
proxy=http://proxy.server:8080
```

# StackStormのインストール

ここからは公式のドキュメントどおりです。
https://docs.stackstorm.com/install/index.html
をインストールスクリプトのURLが変わっていたらこちらを参照してください。

インストールは以下を実行するだけですパスワードの`Ch@ngeMe`は任意のパスワードに変更してください。

```
yum install curl nss
curl -sSL https://stackstorm.com/packages/install.sh | bash -s -- --user=st2admin --password='Ch@ngeMe'
```

以上。

# pipのプロキシ(st2 pack installのために)

st2 pack installで引っかかったのでpipのプロキシ設定も追加します


`.config/pip/pip.conf`をなければディレクトリごと作成し以下を設定

```
[global]
proxy = http://192.168.128.28:8080
noproxy = 127.0.0.1
```
【CSS】display:table-cellで発生する余白を取りたい

#取りたい
##表示サンプル
「56×22」の部分は画像です。画像の下部分に余白が出てしまいます。
これをなくしたい。（確認環境はChrome59）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/176912/f1259c5c-12a3-73a6-7c98-86e1ce07f19c.png)


##余白が出てしまうコード
```HTML:index.html

	<div class="table">
		<div class="table-row">
			<div class="table-cell">
			<img src="img/hogehoge.png">
					</div>
			<div class="table-cell">
			ほげほげ
			</div>
			<div class="table-cell">
			<img src="img/hogehoge.png">
					</div>
			<div class="table-cell">
			ほげほげ
			</div>
		</div>

		<div class="table-row">
			<div class="table-cell">
			<img src="img/hogehoge.png">
					</div>
			<div class="table-cell">
			ほげほげ
			</div>
			<div class="table-cell">
			<img src="img/hogehoge.png">
					</div>
			<div class="table-cell">
			ほげほげ
			</div>
		</div>


...


</div>

```


```CSS:style.css

/*テーブル指定*/
.table {
	display: table;
	line-height: 0;
}

/*セルのクラス指定*/
.table-cell {
	display: table-cell;
	vertical-align:middle;
}	

/*rowクラス指定*/
.table-row {
	display: table-row;
}

/*奇数番目のセルのスタイル*/
.table-cell:nth-child(odd) {
	width: 50px;
	text-align: left;
}	

/*偶数番目のセルのスタイル*/
.table-cell:nth-child(even) {
	background: #CCC;/*わかりやすくするための背景色*/
	border-bottom: solid 1px #000;/*わかりやすくするためのボーダー*/
	width: 60px;
	text-align: right;
}	

```



#解決策

``line-height:0;``をテーブル指定に入れてあげたら余白が無くなった。

```CSS:style.css
/*テーブル指定*/
.table {
	display: table;
	line-height: 0;
}
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/176912/38592d69-a8d0-6ab7-87be-cb729525f4ce.png)

#原理
ちなみに原理がわかりません……
display:table 関連はmarginが利かないあたりが関連しているのかも……？
もし、仕組みがわかる方がいれば教えてください。
sshの接続が切れるたびに前のtmuxセッションにアクセスできなくなった時の対処法

# 環境
- mac
- zsh

# 症状
タイトル通り`ssh`でサーバに繋いで、`tmux`でセッションを作った後、`ssh`を`exit`すると前のセッションにアタッチできなくなりました。
具体的には`exit`した後、

```
> tmux a
no sessions
> tmux ls
error connecting to /tmp/tmp.tmux/tmux-hogehoge/default(No such file or directory)
```

と行った感じにそんなファイルはないと怒られました。

#解決方法
このサイトを参考に`.zshrc`に設定を書き加えました。
http://did2memo.net/2017/05/18/tmux-attach-no-sessions-error/
具体的には

```
export TMUX_TMPDIR=/tmp
```

を`.zshrc`の最後に書き加えました。
上のサイトによると、どうやら`ssh`するたびに`tmux`のセッションの保存場所が変わっていたようです。
そのため、セッションの保存場所を上のコードで設定したみたいです。
Intellij IDEAでGradleでSpring Bootでリモートデバッグ

完全自分用
あとで整理とマークダウンします
Intellijさんを日本語化してるので英語のメニュー名が…わからない。

①待ち受けするものを作成
メニューの実行のエディットコンフィグレーションを起動
Remote追加
名前は適当にわかりやすいものを自由に
ホストとポートは適当に
設定のソースを検索でデバッグしたいプロジェクト選択
上の方のJVMオプションをコピーしておく

②デバッグしたいプロジェクトに①で作成した待ち受けをつなげる
メニューの実行のエディットコンフィグレーションを起動
Gradle追加
タスクにbootrun
VMオプションにコピーしておいたものをペースト


デバッグの実行方法は
メニューの実行の①で作成したした待ち受けのデバッグを選択
Intellijさんのデバッグのタブで
たしか一番上のアイコンをおしてbootrun実行
kerasで画像で主流のFine Tuning（転移学習）を、データ学習でもやってみる

作成したモデルをオンラインサービスで使う場合、新たに蓄積されるデータを使って既存のモデルを日々更新したいですが、毎日バッチで全部のデータを回すのは時間もお金もかかります。
画像の学習では、VGG16のような学習済みのモデルに判別したい画像を読ませてFine Tuningする方法が一般的です。
そこで今回は、普通のデータで構築したモデルを保存し、そのモデルをFine Tuningしてみました。

ここではポイントだけ紹介しますので、実際に動くサンプルコードは以下から見てください。
https://github.com/tizuo/keras/blob/master/%E8%BB%A2%E7%A7%BB%E5%AD%A6%E7%BF%92%E3%83%86%E3%82%B9%E3%83%88.ipynb

#ベースとするモデルを構築する
今回はirisデータを適当に分割して、2回に分けて学習させます。
まずはベースとするモデルを定義します。ポイントとしては、継承したいレイヤーに`name`パラメタを入れることだけです。

```python:
model_b = Sequential()
model_b.add(Dense(4, input_shape=(4, ), name='l1'))
model_b.add(Activation('relu'))
model_b.add(Dense(4, input_shape=(4, ), name='l2'))
model_b.add(Activation('relu'))
model_b.add(Dense(3, name='cls'))
model_b.add(Activation('softmax'))
```
#モデルの重みを保存
ベース用のデータでfitさせた後、モデルの重みを保存します。

```python:
model_b.save_weights('my_model_weights.h5')
```

#入れ先のモデルを準備
レイヤーの`name`を対応させてください。この例では新しいデータが過度に反映されるのを防ぐのにDropout層を追加しています。

```python:
model_n = Sequential()
model_n.add(Dense(4, input_shape=(4, ), name='l1'))
model_n.add(Activation('relu'))
model_n.add(Dense(4, input_shape=(4, ), name='l2'))
model_n.add(Activation('relu'))
model_n.add(Dropout(0.5))
model_n.add(Dense(3, name='cls'))
model_n.add(Activation('softmax'))
```

#重みのロード＆学習
新しく作ったモデルに重みを読み込み、残りのモデルを学習させます。

```python:
#重みの読み込み
model_n.load_weights('my_model_weights.h5', by_name=True)

#コンパイル&実行
model_n.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model_n.fit(new_X, new_Y, epochs=50, batch_size=1, verbose=1)
```

メモリオーバーなどで回らない量のデータを分けて学習させたい場合にも使えそうです。
artisanコマンドメモ


##よく使うもの
**コントローラー作成**
`php artisan make:controller <controller name>`

**Eloquentモデル作成**
`php artisan make:model <model name>`

**コマンド生成**
`php artisan make:command <command name>`

**マイグレーションファイル作成**
`php artisan make:migration <class name>`

**マイグレーション実行**
`php artisan migrate`

**マイグレーション ロールバック**
`php artisan migrate:rollback`

**job作成**
`php artisan make:job <job name>`
[RSpec] example 内で、describe / context / it などを取得する方法

RSpec 3.6 で確認しています。

たとえば、以下のようなサンプルを考えます。

```rb:sample_spec.rb
RSpec.describe "Movie" do
  describe "#price" do
    context "when a customer is under 18" do
      it "1000 yen" do

        # somthing
        # この中で、上の it / context / describe を取得したいと思います
      end
    end
  end
end
```

# 取得する

`self.class` と、`RSpec.current_example` から取る方法を試しています。

```rb
RSpec.describe "Movie" do
  describe "#price" do
    context "when a customer is under 18" do
      it "1000 yen" do


        p self.class.description
        #=> "when a customer is under 18"

        p self.class.superclass.description
        #=> "#price"

        p self.class.superclass.superclass.description
        #=> "Movie"


        p RSpec.current_example.metadata[:description]
        #=> "1000 yen"

        p RSpec.current_example.metadata[:example_group][:description]
        #=> "when a customer is under 18"

        p RSpec.current_example.metadata[:example_group][:parent_example_group][:description]
        #=> "#price"

        # somthing
      end
    end
  end
end
```

# おまけ

`context` に正規表現を入れて、それをそのまま取得したいときがありました。その場合は、上の方法だと、`/regex/.to_s` となってしまいます。これだと少し面倒くさかったのですが、以下のように取ることができました。

```rb
context /(a|b)/ do
  it 'b' do
    p self.class.description
    #=> (?-mix:(a|b))"

    p RSpec.current_example.metadata[:example_group][:description]
    #=> (?-mix:(a|b))"

    p RSpec.current_example.metadata[:described_class]
    #=> /(a|b)/

    # コメントにて教えて頂いた幸せな方法！
    p described_class
    #=> /(a|b)/
  end
end
```

以上です。ありがとうございました。🦑
【メモ】Amazon EC2で既存のインスタンスに利用されているKeyPairを確認する

# やりたかったこと

AWSのアカウントを運用していると増えるKeyPair・・・

そのうち、利用してないKeyPairも増えてきて、「この秘密鍵、必要なん？」ってなると思います。

で、棚卸ししました。

そのときに利用したコマンドをメモしておきます。


## EC2インスタンスで利用されているKeyPairを調べる

以下のコマンドを利用しました。配列が出力されます。

```bash
aws ec2 describe-instances --query "Reservations[].Instances[].KeyName" | jq -r unique
```

現状のjmespathでは配列の重複排除はできないようです。

https://stackoverflow.com/questions/37022753/how-can-i-get-unique-values-in-array-in-a-jmespath-query


## KeyPairの一覧を調べる

以下のコマンドを利用しました。配列が出力されます。

```bash
aws ec2 describe-key-pairs --query "KeyPairs[].KeyName"
```


## 不要なKeyPairを削除する

例えば、「現在利用されていないKeyPairは不要である」として対処します。

**上記の要件はあくまでも一例です。組織・プロジェクトなどによっては必要な場合も当然あり得ますので、個別に判断してください。**
google図形描画をQiitaに埋め込むテスト

http://www.appsupport.jp/docs/embed/
imgタグとして取得できます。
# 作成した図形描画で、ファイル→Webに公開
![image.png](https://qiita-image-store.s3.amazonaws.com/0/69733/9f54bc14-5aab-aaa6-d6ed-3e94802f98a2.png)

# 埋め込むサイズを選んで公開
![image.png](https://qiita-image-store.s3.amazonaws.com/0/69733/92a03a2c-33a2-6346-d11b-735b14193630.png)

# 出てきたimgタグを好きな所に貼り付ける！

ジャン！
<img src="https://docs.google.com/drawings/d/e/2PACX-1vS7XvlNGq1aHBPdfvDK2jgyLsN2DRQTiXm0ffZwhUJjtAY_p1dNzmdcKswaPf9fUmqfvR0BxNSnwgDe/pub?w=1036&amp;h=464">

できました！
画像編集ソフトいらないし、バージョン管理も出来るし、サクッと図を作って公開したい時によさげ！
Elasticsearch 5系 + Kibana 5系　をセットアップする（Windows 7）

# 背景
- Windows 7 でElasticsearch (ES)とKibanaを使ってみたいけど、
    - ESの設定方法が記載された情報のバージョンが古い
    - 情報がLinux OSベースのものが多い
    - 最新のセットアップ方法が基本的に英語

#ElasticsearchとKibanaをWin 7でセットアップ
#### 必要なもの
  - OS: Windows 7 (私の場合は64bit）
  - Java:1.8.0_141
  - Elasticsearch: 5.5.1 (2017/7/25 最新版リリース）
  - Kibana: 5.5.1 (2017/7/25 最新版リリース）

### ダウンロード
#### Java: [ダウンロード](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
  1. "Accept License Agreement" をクリックする。しないと、ダウンロードできない
  2. 32bitまたは64bitに応じてダウンロードするexeツールを決める
      - 32bit:jdk-8u144-windows-i586.exe
      - 64bit:jdk-8u144-windows-x64.exe
      
#### Elasticsearch: [ダウンロード] (http's: //www.elastic.co/downloads/elasticsearch)
  1. ZIPファイルをダウンロードする（ファイル名：elasticsearch-5.5.1.zip)

#### Kibana: [ダウンロード](https://www.elastic.co/downloads/kibana)
  1. ZIPファイルをダウンロードする（ファイル名：kibana-5.5.1-windows-x86.zip）  

#### nssm: [ダウンロード](https://nssm.cc/download)  
※Kibanaを自動起動するために必要
    1. Latest release のnssm 2.24をダウンロードする 
   
  (※)Elasticsearch, Kibana, nssm を管理しやすいよう、解凍後、任意のフォルダにまとめて入れる。（例：srvフォルダ下にElasticsearch, Kibana, nssmのフォルダが入っている状態）

### 設定
#### Javaを使用するために、環境変数を設定する
   1. [スタート]→[コンピュータ]（右クリック）→[プロパティ]を開く
   2. [システムの詳細設定]を開く
   3. ユーザの環境変数にて、変数:_JAVA_OPTIONS, 値:-Xmx512M -Xms256M を追加する
   4. システム環境変数にて、以下2つを追加する
      + 変数:JAVA_HOME 値:C:\Javaフォルダのあるところ\Java\jdk1.8.0_141
      + 変数:PATH 値：%JAVA_HOME%\bin

#### Elasticsearchを設定する  
PC起動時に自動的にESが立ち上がるよう設定
   1. コマンドプロンプトを開き, elasticsearch\binフォルダに移動する  
      ```cd C:\srv\elasticsearch-5.5.1\bin```
   2. Elasticsearch service をインストールする  
       ```elasticsearch-service.bat install```
   3. PC起動時にESが自動的に立ち上がるようES managerを開き、カスタマイズする  
       ```elasticsearch-service.bat manager```
   4. ES managerに対し、以下の設定を行い、okで閉じる
      - [Gerneral]→Startup type: Automatic (自動起動設定）
   5. Elasticsearchを起動する  
       ```elasticsearch-service.bat start```

#### Kibanaを設定する  
PC起動時に自動的にKibanaが立ち上がるようにする。Kibanaはelasticsearchのように自動起動可能なサービスを持たないため、nssmを使用する。
   1. コマンドプロンプトからnssm-2.24/win64（またはwin32）フォルダに移動する  
      ```cd C:*\nssm\bin```
   2. ```nssm install kibana``` を入力し、nssm service installerを開く
   3. nssm service installer にて下記を設定
       - [Application]→Path:C:\Kibanaが格納されているフォルダ\Kibana\bin\Kibana.bat
       - [Application]→Startup directory:C:\Kibanaが格納されているフォルダ\Kibana\bin
       - [Details]→Startup type:Automatic
       - [Dependencies]→elasticsearch-service-x64（win32の場合は、elasticsearch-service-x86)
   4. ```nssm start kibana```でKibanaを起動 

### 動作確認
#### Elasticsearch  
   ブラウザのアドレスバーに```localhost:9200```と入力し、下記のような画面が出ればESが起動していることが分かる
![es.png](https://qiita-image-store.s3.amazonaws.com/0/89402/1df1e6c6-9ce8-6009-fe00-48f97244bfbd.png)

#### Kibana   
   ブラウザのアドレスバーに```localhost:5601```と入力し、おしゃれな画面が出れば起動している
![kibana.png](https://qiita-image-store.s3.amazonaws.com/0/89402/fd5d1458-1859-bd9a-8a7d-fb785798b184.png)
Karabiner-Elementsで特定アプリ以外のキーマップを変更する

# 環境
- MacBook Pro 2016 日本語キーボード
- USB日本語キーボード
- macOS バージョン10.12.5
- Karabiner-Elements バージョン0.91.10

# 前置き
Macで本格的に開発を行うようになって数ヶ月。
当初、外付けキーボードを使っているとCommandキーの位置が微妙だなぁと感じていたんですけど、やはり郷に入れば郷に従え？ということで、「慣れる方がいいのでは」と思ってました。

ところが茶軸のキーボードを使っているのでCommandキーに割り当てられたWindowsキーが重い。ひところ話題になった「スマホ指」みたいに「Command指」になってしまうのではないかという懸念が拭いきれなかった（そこまで大げさではないが痛い)ので、やっぱキーバインドするしかないな、となりました。

変換/無変換を日本語入力切替のためにいれていた Karabiner-Elements を起動します。

左Controlを左Commandに設定して…
よし完了！

いやダメじゃん。
ターミナルアプリはiTerm2を使っていたんですけど、ControlがCommandになってしまったので、いままでのキー配置で使えない。それどころかWindowsキーがCommandなので、これで1日中開発していたらより激しいCommand指になってしまう。
これは困る。

仕方がないのでiTerm2の方のキーマップでCommandキーをControlキーに変更。
「入れ替えたものをまた入れ替えるって、なにをやってるんだ」という気持ちになりましたが仕方がない。

よし完了！

いやダメじゃん。
CommandキーがControlキーになっているのでCommand＋Tabのアプリ切り替えが出来ない。

うーん。どうしましょう。

そうだ。
iTerm2以外のアプリは変更する。iTerm2は変更しない。
これだ。

frontmost_application_unless を使おう！
ということで設定です。

# 設定
1．設定ファイルを作成する

$ vim ~/.config/karabiner/assets/complex_modifications/iterm.json

ファイル名はなんでもかまいません。わかりやすいものをつけてください。

２．以下の内容を記述し、保存。

frontmost_application_unless は今回の目的であるiTerm2を指定しています。

```iterm.json
{
    "title": "iTerm settings",
    "rules": [
        {
            "description": "left_control to left_command(without iTerm)",
            "manipulators": [
                {
                    "type": "basic",
                    "from": {
                        "key_code": "left_control",
                        "modifiers": {
                            "optional": [
                                "any"
                            ]
                        }
                    },
                    "to": [
                        {
                            "key_code": "left_command"
                        }
                    ],
                    "conditions": [
                        {
                            "type": "frontmost_application_unless",
                            "bundle_identifiers": [
                                "^com\\.googlecode\\.iterm2"
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}
```

3．Karabiner-Elementsを起動し、Complex Modifications タブをクリック

4．Add rule をクリック

5．iTerm settings - left_control to left_command(without iTerm) の Enable をクリック

よし完了！（今度こそ）

私はMacBookのキーは変更して欲しくないので Devices で Apple Internal Keybord/Trackpad のチェックは外しています。ここは好みで。
私が本当に使っているMacからSSH接続する際の設定一覧

# はじめに

- 弊社はサービス数やトラフィックの関係から数百台のサーバが日夜働いてます。
- 業務する上でも常に数十台のサーバへの接続が必要なため、それらを直接入力するのは時間の無駄です。
- Windowsでは、色々便利なツールはありますがMacの場合は、以外に他のツール入れるよりデフォルトコンソールが一番便利だったします。（個人的感覚）
- また、通常の接続のほかにも踏み台を経由したりDBや検索エンジンなどにポートフォワードかけて接続する場面もあるので、その辺の情報を使いまわせるようにまとめておきます。

## 前提

- Mac環境の場合です。Windowsは便利なツールたくさんあるので不要かとおもいます。
- 公開鍵認証の設定をしているものとします。
- 補完とかが便利なのでhostsの設定を事前にしておきましょう。

### hostsの設定

```text:/etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost

{対象サーバのIP} {対象サーバのホスト名}    
```

## 基本設定

### タイムアウトしないようにする

```text:~/.ssh/config
# 5秒おきに応答確認をします。
ServerAliveInterval 5
```
### KeepAliveを有効にする
```text:~/.ssh/config
TCPKeepAlive yes
```

### 接続する時にオプションで警告出さないようにする

```text:~/.ssh/config
# 踏み台する際とかにこの警告がでて先に進まない場合とかを防ぐため。
Host *
    StrictHostKeyChecking no
```

## 対象サーバへ接続する

### イメージ

![1.png](https://qiita-image-store.s3.amazonaws.com/0/90598/a6bb2f35-720c-59fb-bc61-3649a98ff697.png)

### 設定内容

```text:~/.ssh/config
Host {対象サーバの名称}
  HostName     {IPアドレス or サーバホスト名}
  Port         {ポート番号}
  User         {接続するユーザ名}
  IdentityFile {秘密鍵の置き場所}
```

### 補足

- 22番ポートはデフォルトポートなので省略できます。
- コンソールからssh {サーバ名の頭文字}を入力してtabを押すと対象サーバが補完して出てくるはずです。 

## 踏み台サーバを経由して対象サーバへ接続する

### イメージ

![2.png](https://qiita-image-store.s3.amazonaws.com/0/90598/030678b7-5a44-1bfb-dd68-5b0b475c8fa5.png)

### 設定内容

```text:~/.ssh/config
Host {踏み台サーバの名称}
  HostName     {IPアドレス or サーバホスト名}
  Port         {ポート番号}
  User         {接続するユーザ名}
  IdentityFile {秘密鍵の置き場所}
Host {対象サーバの名称}
  HostName     {IPアドレス or サーバホスト名}
  Port         {ポート番号}
  User         {接続するユーザ名}
  IdentityFile {秘密鍵の置き場所}
  ProxyCommand ssh {踏み台サーバの名称} -W %h:%p
```

## 踏み台サーバを経由して対象サーバへ特定のIPやポートで接続する

### イメージ

![3.png](https://qiita-image-store.s3.amazonaws.com/0/90598/ab73bfe6-c7fc-9e44-1e30-48bcd0af156b.png)

### 設定内容

```text:~/.ssh/config
Host {踏み台サーバの名称}
  HostName     {IPアドレス or サーバホスト名}
  Port         {ポート番号}
  User         {接続するユーザ名}
  IdentityFile {秘密鍵の置き場所}
Host {対象サーバの名称}
  ProxyCommand ssh -C -f -N -L {指定するIPアドレス}:{指定するポート}:{踏み台サーバの名称}:{踏み台サーバのポート} {対象サーバのIPアドレス}@{対象サーバの{IPアドレス or サーバホスト名}
```

### 補足

- DB接続ツールやcURLなどを使って対象サーバに直接繋げないときに使えます。
ReactではPropsにtrueを渡す際は作法がある。

# Reactで`props`に`true`を渡すときに、どう記述するか？

```js
<MyComponent testProps={true} />
```
こういう時にair-bnbのLinterを導入していると、warningが出る。
[これですね](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md)。

このLintに従うと、こうなる。

```javascript
<MyComponent testProps />
```

なぜこれで、`props`に`true`が渡せるのか？

## 答えは公式にあった！！
[公式](https://facebook.github.io/react/docs/jsx-in-depth.html#props-default-to-true)を参照。

どうやら、コンパイルの際にtrueを渡してくれる模様。
さらに、省略形を推奨している。。。と思う。
読み間違っていて逆を言っているかも:joy:

理由としては、ES6のショートハンドと間違うかららしい。
以下のような形で変数`foo`に`true`を代入して渡すような時に、
`{foo: foo}`のショートハンド`{foo}`と紛らわしいという意味だと思われる。
「変数fooを探してtrueを見つけるよりは、最初から省いておいてtrueを渡しているの明示した方が分かりやすい」という意味と解釈しました。

`it can be confused with the ES6 object shorthand {foo} which is short for {foo: foo} rather than {foo: true}`が上手く訳せない・・・

```javascript
class TestComponent extends React.Component{
  render(){
    return(
      <div>
        <h1>{this.props.children}</h1>
        <h2>{`${this.props.aho}`}</h2>
      </div>
    );
  }
}

const foo = true;
ReactDOM.render(
  <TestComponent aho={foo}>hogehoe00000</TestComponent>,
  document.getElementById('b4')
);
```

私もLintがなくても、ここまで意識してコードを書けるようになりたい。
道は長い・・・
Bluemix の Cloudant に PHP で画像ファイルをアップロード

次のページで行うことと同じことを、PHP で行いました。
[Bluemix の Cloudant に python3 で画像ファイルをアップロード](http://qiita.com/ekzemplaro/items/89e831e30c56e0773d2d)
[Bluemix の Cloudant に Node.js で画像ファイルをアップロード](http://qiita.com/ekzemplaro/items/7d93cf75c677b57d428b)

ダウンロードのサンプルは、こちら。
[Bluemix の Cloudant から、 PHP で画像ファイルをダウンロード](http://qiita.com/ekzemplaro/items/9b875a396acdeaed8aae)

```php:to_cloudant.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	to_cloudant.php
//
//					Jul/27/2017
//
// ------------------------------------------------------------------
function curl_put_proc ($url_in,$str_in)
{
	$ch = curl_init();

	curl_setopt ($ch, CURLOPT_URL, $url_in);
	curl_setopt ($ch, CURLOPT_PROXY, "");
	curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');  
	curl_setopt($ch, CURLOPT_POSTFIELDS, $str_in);

	$data = curl_exec($ch);

	curl_close($ch);
}

// ------------------------------------------------------------------
function curl_delete_proc ($url_in)
{
	$ch = curl_init();

	curl_setopt ($ch, CURLOPT_URL, $url_in);
	curl_setopt ($ch, CURLOPT_PROXY, "");
	curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');  

	$data = curl_exec($ch);

	curl_close($ch);
}

// ------------------------------------------------------------------
print	"*** 開始 ***\n";

$url="https://44b508dd-f332-4f91-81f2-78369c7d29d9-bluemix:9dacdf44b508dddc2a5c16596fc371012e08a61e7132d3b21ecaaf1f63a835fae64@efc189dc-f332-4f91-84f2-72169c7d29d9-bluemix.cloudant.com";
#
$url_collection = $url . '/jpg';

curl_delete_proc ($url_collection);
curl_put_proc ($url_collection,'{}');

$keys=["DSCF6158","DSCF6163"];

foreach ($keys as $key)
	{
	print "key = " . $key . "\n";
	$jpg_in = $key . ".jpg";

	$image = file_get_contents ($jpg_in);
	$url_jpg_file = $url_collection . "/" . $key . "/" . $jpg_in;

	curl_put_proc ($url_jpg_file,$image);
	}

print	"*** 終了 ***\n";

// ------------------------------------------------------------------
?>
```
jenkinsで毎時/毎日ジョブを起動する設定


こんにちはsekitakaです。

jenkinsで定期的に実行したいジョブの設定方法です。

基本的にcronの書式で設定できます。しかし毎日実行したいジョブを例に考えて以下の設定をしたとします。

```
0 4 * * *
```

するとジョブは毎日04:00に起動しますが、他のジョブの設定を把握していないと負荷が集中してしまうかもしれません。
時間に無関係で1日1回実施すればよいという要件の場合、`H`を使って以下のように設定して、ジョブの実施時間を分散することができます。

## 指定していないが一定の時分に毎日ジョブを実施

```
H H * * * 
```

## 指定していないが一定の分に毎時ジョブを実施
```
H * * * * 
```

`H`は明確に値を指定しないが、ジョブ名のhashから生成される値のようです。
だから同じジョブではずっと一定した値が使用されるんですね。
ロボアプリ上でのデータ保存（3）

　前回の投稿『[ロボアプリ上でのデータ保存（2）](http://qiita.com/black_pepper/items/33485535175a424b58d9)』では、Pepper上でのファイルの書き込み・読み込みを行いました。しかしながら、ロボアプリをアップデートした場合、ロボアプリ直下に保存したデータはロボアプリを上書きしたタイミングで削除されてしまいます。構成ファイルなどを残したい場合もあると思いますので、バックアップ方法について考えてみたいと思います。

# ロボアプリのアップデート
　データの保持はロボアプリのローカルストレージにすれば良いことがわかりました。しかし、ロボアプリのアップデートが実施されると、ロボアプリの構成ファイルは保存されているフォルダを含めて全て更新されてしまいます。残しておきたいデータがある場合は、バージョンアップが行われたとしてもデータを保持し続ける仕組みが必要です。

# バックアップと復元
　ロボアプリのデータはロボアプリのローカルストレージ以外に保存できませんので、バックアップ手段を考えてみます。
（本作業は技術的には可能ですが、ローカルストレージ以外への保存はソフトバンクロボティクスが公開している『ロボアプリ品質チェックリスト』違反となります。『[ロボアプリ上でのデータ保存（1）](http://qiita.com/black_pepper/items/cee8f20b26ab1e9ab36f)』をご覧ください。）

## 方法１
　毎回手動で保存したいデータを抜き出し、アップデート後に転送して復元する
例：
1. Pepperからデータファイルを外部バックアップ（ファイル転送プロトコル利用）
2. ロボアプリのアップデート
3. ロボアプリが保存されているフォルダへデータをリストア（ファイル転送プロトコル利用）

## 方法２
　ロボアプリアップデート時や任意のタイミングでデータを何らかのクラウド上に転送し、アップデート後にクラウドへ転送されたデータを新しいロボアプリでダウンロードして復元する
例：
1. ロボアプリのアップデート情報を検知し設定データをクラウドへ転送
2. ロボアプリのアップデート
3. クラウド側から設定データをダウンロードし、ロボアプリに適用

## 方法３
　Pepper内部にはクラウドの接続情報のみを記憶し、データは必要に応じてアップロードもしくはダウンロードを行う
例：
1. ロボアプリの起動とともに設定データをダウンロードし適用
2. 終了時に設定データをクラウドに転送

## 比較表

|   |メリット|デメリット|
|:-----:|:----------------------|:----------------------|
|方法１|クラウドの構築が不要|・運用上現実的ではない（利用者が都度バックアップ・リストアを行うため負荷が高い）|
|方法２|・データはロボット側に保存されているため、クラウドとの接続が切断されてもロボアプリを実行させ続けることができる|・バックアップの漏れが出ないよう、タイミングを適切に設定する必要がある<br>・クラウド側のデータが不完全な場合でロボアップデートが実施されるとバックアップされていないデータが失われる可能性がある|
|方法３|・利用者はデータの保存について意識する必要はない<br>・クラウドもしくはロボアプリで更新したデータが即時反映される|・クラウドとの接続が確保できないとアプリが実行できない（システムダウン・NW障害）<br>・利用要求が想定を越えるとアプリのパフォーマンス低下やシステムダウンに繋がる<br>・容量が多いコンテンツがある場合、その都度データの取得が必要になる|

# まとめ
　実際のロボアプリ設計では、方法2、方法3をうまく使い分けると良いでしょう。
OSXのTime Machineのバックアップディレクトリを丸ごと消す

OSXのTime Machineのバックアップディレクトリを丸ごと消す

http://qiita.com/toyoshim/items/f61f8612614d8dbd34e6
こちらでの記事が参考になりますが、以下のように rm -rvf してあげると処理の進行具合が見えて精神的に優しいです(自分比)。

```
sudo /System/Library/Extensions/TMSafetyNet.kext/Contents/Helpers/bypass rm -rvf /Volumes/<Volume Name>/.Trashes/Backups.backupdb
```

まぁ、なるべくやらないに越したこたぁないですが。
fishで偽グローバルエイリアス

# 関数

[この記事](http://qiita.com/tamanugi/items/43bad0158f4a4bb7d1d2)を参考に、以下の関数を定義する。

```fish:B.fish
function B --description 'peco git-branch'
        echo -n ( git branch --all | string sub --start 3 | string replace 'remotes/' '' | peco )
end
```

```fish:C.fish
function C --description 'peco git-commit'
        echo -n ( git log --full-history --date=format:'%Y/%m/%d %H:%M:%S' --pretty=format:'%h [%ad] %an : %s' | peco | awk '{print $1}' )
end
```

```fish:F.fish
function F --description 'peco git-ls-files'
        echo -n ( git ls-files | peco )
end
```

# 使用例

## ブランチを絞り込み

```
% git checkout (B)
% git diff (B) (B)
```

## コミットを絞り込み

```
% git show (C)
% git diff (C) (C)
```

## ファイルを絞り込み

```
% nvim (F)
```
Bluemix の Cloudant から、 PHP で画像ファイルをダウンロード

次のページで行うことと同じことを、PHP で行いました。
[Bluemix の Cloudant から、python3 で画像ファイルをダウンロード](http://qiita.com/ekzemplaro/items/5fcc8643a8a7711bca5b)
[Bluemix の Cloudant から、 Node.js で画像ファイルをダウンロード](http://qiita.com/ekzemplaro/items/9eb1ef05a758f192cc90)


```PHP:from_cloudant.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	from_cloudant.php
//
//					Jul/27/2017
//
// ------------------------------------------------------------------
function curl_get_proc ($url)
{
	$ch = curl_init();
	curl_setopt ($ch, CURLOPT_URL, $url);
	curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt ($ch, CURLOPT_PROXY, "");

	$data = curl_exec($ch);

	curl_close($ch);

	return $data;
}

// ------------------------------------------------------------------
function file_write_proc ($string_out,$file_out)
{
	$fp_out=fopen ($file_out,"w");
	flock ($fp_out,LOCK_EX);
	fputs ($fp_out,$string_out);
	flock ($fp_out,LOCK_UN);
	fclose ($fp_out);

	chmod ($file_out,0666);
}

// ------------------------------------------------------------------
// [6]:
function download_jpg_proc($url_collection,$key)
{
	$file_jpg= $key . ".jpg";

	$url_jpg = $url_collection . "/" . $key . "/" . $file_jpg;

	$image = curl_get_proc ($url_jpg);

	file_write_proc ($image,$file_jpg);
}

// ------------------------------------------------------------------
// [2]:
function list_keys_proc($url_collection)
{
	$url_all_docs = $url_collection . "/_all_docs?include_docs=true";

	$json_string = curl_get_proc ($url_all_docs);

	$list_aa = json_decode ($json_string,true);

	$rows = $list_aa['rows'];

	$keys= array ();
	foreach ($rows as $unit)
		{
		$keys[] = $unit['key'];
		}

	return $keys;
}

// ------------------------------------------------------------------
print	"*** 開始 ***\n";

$url="https://44b508dd-f332-4f91-81f2-78369c7d29d9-bluemix:e44b508dd666c2a5c16596fc371012e08a61e7132d3b21ecaaf1f63a835fae64@efc189dc-f332-4f91-81f2-2969c7d29d9-bluemix.cloudant.com";
#
$url_collection = $url . '/jpg';
print	"url_collection = " .$url_collection . "\n";

$keys = list_keys_proc($url_collection);

foreach ($keys as $key)
	{
	print $key . "\n";
	download_jpg_proc($url_collection,$key);
	}

print	"*** 終了 ***\n";

// ------------------------------------------------------------------
?>
```