OmniAICreator/Qiita-1.07M huggingface dataset:
vagrant,ansibleを利用した仮想サーバの構築


# 概要
だいぶ今更感もありますが、私の中でサーバの仮想化技術がVirtulBoxあたりで止まっていたので、アップデートしていく。
コマンド一発で欲しい環境を作っちゃう（プロビジョンニング）をやっちゃう。


|項目|解説|cf.|
|:--|:--|:--|
|VirtualBox|仮想サーバの実行環境を提供,vagrantから見るとプロバイダーという位置付け|vmware|
|vagrant|仮想マシンの起動、停止だけでなく、仮想マシンの状態の設定を自動化（プロビジョニング）する機能を備えている。デフォルトのプロバイダーはvirtualbox,vmwareとかも指定可能||
|ansible|構成管理ツール、yamlファイル一つでssh接続可能なサーバに必要なアプリケーションを一括でインストールしてくれる|Puppet,Chef|


# インストール

環境
- macOS 10.12.5

## virtualbox
公式サイトから
> https://www.virtualbox.org/

## vagrant
公式サイトから
> http://www.vagrantup.com/

## ansible

```
$ brew install ansible
```

# 設定

```フォルダ構成
Vagrantfile
provisioning
	hosts
	site.yaml 
```

以下設定ファイル類

```Vagrantfile
Vagrant.configure("2") do |config|

  config.vm.box = "ubuntu/xenial64"
  
  config.vm.network "private_network", ip: "192.168.200.100"

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/site.yaml"
    ansible.inventory_path = "provisioning/hosts"
    ansible.limit = 'all'
  end

end
```

Vagrantfileはvagrantが仮想サーバを立ち上げる際に呼び出すファイル。

config.vm.box = "ubuntu/xenial64"
というのはVagrantの公式box（仮想サーバのイメージみたい）

他にも色々あるので必要に応じて。
> https://app.vagrantup.com/


```hosts
[vagrants]
192.168.200.100 ansible_python_interpreter=/usr/bin/python3
```

ansibleのsshを指定するためのファイル

※ubuntu/xenial64はpython3しか入っていない（pathは/usr/bin/python3となる。）ansibleはpythonを利用するため、interpreterを正しく設定する必要があるようです。

>参考:
>https://stackoverflow.com/questions/32429259/ansible-fails-with-bin-sh-1-usr-bin-python-not-found


```site.yaml
---
- hosts: vagrants
  sudo: true
  user: ubuntu
  tasks:
    - name: install packages zsh
      apt: name=zsh update_cache=yes
```

インストール(ubuntuのapt-getで)するプログラム等を指定するやつ。


# 実行

## インストールの正常性確認

```
$ vagrant --version

$ ansible --version

$ virtualbox --version
```

## 実行とサーバの動作確認

サーバの起動

```
$ vagrant up 
```

zshがインストールされているか確認
vagrant sshで仮想サーバにssh接続できる。

```
$ vagrant ssh

ubuntu@ubuntu-xenial:~$ zsh --version
zsh 5.1.1 (x86_64-ubuntu-linux-gnu)
```


# 感想

VirtualBoxのGUIでごにょごにょしてた時代は大変だったけど、すごい楽になってた。

※この先にさらにリソース状況に応じた自動プロビジョニングといった技術があるようですが、それはまた別のお話。

#参考にさせていただいたサイト
> AnsibleとVagrantで開発環境を構築する
>http://knowledge.sakura.ad.jp/tech/2882/
MySQLでのデータインポート時にMySQL server has gone away

vagrant + ansible でDBの初期処理として、各種データをインポートしている時に、
「MySQL server has gone away」とエラーが発生してしまった時の対応メモ。

ググると、max_allowed_packetについての記事がたくさん出てくるが、
実はmax_allowed_packetにはサーバ側の設定とクライアント側の設定がある。

https://dev.mysql.com/doc/refman/5.6/ja/packet-too-large.html
https://dev.mysql.com/doc/refman/5.6/ja/packet-too-large.html

というわけで、

サーバ側
```[mysqld]
max_allowed_packet=128M
```

クライアント（インポートする時のコマンド）
```mysql --max_allowed_packet=128M  < /XXXXX.sql```

で解決。
vimrc

```
" Configuration file for vim
set modelines=0		" CVE-2007-2438

" Normally we use vim-extensions. If you want true vi-compatibility
" remove change the following statements
set nocompatible	" Use Vim defaults instead of 100% vi compatibility
set backspace=2		" more powerful backspacing

" Don't write backup file if vim is being called by "crontab -e"
au BufWrite /private/tmp/crontab.* set nowritebackup nobackup
" Don't write backup file if vim is being called by "chpass"
au BufWrite /private/etc/pw.* set nowritebackup nobackup
colorscheme onedark
syntax on
set title
set tabstop=4
set expandtab
set shiftwidth=4
set smartindent
set list
set listchars=tab:»-,trail:-,eol:↲,extends:»,precedes:«,nbsp:%
set nrformats-=octal
set hidden
set history=50
set virtualedit=block
set whichwrap=b,s,[,],<,>
set backspace=indent,eol,start
set wildmenu
set number
```
AQDefaultDeviceのログを消去したい

## AQDefaultDeviceのログが邪魔・・・

```
2017-07-22 14:54:00.970429+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:02.978850+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:04.987299+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:06.995812+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:09.004251+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:11.012601+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:13.020905+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
2017-07-22 14:54:15.029681+0900 BowingVision[13128:329786] [aqme] 254: AQDefaultDevice (173): skipping input stream 0 0 0x0
```

## Product > Schema > Edit Schema

<img width="600" alt="xcode.png" src="https://qiita-image-store.s3.amazonaws.com/0/32215/27d4db95-0598-963f-c2e1-77c013dcde26.png">

## OS_ACTIVITY_MODE=disable 追加


<img width="600" alt="BowingVision.xcodeproj.png" src="https://qiita-image-store.s3.amazonaws.com/0/32215/131ea3a5-a931-0cd7-c75e-9b9a9f036ec7.png">


消えました。

## 参考

[ios \- Strange AQDefaultDevice logging \- Stack Overflow](https://stackoverflow.com/questions/40389308/strange-aqdefaultdevice-logging)
A Tour of Go Exercise色々

## このページは？

久々にGoのチュートリアルをやったので、
Exerciseの解答をチラ裏的な感じで書いておきます

## Exercise: Loops and Functions

```
package main

import (
	"fmt"
	"math"
)

func Sqrt(x float64) float64 {
	z_before := 2.0;
	var z_after float64;
	for i := 0; ; i++ {
		z_after = z_before - (z_before * z_before - x) / (2 * z_before);
		if math.Abs(z_after - z_before) < 0.001 {
			break
		} else {
			z_before = z_after;
		}
	}
	return z_after;
}

func main() {
	fmt.Println(Sqrt(2))
}

```
GAS で「一部のスコープへのアクセス権限がありません」と怒られたときの対処法


(今の GAS の挙動に基づいた記事なので、賞味期限短いかもしれません)

# 何が起きたか： GAS の認証エラー

最近、 GAS (Google Apps Script) からスプレッドシートなど他の Google アプリを操作しようとしたときに表示される認証画面で、「invalid_scope  一部のスコープへのアクセス権限がありません」というエラーが表示されるようになりました。

![google_auth2.png](https://qiita-image-store.s3.amazonaws.com/0/54240/4a5b83bc-0d94-d7d0-5b77-bd271773462b.png)

これを突破するのに結構ハマってしまいました。

# 原因と対処法

どうやら、Google Apps Script では、レビューを受けたアプリ以外のアプリからの Google Drive などの操作を原則弾くようになったようです。

「レビューを受けたアプリでないことを承知の上で承認する」というオプションが、日本語版のログインページでは未実装のようで、その影響で新しく作ったアプリの認証がエラーになっているようです。

対処法は、

1. 承認画面に飛ぶ

![google_auth1.png](https://qiita-image-store.s3.amazonaws.com/0/54240/0b85ed20-f441-39fa-f9ca-8c4a51708651.png)

2. 認証に使うアカウントを選択する画面で、左下のプルダウンから「言語を英語にする」

![google_auth3.png](https://qiita-image-store.s3.amazonaws.com/0/54240/383385aa-32e9-1a2a-53de-44201e365495.png)

3. 「このアプリはレビューが済んでいませんよ」という画面に飛ぶので、 `Advanced` をクリック

![google_auth4.png](https://qiita-image-store.s3.amazonaws.com/0/54240/b6ad8488-7d10-55c8-820a-63ac3d04867e.png)

4. 理解したうえで進む (`Go To <アプリ名>`)、というオプションが表示されるのでクリック

![google_auth5.png](https://qiita-image-store.s3.amazonaws.com/0/54240/ae45be44-42bf-3139-9a5a-74982d22d795.png)

5. `Continue` とタイプしてね、と言われるので、タイプする

![google_auth6.png](https://qiita-image-store.s3.amazonaws.com/0/54240/0c5ad32c-1cff-2495-ccfd-f420d0f29d49.png)

これで認証が完了します。

最近 GAS に手を出して詰んでしまった仲間の参考になれば幸いです。
技術を使って組織を超えた仕事をしよう@OIC 2016-07-15

# 登壇者

**関 春之さん(せきはるさん)** twitter @HAL_SK

+ georepublic => システム開発(GIS開発者)
+ hack camp => ハッカソン運用代行業
+ code for japan => シビックハッカー

## 歩み

初めてのIT→Panasonic PSXでゲーム作り
↓
ゆうちょの帳票作成などのシステム作成
↓
インターネットメディア（sportsnavi.com）

+ そこでは実際にサーバーファイルを直接いじくっていた… 

↓
着メロ配信サービス企業
↓
位置情報に連動した広告配信サービス企業(cirius Technologies)

+ Yahooに買収→Yahoo 社員に

↓
georepublic が IPA の未踏プロジェクトに採択され、活動資金が配布された。

+ よって cirius Technologies で働きながら georepublic を起業
+ いくら企業規定にかかれていても、社長に直談判すればできる**（可能性あり）**

↓

## シビックテックって？

東日本大震災をきっかけに SHINSAI_INFO を立ち上げる。

+ Twitterで募集をかけたところ多数の協力者が
+ 情報の鮮度が低い。行政と連携したほうが運用しやすいなど、いくつかの問題が生まれる
+ ジェニファー・バルカの「コーディングでより良い政府を作る」というTEDを見る

↓
Code for Japan 立ち上げ

+ ITを使って行政と共によりよい社会を作る
+ 市民がつながることによって、**創造的なアイディアを出す**
+ そのアイディアを実際にNPOや企業と協力して、実際につくってみる
+ 全国の Code for グループをつなぐ Code for Japan

*これはやってよかったという行政への影響はありますか？*

↓
趣味でやっていたハッカソンを、会社として請け負う企業を立ち上げ

### 各地の Code for グループの実績

+ 五箇山で公共交通アイディアソン・ハッカソン
    + UBERや市長が参加
+ マッピングパーティ（街歩きして街の情報を集める）
    + Wikipedia のタウン誌版のようなものに記録していく
+ NPOや行政と街の問題について考えるオープンカフェ
    + 街の課題をITで解決できないかを話しあったり、アイディアをは穴しあう
+ 街のゴミの収集日を簡単に把握できるOSSアプリ
    + http://5374.jp
+ 会津若松で除雪車の位置を調べることができるapp
+ さっぽろ保育園マップ
+ 大津祭で神輿がどこを走っているのかわかるアプリ
    + ビーコンを使用
+ 阿波おどりの日にどこにどの連（グループ）がいるのかわかるサービス
+ 千葉の地元にある祭りを知ることができるサービス

### ITでつながる課題解決

似たような課題がある自治体のためにOSSにして共有すれば全体でPDCAの共有ができるので、アプリケーション自体の質も上がるし、全体の問題が解決できるWin-Winの関係になれる

### OSSにすることによって発生するメリット

+ 無駄な税金が使われなくなる
+ 使い勝手の良さを共有することができる
+ 共通化することで、簡単に導入しやすい


## メッセージ

### **組織の枠を意識的に越えよう**

例えば、コミュニティへの参加。関さんの場合は OpenStreatMap コミュニティであった

**技術者ならば、興味のある技術系コミュニティに参加すればよいのでは！**

+ Code for OSAKA
+ ハッカソン
+ 勉強会
+ マッピングパーティ
+ GAME JAM

### ITは目的ではない

ITは目的ではなく、**課題解決の手段**。
学生のうちに課題解決の経験を積もう

### 自分は世の中を変えることができる力になれる

自分で**何かを作れる/表現できる**ことは**世の中を変える力**になる

## 質疑応答

+ 社会から評価されるにはどれぐらいの時間がかかるのですか？
    + 一概には言えない。
    + でも、自分が評価されたと感じる軸を作って決めれば良い。
    + 数撃ちゃ当たる精神も大事
+ ハッカソンを参加するときに注意・意識する点って？
    + 自分が続けたいことを作るようにする。
    + 使う人がいそうなものを作るように注意する。
    + 必要無いものを作るときは割りきってもいい。
+ ハッカソンを企画する際に気をつけることって？
    + なぜやるのか。目的をきちんと決める
    + 良いテーマを見つける
+ どうすればハッカソンの良いテーマを見つけられる？
    + 「新しい技術に触れる・課題を解決する・コミュニティのつながりを作る（ネットワーキング）」の３つぐらいのパターンがあるので、それをきちんと決め、それに対するテーマを決めること
+ 課題解決の課題を見つけるコツなどあれば…
    + 現場（活動している）の人の話を聞く
    + 解決したい領域を見つける
+ Code for グループをやっていてよかったこと
    + 役所の中にも行政を変えたいと感じている熱い人もいることを知れたこと
    + 中の人たちとのつながりができ始めていること
+ ルワンダで活動したうえで学生に伝えたいこと
    + ルワンダは虐殺があった国（ジェノサイト）
    + 植民地統治によって内乱が起きた
    + 勉強熱心（ジェノサイトの反省から）
    + 汚職のない国
    + 街が綺麗
    + ITに力が入っている（特にスタートアップ）
    + 志が高い学生が多かったイメージ

### スタートアップって？

起業家。ベンチャーキャピタルなどからお金を集めれるような急成長する企業のこと。

### ハッカソンって？

多少汚くてもいいから何かを作ること(Hack) + マラソンのように続けること (Marathon)
↓
Hackathon(ハッカソン)
圧縮・解凍のお話(zip, tar, gzip/gunzip)

# 目的
圧縮/解凍コマンドって結構使うことが多いのですが、使い方を忘れることが多いのでよく使うコマンドだけを纏めてみました

基本的には、誰もしも一回はお世話になっているでしょう
http://uguisu.skr.jp/Windows/tar.html
こちらを参考にしています

# ZIP

### 形式

```
*.zip
```

### 単一ファイルを圧縮

```
$ zip  filename.zip filename
```

### 単一ファイルを圧縮 + パスワード付

```
$ zip -e filename.zip filename
```


### ディレクトリを再帰的に圧縮

```
$ zip -r dirname.zip dirname/
```

### ディレクトリを再帰的に圧縮 + パスワード付

```
$ zip -re dirname.zip dirname/
Enter password:
Verify password:
```

# GZIP / GUNZIP

### 形式

```
*.gz
```

### 単一ファイルを圧縮

+ 元ファイルを残さない
 
```
$ gzip result1.txt
```

+ 元ファイルを残す
    + `-c` を用いる

```
$ gzip -c result1.txt > result1.txt.gz
```

### 単一ファイルを解凍

+ 元ファイルを残さない

```
$ gunzip result1.txt.gz
```

+ 元ファイルを残す
    + `-c` を用いる

```
$ gunzip -c result1.txt.gz > result2.txt
```


# tar + GZIP(*.tar.gz, *.tgz)

### 形式

```
*.tgz 
*.tar.gz
```

### ファイルorディレクトリの圧縮

```
$ tar zcvf backup.tar.gz file1 file2
$ tar zcvf backup.tar.gz directory
```


### 圧縮ファイルの解凍

```
$ tar zxvf filename.tgz
```

# 余談

必要に応じて加筆していきます。
[Ruby] モジュールの include と prepend-[2]

["前のエントリ"](http://qiita.com/ksh-fthr/items/5bfc3583e85ed124f4bb) で モジュールを prepend すると, オーバーライドがおきると書いた.
ではモジュールを prepend したとき, オーバーライドしたメソッドのなかで super を実行するとどうなるか.

## 確認環境
* Ruby v2.3.7p456

## prepend 時の super の挙動

```ruby:when_prepend_behavior_of_prepend.rb
# モジュールのメソッドで super を実行する
module M
  def hoge
    puts "hoge is defined by module"
    super
  end
end

# モジュールを prepend するクラス
class ClsPrependModule
  prepend M
  def hoge
    puts "hoge is defined by ClsPrependModule"
  end
end
```

## 挙動の確認
```ruby:verify_behavior1.rb
ClsPrependModule.new.hoge # :=> hoge is defined by module
                          # :=> hoge is defined by ClsPrependModule
```

## 結論
prepend されたモジュールの, オーバーライドすることになるメソッドで super を実行すると, オーバーライドされる側のメソッド, つまり prepend したクラスの同名メソッドが実行されることがわかった.

## おまけ
じゃあ, super で実行されるメソッド(つまり prepend したクラスのメソッド)で, さらに super を実行するとどうなるか.

```ruby:verify_exec_super_in_prepended_class.rb
# モジュールのメソッドで super を実行する
module M
  def hoge
    puts "hoge is defined by module"
    super
  end
end

# モジュールを prepend するクラス
class ClsPrependModule
  prepend M
  def hoge
    puts "hoge is defined by ClsPrependModule"
    super
  end
end
```

## 挙動の確認
```ruby:verify_behavior2.rb
# 実行
ClsPrependModule.new.hoge

# 結果
hoge is defined by module
hoge is defined by ClsPrependModule
NoMethodError: super: no superclass method `hoge' for #<ClsPrependModule:0x00007fb0a3a8ee58>
	from (irb):15:in `hoge'
	from (irb):8:in `hoge'
	from (irb):18
	from /usr/bin/irb:11:in `<main>'
```

1. モジュールのメソッドがコールされ実行される
1. super で prepend したクラスのメソッドがコールされ実行される
1. prepend したクラスの上位クラス(ここでは Objectクラス)では「hoge()メソッド」が定義されていないので NoMethodError が発生した
enumへ変数を渡す

# 内部の変数を渡す場合

```swift

import UIKit

enum Fruit: CustomStringConvertible {
    
    case apple
    case banana
    
    static var appleValue: String = "りんご"
    static var bananaValue: String = "バナナ"
    
    var description: String {
        switch self {
        case .apple:
            return Fruit.appleValue
        case .banana:
            return Fruit.bananaValue
        }
    }
    
}

print(Fruit.apple)
print(Fruit.banana)

```

```
りんご
バナナ
```

# 外部から変数を書き換えたい場合

```swift

import UIKit

var aapple = "りんご"
var bbanana = "バナナ"

enum Fruit: CustomStringConvertible {
    
    case apple
    case banana
    
    static var appleValue: String = aapple
    static var bananaValue: String = bbanana
    
    var description: String {
        switch self {
        case .apple:
            return Fruit.appleValue
        case .banana:
            return Fruit.bananaValue
        }
    }
    
}

print(Fruit.apple)
print(Fruit.banana)

```

```
りんご
バナナ
```
[Ruby] モジュールの include と prepend-[1]

モジュールを include したときと prepend したときでは継承順序が異なる.
結果, 同じモジュールを include したときと prepend したときでは当然挙動が変わってくる.

## 確認環境
* Ruby v2.3.7p456

## モジュール定義とクラス定義

```ruby:define_module_define_class.rb
# まずはモジュール定義
module M
  def hoge
    puts "hoge is defined by module"
  end
end

# 定義したモジュールを include するクラス
class ClsInludeModule
  include M
  def hoge
    super
    puts "hoge is defined by ClsIncludeModule"
  end
end

# 定義したモジュールを prepend するクラス
class ClsPrependModule
  prepend M
  def hoge
    super
    puts "hoge is defined by ClsPrependModule"
  end
end
```

## 継承関係の確認
```ruby:verify_inheritane.rb
# モジュールを include したクラス
ClsInludeModule.ancestors # :=> [ClsInludeModule, M, Object, Kernel, BasicObject]

# 継承関係の確認(モジュールを prepend したクラス)
ClsPrependModule.ancestors # :=> [M, ClsPrependModule, Object, Kernel, BasicObject]
```

## 挙動の確認
```ruby:verify_behavior.rb
# モジュールを include したクラス
ClsInludeModule.new.hoge # :=> hoge is defined by module
                         # :=> hoge is defined by ClsIncludeModule

# モジュールを prepend したクラス
ClsPrependModule.new.hoge # :=> hoge is defined by module
```

## 結論
* モジュールを include した場合
 * モジュールは include を行ったクラスの 「上」に来る
 * したがって同名メソッドが定義されている場合, super で呼び出した際には モジュールのメソッドが実行される

* モジュールを prepend した場合
 * モジュールは prepend を行ったクラスの 「下」に来る
 * この場合, prepend を行ったクラスのメソッドは prepend したモジュールのもので オーバーライド される
 * したがって prepend を行ったクラスのメソッドは実行されない
[Ruby] クラスインスタンス変数

Ruby Gold の学習中, 変数のスコープでつまづいたのでメモ.
つまづいたのは「クラスインスタンス変数」.

## 確認環境
* Ruby v2.3.7p456

## クラスインスタンス変数の確認をするコード

```ruby:class_instance_val.rb
class Cls
  # 変数「@cls_instance_val」を宣言: [cls_instance_val]をセット
  @cls_instance_val = 'cls_instance_val'

  # クラスメソッドから参照(get)
  def Cls.get_class_instance_val
    @cls_instance_val
  end

  # クラスメソッドから参照(set)
  def Cls.set_class_instance_val(val)
    @cls_instance_val = val
  end

  # インスタンスメソッドから参照(get)
  def get_class_instance_val
    @cls_instance_val
  end

  # インスタンスメソッドから参照(set)
  def set_class_instance_val(val)
    @cls_instance_val = val
  end
end

cls = Cls.new
#
# クラスメソッドからアクセス
Cls.get_class_instance_val # :-> 初期値「cls_instance_val」が返却される
#
# インスタンスメソッドからアクセス
cls.get_class_instance_val # :-> nil が返却される
#
# インスタンスメソッドからアクセス
cls.set_class_instance_val('instance_val') # :-> 「instance_val」をセット
#
# インスタンスメソッドからアクセス
cls.get_class_instance_val # :-> 「instance_val」が返却される
#
# ではここでクラスメソッドからアクセスしたらどうなるか
Cls.get_class_instance_val # :-> 初期値「cls_instance_val」が返却される
#
# おなじくここでクラスメソッドから「hogehoge」をセットし, インスタンスメソッドからアクセスしたら
# なにが返却されるか
Cls.set_class_instance_val('hogehoge')
cls.get_class_instance_val # :-> 「instance_val」」が返却される
```

## 結論
* クラスのスコープで定義した変数とメソッドのスコープで定義した変数は「同名でも別の変数」となる
* したがって「クラスメソッドからアクセスした変数」と「インスタンスメソッドからアクセスした変数」は別物である
* クラスのスコープで定義した変数を「クラスインスタンス変数」という
* メソッドのスコープで定義した変数を「インスタンス変数」という

## コメントいただいた内容を追記(2017.07.30)
上記の結論を Ruby のオブジェクトの観点で整理し直すと次のようになります。（@kts_hさんから頂戴したご指摘を反映しました）

* インスタンス変数はインスタンスの中に存在する。
* Cls クラスも Class クラスのインスタンスであるから、その内部にインスタンス変数（クラスインスタンス変数）を持つことができる。
* メソッドは、レシーバとなったインスタンス内のインスタンス変数を操作する。
* インスタンスメソッドのレシーバは、普通のインスタンスなので、普通に、インスタンス内のインスタンス変数を操作する。
* クラスメソッドのレシーバは、クラスなので、操作できるのは、レシーバとなったクラス内のインスタンス変数である。
docker cloud で multi-stage なイメージを自動ビルドしてみる

今までDockerイメージにGoなどのコンパイルが必要な言語で書かれたプログラムを埋め込むときは、TravisでプログラムのコンパイルとDockerイメージのビルドをしてから quay.io に push するという方法を使っていたのですが、[docker cloud](https://cloud.docker.com/) が multi-stage builds に対応したので試してみました。

# Multi-Stage Builds とは

こちらの記事がわかりやすかったです。
[Docker multi stage buildで変わるDockerfileの常識](http://qiita.com/minamijoyo/items/711704e85b45ff5d6405)

ひとつの `Dockerfile` で複数回のビルドができて、他のイメージからファイルをもってこれるという機能です。
今回はGo言語のプログラムを前段のビルドでコンパイルし、生成したバイナリを `scratch` イメージにコピーして軽量なDockerイメージを作るために使います。

# 準備

Dockerイメージに埋め込むプログラムを用意します。
`hello, world.` を返すだけのHTTPサーバーです。

```go:main.go
package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "hello, world.")
	})
	http.ListenAndServe(":8080", nil)
}
```

Dockerfile を書きます。

```Dockerfile:Dockerfile
FROM golang:1.8
ADD main.go main.go
RUN go build --ldflags '-s -w -linkmode external -extldflags -static' -o /server

FROM scratch
COPY --from=0 /server /server
EXPOSE 8080
CMD ["/server"]
```

コンパイル部分ですが、なにも考えずに `go build` すると dynamic link なバイナリができてしまうので `ldflags` を指定しています。
`-linkmode external -extldflags -static` で static link なバイナリになるようです。
`-s -w` についてはファイルサイズを減らすために書いています。

`COPY --from=0` が multi-stage builds の他のビルドからファイルをコピーする部分です。

# docker cloud の automated builds 設定

Docker公式ブログに記事があったのでこれを見ながら設定します。
https://blog.docker.com/2017/07/multi-stage-builds/

使用するDockerのバージョンを `17.05.0-ce` に変える必要があるので注意してください。

# 検証

設定が終わったら `git push` してみます。

```console
$ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 360 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/bgpat/helloworld-server
   52f5d80..18cfefd  master -> master
```

しばらくすると docker cloud の自動ビルドが始まります。

<img width="952" alt="スクリーンショット 2017-07-22 11.42.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/69029/b517f2dc-d193-97b7-7039-bd1c0b8999f9.png">

ビルドが終わったら `docker pull` & `docker run` で試してみます。

```console
$ docker pull bgpat/helloworld-server
Using default tag: latest
latest: Pulling from bgpat/helloworld-server
0223ce31a88e: Pull complete 
Digest: sha256:aaafdd815b9448c59da801ac4fa88a548782bb1e1dcef2da0683b08586a176f4
Status: Downloaded newer image for bgpat/helloworld-server:latest
$ docker images bgpat/helloworld-server 
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
bgpat/helloworld-server   latest              004a08d7f83b        About an hour ago   4.79MB
```

イメージのサイズは `4.79MB` でした。軽いです。

```console
$ docker run -d -p8080:8080 bgpat/helloworld-server
4523ae15024fd964d63f3f82c12b6a44d7759ade0e31811a5218b07facc98d1e
$ curl http://localhost:8080/
hello, world.
```

ちゃんと動いているようです。
焼いたDVD(CD)メディアのチェックサムを調べる

入手したISOファイルが壊れているかどうかは、配布元が公開しているチェックサムと比較することで確認できます。ISOファイルを焼いたDVD(CD)メディアの場合には、本記事の方法で確認できます。
例えば、複数枚メディアがあって、その内容が同じかどうかも、この方法で確認できます。

#環境
- Windows 10 Home バージョン 1703 OSビルド 15063.483
- Cygwin 2.8.2-1(x64)
- 対象メディア: DVD-Rにubuntu-14.04.5-server-amd64.iso を焼いたもの 
    
# 方法
単純に考えればdd コマンドで光学ドライブから取り込んでチェックサムを計算すればよいのですが、 そうするとdd結果にゴミがついて出力されることがあるそうです。そのため、isosizeコマンドを使ってセクタ数/セクタサイズを調べたうえで dd を行います。

1. isosizeコマンドを光学ドライブデバイスファイルに実行して、セクタ数とセクタサイズを入手する
1. セクタ数とセクタサイズを指定して dd で取り込む
1. 取り込んだ結果のチェックサムを取る


# 実行結果

```
$ isosize -x /dev/sr0
isosize: /dev/sr0: ISO ファイルシステムではないものと思われます
セクタ数: 316928, セクタサイズ: 2048

$ dd if=/dev/sr0 count=316928 bs=2048 | sha256sum
316928+0 レコード入力
316928+0 レコード出力
649068544 bytes (649 MB, 619 MiB) copied, 126.528 s, 5.1 MB/s
dde07d37647a1d2d9247e33f14e91acb10445a97578384896b4e1d985f754cc1 *-

$ curl -s http://releases.ubuntu.com/14.04.5/SHA256SUMS | grep ubuntu-14.04.5-server-amd64.iso
dde07d37647a1d2d9247e33f14e91acb10445a97578384896b4e1d985f754cc1 *ubuntu-14.04.5-server-amd64.iso
↑たしかに一致している!
```

#参考情報
- [Debian CDのよくある質問 ダウンロードした ISO イメージと書き込んだ光学メディアが正しいものであることの検証をどう行ったらいいのでしょうか?](https://www.debian.org/CD/faq/index.ja.html#verify)
Ruby 破壊的メソッド

# 破壊的メソッド
破壊的メソッドはオブジェクトの値を変更してしまうもの。
同一名のメソッドが存在する場合に破壊的メソッドと非破壊的メソッドのバージョンがある場合、破壊的な方に`!`をつけて命名する慣習がある。
破壊的メソッド全てに`!`が書かれているわけではなくArrayの`#shift`や`#pop`など`!`がつかなくとも破壊的であることはある。

## 非破壊的
`collect`を使用して配列の値を5倍にしてみる。

```ruby:非破壊的
a1 = (1..5).to_a
a2 = a1
puts "a1：#{a1}"
puts "a2：#{a2}"
a3 = a1.collect{|item| item * 5}
#値を確認
puts "a1：#{a1}"
puts "a2：#{a2}"
puts "a3：#{a3}"
#オブジェクトが同じか確認
p a1.equal?(a2)
p a2.equal?(a3)
p a1.object_id
p a2.object_id
p a3.object_id
```

```実行結果
a1：[1, 2, 3, 4, 5]
a2：[1, 2, 3, 4, 5]
a1：[1, 2, 3, 4, 5]
a2：[1, 2, 3, 4, 5]
a3：[5, 10, 15, 20, 25]
true
false
70280240326200
70280240326200
70280240325660
```

非破壊的な場合は使用したオブジェクトの値は変更されていない。
`object_id`を確認するとa3は新たなオブジェクトとして生成されていることを確認できる。

## 破壊的
`collect`に`!`をつけて実行する

```ruby:破壊的
a1 = (1..5).to_a
a2 = a1
puts "a1：#{a1}"
puts "a2：#{a2}"
a3 = a1.collect!{|item| item * 5}
#値を確認
puts "a1：#{a1}"
puts "a2：#{a2}"
puts "a3：#{a3}"
#オブジェクトが同じか確認
p a1.equal?(a2)
p a2.equal?(a3)
p a1.object_id
p a2.object_id
p a3.object_id
```

```実行結果
a1：[1, 2, 3, 4, 5]
a2：[1, 2, 3, 4, 5]
a1：[5, 10, 15, 20, 25]
a2：[5, 10, 15, 20, 25]
a3：[5, 10, 15, 20, 25]
true
true
70138750133780
70138750133780
70138750133780
```

呼び出したオブジェクトの値と参照していたa2も変更される。
a3は新しいオブジェクトとしては生成されず同一のオブジェクトとなっている。
UserDefaultsを使って永続化してみる Swift3.0

コピペ要員として、書き残しておこうと思います

```swift

import UIKit

var jayZsongNameResult : String?

class ViewController: UIViewController {
    
    //構造体に永続化した値を入れておく
    struct artist {
        enum jayZ : String {
            case jayZsongName
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        //最初はnil
        print(UserDefaults.standard.string(forKey: artist.jayZ.jayZsongName.rawValue) as Any)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    @IBAction func save(_ sender: Any) {

        //永続化実行
        let jayZsongName = "4:44"
        UserDefaults.standard.set(jayZsongName, forKey: artist.jayZ.jayZsongName.rawValue)
        jayZsongNameResult = UserDefaults.standard.string(forKey: artist.jayZ.jayZsongName.rawValue)!
    }
}

```

# ソース

[GitHub](https://github.com/Ryosuke-Hujisawa/UserDefault-swift3)

[UserDefaultsを使って永続化してみる Swift3.0](http://off.tokyo/blog/2017/07/22/userdefaults%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E6%B0%B8%E7%B6%9A%E5%8C%96%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B-swift3-0/)
Plot ROC Curve for Binary Classification with Matplotlib


## ROC Curve and AUC
For evaluating a binary classification model, Area under the Curve is often used.  AUC (In most cases, C represents ROC curve) is the size of area under the plotted curve. In ROC (Receiver operating characteristic) curve, true positive rates are plotted against false positive rates. The closer AUC of a model is getting to 1, the better the model is. It means, a model with higher AUC is preferred over those with lower AUC.	

Calculating AUC is not so difficult as you can find scikit-learn module for AUC and all you need to do is passing your prediction vector and target score vector to AUC module. Then, the module calculates true positive rates and false positive rates automatically and returns AUC value. 


## Plot ROC Curve
The purpose of using AUC is to evaluate your model's prediction. As AUC returns results as numeric values. So just by comparing those numbers, you can pick which model has the best prediction performance. However, in my opinion, showing a plot instead of numbers are instinctively much convincible and easy to grab the concept. Therefore, not just calculating AUC, but also I tried to plot ROC  Curve.

Following the instruction here http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html, I implemented the code like below. Note that, in the example below, "predictions_test" contains prediction results by my model and "outcome_test" is target score for comparison.

```
from sklearn.metrics import roc_curve, auc
fpr, tpr, thresholds = roc_curve(predictions_test, outcome_test)
roc_auc = auc(fpr, tpr)

plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=1, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")
plt.show()
```

Then, the following figure returned.

![image](https://qiita-image-store.s3.amazonaws.com/0/186167/fbbea134-7779-e0d5-d7d0-687e68c1c0b7.png)


## ROC Curve for binary classification
Successfully I was able to get ROC Curve polt, however, it is actually a little bit different from what I expected like below.

![image](https://qiita-image-store.s3.amazonaws.com/0/186167/46f8fef1-dd41-02fe-c029-7123fdddee36.png)

It seems like there are only 3 points (including [0,0] and [1,1]) in my ROC curve. It is not a curve at all. I wondered and googled it and I found out this is how ROC curve works.

According to the post: https://stackoverflow.com/questions/30051284/plotting-a-roc-curve-in-scikit-yields-only-3-points, the number of points in ROC curve depends on the number of unique value in input data. In this case, this is binary classification problem so input has only binary value 0 and 1. Therefore, ROC curve for my prediction model is nothing wrong.
Jupyter + Matplotlib > Figureのサイズを拡大する | 字のぼやけを緩和する

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.1.0
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
```

Ubuntu 14.04 LTSからUbuntu 16.04 LTSに変更してから、Matplotlibの環境が変わったように思う。
一つの変化がfigureが小さくなったこと。

figureを大きくする方法を以下に見つけた。
https://stackoverflow.com/questions/332289/how-do-you-change-the-size-of-figures-drawn-with-matplotlib

### 元のサイズ

```py:check_result_170722.ipynb
%matplotlib inline

# learning [Exr,Exi,Eyr,Eyi,Ezr,Ezi] from ADDA
# Jul. 22, 2017

import numpy as np
import matplotlib.pyplot as plt

#data1 = np.loadtxt('log_learn.170722_t1133', delimiter=',')
data1 = np.loadtxt('log_learn.170722_t1200', delimiter=',')

input1 = data1[:,0]
output1 = data1[:,1]

fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)

ax1.plot(input1, output1)

ax1.set_xlabel('step')
ax1.set_ylabel('loss')
ax1.set_xlim([0, 90000])
ax1.set_ylim([0, 0.1])
ax1.grid(True)

#fig.show()
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/25b9cee1-3b0c-3710-d922-58bc0d596e38.png)


### 大きくしてみた

```py:check_result_170722.ipynb
%matplotlib inline

# learning [Exr,Exi,Eyr,Eyi,Ezr,Ezi] from ADDA
# Jul. 22, 2017

import numpy as np
import matplotlib.pyplot as plt
from pylab import rcParams

rcParams['figure.figsize'] = 10,10

#data1 = np.loadtxt('log_learn.170722_t1133', delimiter=',')
data1 = np.loadtxt('log_learn.170722_t1200', delimiter=',')

input1 = data1[:,0]
output1 = data1[:,1]

fig = plt.figure()
ax1 = fig.add_subplot(2,1,1)

ax1.plot(input1, output1)

ax1.set_xlabel('step')
ax1.set_ylabel('loss')
ax1.set_xlim([0, 90000])
ax1.set_ylim([0, 0.1])
ax1.grid(True)

#fig.show()
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/5bde8980-b976-50e7-2a63-ef346e610822.png)

### plt.figure()での指定

文字がぼやける件と関して以下を見つけた。
https://github.com/amueller/word_cloud/issues/188

```py
fig = plt.figure(figsize=(10,10),dpi=200)
```

のようにして、dpiも指定できるようだ。
1200は大きすぎたのでやめて200程度にしてみた。

```py:check_result_170722.ipynb
%matplotlib inline

# learning [Exr,Exi,Eyr,Eyi,Ezr,Ezi] from ADDA
# Jul. 22, 2017

import numpy as np
import matplotlib.pyplot as plt

#data1 = np.loadtxt('log_learn.170722_t1133', delimiter=',')
data1 = np.loadtxt('log_learn.170722_t1200', delimiter=',')

input1 = data1[:,0]
output1 = data1[:,1]

fig = plt.figure(figsize=(10,10),dpi=200)
ax1 = fig.add_subplot(2,1,1)

ax1.plot(input1, output1)

ax1.set_xlabel('step')
ax1.set_ylabel('loss')
ax1.set_xlim([0, 90000])
ax1.set_ylim([0, 0.1])
ax1.grid(True)

#fig.show()
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/d9743b29-50c0-1e04-6ba7-0a73c6095717.png)

字のぼやけ具合が緩和された。
静的ページの更新がキャッシュのせいでできないとき、サーバ側とブラウザ側のどっちを見るべきか

# いくらページをリロードしても何も起きない
...発端は、HTMLとCSSを勉強していた壮年Kのこんな言葉であった。
『**なぜ私がせっかく書いたCSSが一切適用されないのだ？**』

Kはこんな環境で勉強をおこなっている。

- CentOS6.9
- VirtualBox最新版(ついさっき更新した)
- Google Chrome最新版

##そもそも
「キャッシュする要因は**ブラウザ側**か**サーバ側**かにあるはずだ」
そう睨んだK。

Kは待つのが嫌いだ。無論、待たされることも。

結論を言おう。Kは以下の手段を試している。

**ブラウザキャッシュへの対応策**
---
- [ ] スーパーリロード

> Ctrl + F5(Windowsだとこう)


- [ ] 拡張機能「Clear Cache」の導入
- [ ] 開発者用ツールを開いて更新
- [ ] [履歴]からキャッシュを削除

**血迷い策**
---
- [ ] Windowsの再起動
- [x] CentOSの再起動

## 再起動という大気圏突入
『リロードが反映されないなら、お前ごとリロードしてやる』
Kは言った。

Windows、CentOSともに、再起動後は変更が反映された。

しかし彼はそれ以後、二度とVirtualBoxへと足を踏み入れることはなかった。

...

## 復活
Kは一念発起した。
何より、問題を解決せぬまま悶々と過ごす日々に、偽りを感じたのだ。

Kはサーバ側にあると思われる原因を追求した。
**サーバ側キャッシュへの対応策**
---
- [x] Apacheの設定ファイルの編集


ApacheとはWebサーバのソフトウエアである。
つまり、それをいじれば万事解決。
そう考えたKはさっそくコンソールを開き始めた。

## httpd.confファイルを探せ
CentOSではApacheを**httpd**と呼ぶ。
つまりhttpd.confファイルとはApacheの設定ファイルを意味するのだ。

viコマンドで中身を書き換えようとするK。
ところがどこを書き換えたらいいか分からない。

すると、こういう記述を見つけた。

```apache:httpd.conf
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
```
「つまり、『何かいじりたい項目があれば、ここから下に書け』ってことだな。」
そして、その下に"**Directory**"タグが見えるはずだ。

焦ってはいけない。
開始タグだけを見て作業は始められない。


「開始タグが用意されているということは、当然閉じタグもあるということだ。」

## ついに栄華が手中に

```apache:httpd.conf
EnableMMAP Off
EnableSendfile Off
```

Kは書いた。
書ききったのだ。

『更新完了。』
彼は今日もひとつ勉強したのだった。

~完~


# ちなみに

```apache:httpd.conf
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#

# This should be changed to whatever you set DocumentRoot to.
#
<Directory "/var/www/html">
    EnableMMAP Off
    EnableSendfile Off

#
# Possible values for the Options directive are "None", "All",
# or any combination of:
#   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important.  Please see
# http://httpd.apache.org/docs/2.2/mod/core.html#options
# for more information.
#
    Options Indexes FollowSymLinks

#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
#   Options FileInfo AuthConfig Limit
#
    AllowOverride None

#
# Controls who can get stuff from this server.
#
    Order allow,deny
    Allow from all

</Directory>

```

httpd.confファイルにさっきの二行を書き加えると
ブラウザでの更新ができるようになりました。

**要Apacheの再起動です！！！！！！**
FreeBSD インストールメモ on VirtualBox

数年に1回くらいFreeBSDのインストールをするたびに完全初心者スタートになるので、インストール手順くらい残しておこう、という意図のメモ。

# VMイメージのダウンロード

- http://ftp.freebsd.org/pub/FreeBSD/releases/VM-IMAGES/11.0-RELEASE/amd64/Latest/

から `FreeBSD-11.0-RELEASE-amd64.vmdk.xz` をダウンロード

```
$ xz -d FreeBSD-11.0-RELEASE-amd64.vmdk.xz
```

`FreeBSD-11.0-RELEASE-amd64.vmdk`を得る

# VirtualBoxへの取り込み

- 「仮想マシン」-「新規」から仮想マシンを作成、「FreeBSD-11.0」などわかる名前にする
- 「ハードディスク」まで行ったら先ほどの`FreeBSD-11.0-RELEASE-amd64.vmdk`を`$HOME/VirtualBox VMs/FreeBSD-11.0`以下に移動させた上で「すでにある仮想ハードディスクを選択」から選択する
- 仮想マシン作成後「設定」-「ネットワーク」でアダプター2を有効化、ホストオンリーネットワークにする（参照：[VirtualBox上のUbuntuでNAT+ホストオンリーネットワーク構成にするメモ - Qiita](http://qiita.com/hnw/items/77be84138f5ec48353da)）

# 起動＆初期設定

起動してrootでログイン、初期パスワードは無し。

## `/etc/rc.conf`書き換え

```:/etc/rc.conf
ifconfig_em0="DHCP"
ifconfig_em1="inet 10.71.34.11 netmask 255.255.255.0"
sshd_enable="YES"
hostname="freebsd11.hnw.jp"
```

## user追加

```
# useradd
```

hnwユーザーを作成

```
# pw usermod hnw -G wheel
```

wheelグループに追加

## sudoの設定

```
# pkg install sudo
```

```
# visudo
```

wheelにsudo権限を付加（1行コメントアウト）

```:/usr/local/etc/sudoers
%wheel ALL=(ALL) NOPASSWD: ALL
```

ログアウトしてhnwユーザーでログイン

## 設定の続き

あとはお好みで。

```
$ sudo pkg install bash zsh git libxml2 libjpeg-turbo fpc-libpng libmcrypt libxslt
```

某ソフトウェアのFreeBSD上での動作確認環境が作りたかったので、必要パッケージをインストールした。
google-analytics-rails を使ってカスタムディメンション値などを送る方法

`rails` で `google-analytics-rails` を使うと綺麗に `GoogleAnalytics` を導入できて便利。
ただ、カスタムディメンション値を渡したりする方法が若干わかりにくかったのでメモ。

# カスタムディメンション値を設定する

[カスタムディメンション](https://support.google.com/analytics/answer/2709828?hl=ja) を設定するためには二つ手順がある。

## GoogleAnalyticsで設定

https://liginc.co.jp/187767　こちらの記事などを参考に。

## Rails側での設定

`analytics_init`　を通して設定値を渡す。
例えば有料・無料みたいなユーザー属性を渡したいとしたら、以下のような感じで設定できる。

```
// GA::Events::SetCustomDimension.new(カスタムディメンションのインデックス値, 渡したい値)
= analytics_init(custom_vars: GA::Events::SetCustomDimension.new(1, current_user.type))
```

# User ID値を設定する

複数の端末をまたいでセッションのグループを計測したい場合は[
User ID - ウェブ トラッキング](https://developers.google.com/analytics/devguides/collection/analyticsjs/user-id?hl=ja)　などの値を設定する必要があるのでこれの設定方法。

```
= analytics_init( setup: { userId: current_user.id } )
```

こんな感じでできる。
Railsでmysqlに「db:migrate」しようとすると「Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL」

参考ページ
[PRIMARY KEY issue with creating tables in Rails using rake db:migrate command with mysql
](https://stackoverflow.com/questions/33742967/primary-key-issue-with-creating-tables-in-rails-using-rake-dbmigrate-command-wi)

◆事象
railsでmysqlに「db:migrate」しようとすると「Mysql2::Error: All parts of a PRIMARY KEY must be NOT NULL」


◆原因
MySQL 5.7以降では主キーのデフォルト値に「null」は設定不可。


◆解決
・mysqlの場合
　config/initializers/abstract_mysql_adapter.rbを作成

```config/initializers/abstract_mysql_adapter.rb
class ActiveRecord::ConnectionAdapters::MysqlAdapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end
```

・mysql2の場合
　config/initializers/abstract_mysql2_adapter.rbを作成

```config/initializers/abstract_mysql2_adapter.rb
class ActiveRecord::ConnectionAdapters::Mysql2Adapter
  NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
end```
PostgreSQLでのエラー "There are 1 other sessions using the database." 対処

##事象
データベースをアップデート、削除しようとしたところ発生。

##原因と対応
ゾンビプロセスが残ってしまっているので削除する。

DBにログインして以下を実行

```
SELECT 
  pg_terminate_backend(pid) 
FROM 
  pg_stat_activity 
WHERE 
  pid <> pg_backend_pid()
AND datname = 'db_name';
```

##動作環境
PostgreSQL 9.5
centosでgolang + Revel 環境構築メモ

#goインストール

```
 $ yum install golang
```

#ワークディレクトリ作成

```
 $ mkdir gocode
 $ mkdir gocode/{src,bin,pkg}
```

#環境変数設定
```
 $ echo export GOROOT=/usr/lib/golang >> ~/.bash_profile
 $ echo export echo export GOPATH=/XXX/gocode(ワークディレクトリの絶対パス) >> ~/.bash_profile
 $ echo export PATH=$PATH:$GOROOT/bin:$GOPATH/bin >> ~/.bash_profile
 $ source ~/.bash_profile
```
#revel インストール
```
$ go get github.com/revel/revel
$ go get github.com/revel/cmd/revel
```

#revelのパスを通す

```
$ export PATH="$PATH:$GOPATH/bin"
```

#GOPATHへ移動してrevel new

```
 $ revel new myapp
```

#アプリサーバ起動

```
 $ revel run myapp
```

ブラウザから確認 ``localhost:9000``

##動作環境
centos7.2
go 1.7.4
Revel v0.18-dev

##参考
http://qiita.com/kazusa-qooq/items/31db4dad2b44babecd05
http://qiita.com/futoase/items/8134bd96a5c950c497c7
https://github.com/revel/
さくらの VPS で CentOS 7 をインストールした直後にやったこと

# はじめに

さくらの VPS 標準の CentOS 7 をインストールしたあとの作業メモです。

基本的には下記ページを参考にさせていただきました。

* http://qiita.com/yu_0105/items/b7cce7a504eed4e31c79

# ユーザーの追加

上記ページのとおりです。

# SSH の設定

ここも基本的には上記ページのとおりなのですが，再起動時には以下のコマンドを使います。

```bash
% systemctl restart sshd.service
```

# IPTABLES と FIREWALLD

firewalld の方を使います。

インストール状況の確認。 iptables と firewalld がともにインストールされている。

```bash
$ yum list installed | grep -e iptables -e firewalld
fail2ban-firewalld.noarch              0.9.5-3.el7                      @epel
firewalld.noarch                       0.3.9-14.el7                     @base
iptables.x86_64                        1.4.21-16.el7                    @base
```

動作状況の確認。 iptables は停止，firewalld が動作中。

```bash
$systemctl status iptables.service
* iptables.service
   Loaded: not-found (Reason: No such file or directory)
   Active: inactive (dead)

$ systemctl status firewalld.service
* firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-07-19 22:13:22 JST; 2h 57min ago
 Main PID: 511 (firewalld)
   CGroup: /system.slice/firewalld.service
           `-511 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

Jul 19 22:13:17 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon...
Jul 19 22:13:22 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.

$ firewall-cmd --list-all
public (default, active)
  interfaces: eth0
  sources: 
  services: dhcpv6-client ssh
  ports: 
  masquerade: no
  forward-ports: 
  icmp-blocks: 
  rich rules: 
```

とりあえずこのままで良さそう。

# システム文字コードの設定

vim を使おうとしたら日本語の表示が化けていた。
どうやら EUC で表示されている様子。

```bash
$ locale
LANG=C
LC_CTYPE="C"
LC_NUMERIC="C"
...
```

C?
utf に変更する。
基本的には英語表示で良いので en_US.utf8 で。

```bash
$ localectl set-locale LANG=en_US.utf8
# en_US.utf8 の代わりに ja_JP.utf8 でも可
```

ログアウト -> ログインしたら設定完了。

# 開発向けのセットアップ

せっかくなら最新版を使いたい。

## Git のバージョンアップ

本家で紹介されているソースコードからインストールする方法を参考にする。 リポジトリを clone したあと，最初からインストールされている yum のパッケージは削除して，新しいものを入れ直す作戦。

* https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

```bash
$ mkdir ~/repos
$ cd ~/repos
$ sudo yum -y install curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel
$ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
$ git clone git://git.kernel.org/pub/scm/git/git.git
$ git tag
$ git checkout v2.13.3
$ sudu yum -y remove git
$ ./configure --prefix=/usr/local
$ make all
$ sudo make install
# /usr/bin へのパスが残っているので一度シェルを再起動
$ exec bash
$ git --version
git version 2.13.3
```

## tmux のインストール

ソースからインストール。 忘れずに最新版をチェックアウトする。

```bash
$ cd ~/repos
$ sudo yum -y install gcc make autoconf automake pkg-config libevent-devel ncurses-devel
$ git clone https://github.com/tmux/tmux
# 最新版を確認する
$ git tag
$ git checkout 2.5
$ cd tmux
$ ./configure
$ make
$ sudo make install
```

# まとめ

今後は Chef 化したらいいのかな…。
MACにcocos2d-xインストール

#準備
androidやiosでビルドするためにjdkなどの設定が必要
今回めんどくさいのでスキップ

ios:
xcode : storeより

初めてインストールする場合はインストール後、以下のコマンドでビルドできるようにしとく

```
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
```

android:　ビルドツール
ant http://ant.apache.org/bindownload.cgi
SDK https://developer.android.com/sdk/index.html#Other
NDK https://developer.android.com/tools/sdk/ndk/index.html

#cocos2d-xインストール
ダウンロード: http://www.cocos2d-x.org/download

解凍した後、フォルダ内のsetup.pyを実行しセットアップすることでパスが設定されcocosのコマンドが使えるようになる
また先程jdkなどをインストールしていたらここでパスを設定できる

#cocosフォルダを作成


```
cocos new hoge -l cpp
```

cocos new : cocosフォルダを作成
hoge : 名前
-l cpp :　言語指定、cppはC++
MySQLでmysqlimportが出来ない問題を解消

ローカルでうまく動いていた、mysqlimportを含むバッチを開発用サーバーで動かそうとすると
うまく動きません。その原因について調査しました。

## アクセス拒否エラー
以下のようなコマンドを叩くと、

```bat
mysqlimport --fields-enclosed-by='\"' -h [IPアドレス] -u [ユーザー] -p[パスワード] -d [DB名] '/tmp/members.tsv'
```
このようなエラーが発生しました。

```
mysqlimport: Error: 1045, Access denied for user 'someone'@'%' (using password: YES), when using table: members
```
どうやら権限が足りないのでアクセス拒否されたみたいです。
調べてみると同様の質問をしている人が見つかりました。

[stackoverflow mysqlimport: Error: 1045, Access denied](https://stackoverflow.com/questions/6837061/mysqlimport-error-1045-access-denied)

権限を確認してみます。

```mysql
show grants;
→　GRANT ALL PRIVILEGES ON `xxx`.* TO 'someone'@'localhost'
```
GRANT 'ALL' PRIVILEGESと書いてあるから良いのでは？と思ったのですが、
これはDBレベルの権限に該当するもの全てが、特定DBの特定ユーザーに割り当てられているという意味でしかありません。
mysqlimportをするにはFILE権限が必要ですが、権限にも種類があり、FILE権限は「グローバル」レベルというDBレベルよりも上の層にあります。
以下のサイトに権限とレベルの対応表があります。

[権限の種類と設定されている権限の確認](https://www.dbonline.jp/mysql/user/index5.html)

したがって、グローバルレベルで権限を設定するために、

```mysql
GRANT FILE ON *.* to 'someone'@'%';
```
を行う必要があります。普段使っているユーザーでやるとまたAccess deniedと言われてしまったので、
mysqlのrootユーザで入り直して実行しました。

## またエラー
気を取り直してもう一度mysqlimportすると……。

```
The MySQL server is running with the --secure-file-priv option so it cannot execute this statement, when using table: members
```

secure-file-privオプション付きで実行しているのでmysqlimport出来ません！とでました。
解除の方向で調査したのですが、どうもセキュリティ的によろしくないようです。
secure-file-privオプションは特定の場所に置かれているファイルのみインポート出来る設定です。
以下のコマンドをmysql上で叩くことで特定場所を調べられます。

```mysql
SELECT @@global.secure_file_priv;
-> /var/lib/mysql-files/
```

この場所rootじゃないとpermission deniedが出てしまうのでrootでtsvファイル置いて……。

```bat
mysqlimport --fields-enclosed-by='\"' -h [IPアドレス] -u [ユーザー] -p[パスワード] -d [DB名] '/var/lib/mysql-files/members.tsv'
```

うまく動きました！:relaxed:
[Slack] /admin でユーザーが見つからない時は Selected Range で絞ろう [管理者向けTips]

# TL;DR

`YOUR_TEAM.slack.com/admin` の検索結果に管理したいユーザーが含まれないときは絞り込み検索を使う

- ユーザーの状態で絞る
    - Full Members
    - Guest Accounts
    - Deactivated
- Selected Rangeで絞る
    - 対象ユーザーが引っかかるように、 `email` `Username` などの最初の一文字を指定しておく

![image.png](https://qiita-image-store.s3.amazonaws.com/0/1994/47f18789-6c22-97ce-a5a1-80ba18231492.png)

# いきさつ

Slackチームを管理するときよく使う `YOUR_TEAM.slack.com/admin` 。 今日も「このメンバーのアカウントをactivateしてください」という依頼が届きます。よーしまかしとき！と `YOUR_TEAM.slack.com/admin` を開きメールアドレスで検索すると…出てこない。

`YOUR_TEAM.slack.com/team/USERNAME` を直接入力すると、アカウントは存在し、deactivateされていることがわかります。しかし「Enable Account」ボタンは `/admin` の検索結果にしか出てこない。

困ったのでSlackのサポートに雑な英語 + スクショで「この人出てこないねん」とメッセージを投げ込んだら、10分程度で返信がありました。

「ごめんね既知のバグだよ！」

ということで、絞り込み検索してね、という対応策を教わったのでした。

Full MemberとGuest Accounts、あわせて1,500オーバーのチームならではの不具合のような気がしますが、管理画面の検索結果が怪しいな？と思ったらお試しください。早く直るといいな。
Ruby APIリクエスト Hash化への流れ


今回は, Youtube Data APIを例にします.

```rb
require 'net/http'
require 'json'

# baseのURLを設定
uri = URI.parse 'https://www.googleapis.com/youtube/v3/search'

# リクエストの送信
uri.query = URI.encode_www_form({
  :q => "Ruby"
  :key => _api_key_
  :part => "snippet"
})
result = Net::HTTP.get(uri) 
res = JSON.parse(result)

# 取得結果を表示
p res
```

関数化して呼び出すと簡単に使えそう!
Python > 複数のディレクトリにあるファイルの一覧を取得する > glob使用 | modification timeでのソート

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.1.0
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
```

bash > 複数ディレクトリ内のファイルのTFRerocds化 (個別処理)
http://qiita.com/7of9/items/6f6ffdb7dbcebdc8d923
にて作成した複数ディレクトリのTFRecordsをまとめる処理を実装中。

まずはファイルリストの取得。

globというのを使うようだ。
http://www.yukun.info/blog/2008/08/python-directory-listdir-glob.html
情報感謝です。

```combine_TFRecords_170722.py
import glob

"""
v0.1 Jul. 22, 2017
    - get file list
"""

# codingrule:PEP8

res = glob.glob("../run*/IntField-Y_170709.tfrecords")
for elem in res:
    print(elem)

```

```bash
$ python3 combine_TFRecords_170722.py 
../run366_sphere_g26_m1.45/IntField-Y_170709.tfrecords
../run375_sphere_g26_m1.5/IntField-Y_170709.tfrecords
../run354_sphere_g26_m1.33/IntField-Y_170709.tfrecords
../run362_sphere_g26_m1.4/IntField-Y_170709.tfrecords
../run364_sphere_g26_m1.4/IntField-Y_170709.tfrecords
../run368_sphere_g26_m1.45/IntField-Y_170709.tfrecords
../run370_sphere_g26_m1.45/IntField-Y_170709.tfrecords
../run376_sphere_g26_m1.5/IntField-Y_170709.tfrecords
../run367_sphere_g26_m1.45/IntField-Y_170709.tfrecords
../run356_sphere_g26_m1.33/IntField-Y_170709.tfrecords
../run372_sphere_g26_m1.5/IntField-Y_170709.tfrecords
../run355_sphere_g26_m1.33/IntField-Y_170709.tfrecords
../run360_sphere_g26_m1.4/IntField-Y_170709.tfrecords
../run373_sphere_g26_m1.5/IntField-Y_170709.tfrecords
../run365_sphere_g26_m1.45/IntField-Y_170709.tfrecords
../run369_sphere_g26_m1.45/IntField-Y_170709.tfrecords
../run353_sphere_g26_m1.33/IntField-Y_170709.tfrecords
../run357_sphere_g26_m1.33/IntField-Y_170709.tfrecords
../run371_sphere_g26_m1.5/IntField-Y_170709.tfrecords
../run359_sphere_g26_m1.4/IntField-Y_170709.tfrecords
../run358_sphere_g26_m1.33/IntField-Y_170709.tfrecords
../run374_sphere_g26_m1.5/IntField-Y_170709.tfrecords
../run363_sphere_g26_m1.4/IntField-Y_170709.tfrecords
../run361_sphere_g26_m1.4/IntField-Y_170709.tfrecords
```

### modification timeでのソート
(追記 2017/10/03)

参考: https://stackoverflow.com/questions/6773584/how-is-pythons-glob-glob-ordered

glob.glob()実行での並びは`ls -U`と同じになるとのこと。

modification timeでのソートをするにはsort()を使うとのこと。

```py
import os
sorted(glob.glob('*.png'), key=os.path.getmtime)
```
debian9でTensorFlow その２


概要
debian9でTensorFlowやってみた。
kaggleのdogs vs catsやってみた。

環境
linux debian-9.0.0 amd64
python 3.5
tensorflow 1.2.1

写真

100バッチで1000エピソードやってみた。
netは、softmax_linerで10層。
画像は、208*208*3で入力。
ckptを保存した。
タイトルは、accuracy。

![dogs1.png](https://qiita-image-store.s3.amazonaws.com/0/18104/a1e0a16c-41e7-5106-2d15-de51688a5d3f.png)
[クイズ]javascriptと仲良くなるための一歩　第５話「null,undefined,NaNのtypeof」

# null,undefined,NaNのtypeof

```js
typeof null
//=> ?
typeof undefined
//=> ?
typeof NaN
//=> ?
```


:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:

```js
typeof null
//=> "object"
typeof undefined
//=> "undefined"
typeof NaN
//=> "number"
```
Raspberry Pi 3にBluetoothでログインする

# Bluetoothを使う目的

Raspberry Piはとても手軽なデバイスで、WifiもあるのでSSHなどでログインすると普通のLinuxとしても利用でき、HTTPでもいろんなサービスにアクセスでき、重宝します。
私も今週買って試しているのですが、とてもよい！
せっかくなので起動しっぱなしにして必要に応じてHTTPでアクセスしていろんなIoT的な使い方をしたくなりますね。
でも、リブートしたり、またはお家のWifi環境を変えてしまったときにでIPアドレスが変わってしまいSSHでアクセスできなくなります。
Raspberry Pi自体に画面がつけていればip addrコマンドで調べられますが、画面がついていない状態からわざわざセットアップするのが面倒です。

そこで今回は、Bluetoothというペアリング機能を使ってPCと接続状態をいつでも構築できるようにしておき、その接続を使ってTTYでログインできるようにしておきたいと思います。
（これで少なくともSSHがつながらないときに、Bluetoothで一度ログインし、IPだけでも調べることができるようになります）

# ペアリング
(2017/12追記)
接続元はWindows 10を使います。設定→デバイスでBluetoothをみたときに、下記のような状況にしなければなりません。

<img src="https://qiita-image-store.s3.amazonaws.com/0/96277/d77502b1-47bd-fb53-9f90-d481ea1b7b9e.png" width=50%>

手順は下記に書いてありますが、raspberry piをbluetoothで検出可能にします。

https://www.raspberrypi.org/forums/viewtopic.php?t=151112

```
sudo bluetoothctl
[bluetooth] power on
[bluetooth] discoverable on
[bluetooth] agent on
[bluetooth] default-agent
```

次に、Windows 10から「+Bluetoothまたはその他のデバイスを追加する」→「Bluetooth」を選択するとRaspberry Piが見つかるはずと思います（だめであれば、一回Raspberry Pi側でquitしてから何回か上のコマンドをやり直してみる。）

<img src="https://qiita-image-store.s3.amazonaws.com/0/96277/034906f6-8e66-b46b-8f7a-21081a9d30d4.png" width=50%>

ペアリングできたらこうなります。

<img src="https://qiita-image-store.s3.amazonaws.com/0/96277/c3651ba3-1738-0d6f-31ab-656d3ca900de.png" width=50%>


# Bluetoothをシリアル接続で使う設定方法

http://totech.hateblo.jp/entry/2017/03/15/093608

殆どは上記記載の通りでうまくいきました。説明も細かくとても良い記事です。

# 一部だけ変更（watch コマンド）

設定が終わったら、あとは接続先のRaspberry Piでの接続待ち方法を変更し、下記コマンドを打ちます。

```
sudo rfcomm -r watch 0 22 /sbin/agetty -L rfcomm0 115200 &
```
（必要ならこのあとdisown %1か何かで、ログアウト後も動き続けるようにデーモン化しておきましょう）

これでCOMポートにシリアル通信してみましょう。Tera Termを使うならこんな感じ。
（私の場合COM5になっていますが、そこは環境によって変えましょう）

![2017-07-22.png](https://qiita-image-store.s3.amazonaws.com/0/96277/df8ba084-1beb-736b-c5f9-f04206989731.png)

![2017-07-22 (1).png](https://qiita-image-store.s3.amazonaws.com/0/96277/7353e262-8526-ed3a-5914-3a48dd55a22e.png)

少し待ちますが、このようにログイン待機になります。

これでわざわざ画面を触る必要がなくなり、少しハッピーになりました。

# 再起動後も自動起動するようにデーモン化

あと少しです。

デーモン化はこちらが詳しいです。
http://mattintosh.hatenablog.com/entry/20170702/1498985041

かんたんに言うと
sudo vi /etc/systemd/system/dbus-org.bluez.service でExecStart=/usr/lib/bluetooth/bluetoothd --compatのあとに下記を追加します。

```
ExecStartPost=/usr/bin/sdptool add SP
```

次に、rfcomm.serviceという、先程のWatchのデーモンを作ります。

```
[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service
 
[Service]
ExecStart=/usr/bin/rfcomm watch 0 1 /sbin/agetty rfcomm0 115200 linux
 
[Install]
WantedBy=multi-user.target
```

最後にそれをロード。

```
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
sudo systemctl start rfcomm
```

最後にこうなればいいですね。

![2017-07-22 (2).png](https://qiita-image-store.s3.amazonaws.com/0/96277/60eb5138-5d03-230d-9e48-1610859bcc33.png)

お疲れ様でした。結構ハッピーです。