OmniAICreator/Qiita-1.07M huggingface dataset:
raspberry piのイメージファイルを小さな容量のメモリーカードにコピーする方法

#Raspberry Piのイメージを圧縮して完全に完全コピーをする方法
コピー元の16GBのメモリーカードを小さな容量のメモリーカードに完全コピーする方法の忘備録です。今回行う作業は、コピー元のメモリカードは16GB、コピー先のメモリーカードは4GBです。4GBのイメージファイルは、ZIP圧縮すると1.5GB程度になるので何とかインターネット上で配布しても大丈夫なサイズになります。

## 準備するモノ
raspberry pi（コピーするメモリーカードとは別に動かす必要があります)
コピー元のイメージファイル
コピー先のSDカードが必要になります。

## gpartedをインストールします。
  $ sudo apt-get update
  $ sudo apt-get install gparted

## コピーの手順
### 1. コピーするメモリーカードをUSBに挿入してください。
### 2. gpartedを起動します。
  sudoを付けないとメモリアクセスするときにパスワードの入力が必要になります。
  $ sudo gparted

　起動するとこのような画面が開きます。 
![1.png](https://qiita-image-store.s3.amazonaws.com/0/136933/105dcc8b-ec15-9404-8fb6-7800ec5e16f8.png)


/dev/mmcblk0はRaspberry Piのメモリカード
/dev/sdaはコピー先のメモリーカード (4GB)
/dev/sdbはコピー元のメモリーカード(16GB)

sdbのイメージファイルを4GBに圧縮し、sdaにコピーするという作業を進めていきます。

### 3.まずはsda, sdbの全ドライブのマウントを外します。
鍵マークがついているディスクは作業することが出来ません。
まずは、右マウスをクリックしてsda, sdbの全ディスクをunmountしてください。

 ![2.png](https://qiita-image-store.s3.amazonaws.com/0/136933/ba67b0d8-9816-bd4e-3bc7-f24309bcf59d.png)

### 4. コピー先のディスクを消去します。
マウスを右クリックして、sda1, sd2を消去します。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/136933/d4aecd3d-f245-8a05-c400-19e511f7cb81.png)

### 5. Apply All Operationsを押すと実行します。
消去すると、下の写真のようにunallocatedという状態になり、コピー先のディスクは何も使用されていない状態になりました。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/136933/c2969f4d-e780-eff5-bba0-fce9c9848963.png)

### 6. ディスク容量を圧縮する
  コピー元のディスクを右クリックし、「Resize/Move」を選択して、ディスクイメージのサイズを小さくしてください。
　限界まで小さくしても大丈夫です。

### 7. コピー元のイメージをコピーし、コピー先に貼り付けます。
　コピー元のディスクイメージを選択して右クリックから「copy」を選択、コピー先に「paste」します。
![5.png](https://qiita-image-store.s3.amazonaws.com/0/136933/319d5da1-1b17-0054-f7be-9ba453e970bb.png)
fat16とext4が二つあるので、二つとも同じようにコピー & ペーストします。

### 8. 最後に、「Apply」ボタンを押すと、コピーを開始します。
　コピーにはしばらく時間が掛かります。
　無事に終了したら完成です。
 これで完全なイメージファイルのコピーが出来ました。
UIScrollViewでtouchesBeganを使えるようにする(キーボートをタッチで閉じる時など)

UIScrollViewでtouchesBeganが使えなかったのでメモ

New File...で新しいファイル(名前は自分で決めてください.swift)を作成し、以下をコピペ

```
import Foundation
import UIKit 

extension UIScrollView {
    public override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.nextResponder()?.touchesBegan(touches, withEvent: event)
    }
}

```
イベントを処理する側に追加

```
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //キーボードを閉じる
        self.view.endEditing(true)
    }

```

参考にしたサイト
http://mzgkworks.hateblo.jp/entry/uitableview-extension
バッチファイルでMongoLabにデータ投入

MongoLab(現mLab)にデータを投入する方法。

## ユーザ名, パスワードを入手
~~~sh:コマンド
$ heroku config | grep "MONGO"

mongodb://<user>:<password>@xxxxxxxx.mlab.com:53765/<dbname>
~~~

## データ投入用バッチファイルを書く
~~~javascript:initdb.js
for(var i=1; i<=3; i++){
  db.user.insert(
    {
      'name' : i + '太郎',
    }
  );
}
~~~

## データ投入

~~~sh:コマンド
$ mongo xxxxxxxx.mlab.com:53765/<dbname> -u <user> -p <password> initdb.js
~~~

※ 時間がかかる。ちょっと待とう。
環境変数$PATHの見難い文字列をリストでキレイに表示するシェルスクリプト

Windows10で、やっと編集しやすくなった環境変数ですけども、
やっぱりターミナルからだと`echo $PATH`なんかは読みにくいし、grepもかけられないし、
ちょこっと調べたいだけなのに人生つらくなります、、

![SnapCrab_NoName_2016-8-17_23-11-20_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/36728/f1879f2a-40d3-b579-87a9-d6ebd424bc1c.png)

そんなときは、こちらのワンライナーで。

```bash
(IFS=: eval 'arr=($PATH)'; for e in "${arr[@]}"; do echo $e; done)
```

![SnapCrab_NoName_2016-8-17_23-14-15_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/36728/6da9c519-b491-edf4-6c8c-687c315e64d5.png)

`()`でIFSの影響をサブシェルに閉じ込めるのをお忘れなきよう。
ちなみにIFSは (Internal Field Separator)の略で、デリミタです。

sortすると、案の定、同じパスが何個も見つかりました汗

```bash
(IFS=: eval 'arr=($PATH)'; for e in "${arr[@]}"; do echo $e; done | sort -f)
```

これで環境変数ダイエット完了。


参考にさせていただきました。
Bashの配列でjoinやsplitする http://qiita.com/kawaz/items/b82da76ac93b32ddc364

# 編集後記

こっちの方が簡単ですよってコメントもらいました。

```bash
echo $PATH | tr ':' '\n'
```

確かに。
AWS EC2（Amazon Linux）でnpm/bcryptを利用したい病気

## 問題
あびゃー＾q＾

```
[ec2-user@ip-172-31-22-228 roomer_web]$ npm i bcrypt

> bcrypt@0.8.7 install /home/ec2-user/roomer_web/node_modules/bcrypt
> node-gyp rebuild

make: ディレクトリ `/home/ec2-user/roomer_web/node_modules/bcrypt/build' に入ります
  CXX(target) Release/obj.target/bcrypt_lib/src/blowfish.o
make: g++: コマンドが見つかりませんでした
make: *** [Release/obj.target/bcrypt_lib/src/blowfish.o] エラー 127
make: ディレクトリ `/home/ec2-user/roomer_web/node_modules/bcrypt/build' から出ます
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/home/ec2-user/.nvm/versions/node/v5.7.0/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:276:23)
gyp ERR! stack     at emitTwo (events.js:100:13)
gyp ERR! stack     at ChildProcess.emit (events.js:185:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Linux 4.1.17-22.30.amzn1.x86_64
gyp ERR! command "/home/ec2-user/.nvm/versions/node/v5.7.0/bin/node" "/home/ec2-user/.nvm/versions/node/v5.7.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /home/ec2-user/roomer_web/node_modules/bcrypt
gyp ERR! node -v v5.7.0
gyp ERR! node-gyp -v v3.2.1
gyp ERR! not ok
（以下略）
```

## 解決方法
nodejsを--enablerepo=epelオプションをつけて再インストール
```
sudo yum install nodejs npm --enablerepo=epel
```
シェル上でMySQLの複数テーブルの内容が全く同じかどうかさっくりチェック

テーブルの移行するときの使用前使用後のチェックとか、本番環境とテスト環境等でデータが一緒かとか見たいときにさっくりできるとカッコイイ！

マスターテーブルのようなレコード数そんな多くなかったり固定データだったりするものは目視でなんとかなっても、掲示板の書き込みテーブルやログのようなもりもり増えていくテーブルだとそうもいかなくなるんですよね。

# mysqldumpを利用

テスト環境と本番環境にある `nullpo_table` とを比較し、
さらにテスト環境にある `nullpo_table_backup` も比較したいとします。

```bash
# テストのnullpo
~$ mysqldump -u{USER} -p {TEST_DATABASE} nullpo_table --compact | md5sum
46092d34d89418259d00215ce55a15f1  -

# 本番のnullpo
~$ mysqldump -u{USER} -p {PROD_DATABASE} nullpo_table --compact | md5sum
46092d34d89418259d00215ce55a15f1  -

# テストのもう一つのnullpo
~$ mysqldump -u{USER} -p {TEST_DATABASE} nullpo_table_backup --compact | sed "s/nullpo_table_backup/nullpo_table/g" | md5sum
46092d34d89418259d00215ce55a15f1  -
```

md5の出力は例です。全く一緒になればおめでとうございます。ハッシュなので１ミリでも内容が違うと全然違う結果になるため違っていたら一目瞭然です。

`--compact` オプションでいろいろ付いてくる設定や日付のような実行するたびに変わりそうな文字列をなくしてdumpした結果をmd5取って比較します。
AUTO_INCREMENT がずれたりする場合は `--no-create-info` を付与してINSERT文のみにしても良いかと。

データベース違いの場合はそのままでOKですが、テーブル名が異なる場合はダンプされるCREATE文やINSERT文についてくるテーブル名の部分が違うため、sedコマンドをかまして置換します。 (テーブルレコードの内容にテーブル名と同一の文字列があると意図しない置換が発生してしまうのでその場合は諦めましょう)

# SELECT文を利用

こちらのほうがテーブル名に左右されないかもしれないし、ユーザ権限もSELECTのみで済むから楽かもしれない。

```bash
~$ echo "SELECT * FROM nullpo_table;" | mysql -u{USER} -p {TEST_DATABASE} | md5sum
7f8298d8d60e705fc31d787ea131f8b1  -

~$ echo "SELECT * FROM nullpo_table;" | mysql -u{USER} -p {PROD_DATABASE} | md5sum
7f8298d8d60e705fc31d787ea131f8b1  -

~$ echo "SELECT * FROM nullpo_table_backup;" | mysql -u{USER} -p {TEST_DATABASE} | md5sum
7f8298d8d60e705fc31d787ea131f8b1  -
```

SELECT文をいじれば特定のカラムだけチェックしたり、もっと複雑なJOIN結果が同じかとかもチェックできそうですね。

# つぶやき

~~なんか最近こういう泥臭い作業多いな・・？~~

こういう小細工レパートリーを普段から増やしていくことがシステム運用上の事故を未然に防ぐ力につながるんです。きっとたぶん。
atomプラグイン開発環境構築(TypeScript, Windows)

## はじめに

WindowsでTypeScriptなatomプラグインを書く環境構築メモ

## 手順

- atomインストール
- atom-typescriptプラグインインストール
- node.jsインストール
- dtsmインストール

## atomインストール

https://atom.io/

から。お察し

## atom-typescriptパッケージインストール

atom>メニュー>Setting View>Install Packages/Themes

からatom-typescriptを検索してインストール

## node.jsインストール

無くてもatom&TypeScriptでプラグイン開発可能だけど、
npmコマンドでインストールしたい機能があったので。

https://github.com/marcelklehr/nodist

からexeを落としてインストールすれば
Windows上でも簡単にnode.jsインストールとバージョン管理環境が用意できる

## dtsmインストール

TypeScriptでは既存JavaScript資産を流用するために型情報を別途設定できるそう(.d.ts)
型情報ファイル管理が大変なので神様が管理ツールを作ってくれた

```
npm install -g dtsm
```

でインストール

## プラグイン開発準備

- atom起動
- メニュー>パッケージ>Package Generator>Generate Atom Packageでひな形用意
- dtsmでTypeScript型情報ファイルを用意
    - コマンドプロンプトを起動
    - パッケージ作成フォルダ(package.jsonがあるフォルダ)へ移動
    - dtsm install atom/atom.d.tsを実行
- libフォルダとかにhoge.tsを置いてプラグイン実装
- 保存するとTypeScriptコンパイルが動いて.jsが吐かれる
- Ctrl+Alt+rでリロードするとプラグインが反映されて動作確認できる





-
Go 1.7 is released.

おっと 1.7 出てたのか。以下ブックマーク。順次追加予定。

- [Go 1.7 is released - The Go Blog](https://blog.golang.org/go1.7)
- [Go 1.7 Release Notes - The Go Programming Language](https://golang.org/doc/go1.7)
- [Go 1.7 is released - Google グループ](https://groups.google.com/forum/#!topic/golang-announce/Xy1ngO9jejU)
- [go1.7 の気になるところを試した - Qiita](http://qiita.com/tutuming/items/16df6fc7bf82fb5d7eb0)

拙ブログ「[プログラミング言語 Go](http://text.baldanders.info/golang/)」もよろしくね（宣伝）。
rbczmq の幾つかのインストール方法

(2019.06.25 追記)
rbczmq は現時点では非推奨です。どのプラットフォームでも [ffi-rzmq](https://github.com/chuckremes/ffi-rzmq) を使いましょう。

----

IRuby を使おうとすると rbczmq の中で SEGV が発生してしまう場合は、zeromq と czmq の組み合わせが悪い可能性がある。rbczmq が正しく動くインストールのパターンを以下に紹介するので、一番好ましいものを試してみると良い。

rbczmq は gem パッケージの中に zeromq と czmq を同梱しているが、後述する事情により同梱ライブラリを使わない方法を先に紹介する。

## (1) homebrew や apt-get でインストールしたシステムの zeromq, czmq を使う

この方法は、ディストリビューションで用意されている zeromq や czmq を確実に使うので、最もオススメしたい方法である。やり方は、まずシステムに zeromq と czmq を **両方とも** インストールする。次に、以下のコマンドで rbczmq をインストールする。

    $ gem install rbczmq -- --with-system-libs

このオプションを指定することで、rbczmq に付属している zeromq と czmq をビルドせず、参照もしなくなる。

正しくインストールできた場合、`otool -L` でライブラリの依存関係を確認すると、きちんとシステムの zeromq, czmq を見ていることがわかる。

```
$ otool -L ~/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rbczmq-1.7.9/lib/rbczmq_ext.bundle | grep zmq
/Users/mrkn/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rbczmq-1.7.9/lib/rbczmq_ext.bundle:
	/opt/brew/opt/czmq/lib/libczmq.3.dylib (compatibility version 4.0.0, current version 4.0.0)
	/opt/brew/opt/zeromq/lib/libzmq.5.dylib (compatibility version 6.0.0, current version 6.1.0)
```

注意していただきたい点は、**zeromq だけシステムにインストールする** と、rbczmq 内で SEGV が発生する可能性があることだ。

私は、次のようなトラブルを経験した。あるとき zeromq だけを brew install した状態で rbczmq がきちんと動いていた。その後、brew update で zeromq のバージョンが上がった際に rbczmq がリンクしていた libzmq が消えたため、gem pristine したところ rbczmq 内で SEGV が発生するようになった。この原因は、システムにインストールされている zeromq と、rbczmq に付属している czmq の間に互換性がなかったことではないかと推測している。

このようなトラブルを経験したが、この方法は、どんな事情の人でも zeromq と czmq の正しい組み合わせをシステムにインストールしておけば rbczmq が確実に動く方法である。

ただし、私は Windows を所持していないので、Windows 環境でこの方法で上手くいくかどうかは確認できていない。

## (2) rbczmq に付属の zeromq と czmq を確実に使う

IRuby 自体を開発している人でない限り、zeromq のバージョンなんてどうでも良いはず。だから、IRuby を安定して使いたいだけなら、rbczmq に付属の zeromq, czmq を使うのが最もトラブルを避けられるはずである。

以下のコマンドで rbczmq をインストールすると、付属の zeromq と czmq をビルドし、それらを参照するためのオプションをコンパイラとリンカに指定してくれる。

    $ gem install rbczmq

しかし、私の環境では rbczmq に付属の zeromq と czmq は使われなかった。この原因は、私が ruby をインストールする際に `--with-opt-dir=$(brew --prefix)` を指定しているからだと推測している。extconf.rb で生成される Makefile を確認すると、rbczmq に付属の zeromq と czmq よりも先に homebrew の中を探しに行くオプションがコンパイラとリンカに指定されていたからだ ([issue にしておいた](https://github.com/methodmissing/rbczmq/issues/60))。

Windows の場合は、[このような問題が起きるらしい](https://github.com/methodmissing/rbczmq/issues/41) (Windows を所有していないので私は確認していない)。

よって、この方法は現在のところ、システムに zeromq と czmq をインストールしない人に限ってお勧めできる方法である。

jupyter が使う pyzmq は、pip install で配布されるビルド済みパッケージの中に zeromq のビルド済みライブラリを同梱していて、システムにインストールされているものは参照しない。そのため、zeromq を jupyter でしか使わない人は、思い切ってシステムに zeromq と czmq をインストールしない、という選択もありだと思う。
AzureのLog Analyticsを使う Part-3

#はじめに
[Part-2](http://qiita.com/tworks55/items/45485bd08ca1affd0d3b)では自分のPC(Windows10)を接続してみましたが、今回は自分のPC上で稼働しているLinux(CentOS7 on VirtualBOX)を接続してみます。

##参考
[Linux コンピューターを Log Analytics に接続する](https://azure.microsoft.com/ja-jp/documentation/articles/log-analytics-linux-agents/)
[Operations Management Suite Agent for Linux Public Preview (2016-07)](https://github.com/Microsoft/OMS-Agent-for-Linux/blob/master/README.md)

##関連ページ
[AzureのLog Analyticsを使う Part-1](http://qiita.com/tworks55/items/e92f2e16921f50001c52)
[AzureのLog Analyticsを使う Part-2](http://qiita.com/tworks55/items/45485bd08ca1affd0d3b)

#1.OMS Agent for Linux のインストール

```
$> wget https://github.com/Microsoft/OMS-Agent-for-Linux/releases/download/v1.1.0-217/omsagent-1.1.0-217.universal.x64.sh
$> sha256sum ./omsagent-1.1.0-217.universal.x64.sh
$> sudo sh ./omsagent-1.1.0-217.universal.x64.sh --upgrade -w <YOUR OMS WORKSPACE ID> -s <YOUR OMS WORKSPACE PRIMARY KEY>
```

で普通にエージェントのインストールと起動までは確認できた。でもOMSポータルを見ててもまったく反応がなかったので、
[https://github.com/Microsoft/OMS-Agent-for-Linux/blob/master/docs/Troubleshooting.md](https://github.com/Microsoft/OMS-Agent-for-Linux/blob/master/docs/Troubleshooting.md)のI'm not seeing any Linux data in the OMS Portalを参照しいくつかチェックしたところ、
`/etc/opt/microsoft/omsagent/conf/omsagent.conf`
は存在し、
`/etc/opt/microsoft/omsagent/conf/omsadmin.conf`
が存在しなかったので、
[OMS-Agent-for-Linux.md - Onboarding using the command line](https://github.com/Microsoft/OMS-Agent-for-Linux/blob/master/docs/OMS-Agent-for-Linux.md#onboarding-using-the-command-line)を参照し、以下のコマンドで再起動しました。

```
$> service omsagent stop
$> cd /opt/microsoft/omsagent/bin
$> sudo ./omsadmin.sh -w <WorkspaceID> -s <Shared Key>
$> service omsagent start
```

#2.OMSの設定
OMSはDATAの所でLinux Performance countersを設定します。すべてのチェックボックスにチェックを付けて「Add the selected performance counters 」をクリックし左上のSaveをクリックします。
![image](https://qiita-image-store.s3.amazonaws.com/0/131481/858dae6b-66d9-a2e6-24f0-86de472cc93b.png)

#3.OMSでログの確認
Linux側の設定が少し悪いのかHost名がlocalhostになっていますが、ひとまずログの収集ができるようになりました。
![image](https://qiita-image-store.s3.amazonaws.com/0/131481/84b0dd03-f257-5a33-938c-13190fa3d95d.png)

という感じで今回は終了です。
Windows上でOpenAI/gymを実行してみる

強化学習を学べるツールキットとして[OpenAI/gym](https://gym.openai.com/docs)が公開されています。
pythonの開発環境さえあれば動き、ATARIのゲームがいくつが同梱されている他、tensorflowなどと相性が良いということで、機械学習の勉強に大変効果がありそうです。

また、ちょうど最近、Windows 10の年に一度の更新、Anniversary Updateが公開され、適用することでなんとbashが動くようになりました。いろんな人が涙したことでしょう。
Ubuntuのネイティブライブラリが動くということで、pythonの開発環境とも相性が良いです。

Windowsのラップトップしか所有していない筆者でも、OpenAIの雰囲気を感じられるチャンスかもしれません。

今回はbash on Windows上でopenAI/gymを動かしてみます。
（べつにVagrantとか使えばいいのですが、新しさがないので今回はbash on Windowsに焦点を当てました）

# bash on Windowsの動作の確認

下記atmarkITさんの記事が参考になります。
[Windows 10のLinux／Ubuntu互換環境でbashを使う](http://www.atmarkit.co.jp/ait/articles/1608/08/news039.html)

基本的には下記の手順を踏みます。

1. WSL機能を有効化する。
2. 開発者モードをOnにする。
3. 起動し、パスワードなどを設定する。

結果、「Bash on Ubuntu on Windows」というアプリへのショートカットがインストールされていれば成功です。

# Bash上にOpenAI/gymをインストール

インストールされたbash on windowsを起動します。
下記コマンドで最初に必要なpipコマンドをインストールします。
```
sudo apt-get install python-pip
```
ちなみに、私の環境ではpython2.7がインストール済みでした。

次に、pipコマンドで必要なライブラリをインストールします。
[OpenAI/gym document] (https://gym.openai.com/docs)
```
sudo pip install gym
```

# Windows側に画面を表示するためのXmingをインストール
bash on Windowsは開発途中で未実装の機能も多く、画面表示に関する部分も含まれます。
[Running Linux desktop apps on the Windows Subsystem for Linux](https://www.slightfuture.com/how-to/x-on-wsl)
OpenAI/gymが学習結果の画面を表示するときにXの画面を使用しますが、bash on Windowsには入っていません。
対策として、昔からXの画面をWindowsで表示するフリーのソフトはいくつも開発されていますから、bashとは別にそれらをインストールすればよいはずです。

筆者は下記Xmingを使いました。
[フリーのWindows用Xサーバー「Xming」のインストールと基本設定、使い方](https://osdn.jp/magazine/09/10/14/0753240)

次に、bash on Windowsで画面をXmingに飛ばす設定をします。
```
export DISPLAY=:0
```

上記で設定が完了します。
完了できたか確認するには、bash上でX画面を使用するシンプルなアプリxeyesを実行して、その画面がXmingで表示されるかを確認すればいいです。

```
sudo apt-get install x11-apps
xeyes&
```
下記のように新しいウィンドウが作成され画面が表示されます。
![2016-08-17 (2).png](https://qiita-image-store.s3.amazonaws.com/0/96277/7a9effb0-ca0a-a7bd-2358-241faf53c177.png)

# 簡単なOpenAI/gymサンプルを実行

今回は上記ドキュメントの一番簡単なenvironmentであるcartpole-v0を実行します。
一直線上を動くカートの上にグラグラ傾くポールが乗っていて、カートを前後させて倒立させるというシミュレーションアプリです。
bash上で下記のソースコードをcartpole.pyという名前で保存します。
(エディタはviなど何を使っても構いません）

```cartpole.py
import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample())
```

bash上でソースコードを実行してみます。
```
python cartpole.py
```

結果、このような画面がWindows上に出てきます。

![2016-08-17 (5).png](https://qiita-image-store.s3.amazonaws.com/0/96277/79596256-1891-2445-7b95-97fde189bd01.png)

# まとめ

まずcartpoleを実行し、OpenAI/gymがWindows上で動くことを確認しました。gymには幾つかいろんなアプリが入っているようなので、今後試してみたいと思います。
Arch Linux, Kernel-4.7.0, gcc-6.1.1 で VMware Workstation 12.1.1 を動かす

#Arch Linux, Kernel-4.7.0, gcc-6.1.1 で vmware Workstation 12.1.1 を動かす
はい、**VMware workstation**, **VMware player** を使っているとLinux のカーネルやGCCのバージョンが上がるたびにモジュールを書き換えるのが恒例行事となっています。

vmware の中の人も充分知っていると思うのですが…。

ググってみましたのですが、情報がまとまっていなかったり、日本語や英語じゃなかったりしたので、ちょっとまとめてみました。

手順が正しいかどうかわかりませんが、私が行った方法をご紹介します。
暇なチャレンジャーの方は追試してみてください。

##よくわからんので、VMware Workstation 12 Pro for Linux 64-bit を再インストールしてみました
オフィシャルサイトからダウンロードしてきて、rootユーザで

```bash
chmod 755 VMware-Workstation-Full-12.1.1-3770994.x86_64.bundle
./VMware-Workstation-Full-12.1.1-3770994.x86_64.bundle
```
##いつものモジュール改造
また、rootになって、

```bash
cd /usr/lib/vmware/modules/source
tar -xf vmnet.tar
tar -xf vmmon.tar
```
diffってみました。

```diff:hostif.patch
--- vmmon-only.old/linux/hostif.c       2016-08-17 23:27:30.139042733 +0900
+++ vmmon-only/linux/hostif.c   2016-08-17 23:28:28.465314240 +0900
@@ -1162,7 +1162,7 @@
    int retval;
 
    down_read(&current->mm->mmap_sem);
-   retval = get_user_pages(current, current->mm, (unsigned long)uvAddr,
+   retval = get_user_pages_remote(current, current->mm, (unsigned long)uvAddr,
                            numPages, 0, 0, ppages, NULL);
    up_read(&current->mm->mmap_sem);
```

```diff:userif.patch
--- vmnet-only.old/userif.c     2016-08-17 23:27:39.698973927 +0900
+++ vmnet-only/userif.c 2016-08-17 23:29:23.404983594 +0900
@@ -113,7 +113,7 @@
    int retval;
 
    down_read(&current->mm->mmap_sem);
-   retval = get_user_pages(current, current->mm, addr,
+   retval = get_user_pages_remote(current, current->mm, addr,
                           1, 1, 0, &page, NULL);
    up_read(&current->mm->mmap_sem);
```

```diff:netif.patch
--- vmnet-only.old/netif.c      2016-08-17 23:27:39.698973927 +0900
+++ vmnet-only/netif.c  2016-08-17 23:32:02.714141615 +0900
@@ -465,7 +465,7 @@
    VNetSend(&netIf->port.jack, skb);
 
    netIf->stats.tx_packets++;
-   dev->trans_start = jiffies;                                                                                   
+   netif_trans_update(dev);                                                                                      
 
    return 0;
 }
```

```bash
vi vmnet-only/userif.c
vi vmnet-only/netif.c
vi vmmon-only/linux/hostif.c
tar -cf vmnet.tar vmnet-only
tar -cf vmmon.tar vmmon-only
```

上記を実行して、tarを作り直します。

##VMware Workstation を起動
無事GUIで起動できました。

```bash
vmware-modconfig --console --install-all
```
でモジュールを作り直してもいいかもしれません。

毎回こういうことやるのもやんなっちゃうので、
**VirtualBox**にすることも考えたのですが、
ディスクアクセスがどうやらVMwareの方が速いみたいで…。
Androidの広告IDを取得する

# 広告IDとは

androidには端末毎に広告IDというものがあって
google設定アプリ > 広告 から見ることが出来る。

![screenshot-160817214621.png](https://qiita-image-store.s3.amazonaws.com/0/22527/28ecb3b0-b14a-a847-27cf-4383b1f66575.png)


[公式ドキュメント](https://support.google.com/googleplay/android-developer/answer/6048248?hl=ja)

このIDをトラッキングしてユーザに適した広告を配信しているようだ。
トラッキングされるのが嫌な人はオプトアウトをする事も出来るが、
結局アプリからIDは見えてしまうのでアプリを信じるしか無さそう。

# 取得方法

gradleでplay-services-analyticsをimport

```groovy
compile 'com.google.android.gms:play-services-analytics:x.y.z'
```

`AdvertisingIdClient.getAdvertisingIdInfo(context)`はメインスレッドでは取得出来ないので、別スレッドを指定する必要がある。
ここはRx様々:pray:

```kotlin
Observable.fromCallable { AdvertisingIdClient.getAdvertisingIdInfo(context).id }
            .subscribeOn(Schedulers.computation())
            .subscribe({
               it.id // 広告ID
               it.isLimitAdTrackingEnabled // optoutの設定
            }, {
                // error
            })
```
JavaScriptオブジェクトの仕様


##オブジェクトを生成する
・javascriptはjavaやC++のように、クラス定義をせず、オブジェクトを作ることができる

・javascriptにおけるコンストラクタ関数の例を以下に示す。

```
var Person = function(living, age, gender){
 this.living = living;
 this.age = age;
 this.gender = gender;
 this.getGender = function(){
  return this.gender;
 };
};

//インスタンスの生成
var cody = new Person(true, 33, 'male');
var lisa = new Person(true, 34, 'female');

```
new演算子を伴って呼ばれた場合、オブジェクトが生成される。オブジェクトの特徴を次の項目で確認していく。


＊ちなみにコンストラクタ関数に使用する関数の名前は、通常の関数との混同を避けるために最初の文字を大文字にする。


##オブジェクト　≠　プリミティブ
プリミティブとオブジェクトは違う。プリミティブ型は「そのデータ型の定義の中に部分として他の型を含まないような型」という定義である。　null, undefined, 'string',10,ture,falseはプリミティブ型である。以下の例をみると、オブジェクトとプリミティブの違いがわかる。

```
var a = 10;
var b = new Number('10');

console.log(a); //出力 : 10
console.log(b); //出力 : Number { 10 }
console.log(a === b); //出力 : false

/*JavaScriptではいつでもオブジェクトにプロパティやメソッドを追加することができる（ただしオブジェクトに限る）これを動的プロパティという*/
a.key = 20; //プリミティブ型は新しく値を格納することができない
b.key = 20; //オブジェクトは新しい値を格納することができる

console.log(a); //出力 : 10
console.log(b); //出力 : Number { 10, key: 20 }

```
また、新たにプロパティを追加しているのが確認できたと思うが、JavaScriptのオブジェクトのプロパティは可変（ミュータブル）である。これが、JavaScriptの強みなのではないか。

##オブジェクトのコピーは参照
オブジェクトは参照によって保存される。以下のコードを

```
var objA = {a : 'A'};
var objB = objA;
var objC = {a : 'C'};

console.log(objA === objB); //出力 : true
console.log(objA === objC); //出力 : false オブジェクトは同値判定に参照を使用するため中身が同じオブジェクト同士でも同値とみなされない

objA.b = 'B'
console.log(objB); //出力 : Object { a: "A", b: "B" }
console.log(objA === objB); //出力 : true


var objD = objB;

console.log(objA,objB,objD); //出力 : Object { a: "A", b: "B" } Object { a: "A", b: "B" } Object { a: "A", b: "B" }

objA.a = 'B'; // 出力 :
console.log(objA,objB,objD); //出力 : Object { a: "B", b: "B" } Object { a: "A", b: "B" } Object { a: "A", b: "B" }

```
・プリミティブ型の変数には、値が格納される。プリミティブ型の変数がコピーされると、文字通り変数が複製されるが、オブジェクトを格納する変数には、実際にはオブジェクトへの参照が格納される。したがってこれがコピーされると、変数の値自体ではなく、参照がコピーされる。
・プリミティブ型の変数を同値比較（===）する場合は、それらの値が同じであれば同値とみなされるが、オブジェクトを同値比較する場合は、同じ参照値を持っている場合のみに同値とみなされる。つまり、同じオブジェクトを参照している場合のみに同値とみなされる。

##リファレンス
開眼！JavaScript(第１章) (https://www.oreilly.co.jp/books/9784873116211/)
SICP読書女子会#19 2.2.2


[オンラインSICP読書女子会 #19 (2.2.2(2)) - connpass](http://ladiespp.connpass.com/event/37846/)
[SICP/2.2.2.scm at master · cocodrips/SICP](https://github.com/cocodrips/SICP/blob/master/2.1/2.2.2.scm)

## Ex 2.26
```lisp
(display "==========Ex 2.26===========")
(newline)

(define x (list 1 2 3))
(define y (list 4 5 6))

(display (append x y)) (newline)    ;(1 2 3 4 5 6)      引数がlist
(display (cons x y)) (newline)      ;((1 2 3) 4 5 6)    引数なんでもいい
(display (list x y)) (newline)      ;((1 2 3) (4 5 6))　 引数なんでもいい
```

## Ex 2.27

```lisp
(display "==========Ex 2.27===========")
(newline)
(define x (list 1 2))
(define y (list 3 4))
(define xylist (list x y))

(display xylist)
(newline)

(define (deep-reverse items)
    (define (itr src dist)
        (display src)
        (display "|")
        (display dist)
        (newline)
        (cond 
            ((null? src) dist)
            ((list? (car src)) (itr (cdr src) (cons (deep-reverse (car src)) dist)))
        (else   
            (itr (cdr src) (cons (car src) dist)))))
    (itr items (list)))

(display (deep-reverse xylist))
(newline)
```


## Ex 2.28

```lisp
(display "==========Ex 2.28===========")
(newline)

(define (fringe items)
    (define (itr src dist)
        (display src)
        (display "|")
        (display dist)
        (newline)
        (cond 
            ((null? src) dist)
            ((list? (car src)) 
                (itr (cdr src) (itr (car src) dist)))
        (else
            (itr (cdr src) (cons (car src) dist)))))
    (reverse (itr items (list))))

(define x (list (list 1 2) (list 3 4)))
(display (fringe x))
(newline)

(display (fringe (list x x)))
(newline)
```

## Ex 2.29

```lisp

(display "==========Ex 2.29===========")
(newline)

; 二枝モビール
; a.
(define (make-mobile left right)
    (list left right))

(define (left-branch mobile)
    (car mobile))

(define (right-branch mobile)
    (car (cdr mobile)))

(display "a.")
(newline)

(define m (make-mobile 1 2))
(display "Base:")
(display m)
(newline)

(display "left: ")
(display (left-branch m))
(newline)

(display "right: ")
(display (right-branch m))
(newline)
;a.
;Base:(1 2)
;left: 1
;right: 2


; b.
(display "b.")
(newline)

(define m (make-mobile 1 2))
(define (total-weight mobile)
    (if (list? mobile)
        (+ (total-weight (left-branch mobile)) (total-weight (right-branch mobile)))
        mobile))

(define m (make-mobile (make-mobile 3 5) 2))
(display "Base:")
(display m)
(newline)
(display "Weight:")
(display (total-weight m))
(newline)

;b.
;Base:((3 5) 2)
;Weight:10

(display "c.")
(newline)

(define (balance? mobile)
    (= (total-weight (left-branch mobile)) (total-weight (right-branch mobile))))

(display m)
(display ":")
(display (balance? m)) 
(newline)

(define m (make-mobile (make-mobile 3 5) (make-mobile 2 6)))
(display m)
(display ":")
(display (balance? m)) 
(newline)
;c.
;((3 5) 2):#f
;((3 5) (2 6)):#t


(display "d.")
(newline)

(define (make-mobile left right) (cons left right))
(define (make-branch length structure)
    (cons length structure))

(define m (make-mobile 1 (make-mobile 2 3)))
(display m)
(newline)

; make-branchがよくわからない

```
Cloudera Managerで新規ホストを追加する

Cloudera Manager(以下CM)でのホスト(CMにおけるサーバやインスタンスのこと)を紹介する。


# 環境
- Cloudera Manager 5.8


# 手順

**ホスト** → **クラスタへの新しいホストの追加** をクリックする。

![CM58 ホスト画面.png](https://qiita-image-store.s3.amazonaws.com/0/17749/08df320f-3f8b-2bd3-72a1-f8f873e09609.png)


もし Cloudera Director で環境構築していたらこの操作はせず、Director 側で追加を行う。そうでなければ **従来のウィザード** をクリックする。

![CM58 ホスト追加ウィザード00 EC2のクラスタの管理.png](https://qiita-image-store.s3.amazonaws.com/0/17749/f075fa57-4e68-4f6c-3f3a-5de6a0e7c28d.png)


**続行**をクリック。

![CM58 ホスト追加ウィザード01 スタート画面.png](https://qiita-image-store.s3.amazonaws.com/0/17749/3127074f-d0b3-30da-9c2d-109aab733054.png)


ホストのIPアドレスあるいはホスト名を入力し、追加対象のホストを指定する。

![CM58 ホスト追加ウィザード02-1 CDHクラスタインストールのホスト指定.png](https://qiita-image-store.s3.amazonaws.com/0/17749/53d3b89d-a4d7-5b79-444f-46148991a293.png)


ネットワークが疎通していればホストが表示される。追加対象のホストを選択して**続行**をクリック。

![CM58 ホスト追加ウィザード02-2 CDHクラスタインストールのホスト指定(ホスト表示後).png](https://qiita-image-store.s3.amazonaws.com/0/17749/12f7ebd6-8373-00d9-a59a-793dcbf3b435.png)


**続行**をクリック。

![CM58 ホスト追加ウィザード03 リポジトリの選択.png](https://qiita-image-store.s3.amazonaws.com/0/17749/69a33862-30cd-d659-2ab0-d3934ae3edd2.png)


JDKをインストールする場合はチェックして**続行**をクリック。

![CM58 ホスト追加ウィザード04 JDKインストールオプション.png](https://qiita-image-store.s3.amazonaws.com/0/17749/08e193e9-1cee-f312-5918-07ca1acba444.png)


追加対象ホストのrootアカウントもしくはsudo権限を持つユーザのパスワードあるいは秘密鍵を登録して、**続行**をクリック。すぐにインストールが始まる。

![CM58 ホスト追加ウィザード05 SSHログインの資格情報.png](https://qiita-image-store.s3.amazonaws.com/0/17749/8f9c4729-7ab4-3007-c030-1ee160ed887b.png)

インストールはしばらく時間がかかる。

![CM58 ホスト追加ウィザード06-1 インストール中.png](https://qiita-image-store.s3.amazonaws.com/0/17749/1195a5ea-1056-cc26-13f0-993a59ffa6d1.png)

インストールが完了したら**続行**をクリック。

![CM58 ホスト追加ウィザード06-2 インストール完了.png](https://qiita-image-store.s3.amazonaws.com/0/17749/c92708f7-2c4e-defd-fedd-1e184adcad35.png)

Parcelのインストールが始まる。終わったら**続行**をクリック。

![CM58 ホスト追加ウィザード07-1 Parcelのインストール.png](https://qiita-image-store.s3.amazonaws.com/0/17749/a64b0943-3816-6136-52dc-0d045ca277cb.png)

ホストインスペクタが実行され、ホストの状態をチェックする。問題なければ**続行**をクリック。

![CM58 ホスト追加ウィザード08 ホストインスペクタ.png](https://qiita-image-store.s3.amazonaws.com/0/17749/2103d732-6698-ba8d-50ee-7cf2d94f952f.png)

ホストテンプレートを選択する。ホストテンプレートとは、新規にホストを追加する際に割り当てるためのロールのセットで、たとえば「ワーカーノード用」「クライアントマシン用」などに分けて作成しておくと便利。
ホストテンプレートがない場合はその場作成することができる。

![CM58 ホストテンプレートの作成.png](https://qiita-image-store.s3.amazonaws.com/0/17749/1262e731-9a59-ee32-987c-86b9e074b564.png)

選択したら**続行**をクリック。

![CM58 ホスト追加ウィザード09 ホストテンプレートの選択.png](https://qiita-image-store.s3.amazonaws.com/0/17749/5cb99bae-f617-821c-8570-d562205775fa.png)


ホスト上のロールが開始される。終わったら**続行**をクリック。

![CM58 ホスト追加ウィザード10 ホスト上のロールの開始.png](https://qiita-image-store.s3.amazonaws.com/0/17749/8fd68d61-5252-90cb-4343-65cab20d0259.png)

最後にクライアント設定を展開する。終わったら**完了**をクリック。

![CM58 ホスト追加ウィザード11 クライアント設定の展開.png](https://qiita-image-store.s3.amazonaws.com/0/17749/e7e1ff62-1bfd-e1bc-47aa-72deee7b7c66.png)

これで新規ホストの追加が完了した。
winserを使用してnode.jsアプリをWindowsサービスに登録・実行する


# winserを使用してnode.jsアプリをWindowsサービスに登録・実行する

`koa` で作成したWebアプリをWindowsサービスとして実行したかったので `winser` というモジュールを使用してみました。


## 概要

* [winser](https://github.com/jfromaniello/winser) を使用すると、node.jsのアプリを *Windows Service* に登録できる
* winserは [NSSM](http://nssm.cc/) をラッピングしている
* *npm script* にインストール・アンインストールのコマンドを登録する
* `package.json` の `name` がサービス名として使用される
* インストール後はWindowsの *SC* コマンドを使用してサービスを起動・停止する
* 登録したサービスを実行すると `npm start` に登録した内容が実行される


## 詳細

### 1. winserのインストール

普通に `npm install winser` でOK。

### 2. package.jsonの修正

1. `name` をWindowsサービスに登録したい名前にする
2. `npm start` でアプリが実行されるように修正する
3. `npm run install-service` で *winser* を使用してサービスをインストールするよう修正する
4. `npm run uninstall-service` で *winser* を使用してサービスをアンインストールするよう修正する

```json
{
  "name": "hoge-service",
  "version": "1.0.0",
  "description": "Hogehoge Front-End Service",
  "main": "app.js",
  "scripts": {
    "start": "node.exe app.js",
    "test": "gulp",
    "install-service": "winser -i -a",
    "uninstall-service": "winser -r -x"
  },
  :
}
```

各オプションの意味は、以下のとおり。

* `-i` : サービスのインストール
* `-a` : サービス登録後に自動的に実行する
* `-r` : サービスの削除
* `-x` : サービス削除前に停止する

winser の README にあるように、 *postinstall* にインストールコマンドを指定すれば、 `npm install` 完了後に続けてサービス登録するようにできますが、今回は本番環境でのみサービス登録したかったので、明示的にコマンドを叩くようにしました。


### 3. サービス登録

*2. package.jsonの修正* で登録した `install-service` を実行してインストールを行います。

実際にサービス実行されるとき、 `npm start` の内容が実行されます。
*Local System* の権限で動くので、システム環境変数で `node.exe` に `PATH` が通るように設定しておく必要があります。

* コマンドプロンプトを *管理者として実行* します。
* `npm run install-service` でインストールが実行されます。

```
C:\App\workspace\web-app>npm run install-service

> hoge-service@1.0.0 install-service C:\App\workspace\web-app
> winser -i -a

Use start command "node.exe app.js".
The program "hoge-service" was installed as a service.
The service for "hoge-service" was started.
```


### 4. サービス削除

* コマンドプロンプトを *管理者として実行* します。
* `npm run uninstall-service` でインストールが実行されます。

```
C:\App\workspace\web-app>npm run uninstall-service

> hoge-service@1.0.0 uninstall-service C:\App\workspace\web-app
> winser -r -x

The service for "hoge-service" was removed.
```


------

## 参考

* [WinserでNode.jsのサーバーをサービス化してみる](http://sourcechord.hatenablog.com/entry/2015/05/21/011501)
Server MAN VPS CentOS6.5 SIPp3.6 で WAV音源 を RTP Stream に流してみた②　＊SIPpシナリオ作成＊


[『Server MAN VPS CentOS6.5 SIPp3.6 で WAV音源 を RTP Stream に流してみた①　＊環境構築編＊』](http://qiita.com/aoken/items/247e4ec9a20bf0aefaf5)
こちらの記事の続きです。

##■目的
SIPpで用意したwav音源をRTPで送信すること ※DTMF入力
　◇[Server MAN VPS CentOS6.5 SIPp3.6 で WAV音源 を RTP Stream に流してみた①　＊環境構築編＊](http://qiita.com/aoken/items/247e4ec9a20bf0aefaf5)
　◆[Server MAN VPS CentOS6.5 SIPp3.6 で WAV音源 を RTP Stream に流してみた②　＊SIPpシナリオ作成＊]
(http://qiita.com/aoken/items/897419cfa1560a0c813b)

##■環境構成
- DTI ServersMan@VPS Entry プラン 月額467円（税抜）
- CentOS release 6.5 (Final)
- SIPp v3.6-dev-88-g04c3874-TLS-PCAP-RTPSTREAM built Aug 16 2016, 19:24:25.

# ★上記の環境構築は①で済んでいるので、SIPpシナリオ作成し、WAV音源をRTP Streamに載せて送信できるところまでをメモ★

## ■作業の流れ

① SIPpデフォルトシナリオとして uac が存在するので、任意のディレクトリにエクスポート
② WAV音源の準備（※今回は、Codec：g711 ulaw）
③ エクスポートしたuac.xmlシナリオにrtp_streamを追加
④ tcpdumpコマンドで RTP/SIPキャプチャ、SIPp実行スクリーン上でのRTP Packet 送信の確認

## ■実際の作業内容

① SIPpデフォルトシナリオとして uac が存在するので、任意のディレクトリにエクスポート
　`sipp -sd uac > uac.xml`
　※今回は、着側からRTPを送信しないので　uas はエクスポートしない。

***
② WAV音源の準備（※今回は、Codec：g711 ulaw）
こちらからいただきました。
SPECIAL THANKS‼
[Voxeo's Global Developer and Support Portal](https://evolution.voxeo.com/library/audio/prompts/dtmf/index.jsp)

soxiコマンドでコーデック確認します。
G711 u-lawであることが確認できます。

***
>\# soxi dtmf-star.wav
Input File     : 'dtmf-star.wav'
Channels       : 1
Sample Rate    : 8000
Precision      : 14-bit
Duration       : 00:00:00.20 = 1600 samples ~ 15 CDDA sectors
Sample Encoding: 8-bit u-law


***
③ エクスポートしたuac.xmlシナリオにrtp_streamを追加

[参考：Media/RTP command](http://sipp.sourceforge.net/doc/reference.html#Media%2FRTP+commands)

***
![参考：Media/RTP command](https://qiita-image-store.s3.amazonaws.com/0/85364/9c570bf5-bea2-651c-dd41-3cb423c369cb.png)
***

>★200 OK 後の ACKの下にpauseタグがあるので、その部分にrtp_streamを追加★
`</send>`
`<!-- This delay can be customized by the -d command-line option       -->`
`  <!-- or by adding a 'milliseconds = "value"' option here.             -->`
`  <pause milliseconds="3000"/>`
`<nop>`
`  <action>`
`    <exec rtp_stream="dtmf-star.wav,1,0"/>`
`  </action>`
`</nop>`


***
④ tcpdumpコマンドで RTP/SIPキャプチャ、SIPp実行スクリーン上でのRTP Packet 送信（※赤枠）の確認
>`tcpdump -i any -v -s0 udp -w [output filename]`

SIPp実行コマンド
>uas側
`sipp -sn uas`
uac側
`sipp -sf uac_wav.xml -p 5061 -r 0 -i [local ip address] [destination ip address]`

![SIPp実行画面 uas, uac](https://qiita-image-store.s3.amazonaws.com/0/85364/6ef4413a-d185-8a59-1bb9-75186973a72a.png)

RTP/SIPをキャプチャしたファイルをWiresharkで開いてみる。
赤枠部分でRTPがG711 PCMU（u-law）で送信していることが確認できる。
　※Wiresharkの機能で音も聞けるので、実際の音を確認する場合はそちらを使用する。
![wireshark rtp/sip image](https://qiita-image-store.s3.amazonaws.com/0/85364/4f277804-d4b3-9648-c159-dba987e58118.png)
***

以上
tailコマンドでログを監視して、slackにアラート投げる

時間がかかるバッチを叩いて終わった時に通知が欲しいと思ったので、
なんかないかなと思ったら以下の記事を発見。

[ERRORログをメールで通知する　～tailコマンド編～](http://lab.hde.co.jp/2008/04/tail.html)

記事中のスクリプトで `mail` コマンド叩いているところを
slack の Incoming webhook に変更

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

slack_alert() {
  while read i
  do
    echo $i | grep -q "Finish."
    if [ $? = "0" ];then
        curl -X POST -H 'Content-type: application/json' \
        --data '{"text":"Finish!!"}' \
        https://hooks.slack.com/services/{Incoming Webhook URL}
    fi
  done
}

tail -n 0 --follow=name --retry $1 | slack_alert
```

```
$ ./slack_alert.sh output.log
```

logwatch とかだと重すぎるってときとかにさらっと使えてよさげ。
Google Chrome の重要なプラグインコンテンツを検出して実行の判定について

いつからだったか Google Chrome では Flash バナー広告などの重要ではないプラグインコンテンツは、一度描画領域をクリックしないと実行されなくなった[^1]。
結果として Flash バナー広告はバナー広告市場から消え、HTML5 バナー広告の時代が始まったのだった。


まぁそれはどうでもいいんだけど、プラグインコンテンツで **重要** か **そうでないか** というのはどうやって判別しているのだろうか？
と疑問に思ったので調べてみた。


![こんなやつ](https://qiita-image-store.s3.amazonaws.com/0/2546/3e48fbf5-ff4f-0501-5d76-04f44757fa50.png)
Flashバナー広告はこんな感じに表示される。

# 調査結果

> 幅 398px 以上で、かつ高さ 298px 以上のプラグインコンテンツは重要なプラグインコンテンツとして判定される。
> そして、重要なプラグインコンテンツかどうかの判定は**完全修飾ドメイン名**毎に判定される。

どういうことかというと
例えば 100x100 の大きさで埋め込まれたプラグインコンテンツは、1度クリックしないと実行されないが、同一の完全修飾ドメイン名を持つ a と b を同じページに埋め込み、a を 400x300 で埋め込んでおくと、b を 100x100 で埋め込んでも表示される。
ちなみに、一度実行可能な大きさでで表示してから JavaScript でサイズを小さくしても実行される。

上のキャプチャでもわかるように実行される前にサムネイルは表示される。
どうやら**1度だけ描画することができるらしい**。
例えば1分後に1度だけ描画されるようなつくりであれば、1分後に1度だけ描画され、それがサムネイルになる。

描画される前も描画された後も実は**バックグラウンドでずっと実行されているらしい**。
ただし制限はある。
タイマーは **500ms** に制限されて、**Socket などの通信系は実行できない**。
ちなみに、1度描画されるまではマウスイベントも送出される[^2]。

# 結論
**バナー広告は動くな**
もう Flashバナー広告は見ないけど HTML5 広告は同じ道を進み始めている。
先日若干重いと思ったらバナー広告内で Youtube の動画が再生されていた。
画像でいいよ画像で…。


[^1]: デフォルトの設定でそうなった。
[^2]: マウスムーブなど
Cloudera Director 2.x へのマイナーアップグレード

Cloudera Director 2.x を 2.y にアップグレードする。
Cloudera Director 2.0 のインストールは[こちら](http://qiita.com/shiumachi/items/90649830cb9b45726d99)を参照。

# 動作確認

- 2.0 → 2.1
- 2.1 → 2.2
- 2.2 → 2.3

# 環境

- Cloudera Director 2.x
- CentOS 7.1

# 手順

## 事前準備

実行中の処理は全て終了する。

Cloudera Director をシャットダウンする。

```shell-session
$ sudo service cloudera-director-server stop
```

Cloudera Director の DB をバックアップする。ここではバックアップ先を `/tmp/backup`とする。

```shell-session
$ sudo cp /var/lib/cloudera-director-server/state.h2.db /tmp/backup/
```

yum リポジトリをアップデートする。

```shell-session
$ cd /etc/yum.repos.d/
$ sudo wget "http://archive.cloudera.com/director/redhat/7/x86_64/director/cloudera-director.repo"
```

アップグレードする。

```shell-session
$ sudo yum clean all
$ sudo yum -y update cloudera-director-server cloudera-director-client
```

Cloudera Director を起動する。

```shell-session
$ sudo service cloudera-director-server start
```

ブラウザ上から Cloudera Director の画面を確認する。以下の画面は Cloudera Director 2.1 の例である。

![CD21 クラスタ画面.png](https://qiita-image-store.s3.amazonaws.com/0/17749/26931982-7a68-38c6-5aac-55e8e18f9b29.png)




# 参考

https://www.cloudera.com/documentation/director/latest/topics/director_upgrade.html
Bash on Ubuntu on Windows に cfコマンドをインストールしたが、cf pushでerror 500が返ってくる

# 概要
タイトルの通りとなりますが、IBM Bluemixに対してcf pushを実行したがデプロイに失敗します。
原因は分かりませんが、IBM Bluemix 側のような気がします、cfの問題？IBM Bluemixとの相性？

# 対象ユーザ
Windows10 Bash にcfコマンドをインストールし、Bashを起動して、
[IBM Bluemix](https://www.ibm.com/developerworks/jp/bluemix/) に「hubot」（デフォルトのまま）をcfコマンドでpushしようと考えている人

# 前提
- OS：Windows10 Anniversary Update
- PaSS：IBM Bluemix 
- CF：Linux版（※Windows版はうまくいきます）

# Bashを起動したら、rootユーザに切り替えられない
最初に躓いたのですが、Windows10 Anniversary Update にしたときに、専用ユーザを作成し、Bashを起動すると、そのユーザになります。ディレクトリ構成が殆どrootオーナなので、何かとインストールするためには rootユーザになる必要があります。rootパスワードの設定をしていないことから切り替えできません。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/71427/cd269c2e-7366-da6a-d286-2f09c74f7695.png)

そうこう悩んで探しているうちに、[Windows 10で始めるBash](http://news.mynavi.jp/series/bashonwindows/004/) を参考に、Bash起動時のデフォルトユーザを選択できるみたいです。

![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/71427/6a9d8651-bb14-95d5-6ce9-84043e0d3c80.png)

# Bashを起動して、cfコマンドにインストール
cfコマンドのインストールは本当に簡単です。

```bash:CFコマンドのインストール手順

# /sbinにcfコマンドをインストール
cd /sbin

# cfコマンドを取得
curl -L "https://cli.run.pivotal.io/stable?release=linux64-binary&source=github" | tar -zx

# cfコマンドを権限付与
chmod 755 ./cf
```

# 問題内容
さて本題の悩んでいるところです。
cf login | logout や、cf start | restart | stop などは利用できますが、
cf push だけ失敗してしまうのです。

```bash:
# cf push でアプリのdeploy
cf push hubotdev -m 256m --no-start
```

```:標準出力の内容
REQUEST: [2016-08-17T07:00:47+09:00]
POST /UAALoginServerWAR/oauth/token HTTP/1.1
Host: login.ng.bluemix.net
Accept: application/json
Authorization: [PRIVATE DATA HIDDEN]
Connection: close
Content-Type: application/x-www-form-urlencoded
User-Agent: go-cli 6.21.1+6fd3c9f / linux

grant_type=refresh_token&refresh_token=※省略

RESPONSE: [2016-08-17T07:00:50+09:00]
HTTP/1.1 200 OK
Connection: close
Transfer-Encoding: chunked
Cache-Control: no-cache, no-store, max-age=0, must-revalidate,no-store
Content-Type: application/json;charset=UTF-8
Date: Tue, 16 Aug 2016 22:00:47 GMT
Expires: 0
Pragma: no-cache,no-cache
Server: Apache-Coyote/1.1
X-Backside-Transport: OK OK,OK OK
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Global-Transaction-Id: 2648764701
X-Powered-By: Servlet/3.1
X-Xss-Protection: 1; mode=block

---- ※省略

OK

Uploading hubotdev...

REQUEST: [2016-08-17T07:00:59+09:00]
PUT /v2/resource_match HTTP/1.1
Host: api.ng.bluemix.net
Accept: application/json
Authorization: [PRIVATE DATA HIDDEN]
Connection: close
Content-Type: application/json
User-Agent: go-cli 6.21.1+6fd3c9f / linux

[{"sha1":"fa419742b5 ※省略

RESPONSE: [2016-08-17T07:03:04+09:00]
HTTP/1.1 500 Internal Server Error
Connection: close
Content-Type: text/xml; charset="utf-8"
X-Backside-Transport: FAIL FAIL

500 Error: Network error
FAILED
Error processing app files: Error uploading application.
Server error, status code: 500, error code: 0, message: 

```

HTTP 500 のエラーです。

これがWindows版のcfだと正常に終了します。
せっかくだからということでBashを使ってみようと思ったら、
問題（壁）にあたってしまった内容となります。
複雑なtableタグをGoogleSpreadSheetで作る

# こういうテーブルを作りたい

GoogleSpreadSheet上で、セル結合をいっぱい使って図形を描画していく。
![スクリーンショット 2016-08-17 20.26.48.png](https://qiita-image-store.s3.amazonaws.com/0/53489/99ac4f7b-b06a-2063-09fc-9caac4685c9e.png)

# 範囲選択してコピー

![スクリーンショット 2016-08-17 20.28.18.png](https://qiita-image-store.s3.amazonaws.com/0/53489/92678a9c-ea5a-a7c8-8309-95294010c79e.png)


# 別タブを開いて 編集可能なHTMLを開く

```
data:text/html, <html contenteditable>
```
をアドレスバーに入れてエンター。そしてペースト

![スクリーンショット 2016-08-17 20.30.56.png](https://qiita-image-store.s3.amazonaws.com/0/53489/ccb4ffb1-6308-02e1-a73d-a2336f0365cf.png)

# ⌘Sで保存をすると、インラインCSSだけで完結したテーブルタグが出来上がり

![スクリーンショット 2016-08-17 20.32.30.png](https://qiita-image-store.s3.amazonaws.com/0/53489/663f03aa-7be4-3e68-4645-bd1d500f1674.png)

インラインCSSで完結しているので、パーツとしてあちこちに貼り付けやすい。
[ fish shell ] 今年からfish shell使ってるので初期設定ファイルを貼っておきます

今までzshを使ってたんですが、マシンの再セットアップをした際ノリでfish shellを導入しました。

もうほんとに最低限の設定しかしてませんし、<del>実は設定方法もよくわかってないし、</del>とりあえずな感じで使ってますが、補完も優秀だし普段使いには全く問題ない感じで便利に使ってます。

ぼくは[oh-my-fish](https://github.com/oh-my-fish)というフレームワークを使っていますが、[fisherman](https://github.com/fisherman/fisherman)というプラグインマネージャもいい感じらしいです。（未検証）

[追記] 
Fishermanについてよくまとまった記事を見つけたので参考とさせていただきました。
[初心者がShellを知りFish〜Fishermanを導入するまで - Qiita](http://qiita.com/nutsinshell/items/5f111184b50f7081c92f)

個人的にzsh + preztoより軽量で快適だったので、fish shell使っていこうと思ってます。

設定方法間違ってるよ！とかあればぜひご教授いただければ幸いです。

``` config.fish
# Path to Oh My Fish install.
set -gx OMF_PATH "/Users/[ユーザー名]/.local/share/omf"

# Customize Oh My Fish configuration path.
set -gx OMF_CONFIG "/Users/[ユーザー名]/.config/omf"

# Load oh-my-fish configuration.
source $OMF_PATH/init.fish

# homebrew
set -U fish_user_paths /usr/local/bin $fish_user_paths

# nodebrew
set -x PATH $HOME/.nodebrew/current/bin $PATH

# rbenv
#eval "$(rbenv init -)";
set -x PATH $HOME/.rbenv/bin $PATH
set -x PATH $HOME/.rbenv/shims $PATH
rbenv rehash >/dev/null ^&1

# pyenv
# export PATH="$HOME/.pyenv/shims:$PATH" 
status --is-interactive; and . (pyenv init -| psub)

# plugins
set fish_plugin peco

# cd > ls
function cd
  builtin cd $argv
  ls -a
end

# rmstash
alias rm='rmtrash'

# theme
set fish_theme batman

# peco
function peco
  command peco --layout=bottom-up $argv
end

function fish_user_key_bindings
  bind \cr 'peco_select_history (commandline -b)'
end

# encoding
set -x LANG ja_JP.UTF-8
```

fish shell、いい感じなんですが情報が少ないため導入を避けてる人も多いと思うので、特に目新しい情報ではないですが記事を書いてみました。ひとりでも多くの人がfish shellにトライしますように。
macOS（OS X）にAnyenvでRuby,PHP,NodeJSの環境を構築する


macOS（OS X）で、RubyやPHPの環境を構築する場合、rbenv,phpenvを使う人が多いと思います。筆者もその１人です。rbenv,phpenvは個別に考えると凄く便利なのですが、一緒に使用しようとすると少々面倒臭い印象を受けます。何かいい方法はないかと探していたところ、Anyenvという◯◯envをインストール・管理できるツールがあることを知り、早速使用してみました。

以下は色々簡単に纏めたものです。玄人向けと思っていただいた方がいいかもしれません（笑）

## 前提

事前にHomebrewをMacにインストールして置いてください。

## brewでインストールしたものをアンインストール

brew uninstallは一例です。自身の環境に合わせて変更してください。そもそもインストールしてないのであれば、この作業はスキップしてください。

```shell
$ brew uninstall rbenv ruby-build phpenv php56 &&\
rm ~/.ruby-version
```

## Anyenvのインストール

brew installは一例です。自身の環境に合わせて変更してください。

```shell
$ git clone https://github.com/riywo/anyenv ~/.anyenv &&\
brew install libxml2 libmcrypt openssl re2c &&\
anyenv -h
```

## AnyenvへのPathをとおす

```shell
$ vi .bash_profile

if [ -d $HOME/.anyenv ] ; then
  export PATH="$HOME/.anyenv/bin:$PATH"
  eval "$(anyenv init -)"
  for D in `\ls $HOME/.anyenv/envs`
  do
    export PATH="$HOME/.anyenv/envs/$D/bin:$PATH"
  done
fi
```

設定を反映させるために

```shell
$ exec $SHELL -l
```

または

```shell
$ source ~/.bash_profile
```

## 各envをインストール

### インストールできるenvを確認

```shell
$ anyenv install --list
```

### envをインストール

```shell
$ anyenv install rbenv phpenv nodeenv
```

インストールした各envを認識させるために

```shell
$ exec $SHELL -l
```

または

```shell
$ source ~/.bash_profile
```

## ヒント

ヒントという名のメモ。

### NodeJSについて

筆者個人的にNodeJSは、brewでインストールしてnモジュールでバージョンを切り替えるのがいいのではないかと思います。

### configure: error: Cannot find libz

`$ phpenv install` を実行した時に "configure: error: Cannot find libz" というメッセージが表示されて、Build errorが発生する場合は、`$ xcode-select --install` を実行すると解決します。

### PHPのBuild時にOpenSSLでコケる
OS Xから、OpenSSLのヘッダファイルがなくなり、`$ brew link --force openssl` でエラーができるようになったそうです。そのため、コンパイラにパスを渡さないといけないそうです。

```shell
$ vi .bash_profile

export PHP_BUILD_CONFIGURE_OPTS="--with-openssl=$(brew --prefix openssl) --with-openssl-dir=$(brew --prefix openssl) --with-libxml-dir=$(brew --prefix libxml2)"
```

設定を反映させるために

```shell
$ exec $SHELL -l
```

または

```shell
$ source ~/.bash_profile
```

参考: [brew link openssl --force ができなくて phpenv & php-build で PHP がビルドできない](http://qiita.com/chatii0079/items/b30cf35c4ec9bdf8dd70)
C > bit演算 > 入力:1,0,1,0 > 出力: 0b0101

### やりたいこと

- 4つの入力がある
  - 1, 0, 1, 0
- LSB Firstの順番で0b0101のように出力する

### code

http://ideone.com/9GieOg

```c
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

uint8_t toBinary(bool array[4])
{
	uint8_t resflg = 0;
	uint8_t flagBit = 0x1;
	
	for(int idx=0; idx<4; idx++) {
		if (array[idx]) {
			resflg |= flagBit;
		}
		flagBit <<= 1;
	}
	
	return resflg;
}


int main(void) {
	uint8_t res;
	bool array[4] = {1, 0, 1, 0};
	
	res = toBinary(array);
	printf("%d\n", res);

	return 0;
}
```

```txt:結果
Success	time: 0 memory: 2168 signal:0
5
```

- flagBitのビット位置をずらすという思いつき
  - 最初はresFlgのビットずらしを考えたが、その場合、期待通りの結果にならなさそう (MSB Firstならこちらで良さそう)
- 2進数の表示はただのCの場合面倒そうなので、%dでprintfした
  - C++の場合、マニピュレータ使えばすぐできる
CentOSのDockerコンテナでusermodするときに注意すること


# 現象
CentOSなDockerコンテナであらかじめ作っておいたユーザアカウントのユーザIDをusermodコマンドで変更しようとすると次のようなエラーに遭遇しました。

```
[root@e0f1f3c6fe33 /]# id testuser
uid=1000(testuser) gid=100(users) groups=100(users)
[root@e0f1f3c6fe33 /]# usermod -u 1001 testuser
failed to change mailbox owner: Read-only file system
```
念のためメール保存ファイルのユーザIDを確認するとusermod実行前の1000のまま変わっていません。

```
[root@e0f1f3c6fe33 /]# id testuser
uid=1001(testuser) gid=100(users) groups=100(users)
[root@e0f1f3c6fe33 /]# ls -lnd /var/spool/mail{,/testuser}
drwxrwxr-x 2    0 12 4096 Aug 17 08:00 /var/spool/mail
-rw-rw---- 1 1000 12    0 Aug 17 08:00 /var/spool/mail/testuser
```
このファイルのパーミッションは660だし、chownコマンドだとエラーなくユーザIDを変えられること、そもそもこのusermodコマンド実行時にホームディレクトリのユーザIDは問題なく変更が完了していることからファイルシステムが読み込み専用というわけではないはずです。

# 調査
straceコマンドで追っかけてみました。

```strace_usermod_-u_1001_testuser出力結果から抜粋.
open("/var/spool/mail/testuser", O_RDONLY|O_NONBLOCK) = 4
fstat(4, {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
fchown(4, 1001, 4294967295)             = -1 EROFS (Read-only file system)
```
`O_RDONLY|O_NONBLOCK` でオープンした対象ユーザのメール保存ファイルを`fchown()`を使ってユーザID変更しようとしたところで`EROFS`くらってることがわかります。この問題はDockerのストレージドライバにOverlayFSを使っているときのみ起こります。AuFS/DeviceMapper/Btrfs/ZFSでは発生しません。

OverlayFSのドキュメントを見てみるとまさにこの問題に関する記述がありました。
https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt

```overlay.txtから抜粋
On a file opened with O_RDONLY fchmod(2), fchown(2), futimesat(2) and
fsetxattr(2) will fail with EROFS.
```
どうやら既知の問題のようです。[usermod.cのソースコード](https://github.com/shadow-maint/shadow/blob/4.1.5.1/src/usermod.c#L1721-L1757) をみると、たしかに1724行目で`O_RDONLY`でオープンしたfdを1745行目で`fchown()`してますね。ちなみにホームディレクトリのユーザID書き換えでは`lchown()`が使われていました。

# 対応策
このエラーにおける対策としては、コンテナを実行中、もしくはDockerイメージを作る際に次のような処置が考えられます。

<dl>
<dt>1. 事前にメール保存ファイルをカレントレイヤにcopy-upしておく
<dd>touch /var/spool/mail/&lt;USERNAME&gt; で下層レイヤからcopy-upしておいてからusermodコマンドを実行する
<dt>2. メール保存ファイルが不要ならば消してしまう
<dd>rm /var/spool/mail/&lt;USERNAME&gt; して消してからusermodコマンドを実行する
<dt>3. そもそもメール保存ファイルを作らない
<dd>useraddコマンドでユーザを作るときに-rオプションを使うなり /etc/default/useradd ファイルにCREATE_MAIL_SPOOL=noを記述するなりしてメール保存ファイルを作らないようにする。ちなみにDebian系ディストリは CREATE_MAIL_SPOOL=no がデフォルト。
<dt>4. エラーを無視する
<dd>メール保存ファイルの所有者権限がなくとも動作に支障なければ無視するのもありですね。
</dl>
Python でユーザーローカルの人工知能 API を遊んでみた話

[User Local](http://ai.userlocal.jp/) が提供している人工知能 API の事前応募に応募していて、6 月くらいには API キーをもらっていたのですが、なかなか手を出せていませんでした。僕は Web API に慣れ親しんでいないので、簡単なところからの投稿になります。

とりあえず、今回は Python から API を叩いて、どんな感じか確かめてみます。

<i class="fa fa-chevron-right" aria-hidden="true"></i> Python で人工知能 API を叩く
------------------------------------------------------------------------------------------------------
GET リクエストをすればいいらしいので、以下のように Python コードを書いてやりました。`apikey_pram` はご自身のものを指定してください。実は、API Key は `"sample"` にすることで 1 時間に 10 回までは遊ぶことができます。

```python
#! /usr/bin/env python -O
# -*- encode: utf-8 -*-
import sys
import json
import urllib.request
import urllib.parse

message_param = sys.argv[1]
apikey_param = "plz set your api key"
url = "https://chatbot-api.userlocal.jp/api/chat?"

params = {
    "message": message_param,
    "key": apikey_param
}

url += urllib.parse.urlencode(params)
if __debug__:
    print("access to {0}".format(url))

with urllib.request.urlopen(url) as res:
    html = res.read().decode("utf-8")
    root = json.loads(html)
    print("AI: {0}".format(root["result"]))
```

これを `sample_userlocal.py` という名前で保存しました。

<i class="fa fa-chevron-right" aria-hidden="true"></i> 結果
-----------------------------------------------------------

人工知能と名付けられているので、ちょっと意地悪ですが、こんな風に聞いてみました。

```bash
~ $ ./sample_userlocal.py 人工知能って何？
AI: わたしのこと？笑
~ $ ./sample_userlocal.py まじで？
AI: まじ
~ $ ./sample_userlocal.py うおー、すげー！
AI: ぶぎー((´^ω^))
```

ぶぎーーーー((´^ω^))!!!「なんかいい感じじゃねーか笑」 という気分に。もう少し遊んでみます。

```bash
~ $ ./sample_userlocal.py おなかへった
AI: おかえりーですー！
~ $ ./sample_userlocal.py ただいま
AI: おつかれ
~ $ ./sample_userlocal.py ありがとう
AI: うむ
```

うーん、「おなかへった」で「おかえり」っていうのはなくはないけど... これだけだと不自然な気がしますが、そのまま無理やり会話してみるとなんとなくの会話はできます。最後に、「人工知能って何」をもう一回聞いてみて終わりにしました。

```
~ $ ./sample_userlocal.py 人工知能って何？
AI: 人工知能というより人工無脳かな
```

えええええええええ笑 まじかよ。(君が言っちゃダメな奴)

<i class="fa fa-chevron-right" aria-hidden="true"></i> まとめ
------------------------------------------------------------------
公式も言っていますが、学習中の API なため、ちょこちょこおかしなことを言ってきます。まあ結構面白いので、次回はこやつを研究室 Slack の bot にしてやろうと思います(小並感)

簡単ですが、備忘録までに。