OmniAICreator/Qiita-1.07M huggingface dataset:
DeepSecurity AgentをインストールしたけどManagerに登録できなくて心が折れてこれからの人生を考えている人に贈る最高に予算の大切さを理解できる薄い記事

俺です。

DeepSecurity Agent(DS Agent)のインストールスクリプトを使い、
DS AgentがDS Managerに登録できず、悩んでたんですが答えはすごく簡単でした。


* 原因

DSの`ライセンス足りねえ`

* 対策

DSの`ライセンス買う`

* エラーメッセージ

以下なメッセージを見たらライセンス不足してそうな気配がするのでDS Managerコンソールにアクセスしてチェックしましょう。

`Error: activation was not successful. The manager may not be configured to allow agent-initiated activation,`

```
$ sudo <DSM上で生成したインストールスクリプト>
+ wget -O /tmp/agent.rpm --quiet
+ rpm -ihv /tmp/agent.rpm
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:ds_agent-X.Y.Z-XXXX              ################################# [100%]
ds_agent を起動中: [  OK  ]
Starting thread 'CScriptThread' with stack size of 1048576
HTTP Status: 200 - OK
Starting thread 'CScriptThread' with stack size of 1048576
Activation will be re-attempted 30 time(s) in case of failure
dsa_control
HTTP Status: 400 - OK
Response:
Attempting to connect to https://XXXXXXXXXXXXXXXXXXXXXX/
SSL handshake completed successfully - initiating command session.
Connected with (NONE) to peer at agents.deepsecurity.trendmicro.com
Received a 'GetHostInfo' command from the manager.
Received a 'GetHostInfo' command from the manager.
Error: activation was not successful. The manager may not be configured to allow agent-initiated activation,
or the manager may not be configured to allow re-activation of existing hosts.

Check the manager's System Events for more information.
Operation failed, 30 attempts left; will retry in about 10 seconds```
```

* エラー画面

ああ買わなきゃライセンス

![shinimasu.png](https://qiita-image-store.s3.amazonaws.com/0/42755/821a0e24-f666-6a36-8263-a38fd154b024.png)


おわり
Zabbixのログ監視にてoutput指定をした場合、regexpには厳密に正規表現を書いたほうがいいよ、という話

# この記事は？
- Zabbixにおけるログ監視では正規表現を用いたフィルタリングができる。
- Zabbix2.2からはフィルタリングしたログからさらに出力データを抽出できるようになった。
- が、この正規表現が曖昧だったがゆえに思ったとおりに動かない場合があるので共有します

# Zabbixのログ監視
## ログ監視の監視設定フォーマット
詳細については [Zabbix3.4におけるWEBマニュアル](https://www.zabbix.com/documentation/3.4/manual/config/items/itemtypes/log_items) を参照してください。

```
log[file,<regexp>,<encoding>,<maxlines>,<mode>,<output>,<maxdelay>]
or
logrt[file,<regexp>,<encoding>,<maxlines>,<mode>,<output>,<maxdelay>]
```
| パラメータ | 必須/任意 | 設定内容 |
|:-:|:-:|:-:|
| file | 必須 | ログ監視のファイル名をフルパスで指定。  |
| regexp  | 任意 | フィルタリングする文字列を正規表現で指定。 |
| encoding  | 任意 | 文字コードを指定。Linuxであればiconv -l の結果から、Windowsであれば [Code Page Identifiers](https://msdn.microsoft.com/ja-jp/library/windows/desktop/dd317756(v=vs.85).aspx) のIdentifierか.NET Nameを指定する。 | 
| maxlines  | 任意 | zabbix_agentdが読み取り/送信するログの最大行数の制限。zabbix_agentd.confのMaxLinesPerSecondの値をオーバーライドする。 |
| mode  | 任意 |  all、もしくはskipを指定することで、監視データをどこから読み取るかの指定を行う。デフォルトはall。 |
| output  | 任意 | regexpにてグループ化された場所を\0,\1,\2 .. \9までに区分し、出力する。  |
| maxdelay | 任意 | 大量にログが発生した場合などにログ遅延が発生することを防ぐため、最新のログの時間＋指定時間までのログを遅延が発生しないよう、読み飛ばすようにする時間を指定する  |

## outputの指定で何ができるか
@atanaka7さんの記事 [Zabbix 3.0の新機能：ログファイルから数値を取得](http://qiita.com/atanaka7/items/0e7ad1735d281adcec45) でも紹介されているように、
ログの切り出しや、ログから数値型データの取得・グラフ化ができるようになりました。
私はBIND(DNS)のログ監視などに、結構使っています。

# で、正規表現が厳密でないとどうなるの？
## たとえば、こんなログが出力されると…
zabbix_agent.confにおけるEnableRemoteCommandsとLogRemoteCommandsを有効化(1)にし、
zabbix_getにて次のsystem.runアイテムの取得をします。

```
 $ zabbix_get -s ServerName -p 10050 -k "system.run[echo Msg01 Msg02 Msg03 Msg04 Msg05 Msg06 Msg07 Msg08 Msg09 Msg10 Msg11 Msg12,wait]"
```

すると、zabbix_agentd.logには次のようにログ出力されます。

```
  3644:20170111:160652.658 Executing command 'echo Msg01 Msg02 Msg03 Msg04 Msg05 Msg06 Msg07 Msg08 Msg09 Msg10 Msg11 Msg12'
```


## 監視設定を行い、フィルタリングして拾います
フィルター条件として、「echo (.\*) (.\*) (.\*) (.\*) (.\*) (.\*) (.\*) (.\*) (.\*) (.\*)」と大雑把な設定をしてみます。
outputを指定する前段階では、次のように取得できています。
![Capt1.PNG](https://qiita-image-store.s3.amazonaws.com/0/129674/d137da14-13fc-3db1-257c-e52d1b886e96.png)

##想定では…?
次のようになるつもりでした。

| output | 取得値 |
|:-:|:-:|
| \0  | echo Msg01 Msg02 Msg03 Msg04 Msg05 Msg06 Msg07 Msg08 Msg09 Msg10 Msg11 Msg12'  |
| \1  | Msg01 |
| \2  | Msg02 |
| \3  | Msg03 |
| \4  | Msg04 |
| \5  | Msg05 |
| \6  | Msg06 |
| \7  | Msg07 |
| \8  | Msg08 |
| \9  | Msg09 Msg10 Msg11 Msg12 |

## 実際はこうなった
結果をドン。

![Capt2.PNG](https://qiita-image-store.s3.amazonaws.com/0/129674/3e4e224b-2e6e-b248-1584-bbf23c44aa0b.png)

| output | 取得値 |
|:-:|:-:|
| \0  | echo Msg01 Msg02 Msg03 Msg04 Msg05 Msg06 Msg07 Msg08 Msg09 Msg10 Msg11 Msg12'  |
| \1  | Msg01 Msg02 Msg03 |
| \2  | Msg04 |
| \3  | Msg05 |
| \4  | Msg06 |
| \5  | Msg07 |
| \6  | Msg08 |
| \7  | Msg09 |
| \8  | Msg10 |
| \9  | Msg11 |

## 結果として
どうにも前からパースしてくれているのだと思い込んでいましたが、
どうやらZabbixで使用している正規表現エンジンは後ろからパースするようで、
Msg01から順番に区切ってくれていなかった。
もし一行のログから複数のデータを取得したい場合には、
「ある程度正規表現を厳密にして、そもそものログデータの範囲を絞る」
「後ろからパースされることを気にしつつグループ化する」
ということを頭の片隅においておくといいかもしれない。

* * *
以上
hubot-slack v4でチャネルのID、名前変換

hubot-slack v4になってメッセージを送信する場合、チャネル名(#general)ではなく、チャネルID(Cxxxxx)で送信する必要があります。

`respond` 等でメッセージを受けて処理する分には `msg.envelope.room` にチャネルIDが設定されている為、簡単に処理できるのですが `node-cron` 等を利用してチャネル指定で送信する場合には困ってしまいます。

slack apiにチャネルリストを取得するものがありますが、出来ればhubot内で完結させたい…
https://api.slack.com/methods/channels.list/test

なので、以下メソッドを利用するとid->名前、名前->idの変換ができます。

#### チャネルID -> チャネル名
```js
// room_id...チャネルID
robot.adapter.client.rtm.dataStore.getChannelGroupOrDMById(room_id).name
```

#### チャネル名 -> チャネルID
```js
// room_name...チャネル名
robot.adapter.client.rtm.dataStore.getChannelOrGroupByName(room_name).id;
```
GoogleスプレッドシートのQuery関数で複数行セルにmatchsをヒットさせるには

## Query関数とは
Googleスプレッドシートのワークシート関数に[Query](https://support.google.com/docs/answer/3093343?hl=ja)というのがあって、これが[SQL風の記述](https://developers.google.com/chart/interactive/docs/querylanguage)で他のセルや配列から条件に合った者を抽出できて超便利。検索条件も色々あるが、自分は正規表現による複雑な検索が可能な matches をよく使います。

## matches が改行を含んだセルにヒットしない
なぜか存在するはずのクエリ結果が空になる謎現象があり、調べてみるとセルに改行が入っていた。
一行目にmatchesにヒットするはずの部分文字列があり、二行目には何も入ってなかった。
（二行目に文字があってもなくても結果は同じ）
何が起きてるのかはよくわからないが、matchesは複数行のセルを正しく解釈してくれないようだ。
（starts withとかだと大丈夫）

## 対策
以前[似たような記事](http://qiita.com/Shinoda_Naoki/items/d73e28a8a99fdc5ec1f5)を書いたが、
それと同じ発想で改行を無くしてしまえばよいのではないか、と考えて出来た解決策がこれ。

```js
=QUERY(ARRAYFORMULA(SUBSTITUTE('シート1'!A:X,CHAR(10),"")),"select Col1... where Col1...")
```

見ての通り改行コード`CHAR(10)`をヌル文字で置換しました（除去とも言う）。改行を維持したいなら一旦適当な文字列で置き換えて、再度復元したらいいでしょう。

例えばこう。

```js
=SUBSTITUTE(QUERY(ARRAYFORMULA(SUBSTITUTE('シート1'!A:X,CHAR(10),"<BR>")),"select Col1... where Col1..."),"<BR>",CHAR(10))
```

それにしてもQuery関数は色々癖があって、合わせるのに苦労しますね・・・
Pythonの勉強 Part.1 環境作成編

#はじめに

Pythonを仕事で使うことになりそうなので、メモとして残していきます。
既に多くのサイトにある情報ばかりですが、
記事を書くことで、身について行きやすいのでこの場を使用します。

# 環境作成

python 3.5.0を採用する予定のため、この環境づくりから実施します。

## OSのインストール

1年間無料で使用できる[Amazon Web Service](https://aws.amazon.com/jp/)で環境を作成します。
無料で環境構築が簡単なAmazon Linux AMIを選択して作成します。
このあたりことは、別の記事を参考にしてください。

まずは、EC2のインスタンスの作成を行ってください

## インスタンス作成が終わったら

1. ネットワーク & セキュリティ
 1. Elastic IPを選択
 2. 新しいアドレスの割り当てを実施してパブリックIPアドレスを取得
 3. "アクション"メニューのアドレスの関連付けを実行
 4. 作成したインスタンスとプライベートIPアドレスを設定して関連付けします
 5. この作業は、サーバー再起動時にグローバルIPアドレスが変更されないようにする対策です
2. SSHでリモートログイン
 1. インスタンス作成時にダウンロードしたpemファイルを使ってSSH(私の場合は、teratermを使用しています)でログイン
 2. ec2-userユーザーでログインされます
 3. 念のため、```# passwd ec2-user```でパスワードを変更
 4. rootのパスワードの変更を実施 ```# sudo su -```でroot化
 5. ```# passwd```でrootのパスワードを変更
 6. 一旦、ログアウト
 7. ```# su - ```でログイン
3. yum update
 4. ```# yum update -y```でシステムのアップデートを実施

## python環境を作成する

結構大変でした。。。

ですが、わかってしまえば簡単です。

前提条件：
　ec2-userでpython3.5.0を使用する
　pyenvでpythonを管理する

　※　pyenvはpython環境を管理するツールです
　※　pythonは、複数のバージョンを同じOS内で切り替えて使うことができます


1. pyenvに必要な機能をインストール
 2. rootユーザーになります
 2. yumで必要なものをインストール　
 3. ```# yum install mlocate openssl-devel bzip2-devel zlib-devel bzip2 bzip2-devel readline-devel sqlite3 sqlite-devel openssl-devel gcc gcc-c++ git```
 3. ```# exit```で一旦元のユーザーに戻る
2. pyenvをインストール ```# git clone https://github.com/yyuu/pyenv.git ~/.pyenv```
3. ```# vi .bash_profile``` でプロファイルに以下を追加
> export PYENV_ROOT="${HOME}/.pyenv"
> if [ -d "${PYENV_ROOT}" ]; then
> export PATH=${PYENV_ROOT}/bin:$PATH
> eval "$(pyenv init -)"
> fi

1. ``` # source ~/.bash_profile```で読み込み
2. pythonをインストール　``` # pyenv install 3.5.0```
3. ```# pyenv versions```で現在の状態を確認
> \* system
>　3.5.0 (set by /home/ec2-user/.pyenv/version)

1. pythonのバージョンを変更　```# pyenv global 3.5.0```
2. 再度```# pyenv versions```で現在の状態を確認
>　system
> \* 3.5.0 (set by /home/ec2-user/.pyenv/version)

1. バージョンが変更されていることを確認
2. python自体でもバージョン確認 ``` # python -V```
> Python 3.5.0

3. 一旦、リモートログアウトして再ログインして、pythonのバージョンを再確認
4. 問題なければ、これで環境作成終わり


# 終わりに

インストールの行い方は色々ありますが、これが一番簡単だと思います。
時間軸でログをマッピングするRubyスクリプトサンプル


## Goal

いつどの程度の量あるかわからないログデータを時間軸でプロットして、単位時間内の合計や平均を出力するスクリプトを作る.

## Code

```request.log
datetime,elapse,request_url
2016-12-16T14:00:00Z,123,/blogs
2016-12-16T14:00:00Z,124,/login
2016-12-16T14:00:00Z,30,/blogs
2016-12-16T14:00:00Z,862,/blogs/23456
```

```rb:csv_datetime_mapper.rb
#!/usr/bin/env ruby

require "time"

# max_datetime_count: 無限ループや不要なループをなくすため十分大きい数を設定している
max_datetime_count = 50000
# start_datetime: 時間軸プロット開始時間
start_datetime = nil
# interval_ms: 時間軸プロット間隔ミリ秒
interval_ms = 1000

map = {}

STDIN.each_line do |line|
  # 入力形式
  datetime, elapse, request_url = line.split(',')
  unless start_datetime
    start_datetime = datetime
  end
  t = Time.parse(datetime)
  base_ms = ((t - Time.parse(start_datetime))*1000).div(interval_ms) * interval_ms
  map[base_ms] = [] unless map[base_ms]
  map[base_ms] << elapse.to_i
end

max_datetime_count.times do |i|
  delta_ms = interval_ms * i
  break if delta_ms > map.keys.max
  current_ms = (Time.parse(start_datetime).to_i * 1000) + (interval_ms * i)
  total_elapse = map[delta_ms] ? map[delta_ms].reduce(:+) : 0
  request_count = map[delta_ms] ? map[delta_ms].length : 0
  average_elapse = (request_count > 0) ? total_elapse / request_count : 0
  datetime = Time.at(current_ms / 1000)
  # 出力形式
  puts "#{datetime},#{total_elapse},#{request_count},#{average_elapse}"
end
```

```bash
cat request.log | ruby csv_datetime_mapper.rb

# datetime,total_elapse,request_count,average_elapse
# 2016-12-16T14:00:00Z,32301,209,154
# 2016-12-16T14:01:00Z,33961,213,159
# 2016-12-16T14:02:00Z,35448,237,149
# 2016-12-16T14:03:00Z,34818,237,146
# 2016-12-16T14:04:00Z,34270,231,148
# 2016-12-16T14:05:00Z,36255,257,141
# 2016-12-16T14:06:00Z,35169,245,143
# 2016-12-16T14:07:00Z,32747,232,141
# ...
```

## Behavior

* （ログ時間 - 開始時間）エポックタイム変換ミリ秒を間隔ミリ秒(interval_ms)で割り、これを基底時間とする
* あるログ情報から基底時間を計算しこれをキーとして、ハッシュにログデータを保存する
* 開始時間から間隔ミリ秒を加算していって、ハッシュからデータを取り出し必要な情報を出力する

![スクリーンショット 2017-01-11 14.05.03.png](https://qiita-image-store.s3.amazonaws.com/0/36978/e5e9acbb-783b-836a-ff40-f7f21bbd7dfd.png "スクリーンショット 2017-01-11 14.05.03.png")

### Merit

* 一度基底時間をキーにハッシュ作成するので、ログが時間順でソートされている必要がない
* ハッシュ内データに頼らずに出力をおこなうので、ログが存在しない時間帯があっても抜けがおこらない

### Demerit

* 一度ハッシュに展開するのでメモリを消費する（interval_msを大きくすることでメモリ量をおさえるなどの対応はできる）
Windows 10 KB3176934/KB3176936アップデート中のエラー修復

アップデートによるデータ損失を避けるため、アップデートする前にシステムと大事なデータをバックアップしておくことが重要です。ここで、無料なバックアップソフト―<a href="https://jp.easeus.com/backup-software/free.html">EaseUS Todo Backup Free</a>を皆さんにお薦めします。簡単なステップでシステムとデータをバックアップすることができます。

<h1>トラブルシューターでKB3176934/KB3176936アップデートエラーを解決する</h1>

アップデートする時エラーが発生したら、windowsのトラブルシューターで修復してみるのはいい方法といわれます。KB3176934/KB3176936をアップデートするため、まずはトラブルシューターを使ってみましょう。

１．サーチで「troubleshooting」と検索し、「システム＆セキュリティ」にて「Windowsアップデートエラー修復」を選択します。
２．「Advanced」にて「Apply repairs automatically」をチェックします。
３．「Run as administrator」を選択して、 「次へ 」をクリックします。

<h1>システムファイルチェッカーでシステムエラーを修復する</h1>

１．「Windows」+「R」を同時に押して、「Command Prompt (Admin)」をクリックします。
２．「cd\」と入力してから「Enter」。
３．「sfc /scannow」と入力してから「Enter」。
４．ファイルシステムチェックが自動的に行いますので、エラースキャンと修復が完了するまで待ちます。
Swift3.0 で Array の Element が特定の型のときだけ extension したい

## Swift3.0
Swift3.0 では以下のように Array を直接拡張しようとすると `error: same-type requirement makes generic parameter 'Element' non-generic` と言われてできない。

```swift
extension Array where Element == Book {
...
}
```

調べてみたら以下の2つのやり方で実現できそうだった。

### 1. Collection または Sequence を拡張する

```swift
struct Book {
    let title: String
    let author: String
}

extension Collection where Iterator.Element == Book {
    
    subscript(title title: String) -> Book? {
        return filter{ $0.title == title }.first
    }
    
    subscript(author author: String) -> Book? {
        return filter{ $0.author == author }.first
    }
    
}

let books = [
    Book(title: "the starry rift", author: "james tiptree, jr"),
    Book(title: "hello summer, goodbye", author: "michael coney"),
]

// タイトルが一致する Book を取得
books[title: "the starry rift"]?.author // "james tiptree, jr"
// 著者が一致する Book を取得
books[author: "michael coney"]?.title   // "hello summer, goodbye"

let notBooks = [1, 2, 3]
// Array<Book> ではないのでエラー
notBooks[title: "1"]    // error: ambiguous reference to member 'subscript'
```

上記の例では filter くらいしか使ってないので Sequence を拡張しても正しく動くはず。
ただ、このやり方だと「Collection を実装していて Element が Book」の型が Array 以外に存在したときに意図しない挙動をしそうで怖い。なさそうだけど。

### 2. 対応する protocol を作って Element がその protocol に準拠しているときだけ拡張する

```swift
protocol BookType {
    var title: String { get }
    var author: String { get }
}

struct Book: BookType {
    let title: String
    let author: String
}

extension Array where Element: BookType {
    
    subscript(title title: String) -> Book? {
        return filter{ $0.title == title }.first as? Book
    }
    
    subscript(author author: String) -> Book? {
        return filter{ $0.author == author }.first as? Book
    }
    
}

let books = [
    Book(title: "the starry rift", author: "james tiptree, jr"),
    Book(title: "hello summer, goodbye", author: "michael coney"),
]

// タイトルが一致する Book を取得
books[title: "the starry rift"]?.author // "james tiptree, jr"
// 著者が一致する Book を取得
books[author: "michael coney"]?.title   // "hello summer, goodbye"

let notBooks = [1, 2, 3]
// Array<Book> ではないのでエラー
notBooks[title: "1"]    // error: cannot subscript a value of type '[Int]'
```

KickStarter-Prelude のコードを読んでいるときに見つけた。
https://github.com/kickstarter/Kickstarter-Prelude/blob/master/Prelude/Array.swift

Array 自体を拡張できるのはよいけど、このためだけに protocol を定義するのはちょっとやり過ぎ感があるなぁ...

## Swift3.1
Swift3.1 では最初に書いたような書き方ができるっぽい。やりたいことをストレートに表現できてよさそう。はやくこれになりたい。

```swift
extension Array where Element == Book {
...
}
```

https://github.com/apple/swift/blob/master/CHANGELOG.md#swift-31
Arch LinuxにChrome Remote Desktopをインストールする

Arch LinuxにChrome Remote Desktopを入れたときのメモ。

環境
----
* デスクトップ環境はMATE、日本語入力はfcitx-mozc
* Google Chromeインストール済(`yaourt -S google-chrome`)

Chrome Remote Desktopのインストール
----
[AURのパッケージ](https://aur.archlinux.org/packages/chrome-remote-desktop/)をインストール

```
$ yaourt -S chrome-remote-desktop
```

初期設定

```
$ crd --setup
```

* 作業中のユーザがchrome-remote-desktopグループに追加される
* セッションの設定と画面解像度の設定で都合2回nanoが立ち上がるので、必要な編集をしたあと`Ctrl+X`→`Y`で保存する。
    * セッションの設定では`# exec mate-session`の`#`を消す。
    * 解像度の設定では好みの解像度を入力する。(コメントは書けないらしい)

Chrome Remote Desktopの有効化
----
Chromeウェブストアから「Chromeリモートデスクトップ」をインストールし、設定画面を開いて「リモート接続を有効にする」をクリック。PINを設定する。
![スクリーンショット_2017-01-11_14_26_14.png](https://qiita-image-store.s3.amazonaws.com/0/116906/4a3c2371-fd72-ed3b-d46a-1605181884ce.png)

セッション設定の追加
----
この段階でリモート接続してみると、`Failed to connect to socket /tmp/dbus-**********: Connection refused`というエラーが出て画面が表示されない。MATEがdbusを認識できないのが原因なので、セッションの設定を追加する必要がある。ついでに日本語入力も使えるようにする。

```
$ vim ~/.chrome-remote-desktop-session
```

```
# You will have to...
# Remove...
#
eval $(dbus-launch --sh-syntax) ←ここから
export GTK_IM_MODULE=fcitx 
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx" ←ここまで追記
exec mate-session
```

サービス有効化&起動
----

systemdのサービスを有効化して起動する。

```
$ systemctl --user enable chrome-remote-desktop
$ systemctl --user start chrome-remote-desktop
```

ユーザがログアウトした状態でもサービスを起動したままにするため、lingerを設定。

```
$ loginctl enable-linger <ユーザ名>
```

動作確認
----

別のマシンにもChromeウェブストアからChromeリモートデスクトップをインストールして、設定したマシンに接続してみる。サーバ側のサービス起動直後は「サーバが応答しない」というエラーが出ることがあるので、1分ほど待ってから接続先マシンのリストを更新するといいかもしれない。

あと、VirtualBox上のマシンにChrome Remote Desktopをインストールした場合で、マウスカーソルが出ない時はVirtualBoxのマウス統合をオフにする。

参考
----
* [Arch Linux で Chrome Remote Desktop](http://crckyl.hatenablog.com/entry/2015/03/14/Arch_Linux_%E3%81%A7_Chrome_Remote_Desktop)
* [mate-session cannot start with closed stdin (dbus: connection refused) #94](https://github.com/mate-desktop/mate-session-manager/issues/94)
* [systemd/ユーザー#systemd のユーザーインスタンスを自動起動 - ArchWiki](https://wiki.archlinuxjp.org/index.php/Systemd/%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC#systemd_.E3.81.AE.E3.83.A6.E3.83.BC.E3.82.B6.E3.83.BC.E3.82.A4.E3.83.B3.E3.82.B9.E3.82.BF.E3.83.B3.E3.82.B9.E3.82.92.E8.87.AA.E5.8B.95.E8.B5.B7.E5.8B.95)
渋谷LT1/11

社内で行った勉強会のメモ・感想を書いていきます
#今日のLT
プレゼンター:楢崎さん
OWASP top10の説明
<iframe src="//www.slideshare.net/slideshow/embed_code/key/GwN7KpdmE5zCLG" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/secret/GwN7KpdmE5zCLG" title="20170111 lt" target="_blank">20170111 lt</a> </strong> from <strong><a target="_blank" href="//www.slideshare.net/kumaco">kumaco</a></strong> </div>
###感想

プログラマーとして仕事を始めた以上はセキュリティーのことをよく考えなくてはいけなくて、コードを直接触っているからこそ気づきにくい落とし穴もありそうですね。
覚えなければいけないことはまだまだ多いなと感じました。
#ゼロから作るDeep Learning第二回
プレゼンター：末永さん
なんと大学時代はニューラルネットワーク周りを専攻してたとか
今日は2.5から３.２.５までやりました

###今日のメモ
#####パーセプトロンは座標でイメージするとわかりやすい
y=ax+bのような一次式（閾値）よりも原点に近ければ０、遠ければ１を出力するらしい
#####パーセプトロンは重ねることができる
論理回路のように幾つものゲートを組み合わせることができる
単体のパーセプトロンではXORを作ることができないけれど、ANDとNANDとORを組み合わせることでXORを表現できるようになった
#####複層のパーセプトロンの呼び方
３層で構成されたパーセプトロンは重みを持つ層が２つなので「２層のパーセプトロン」と呼ぶらしい
#####パーセプトロンの組み合わせでコンピュータが作れる
コンピュータはNANDゲートの組み合わせで作れるのでパーセプトロンを重ねていけばコンピュータを作ることができるらしい
NANDゲートによるコンピュータの理論については「NAND to Tetris」というDeepLerning中で紹介されていた本の英語版が無料で読めるらしい
#####パーセプトロンの欠点
閾値は人が決めなくてはならない
つまりは判断基準を人間が設定してあげなければいけないということ
#####活性化関数
y=ax+bという式（閾値）と入力値を比べて1や0を出力する関数を活性化関数という
#####ステップ関数
パーセプトロンの活性化関数で、ある一点を越えると０が１に変化する
#####シグモイド関数
ニューロンでよく使われる活性化関数の一つで、0から1に滑らかに（曲線状に）増えていく
###感想
専攻していただけあって末永さんの説明がとても丁寧でわかりやすい、けれども内容が無いようなのでついていけているようなついていけないような・・・
これを期に高校数学から勉強し直したほうがいいのかもしれない
ElixirからCowboy 1.0と2.0を使ってみる Part 6

# はじめに
ElixirにてCowboyを直接動かすための記事となります。
[前回](http://qiita.com/hayabusa333/items/f3feb22aa54a0954f3b4)の記事では、cssやJavaScriptなどのスタティックファイルをレスポンスで返すようにして、HTMLで読み込めるようにしました。
今回の記事では、画像ファイルをrouteから受け渡すように設定を行います。

[Cowboy1.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/image_file_cowboy)

[Cowboy2.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/image_file_cowboy_two_pre4)

# バージョン
使用した言語やライブラリのバージョンは下記となります。

## cowboy 1.0のバージョン
|  | Version |
|:-----------|--------:|
| Elixir | 1.3.2 |
| Erlang | 19.2 |
| Cowboy | 1.0.4 |

## cowboy 2.0のバージョン
|  | Version |
|:-----------|--------:|
| Elixir | 1.3.2 |
| Erlang | 19.2 |
| Cowboy | 2.0.0-pre4 |

# リクエスト情報からHTMLを作成

今回はimage用のファイルをrouteに設定して、画像ファイルをHTMLに受け渡してみます。
`:cowboy_static` にて今回は画像ファイルを引き渡しますが、`:cowboy_static`で引き渡す場合には`priv`ディレクトリ配下のディレクトリからスタティックファイルを受け渡すするようになっています。
routesに設定を行ったら、htmlにimageファイルの読み込みとimageファイルを所定のディレクトリに配置して完成です。

## cowboy 1.0と2.0の場合

``` elixir:lib/elixir_cowboy_example.ex
  def run do
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []},
      {"/priv/static/image/[...]", :cowboy_static, {:priv_dir, :elixir_cowboy_example, "static/image"}}
    ]

    dispatch = :cowboy_router.compile([{:_, routes}])

    opts = [port: 4000]
    env = [dispatch: dispatch]

    {:ok, _pid} = :cowboy.start_http(:http, 100, opts, [env: env])
  end
```

``` html:priv/static/html/index.html
<html>
  <head>
    <meta charset=\"utf-8\">
      <title>Cowboy Hello!</title>
    <script type="text/javascript" src="priv/static/js/main.js"></script>
    <link rel="stylesheet" type="text/css" href="priv/static/css/main.css">
  </head>
  <body>
    <h1>Cowboy Hello!!</h1>
    <h2>file load test<h2>
    <img src="priv/static/image/button.png" class="button" type='submit' value='test' onclick="func()">
  </body>
</html>
```
サンプル用の画像としては下記の画像を使用しております。
![button.png](https://qiita-image-store.s3.amazonaws.com/0/3014/32ec5a75-0e5a-be6e-4f11-0006009c0be1.png)


# 記載したコードの実行
コードの記述が完了しましたので、それでは実行していきましょう。
いつも通り `iex -S mix` にて cowboy を実行していき、`http://localhost:4000/xxx`にアクセスしてみましょう。
下記のようにブラウザの画面に表示されれば成功です。（）

<img width="1392" alt="スクリーンショット 2017-01-11 15.09.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/b8f4ed19-a3da-a29f-5085-a3b59821ec33.png">

# 最後に
前回と違って今回はHandlerを記載せずにスタティックファイルの受け渡しをおこなうことができました。
スタティックファイルの受け渡しだけならば、今回の方法で受け渡しができますので是非試してみてください。
それではまた次回

# 参考サイト
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/1.0/guide/)
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/2.0/guide/)
[Cowboy Tutorial Part 2: Creating Flat File Blog](http://www.elixirdose.com/post/elixirdose_flatfileblog)
GoでElasticsearchのドキュメントをBulkUpdateする

# 本エントリの内容
Goのelasticsearchクライアントパッケージ elastic を使ってElasticsearch（以下ES）にBulk APIリクエストを送ります。
elasticパッケージのNewBulkUpdateRequestメソッドを使用しますが、使い方がわかりづらく時間がかかってしまったのでまとめておきます。

elastic: https://github.com/olivere/elastic
NewBulkUpdateRequestのGoDoc: https://godoc.org/gopkg.in/olivere/elastic.v5#BulkUpdateRequest

## 検証環境

elasticパッケージ: v3
ES: v2.4.0
Go: v1.6.2

## やること

ESのこういう形式のドキュメント群に

```json
{
    "_index": "shelf",
    "_type": "book",
    "_id": "12345", 
    "_source": {
        "title": "hogehoge",
    }
}
```

1. string型フィールドを追加します
2. array型フィールドを追加します

## string型フィールドを追加する

基本的なコードは以下のとおりです。

```go
b := client.Bulk()
for _, book := range books {
	bookID := strconv.Itoa(int(key))
	req := elastic.NewBulkUpdateRequest().
		Index("shelf").
		Type("book").
		Id(book.ID).
		Doc(map[string]string{
			"author_name": book.AuthorName,
		}).
		DocAsUpsert(true)
	s.Add(req)
}
bulkResponse, err := b.Do()
```

1行目*elastic.Client.Bulk()で *BulkService を作ります。
2行目からのループでアップデートするデータを作成していきます。
IDでESのドキュメントidを指定し、Docで更新するデータを指定します。
上記コードではDocにmap[string]string型を指定しているのでESのドキュメントは次のように更新されます。つまりmapのキー文字列がそのままフィールド名となります。

```json
{
    "_index": "shelf",
    "_type": "book",
    "_id": "12345", 
    "_source": {
        "title": "hogehoge",
        "author_name": "fugafuga"
    }
}
```

ループ処理でデータを準備し終わったら最後に *BulkService.Do() でアップデートリクエストを送信します。
この戻り値のerrがnilの場合でも正常に更新できているとは限りません。bulkResponse.Errorsがtrueの場合は更新に失敗しています。
errはelasticパッケージのエラーでbulkResponse.ErrorsはESの更新エラーという区別のようです。

## array型フィールドを追加する

次にarray型のフィールドbook_tagsを追加してみます。
と言ってもDocの中身を変えるだけです。

```go
Doc(map[string][]bookTag{
	"book_tags": bookTags,
}).
```

bookTagは次の構造のstructとなっています。json表記を指定しておくとESのフィールド名をよしなにしてくれます。

```go
bookTag struct {
	TagID   string `json:"tag_id"`
	TagName string `json:"tag_name"`
}
```

これでESのドキュメントは以下のようになります。

```json
{
    "_index": "shelf",
    "_type": "book",
    "_id": "12345", 
    "_source": {
        "title": "hogehoge",
        "author_name": "fugafuga",
        "book_tags": [{
            "tag_id": "1",
            "tag_name": "JavaScript"
        }, {
            "tag_id": "2",
            "tag_name": "Ruby"
        }],
    }
}
```

### メモ

- 追加するフィールド名を"tags"にするとESの更新エラーとなります。
- ESのscriptを使うともっと細かいことができるようですが（[参考](https://github.com/rjbhewei/customer-property-batch/blob/f5717a9151dff08bdf1d74427973ffe63a7e8a01/KafkaToES2x.go#L187)）、ちょっとうまく動かなかったです。自分で需要ができたらもう少し調べます。
WatchとiPhone間でUserDefaultsを使ってデータを共有するには（watchOS3対応版）

## watchOS1の場合
watchOS1では、AppGroupを使えば、watch・iPhone間でUserDefaultsを共有できたらしい。

[Watch Kit AppとiPhone App間でNSUserDefaultsを使ってデータ共有をする \- NSBlogger](http://nsblogger.hatenablog.com/entry/2015/02/15/nsuserdefaults_watch_kit_and_iphone_app)

## watchOS2以降
watchOS2からはAppGroup使っても共有できなくなった。

[nsuserdefaults \- Swift UserDefault :sharing data via share group doesn't work \- Stack Overflow](http://stackoverflow.com/questions/35432006/swift-userdefault-sharing-data-via-share-group-doesnt-work/35432186)

watch側でUserDefaultsを使うこと自体はできる。**WatchConnectivityでiPhoneからwatchにデータを送って、watch側のUserDefaultsに書き込むしかないみたい。**

## 謎

公式のプログラミングガイドには以下の記述がある。

> iOSが自動的に、iOSアプリケーションの環境設定データ（読み取り専用のコピー）を、Apple Watchに転送するようになっています。WatchKitエクステンションはNSUserDefaultsオブジェクトを使って環境設定を読むことができますが、デフォルト設定を格納しているデータベースを、直接書き換えることはできません。

[watchOSアプリケーション：プログラミングガイド：データの共有](https://developer.apple.com/jp/documentation/General/Conceptual/WatchKitProgrammingGuide/SharingData.html#//apple_ref/doc/uid/TP40014969-CH29-SW1)
[App Programming Guide for watchOS: Sharing Data](https://developer.apple.com/library/content/documentation/General/Conceptual/WatchKitProgrammingGuide/SharingData.html#//apple_ref/doc/uid/TP40014969-CH29-SW1)

が、試したところ、iPhone側のUserDefaultsをwatch側から参照することはできなかった。
環境設定データというのはUserDefaultsのことではないのだろうか。

もし何か分かる人いたら教えてください :bow:
VPCプライベートサブネット内にあるMongoDBのバックアップをS3に保存する

# ◆ 今日やること

PrivateVPN内にあるmonodbのバックアップをS3に保存する

- VPCプライベートサブネットからS3にアクセスするためのエンドポイントの作成
- バックアップするための権限を絞ったIAMユーザーの作成
- mongodbのバックアップの処理のシェルの作成



# ◆ 実装編

### > VPCプライベートサブネットからS3にアクセスするためのエンドポイントの作成

- 手順は変わっていないので、以下のリンクで説明されている通りにエンドポイントを作成します
    - [【新機能】S3がVPCのプライベートサブネットからアクセス可能になりました！ ｜ Developers\.IO](http://dev.classmethod.jp/cloud/vpc-endpoint-for-s3/)

### > バックアップするための権限を絞ったIAMユーザーの作成

- S３バケットの作成
    - バックアップを格納するためのS3バケットを作成します
    
- ポリシーの作成
    - MongoDbbkupPolicy

```
 {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::{作成したバケット}"
        }
    ]
}
```


- 検証ツール
    - [AWS Policy Generator](https://awspolicygen.s3.amazonaws.com/policygen.html)
    - [IAM Policy Simulator](https://policysim.aws.amazon.com/home/index.jsp?#users/mongo_bkupuser/MongoDbbkupPolicy)
    
- IAMユーザーの作成
    - ユーザーを作成したら、上記で作成したポリシーをアタッチします。




### > mongodbのバックアップの処理のシェルの作成

```bash

BUCKET_NAME=hogehoge
BUCKET_PATH=dump

LIMIT=5
BACKUP_FILE=`date +"%Y%m%d-%H%M%S".dump`
BACKUP_DIR=/home/ec2-user/bkup
LOG=${BACKUP_DIR}/${BACKUP_FILE}.log


mongodump -o ${BACKUP_DIR}/${BACKUP_FILE} 2>&1 | tee -a $LOG
tar cvzf ${BACKUP_DIR}/${BACKUP_FILE}.tar.gz ${BACKUP_DIR}/${BACKUP_FILE} 2>&1 | tee  -a $LOG

rm  -rf ${BACKUP_DIR}/${BACKUP_FILE}
rm  -rf ${BACKUP_DIR}/${BACKUP_FILE}.log

# s3へ格納
aws s3 cp ${BACKUP_DIR}/${BACKUP_FILE}.tar.gz s3://${BUCKET_NAME}/${BUCKET_PATH}/

file_count=`ls -1 | grep dump.tar.gz | wc -l`
file_name=`ls -1 | grep dump.tar.gz | head -1`
if [ $file_count -gt $LIMIT ]
then
        aws s3 rm s3://${BUCKET_NAME}/${BUCKET_PATH}/${file_name}
        rm -rf `ls -1 | grep dump.tar.gz | head -1 | xargs rm -rf`
fi
```

- crontabなどで設定

```
*/5 * * * * /bin/bash /home/ec2-user/bkup/bkup.sh 2>&1
```


そういえば、Lambdaでやればよかったかも・・・。


# ◆  参考

- [AWS リソースの管理に関するポリシーの例 \- AWS Identity and Access Management](http://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_examples.html)
- [特定のS3のフォルダにのみアクセス権のあるIAMユーザーを使ってCyberduckから参照する ｜ Developers\.IO](http://dev.classmethod.jp/etc/specify_s3_folder_iam_cyberduck/)
- [ユーザーポリシーの例 \- Amazon Simple Storage Service](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-policies-s3.html)
- [IAM ロールの切り替え（AWS Command Line Interface） \- AWS Identity and Access Management](http://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_use_switch-role-cli.html)
2バイト文字は2として文字列の長さをカウントするGoogleAppsScript関数

# 文字列の長さをカウントする関数
* GoogleAppsScriptでの文字カウント

　次のようにしても，lenが7になってしまう。

```java:文字数カウント
  var str="ようこそGAP";
  var len = str.len; //lenは7になる
```

* 2バイト文字は2としてカウントする関数

```java:文字数カウント
function main(){
  var str="ようこそGAP";
  var len = strLenJ(str); //lenは11になる
}

function strLenJ(str) {//2バイト文字は2として文字数をカウント
  var len = 0;
  str = escape(str);
  for (var i = 0; i < str.length; i++, len++) {
    if (str.charAt(i) == "%") {
      if (str.charAt(++i) == "u") {
        i += 3;
        len++;
      }
      i++;
    }
  }
  return len;
}
```

参考：http://www.tohoho-web.com/js/string.htm
e.stopPropagationメソッドを使ったらRailsのlink_toでGETメソッドにしか飛ばなくなった

## 概要
Ruby on Railsでアプリケーションを作成中、jQueryでプルダウンを作成することに。
プルダウンメニューには

`link_to ~~_path, method: :delete`

 というログアウト用のリンクを設定。
プルダウンも無事実装し、めでたしめでたし・・・ん？
リンクで飛ぶと Routing Erorrが発生するぞ？
`method: :delete`で　指定しているはずなのに、何故かDELETEに飛ばずにGETに飛ぶ現象に

## 問題のコード

```
$(function(){
    $('.クラス名').on('click',function(e){
        $(this).children('.クラス名').slideToggle();
        e.stopPropagation();
  });

  $(document).on('click', function() {
    $('.クラス名').hide();
    });

  $('.クラス名').click(function(e) {
    e.stopPropagation();});
});

```

## 原因
プルダウンを作ったjQueryの`e.stopPropagation`メソッドが悪さをしていた。


## 解説


`link_to method: :delete` は aタグに変換された時に`data-method="delete"`の形になる。
この形で実際に行われる挙動はjavascriptが担っており、階層としてはdocumentにイベントを仕掛けている。
`e.stopPropagation`メソッドは親階層への伝播をとめるメソッド
ここでは、プルダウンを開くために押した先に要素より親の階層へのイベントの伝播がしなくなっている状態。
結果としてdocumentに仕掛けている`data-method="delete"`までクリックしてもイベントが届かない。
つまりdeleteが無効化されてデフォルトのGETで　リンクを飛ばしている、ということになっている。

## 何をしたか
`e.stopPropagation();`を使いつつ解決する方法が分からなかった。
ということで、documentを何処でもクリックしたらプルダウンを閉じる、
という記述にプルダウンとプルダウンメニューを押したときだけは閉じない、というif文を加えた。


## 修正したコード
```
$(function(){
    $('.クラス名').on('click',function(e){
        $(this).children('.クラス名').show();
  });

  $(document).on('click', function(e) {
    if (!$(e.target).closest('.クラス名').length){
      $('.クラス名').fadeOut();
  }
});
});

```
DB2DBA: スキーマ内の全オブジェクトを削除する

管理プロシージャADMIN_DROP_SCHEMAを使用することで、スキーマ内の全オブジェクト（表、索引等）を一括DROPすることができます。

# 手順
## SYSTOOLSPACE表スペースの作成
ADMIN_DROP_SCHEMAを実行するためには、SYSTOOLSPACEという名称の表スペースを事前に作成しておく必要があります。以下はSYSTOOLSPACEのCREATE文の例です（マニュアル上指定がないため、CREATE TABLESPACEの各オプションはデフォルトでよいと思われます）。

```sql
CREATE TABLESPACE SYSTOOLSPACE
	MANAGED BY AUTOMATIC STORAGE USING STOGROUP IBMSTOGROUP
	EXTENTSIZE 4 ;
```

## ADMIN_DROP_SCHEMAの実行
以下の引数を指定してプロシージャを実行します。

1. 対象スキーマ名
2. NULLで固定
3. エラーテーブルのスキーマ名
4. エラーテーブル名

エラーテーブルはSYSTOOLSPACE上に作成され、DROPに失敗したオブジェクトに関する情報がINSERTされます（詳細は後述）。

```sql
CALL ADMIN_DROP_SCHEMA('TEST01', NULL, 'SVC34', 'ADMIN_DROP_SCHEMA_ERROR') ;

  出力パラメーターの値
  --------------------------
  パラメーター名: ERRORTABSCHEMA
  パラメーター値: SVC34

  パラメーター名: ERRORTAB
  パラメーター値: ADMIN_DROP_SCHEMA_ERROR

  リターン状況 = 0

```

## エラーテーブルの確認
DROPに失敗したオブジェクトがあった場合、エラーテーブルを参照し原因を特定してください。エラーテーブルのレイアウトは以下の通りです。

|列名|データ・タイプ|説明|
|:---|:-----------|:---|
|OBJECT_SCHEMA|VARCHAR(128)|DROP対象オブジェクトのスキーマ名|
|OBJECT_NAME|VARCHAR(128)|DROP対象のオブジェクト名|
|OBJECT_TYPE|VARCHAR(30) |DROP対象のオブジェクトタイプ|
|SQLCODE|INTEGER|DROP失敗時のSQLCODE|
|ERROR_TIMESTAMP|TIMESTAMP|DROPが失敗した時刻|
|STATEMENT|CLOB(2 M)|DROP対象オブジェクトのDDL|
|DIAGTEXT|CLOB(2 K)|DROP失敗時のエラーメッセージ|



## エラーテーブルの削除
エラーテーブルは再利用できないので、結果確認後に削除しておきましょう。

```sql
DROP TABLE SVC34.ADMIN_DROP_SCHEMA_ERROR ;
```

# 注意事項
以下のオブジェクトはADMIN_DROP_SCHEMAでは削除されません。
- Index extensions
- Nicknames
- Packages
- Typed tables
- Array types
- User-defined structured types (and their transform functions)
- Typed views
- Jars (Java™ routine archives)
- Staging tables
- XSR objects

また、対象のスキーマそのものも削除されないため、必要であればDROP SCHEMAを実行してください。

# 参考資料
- IBM Knowledge Center
    - DB2 for Linux UNIX and Windows 11.1.0
        - [ADMIN_DROP_SCHEMA プロシージャー - 特定のスキーマとそのオブジェクトのドロップ](https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.1.0/com.ibm.db2.luw.sql.rtn.doc/doc/r0022036.html)
        - [SYSTOOLSPACE および SYSTOOLSTMPSPACE 表スペース](https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_11.1.0/com.ibm.db2.luw.admin.gui.doc/doc/c0023713.html)
phpディレクトリ作成

#phpディレクトリ作成

ディレクトリがある場合は何もせず、無い場合は作成する処理。(入れ子構造対応)

```php:
public function mkdir($path, $mod= 0777) {
    if (file_exists($path))
        return TRUE;
    if (@mkdir($path, $mod, TRUE)==FALSE)
        return FALSE;
    chmod($path, $mod);
    if (file_exists($path))
        return TRUE;
    return FALSE;
}
```

mkdirの箇所は権限関係で書き込めない場合のエラーを@でエラー表示をしないようにしている。
is_writeble関数で下記のように権限チェックも考えたが、再帰的にディレクトリを作成する際のチェックも面倒なので無し。

```php:
    if (is_writable($xxxx)==FALSE)
        return FALSE;
```
また、mkdirの第二引数の権限付与はumaskの影響を受けるため、直後にchmodで対応している。

##備考
php7.0以降で書く場合は、引数・戻り値ともに型指定ができるので下記になる。

```php:
public function mkdir(string $path, int $mod= 0777) :bool {}
```

以上メモ。
Storyboardで消耗しないためのTipsその２ - Storyboardの変更を翻訳stringsファイルを追従させるまともな方法

Storyboardを変更してもstringsファイルが追従してくれない問題について
http://qiita.com/kenmaz/items/5e749f37e7095e0d54f2#storyboardの変更をstringsに反映する
で解決策を書きましたが、やや不安定な挙動だった＆Xcode8.2.1の時点でこのテクニックは使えなくなったようです。

そこで他に解決策がないか調べたところ、より単純でまともな解決策が見つかりました。

# XLIFFをexportしてimportするだけでOK
Storyboardを変更したらXLIFFをexportして、.xliffを修正した後にimportするだけで、Storyboardの変更に翻訳済みstringがうまくマージされてくれます。至って単純です。

## 検証環境
Xcode8.2.1(8C1002)

## 手順
LabelがひとつだけあるStoryboardを作成し、Localizationの設定でJapaneseを追加しておきます。この時点では`Main.strings (Japanese)`は空です。
![スクリーンショット 2017-01-11 12.03.28.png](https://qiita-image-store.s3.amazonaws.com/0/8399/31fdf86f-82b5-bae1-522d-75dc692775ed.png)

おもむろにメニューから `Editor > Export for Localization..`を選択してja.xliffファイルを生成します。xliffを開くと、`Label`キーが見つかるので、適当に翻訳文字列を記述して保存します。
![スクリーンショット 2017-01-11 12.04.04.png](https://qiita-image-store.s3.amazonaws.com/0/8399/8d25fde2-db29-86f2-efd3-383bbd876a67.png)

Xcodeに戻って`Editor > Import Localizations`を選択してja.xliffをインポートします。すると`Main.strings (Japanese)`に翻訳キーと文字列が追加されます。
![スクリーンショット 2017-01-11 12.04.45.png](https://qiita-image-store.s3.amazonaws.com/0/8399/a6d8e7a4-90e2-dfa4-8fc0-95f221c2cf0f.png)

次にStoryboardに変更を加えます。`Label2`を追加します。
![スクリーンショット 2017-01-11 12.05.00.png](https://qiita-image-store.s3.amazonaws.com/0/8399/d631669d-bc62-7402-e52b-52f6f1cabcdb.png)

先程と同様にja.xliffをエクスポートすると、既存の翻訳文字列（`Label=ラベルです`）が維持されたまま、`Label2`キーが追加されていることがわかります。
![スクリーンショット 2017-01-11 12.05.34.png](https://qiita-image-store.s3.amazonaws.com/0/8399/7eedd024-e2f3-241d-ebb8-d8b3e2a7f3c3.png)

ja.xliffで新たな翻訳`Label2=ラベル2です`を追記し、Xcodeにインポートし直します。`Main.strings (Japanese)`に翻訳が追加されます。Storyboardの変更にstringが追従できていますね。
![スクリーンショット 2017-01-11 12.06.17.png](https://qiita-image-store.s3.amazonaws.com/0/8399/f43b9063-1182-a95c-fd4b-b5678d6484fc.png)

要素が削除されてもきちんと追従してくれます。`Label`を削除して見ましょう。
![スクリーンショット 2017-01-11 12.06.27.png](https://qiita-image-store.s3.amazonaws.com/0/8399/370b867d-6bec-7dee-95dd-c0f952452e5c.png)

ja.xliffをエクスポートすると、削除したLabelに対応する翻訳設定も削除されていることがわかります。
![スクリーンショット 2017-01-11 12.06.56.png](https://qiita-image-store.s3.amazonaws.com/0/8399/9bbbb96a-1b33-ad1b-740c-4f7b23221c24.png)

何も変更を加えずにja.xliffをインポートすると、`Main.strings (Japanese)`からも`Label=ラベル1です`が削除されていることが確認できます。削除にも追従できていますね。
![スクリーンショット 2017-01-11 12.07.18.png](https://qiita-image-store.s3.amazonaws.com/0/8399/49ec641f-f31f-58b8-c49f-b384a6830571.png)

きちんとPreviewもできています。
![スクリーンショット 2017-01-11 12.07.58.png](https://qiita-image-store.s3.amazonaws.com/0/8399/70c26a51-17c6-b25f-25c4-55814d2d4c17.png)

# 所感
いつからこういう挙動になってくれたのかは不明ですが、これでまともなStoryboardの翻訳作業ができそうです。
とはいえAndroid Studioなど比べるとまだまだこういう点は弱いので、Xcodeには頑張って欲しいところです。
jupyter 上で、データを暗号化して保存し、必要に応じて復号する

サーバ上にカジュアルに、パスワードを暗号化しておいておいて、復号化して使いたいというようなことを思ってつくったスクリプトです。

```
# サーバ上にパスワードなどを暗号化した状態でおく方法
# 共通鍵での保存しておいて、jupyter で呼び出します。
# カジュアルな利用ではまあいいかなと

import gnupg
gpg = gnupg.GPG()

# 保存するテキストを作成
conf = """
{'id':'foo',
'passwor':'bar'
}
"""
# これで共通鍵 bar でテキストで暗号化
x = gpg.encrypt(conf, symmetric=True, passphrase='bar', encrypt=False)

# ファイル test.txt に保存　バイナリーなんで、utf-8 のテキスト化行います。
f = open('test.txt','w')
f.write(x.data.decode('utf-8'))
f.close()

# 保存したファイルを呼び出して復号します。
f = open('test.txt','r')
y = gpg.decrypt((f.read()), passphrase='bar')
conf = eval(y.data.decode('utf-8'))
print(conf)

```
VMware > OpenGL3.0以降の対応

```txt:動作環境
Windows 8.1 pro (64bit)
on VMware Workstation v12
SketchUp 2017
```

SketchUp の2017を上記のゲストOS上で実行しようとすると「OpenGLは3.0以降でないとだめですよ」となり起動しなかった。

VMware Workstation Playerでの情報は
http://pubs.vmware.com/Release_Notes/jp/workstation/12player/player-12-release-notes.html

> 高度なグラフィックス
> OpenGL 3.3

[Workstation 12 Player for Windows ドキュメント センター](https://pubs.vmware.com/player-12-windows/index.jsp?topic=%2Fcom.vmware.player.win.using.doc%2FGUID-EA588485-718A-4FD8-81F5-B6E1F04C5788.html)
に「3D グラフィックス アクセラレーションを使用するためのホスト システムの準備」がある。
このあたりを設定することになるのだろうか。

VMwareの有償版(Playerではない)の設定の場合上記と異なるかは未調査。
Laravel5.3でselect for update する方法

# select for updateしたい！
公式ドキュメントにはサラッとtransactionの事が書いていますが、select for updateはどうするのかがわかりません。

# laravelのtransactionはなんて素敵な仕組み
* オフィシャルのドキュメントを読んで頂ければわかるんですが
 * https://laravel.com/docs/5.3/database#database-transactions

> You may use the transaction method on the DB facade to run a set of operations within a database transaction. If an exception is thrown within the transaction Closure, the transaction will automatically be rolled back. If the Closure executes successfully, the transaction will automatically be committed. You don't need to worry about manually rolling back or committing while using the transaction method:

* transactionメソッドのclosure内で書いておけば、commitやrollbackも自動でやってくれる素敵仕様
* デッドロックした場合の再試行もtransactionメソッドの引数で指定できます。

# 結論
* いやーオフィシャルドキュメントを疑ってしまうぐらい簡単に書けますね・・・。

```php
\DB::transaction(function () use ($id) {
    $model = \Hoge\Model::lockForUpdate()->find($id);
    $model->name = 'ほげ太郎';
    $model->save();
});
```
Visual Studio2015でPython3 NumPyをGUIからインストール

# GUIからインストールする方法

## Install Python Packageを選択
![pack.png](https://qiita-image-store.s3.amazonaws.com/0/158129/275d61fd-9a24-7d84-c213-b4468f226d3d.png)

## numpyを入力してOK
![pack2.png](https://qiita-image-store.s3.amazonaws.com/0/158129/c7343b6d-c895-d607-bed4-4ce9d90ce693.png)

上記で完了
Windows上のvagrantでネットワークドライブを自動で割り当てる

# Windows上のvagrantでネットワークドライブを自動で割り当てる

## 前提条件

- Windows10上で確認しています。
- VMのIPアドレスは固定（例：10.x.y.z）とします。
- VM上ではSambaなどでファイル共有の設定が完了しているものとします。
- ネットワークドライブの文字はあらかじめ決めておく（例：J）ものとします。
- ネットワークドライブに割り当てるファイル共有のパスはあらかじめ決めておく（例：\\\\10.x.y.z\\share）ものとします。

## 準備1. vagrant-triggersプラグインのインストール

```bat:
vagrant plugin install vagrant-triggers
```

## 準備2. 資格情報の登録

ファイル共有の資格情報を登録します。Windows10の場合は↓のとおり。IPアドレス、ユーザー名、パスワードを入力してOKで登録。

```
コントロールパネル→ユーザーアカウント→資格情報マネージャー→Windows資格情報の追加
```

Powershellからコマンドで登録する場合はこちら。

```bat:
cmdkey /add:10.x.y.z /user:ユーザー名 /pass
```

コマンドで登録内容を確認するにはこちら。

```bat:
cmdkey /list
```

## 準備3. Vagrantfileの変更

「J:」に割り当てる場合は以下の内容をVagrantfileに追加します。  `J` と`\\\\10.x.y.z\\share` は適宜変更してください。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  # other configuration ...

  config.trigger.after :up do
    run 'powershell -Command "New-PSDrive -Name \"J\" -PSProvider FileSystem -Root \"\\\\10.x.y.z\\share\" -Persist"'
  end
  config.trigger.before :halt do
    run 'powershell -Command "Remove-PSDrive -Name \"J\" -PSProvider FileSystem -Force"'
    run 'net use /delete J:'
  end
end
```

## 実行

- `vagrant up` するとネットワークドライブが割り当てられます
- `vagrant halt` するとネットワークドライブが切断されてドライブ自体も登録が解除されます
GitHubでIPアドレスを検索する方法

# 概要
IPアドレスの置き換えをするので、使用元コードをGitHubで探そうとしたけどうまくでてこなかったのでちょっと工夫してみたという話です。

# やりかた
結論からいうと、IPアドレスを検索したいときは、IPアドレスをダブルクオートでくくってやれば良さそうです。
ダブルクオートでくくる事でand検索ができて、かつ、ドットのような記号が無視されるそうです。
172.28.1.2を検索する場合は、
"172.28.1.2"とすると良いです。
ただ、172と28と1と2を含む文字列の検索になるので、不要な単語を含んでしまう事ももちろんあります・・・。

## 参考
https://help.github.com/articles/searching-code/#considerations-for-code-search
組み込みのechoと/bin/echoの違い

c++のユニットテストでhttpのモックサーバーをsystem関数で作った時、Ubuntuでうまく動作しませんでした。

```c
system( "echo -e 'HTTP/1.0 200 OK\\r\\nContent-Type: text/plain\\r\\n\\r\\nhoge' | nc -l 8080 > /dev/null &");
```

system関数は内部的に sh -c "command" の形式で実行されます。つまり、

```
$ /bin/sh -c "echo -e 'ho\nge'"
```

のような感じです。echo の -e オプションはエスケープシーケンスを解釈する指定です。
これをUbuntuで実行すると期待する結果になりません。

```
-e ho
ge
```

-eが余分です。
これは、Ubuntuでは/bin/shのデフォルトがdashで、dashの組み込みのechoに-eオプションが無いためです。

```
$ man dash
```

で確認してみるとたしかに -e オプションはありません。
元のテストコードは次のように /bin/echo にして対処しました。

```c
system( "/bin/echo -e 'HTTP/1.0 200 OK\\r\\nContent-Type: text/plain\\r\\n\\r\\nhoge' | nc -l 8080 > /dev/null &");
```

まとめ

- 組み込みコマンドと外部コマンドの仕様が異なる場合があるので注意する（echoに限らず）

また、外部コマンドの場合も環境によって仕様が異なる場合もあると思うため、注意が必要です。
devise + paranoia で validates にも deleted_at で scope されちゃって、 emailなどの uniqueness の validationができない件

http://qiita.com/akasakas/items/f57286a1de9b6403c745

環境 Rails 5. Paranoia 2.2.0, devise 4.2.0
soft delete を paranoia を使って実装。deviseをつかってuserを実装。
状況として、登録済みのuserをsoft deleteしているとする。このとき、同じemailで再登録をしようとしていると仮定。
このとき、validates においても soft delete されたエントリーは除外されてしまうため、DBへの書き込み時にuniquenessについてのエラーが出てしまう (email に indexつけてたら）。

ref.
https://github.com/rubysherpas/paranoia/issues/319

しょうがないので、custom methods を追加。User.with_deletedについてmanuallyに検査してあげる。

```app/model/user.rb
  validates :email, email: { strict_mode: true }, presence: true, uniqueness: true
  validate :is_unique_from_all_entries, on: :create

  def is_unique_from_all_entries
    test = User.with_deleted.find_by(email: email)
    if test.present?
      if test.deleted_at.nil?
        errors.add(:email, "is already used.") #ここには来ないはずだが...
      else
        errors.add(:email, "is soft deleted.") #今回どうにかしたいのはこのケース
      end
    end
  end
```
GAE/Goでurlfetch: SSL_CERTIFICATE_ERRORが出たときの対処法

正月休み明けに、GAE/Goのサーバを動かすとCloudStorageへのアクセスを行うコードなどで次のようなエラーが出るようになりました。

```
API error 6 (urlfetch: SSL_CERTIFICATE_ERROR): [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
```

そのときの環境は、OSX上でAppEngineのGo SDK 1.9.48を使っていて、GoogleCloudSDKは138.0.0でした。

その後`gcloud beta auth application-default login`などを試すも解決せず、ずっとハマってましたがようやく解決方法を見つけました。

- [Issue 13476 \- googleappengine \- ssl certificate error \- Google App Engine \- Google Project Hosting](https://code.google.com/p/googleappengine/issues/detail?id=13476)
- [Issue 12588 \- googleappengine \- UrlFetch fails to validate SSL certificate Subject Alternate Names \- Google App Engine \- Google Project Hosting](https://code.google.com/p/googleappengine/issues/detail?id=12588)


原因がよくわからないので次の対応でいいのか分かりませんが、とりあえず動かすことができます。

GoのAppengineSDKの中の、`google/appengine/api/urlfetch_stub.py`の以下の箇所を修正。

```
before
> 401           default_port = 443

after
> 401           connection_class = httplib.HTTPSConnection                                                                        
> 402           default_port = 443
```


google-cloud-sdkの方のappengine SDKを使っている場合は、
`google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch_stub.py`に同様の修正をすると解決します。

appengine SDKのバージョンが変わると、修正箇所が変わるかもです。
GolangのhttptestでHTTP2を使う

Golangは[Go1.6でHTTP2をサポートした](https://golang.org/doc/go1.6#http2). また2017年2月にリリース予定のGo1.8ではServer Pushを行うためのメソッドも新たに[追加される](https://tip.golang.org/doc/go1.8#h2push)（使い方は [HTTP/2 Server Push · Go, the unwritten parts](https://rakyll.org/http2push/) が詳しい）. 今後GolangでのHTTP2の利用はさらに増えると考えられる. HTTP2を使うアプリが増える分そのテストも重要になる. 

Go1.6におけるHTTP2サポートは素晴らしくAPIの変更なしにサポートが行なわれた.　Server側でh2を有効にするには`ListenAndServeTLS`で起動すればよいしClientも`DefaultClient`を使えばよい.　Golangでサーバーのテストをするときは[httptest](https://golang.org/pkg/net/http/httptest/)パッケージが主に利用されるが，これほど簡単に使える訳ではない.　以下のように軽く設定を入れる必要がある.

```go
func TestHTTP2Server(t *testing.T) {
	ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	}))

	if err := http2.ConfigureServer(ts.Config, nil); err != nil {
		t.Fatalf("Failed to configure h2 server: %s", err)
	}
	ts.TLS = ts.Config.TLSConfig
	ts.StartTLS()

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}

	if err := http2.ConfigureTransport(tr); err != nil {
		t.Fatalf("Failed to configure h2 transport: %s", err)
	}

	client := &http.Client{
		Transport: tr,
	}

	res, err := client.Get(ts.URL)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer res.Body.Close()

	t.Logf("is HTTP2: %v (%s)\n", res.ProtoAtLeast(2, 0), res.Proto)
}
```

`httptest.Server`と`http.Transport`を準備し（`InsecureSkipVerify`が必要），`http2.ConfigureServer`と`http2.ConfigureTransport`を呼ぶ必要がある. これで`NextProtos`などh2のネゴシエーションに必要な設定がされる.

GolangのHTTP2パッケージは今も[golang.org/x/net/http2](https://godoc.org/golang.org/x/net/http2)で開発がされており，リリース時には[bundleコマンドというパワー系コマンド](http://qiita.com/deeeet/items/87aaca2ef9c8ab145877)で標準の`net/http`にぶっ込まれる. テストは主にxにあるが`net/http`にもh2のテストがある．ここでも今回紹介した方法でテストが書かれている（[参考](https://github.com/golang/go/blob/master/src/net/http/clientserver_test.go#L76-L112)）.


ちなみに`http.Client`ではServer Pushを受け取ることはできない.テストを書くには[フレームのDecodeなどを頑張る必要がある](https://github.com/golang/net/blob/master/http2/server_push_test.go)...
RailsでSlimでAjax通信を簡単に実装する

#RailsでSlimでAjaxで送信する

```haml:view側処理

= link_to '承認', apporoval_path(oem), class: "apporove_ajax", remote: true, method: "patch", data: { confirm: '送信しますか？' }
                
javascript:
  $('.apporove_ajax').on('ajax:success', function(event, xhr, status, response) {
    alert("成功！")
  });

  $('.apporove_ajax').on('ajax:error', function(event, xhr, status, response) {
    alert("失敗！")
  });
```

```rb:controller側
def apporoval
  render json: @oem, status: 200
end
```


その他にも色々なAjaxイベント取得できる
これを参照するとわかりやすかった。

https://github.com/rails/jquery-ujs/wiki/ajax


もし動かなかったらApplication.jsに
//= require jquery_ujs
があるかチェック
XenServerをZabbixでエージェント監視する

##前提
- XenServer 6.5(Virtualbox上)→今回ホスト名はtest-XenServer
- zabbix 2.4(今回はVirtualbox上のCentOS6.8)
- zabbix-agent 2.4
- SSH接続にTeraTermを使用

XenServerのVirtualboxへの構築は[こちら](http://qiita.com/E_M/items/f1d300a962c911bd19ef)を参照

Zabbixの構築は[こちら](http://qiita.com/E_M/items/c0a96cc715d9127acc54)を参照

##XenServerにzabbix-agentをインストールする
1.まずXenServerにSSHで接続する
![WS000016.JPG](https://qiita-image-store.s3.amazonaws.com/0/140216/fa008434-41bb-bcb5-c1d4-5527645d7481.jpeg)
![WS000018.JPG](https://qiita-image-store.s3.amazonaws.com/0/140216/44852ca7-e0b0-98eb-a2d3-95cfca6fb043.jpeg)


2.SSHで接続できたら、以下のコマンド実行でリポジトリの登録。
```
rpm -ihv http://repo.zabbix.com/zabbix/2.4/rhel/5/x86_64/zabbix-release-2.4-1.el5.noarch.rpm
```

3.次に以下のコマンドでzabbix-agentをインストールする。
```
yum install zabbix-agent --disablerepo=citrix,base,epel
```


##zabbix-agentの設定をする
###◆/etc/zabbix/zabbix_agentd.confの中を編集

```
Zabbixサーバーを指定
Server=192.168.XX.XX

Zabbix サーバーを指定
ServerActive=192.168.XX.XX

XenServerのホスト名を指定
Hostname=test-XenServer
```

###◆zabbix-agentの起動と自動起動設定

```
service zabbix-agent start
chkconfig zabbix-agent on
```

###◆XenServerのポートの開放
zabbixと通信するにはデフォルトで10050ポートを使用する為、
10050ポートを開放する。

```
vi/etc/sysconfig/iptablesの中に以下の一文を追加
-A RH-Firewall-1-INPUT -m conntrack --ctstate NEW -m tcp -p tcp --dport 10050 -j ACCEPT

追加したらiptablesを再起動する
/etc/init.d/iptables restart
```

##zabbixサーバのブラウザ上での設定
1.[設定]→[ホスト]→[ホスト作成]を選択。
「ホスト」タブで以下のように設定(例)

|        |         |
|:-----------------|:------------------|
| **ホスト名**            |     XenServer|  
| **所属グループ**           |   Virtual machines |    
| **エージェントのインターフェース** | IPアドレス/ポート10050|
  
2.「テンプレート」タブで[Template OS Linux]を選択。
そこまで設定したら一旦[追加]。

3.テンプレートまで設定すればグラフが自動で出来るのでそれらでスクリーンを作成すればこんなかんじに。
![image](https://qiita-image-store.s3.amazonaws.com/0/140216/29a0869c-39e0-17f7-ddaa-71022110d505.png)

##まとめ
CPU使用率などはXenCenterで見れるけど監視項目はzabbixのが見やすいかな。
ただVirtualboxで構築したXenServerは接続が切れやすいのでテスト用として・・・
MySQL がテーブル壊れてるらしいエラー吐いて死ぬかと思った話


## 確認
### 構成
基本的な LAMP 環境に PHP フレームワークの CakePHP で構築されていたウェブシステム。
5年くらい前に作られたシステムらしく、自分はハードウェアもソフトウェアも構築に関与していなかったので手探りで調査。

### 症状
特定のページがエラーになるらしい。

### CakePHP のエラーログ
`Error: [PDOException] SQLSTATE[HY000]: General error: 126 Incorrect key file for table '/tmp/#sql_******'; try to repair it`

## `Incorrect key file for table` ?

### 検索
とりあえず怪しいキーワードを調べますよね。
そしたら以下の記事がヒットしたわけですよ。
[15.2.4.1 MyISAM テーブルの破損](http://dev.mysql.com/doc/refman/5.6/ja/corrupted-myisam-tables.html)
見た瞬間死んだな、って思いますよね。

### 破損を確認
`CHECK TABLE` コマンドとやらで確認できるとのことで、エラーになっているページでアクセスしているテーブルをかたっぱしからチェックして見るものの、ステータスは `OK` だった。
これはアウト？セーフ？

### ステータス OK を追加して再度検索
[mysqlでIncorrect key file for table](http://d.hatena.ne.jp/fuki1234/20090727)
神よ！
ちょっと古い記事だけど、まさしく求めていた記事。
確かにさっきのエラーメッセージに `/tmp` がなんたらって出てるものね。

### さっそく /tmp を確認
`df -h /tmp`

```
Filesystem            Size  Used Avail Use% マウント位置
/dev/mapper/vg_***-lv_root
                       50G   49G   43M 100% /
```

`/tmp` に空きがないとかいうレベルじゃない。
`/` がパンパンだ。
しかも詳しく調べて見ると、 `/var` とかもそこに入ってた。
もちろん `/var/www` も `/var/log` も `/var/lib/mysql` も。
要はウェブシステム含めてサーバのシステムほぼ丸ごと 50GB で賄おうって設計らしい。
うーん。5年前はそれで良かったのだろうか…。
なお `/home` は単独で切ってあって、大量に余ってた。
まさかこれ OS をデフォルト設定…？

### ファイルを削除
とりあえず不要不急の古いファイルをいくらか削除したところ、エラーは解消した。
ただ、これは場当たり的な対応なので、近いうちに構成から見直さないとならないと思う。


## 参考
* [15.2.4.1 MyISAM テーブルの破損](http://dev.mysql.com/doc/refman/5.6/ja/corrupted-myisam-tables.html)
* [mysqlでIncorrect key file for table](http://d.hatena.ne.jp/fuki1234/20090727)