OmniAICreator/Qiita-1.07M huggingface dataset:
S3のスタティックサイトにSSLを当てる(Cloudfront必須)

# やりたいこと

s3に入れたスタティックなサイト(静的サイト)にSSLを当てたい！と思った。
httpsでもhttpでもウェブサイトを見せてくれという。

httpsを転送したいとかではない。なお転送したい場合は、今回のCloudfrontで転送の設定すれば良いだけなのでほぼ同じ道をたどればOK

## [重要] S3単体では不可能 ※20170530時点

色々調べたんですが、出来なさそう。設定がない。SSLの設定をする項目がない。
どうやっても出来ないのでCloudfrontを使う必要あります。
(てか出来るなら誰か教えてください。。。)

## S3にバケットを作ってスタティックサイトを設置する

ざっと書くと
1. awsにログインして、S３へ。
2. ドメイン名( www.hogehoge.com )というバケットを作る
3. Static website hostingという項目から「このバケットを使用してウェブサイトをホストする」をONにする
4. データを入れる

## Cloudfrontを準備する

こっからが本番でーす。

1. awsにログインして、Cloudfrontへ
2. Create Destribution を押す
3. Webを選択
4. Origin Settings の Origin Domain Name にある入力フォームを選択するとS3のバケットが、アシストされて表示されるのでそのS3バケットを選択する(この時点で勝手にOriginIDも設定されて便利)
5. だいぶスクロールして、Distribution Settings の SSL Certificate へ
6. 特にドメイン名とかどうでもよければそのままで。独自ドメインにしたければCustom SSL Certificateを(ここではkeyとか設定面倒なのでそのままで)
7. Default Root Object に index.html などを入れる(**※重要 これ忘れるとドメイン直のアクセスが死ぬ**)
8. 保存

## Route53に設定する

1. Route53へ
2. DNSを当てたいドメインを選択
3. DNSレコード www.hogehoge.com に Typeを A で選択
4. AliasをYESに
5. Alias TargetにCloudfrontが選べるはずなので選択する
6. 保存

## サブディレクトリのindex.htmlへ行けるように

すごくよくぶつかるからここにインクルード。
Cloudfrontは通常設定すると、ドメインルートのみindex.htmlとかに転送してくれるがサブディレクトリは駄目。

* aaaaa.com
    * => aaaaa.com/index.html
* aaaaa.com/directory
    * => [403]

さて、困ったってことですが、Cloudfrontを当てるS3バケット先をアシストされたバケット名ではなく、ウェブアクセス用のバケットを手動で当て直す必要があります(なんでこんな面倒なのか)。

* [これは×] aaaaa.com.s3.amazonaws.com
* [これが○] **aaaaa.com.s3-website-ap-northeast-1.amazonaws.com**

websiteなんちゃらがついてる方であればサブディレクトリもいわゆるWEBサイトっぽい挙動をしてくれる。

## 余談

最後のRoute53で、Alias TargetにS3のバケットを直接選択することもできる。というかそれが通常の使い方。
https,httpの両方をカバーしたい、ないしはhttpsのアクセスをhttpに飛ばしたいなどは上記のCloudfrontを使おうぜという話。

※スクリーンショットが無いのは、面倒だったのと、どうせすぐインターフェースかわるのでいっかなーという甘え。甘え。

## 余談2

Cloudfrontはキャッシュしてくれるサービスでもある(というかこっちが本来の姿)ので、キャッシュします。
FTPなどでファイル更新したあとはキャッシュを消す作業をしないと、即時反映しません。

### キャッシュの殺し方

Cloudfrontのキャッシュは、Invalidationsから殺害できます。
ちょっと奇妙な感じなんだけど、キャッシュを消すためにInvalidationをCreateします（直感的ではないなぁ)。

1. awsにログインして、Cloudfrontへ
2. 作ってあるCloudfrontを選択して、Destribution Settings を押す
3. Invalidationsのタブを選択
4. Create Invalidation 押す
5. 消すキャッシュを特に限定することは無い場合は、そのままInvalidateボタンを押す
6. 完了

これでキャッシュは消え去ります。
Pull Requestに潜むタイポを自動的に検出し、修正を代行するBot

いざPull Requestのレビュー！と挑んだ瞬間、「ここタイポな」という先制パンチをくらうのはとても残念なことです。
また、これは指摘しているほうにとってもチェックが負担で、気が重いものです。

人間は人間にしかできないチェックに集中すべきですし、貴重なレビュー時間を誤字脱字の修正に使うのはもったいないです。そこで開発したのが、タイポの自動検知と修正を代行するBot。その名も**typot**です。

[chakki-works/typot](https://github.com/chakki-works/typot)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/25990/4c1f9c1b-b7aa-56a6-0bd4-4ab92fe4071a.png)

こちらは先日公開がアナウンスされた[GitHub Marketplace](https://github.com/blog/2359-introducing-github-marketplace-and-more-tools-to-customize-your-workflow)と共に公開された、新しいGitHubアプリの形態である[GitHub Apps](https://developer.github.com/apps/)で作成しています(それまではWebhookかOAuthだった)。
GitHub AppsはOAuthのようにユーザーではなく、リポジトリにひもつく形態になります。そのため、管理者ユーザーがいなくなった(あるいは権限を失った)からアプリが使えなくなるというような事態を防ぐことができます。この辺り＋開発の方法についてはいろいろと知見が積めたので、[別途記事にて公開しています](http://qiita.com/icoxfog417/items/fe411b94b8e7ae229e3e)。
何はともあれ、端的には使ってみようと思ったら対象のリポジトリにだけインストールが可能ということです。

# Feature

百聞は一見に如かずということで、実際に**typot**がどのような動きをするかご覧ください。

![typot.gif](https://qiita-image-store.s3.amazonaws.com/0/25990/7998526f-f075-d2fd-8812-c4ddbf632b77.gif)

* タイポがあった場合レビューコメントで指摘が行われる
* 指摘と共に提示される修正候補を選択するだけで、修正が自動的に行われる

この点が動作デモから確認できると思います。

# How it works

**typot**は、インストールされたリポジトリでPull Requestがオープンされると、そこに対しタイポのチェックを実行します(※現在サポートしているのは英語のみで、チェックには[PyEnchant](http://pythonhosted.org/pyenchant/)を利用しています)。タイポが発見された場合、修正候補と共にレビューコメントとして指摘を行います

![typo_comment.png](https://qiita-image-store.s3.amazonaws.com/0/25990/2e3f1af4-7a58-7871-889d-0811a94f7b08.png)

そして、修正候補の中に適切なものがあれば、それを選択するだけで自動的にファイルの修正が実行されます。

![typo_fix1.png](https://qiita-image-store.s3.amazonaws.com/0/25990/e617ee81-7063-8fc4-47f2-7b83c68343b0.png)
![typo_fix2.png](https://qiita-image-store.s3.amazonaws.com/0/25990/d9ee2a0c-00bd-5fee-6cc5-bf367792053d.png)

これで、タイポのチェックは自動化され、さらにその修正に煩わされることもなくなります。
これらの操作はすべてGitHubのAPIで実装しています。そういう意味では、GitHubのAPIの充実ぶりがわかろうかというものです。

現在はタイポのチェックだけですが、私のチームは自然言語処理/機械学習を生業としているので、もう少し高度な、人のレビュー負荷を軽くするようなチェックができればなとは考えています(チームの活動については[チームブログ](https://medium.com/chakki)をぜひお読みいただければと思います)。

皆様のレビューのお役に立てば幸いです！(Starを頂ければ作った甲斐がありますm(_ _)m)

[chakki-works/typot](https://github.com/chakki-works/typot)
【Excel】マクロでアウトラインの開閉を行う

マクロでアウトラインの開閉を行っている例を調べてみると `ShowDetail` を使っているパターンが多かった。

```
Sub collapseExpand()
  Columns(1).ShowDetail = Not Columns(1).ShowDetail
End Sub
```

これだと1回目はうまくいくのですが、連続して実行するとShowDetailの値が変わっておらずエラーになってしまいました。


# じゃあどうするのか
発想を変えて「見えなくすれば良いのでは？」ということで `Hidden` を使ってみました。

```
Sub collapseExpand()
  Columns(1).Hidden = Not Columns(1).Hidden
End Sub
```

無事にアウトラインの開閉が連続で行えるようになりました。
Rails5.1 db:migrate で Mysql2::Error: Table 'XXX' doesn't exist が出た時はMigrationのバージョンが問題かも

#多対多の中間テーブルが作れない
いつも通り開発していた夕方．なんどやってもエラーが取れない．
***Table doesn't exist***
テーブルはあるはずなのにないと言われる．

```
== 20170530075224 CreateCourseHomerooms: migrating ============================
-- create_table(:course_homerooms)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Table 'hogehoge_v2_development.course_homerooms' doesn't exist: SHOW FULL FIELDS FROM `course_homerooms`
/Users/daisuke/Development/hogehogeServer_v2/db/migrate/20170530075224_create_course_homerooms.rb:3:in `change'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `require'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `<top (required)>'
/Users/daisuke/Development/hogehogeServer_v2/bin/spring:14:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'hogehoge_v2_development.course_homerooms' doesn't exist: SHOW FULL FIELDS FROM `course_homerooms`
/Users/daisuke/Development/hogehogeServer_v2/db/migrate/hogehoge20170530075224_create_course_homerooms.rb:3:in `change'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `require'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `<top (required)>'
/Users/daisuke/Development/hogehogeServer_v2/bin/spring:14:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Mysql2::Error: Table 'hogehoge_v2_development.course_homerooms' doesn't exist
/Users/daisuke/Development/hogehogeServer_v2/db/migrate/20170530075224_create_course_homerooms.rb:3:in `change'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `require'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `<top (required)>'
/Users/daisuke/Development/hogehogeServer_v2/bin/spring:14:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Mysql2::Error: Cannot add foreign key constraint
/Users/daisuke/Development/hogehogeServer_v2/db/migrate/20170530075224_create_course_homerooms.rb:3:in `change'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `require'
/Users/daisuke/Development/hogehogeServer_v2/bin/rails:9:in `<top (required)>'
/Users/daisuke/Development/hogehogeServer_v2/bin/spring:14:in `<top (required)>'
bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
```

#Migrationのversionを5.1から5.0へ戻したら動いた
```original_migration.rb
class CreateCourseHomerooms < ActiveRecord::Migration[5.1]
  def change
    create_table :course_homerooms do |t|
      t.references :course, foreign_key: true
      t.references :homeroom, foreign_key: true

      t.timestamps
    end
  end
end
```

```fixed_migration.rb
class CreateCourseHomerooms < ActiveRecord::Migration[5.0]
  def change
    create_table :course_homerooms do |t|
      t.references :course, foreign_key: true
      t.references :homeroom, foreign_key: true

      t.timestamps
    end
  end
end
```
こんな簡単なことでよかったのか？？
原因がなんだったかはよくわかってないのですが，ActiveRecord::Migrationのバージョンで```[5.1]```と```[5.0]```が共存するのはあまり良くないのかな？

その辺り，まだまだ勉強不足ですが，この記事が誰かの助けになれば幸いです．
Flask メモ


##unescape
pythonから表示したいのテキストにhtmlコードがあるとき、flaskが自動的に'<''&'などエスケープしたため、テキストは直接\<span>みたいのように表す 
[Jinja2](http://jinja.pocoo.org/docs/dev/templates/#html-escaping) から
> * the context dictionary by the application with MarkupSafe.Markup

> * the template, with the |safe filter

二つ方法解決

```py3

from flask import Markup
text = Markup('<span>hogehoge</span>')

```

もしくはテンプレートファイルに



```html

       <div class="col-sm-10">
                   {{ text|safe }}
       </div>
```
MySQLのロック機能


[排他ロック](https://dev.mysql.com/doc/refman/5.6/ja/glossary.html#glos_exclusive_lock)や[共有ロック](https://dev.mysql.com/doc/refman/5.6/ja/glossary.html#glos_shared_lock)ではなく、[innoDBやそこら辺](https://dev.mysql.com/doc/refman/5.6/ja/innodb-lock-modes.html)でもなく、[内部レベル](https://dev.mysql.com/doc/refman/5.6/ja/internal-locking.html)の[行ロック](https://dev.mysql.com/doc/refman/5.6/ja/glossary.html#glos_row_lock)や[テーブルロック](https://dev.mysql.com/doc/refman/5.6/ja/glossary.html#glos_table_lock)でもなく、[GET_LOCK](https://dev.mysql.com/doc/refman/5.6/ja/miscellaneous-functions.html#function_get-lock)関数のメモ書き。

MySQLにあるLock機能があって、任意の名前のロックを作成する事ができる。何それ知らないって言ったら笑われたのを今頃思い出した。MySQLを使ってファイルロックをする感じ。

# 使い方

`IS_FREE_LOCK`, `GET_LOCK`, `RELEASE_LOCK` を使う。

- IS_FREE_LOCK(str)
	- 文字列strのロックが使えるか確認する。 `1` が帰ってきた時は使用可能
- GET_LOCK(str, timeout)
	- timeout秒だけ文字列strで指定されたロックの取得を試みる。timeoutが負の時は無制限。取れるまで待つ。
- RELEASE_LOCK(str)
	- ロックを解除する。1 の時は成功を表す


# 実験

ターミナル1とターミナル2を作り、それぞれ別セッションで `mysql` につなげる。

`mysql`データベース上に `time` ロックを作ってゴニョゴニョ

```ターミナル1
mysql> SELECT GET_LOCK('time', 10);
+----------------------+
| GET_LOCK('time', 10) |
+----------------------+
|                    1 |
+----------------------+
1 row in set (0.00 sec)

mysql> 
```

`time` のロックが取れたので、ターミナル2でLOCK

```ターミナル2
mysql> SELECT IS_FREE_LOCK('time');
+----------------------+
| IS_FREE_LOCK('time') |
+----------------------+
|                    0 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT GET_LOCK('time', 10);
+----------------------+
| GET_LOCK('time', 10) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (10.08 sec)

mysql> SELECT GET_LOCK('TIME', 10);
+----------------------+
| GET_LOCK('TIME', 10) |
+----------------------+
|                    0 |
+----------------------+
1 row in set (10.07 sec)

mysql> 
```

期待通り`0`を返してきている。ついでに `time` を大文字の `TIME` にしてみたら `0` を返した。

ターミナル2からロックが開放されない事を確認してみる。

```ターミナル2
mysql> select RELEASE_LOCK('time');
+----------------------+
| RELEASE_LOCK('time') |
+----------------------+
|                    0 |
+----------------------+
1 row in set (0.00 sec)

mysql> SELECT IS_FREE_LOCK('time');
+----------------------+
| IS_FREE_LOCK('time') |
+----------------------+
|                    0 |
+----------------------+
1 row in set (0.00 sec)

```

`GET_LOCK`で取得したロックは、セッションが切れたら自動的に解放されるはずなので試してみる。

```ターミナル1
mysql> ^DBye
(py2) [yasui@YASUI-MBP1: 17-05-30 17:37]~ $ 
```

ターミナル1の`prompt`には、17時37分が表示されている。ターミナル2の方で使えるか確認をする。

```ターミナル2
mysql> select CURRENT_TIME;
+--------------+
| CURRENT_TIME |
+--------------+
| 17:38:09     |
+--------------+
1 row in set (0.00 sec)

mysql> SELECT IS_FREE_LOCK('time');
+----------------------+
| IS_FREE_LOCK('time') |
+----------------------+
|                    1 |
+----------------------+
1 row in set (0.00 sec)

```

`1`を返してきたので使える。

使えるシーンと言えば、あまりない…かな…

てか名前が`LOCK`だから影が薄くて……
Cognos SDKのリモート・デバッグ

##概要
今回はCognos SDKで開発をする時の、リモート・デバッグの設定方法の情報紹介です。

##EclipseツールでCognos SDKを動かす
Cognos SDKをEclipseツールで開発するためには、C:\Program Files\IBM\cognos\c10_64\sdk\javaフォルダーをインポートします。
Javaフォルダをチェックし、Finishをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/ff3d349b-df6b-47ac-8b35-ca6e59ec6215.png)

インポートしたlibフォルダ配下のjarファイルを選択し、右クリック「Add to Build Path」　を選択し、ビルドパスに追加します。 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/4d85fcdc-dcfc-0b60-71e2-fa25b780bcf5.png)


##リモート・デバッグのセットアップ
すいません、参照先の紹介のみです。

**・Cognos Analyticsや、Cognos BIで組み込みのLiberty & Tomcatを使っている場合**
普通の環境であれば、こちらのTechnoteの手順で、リモート・デバッグの設定が可能です。
**　Debugging Remote Java Applications using Eclipse**
　http://www-01.ibm.com/support/docview.wss?uid=swg21338811


**・Cognos BIでWebSphere Application ServerのND等にのっけて動かしている場合**
p2pd.earを作成して、WASにデプロイして動かしているパターンです。
以前こちらのリンクで設定してみて、対WASでもCognos SDKのリモート・デバッグが動く事確認しました。
**　Remote Debugging with Eclipse + WebSphere 7**
　https://www.mkyong.com/websphere/remote-debugging-with-eclipse-websphere-7/

ご参考まで。
Androidエミュレーターのhostsファイルを書き換える

ターゲット: Android 7.1.1

例えば、 /etc/hosts の内容で置き換えたい場合。

adb push /etc/hosts /system/etc/

だと、

```shell-session
adb: error: failed to copy '/etc/hosts' to '/system/etc/hosts': remote Read-only file system
```
などとエラーになってしまうので、

```shell-session
adb root && adb remount && adb push /etc/hosts /system/etc/
```
と実行すれば良い。

adb shell などでやろうとするとうまくいかないので、一度エミュレータを再起動してから上記を実行すること。
WindowsユーザがMacを使う時に最初に設定したいマウスとキーボードの設定

WindowsとMacはマウスとキーボードの動きが結構違うので、最初はとまどいます。

WindowsユーザーがMacを利用する場合、最初に以下の幾つかの設定を行うと、格段に使いやすくなります。
この記事には元Windowsユーザとしての筆者の偏りが含まれているかもしれませんが、ご容赦ください。

## マウスの設定

- [システム環境設定]の[マウス]から設定画面を開きます。

![マウス.png](https://qiita-image-store.s3.amazonaws.com/0/79673/c8280de5-5ff6-80f6-d141-d5c4a7813ec1.png)

- **スクロールの方向「ナチュラル」のチェックを外します**
MacのナチュラルはWindowsの逆です。
Windowsのニュアンスでスクロールしようとすると、逆の動きをするのでびっくりします。

- **副ボタンのクリックのチェックを入れます**
Macは昔はマウスに右クリックがなく、オプションボタンを押しながらクリックしてクリックメニューを表示していました。
今はMacでも割と普通に右クリックが使用されています。

- **マウスの軌跡の速さを早めに設定する**
マウスの性能差もありますが、Macだとポインタの移動が結構遅いので、早めに設定します。
マウスによって、マウス本体自体にポインタの移動速度の設定があるものもあります。


## キーボードの設定

- [システム環境設定]の[キーボード]の設定画面を開きます。

![キーボード.png](https://qiita-image-store.s3.amazonaws.com/0/79673/56a33ac4-6673-3030-4722-e51e8dd417c1.png)

- **キーのリピートとリピート入力認識までの時間を最短にする**
Macの最初の設定では、キーのリピートとリピート入力認識までの時間がかなり遅いです。
最短に設定してもなお、遅いと感じることがあります。
その場合は、[karabiner](https://pqrs.org/osx/karabiner/index.html.ja)などのツールを使って調整します。
karabinerは Windowsで言うところの窓の手みたいなものです。

- **F1,F2などのすべてのキーを標準のファンクションキーとして使用をチェックする**
Macのファンクションキーにはブライトネスや音量などのキーが割り当たっています。
Windowsを使っているとF7,F8などでカナ変換などを行うと思いますので、ファンクションキーとして利用する方が自然です。
(この設定は後述のWindows風のキー操作と共に使います)
このチェックを有効にした場合、音量などのキーを使う時は「fn」キーを押しながら音量キーなどを押します。



- 同じキーボード設定の[入力ソース]タブを開きます



![キーボード２.png](https://qiita-image-store.s3.amazonaws.com/0/79673/4559d195-af31-5270-5ee3-138215d8c41c.png)

- **ライブ変換のチェックを外す**
Macは入力中に単語の変換をスペースキーを押さなくても自動的に変換してくれます。
しかし、Windowsユーザはスペースキーでの変換に慣れているので、ライブ変換があると使いにくく感じます。

- **Windows風のキー操作のチェックを入れます**
Windows風のキー操作で得られる操作感の違いは、いくつかありますが、恐らく最も多様されるのが、F7,F8などのファンクションキーをひらがな、カタカナ変換などで使用する部分だと思います。
それ以外にも得られる恩恵は幾つかありますので、[こちら](http://inforati.jp/apple/mac-tips-techniques/windows-hints/how-to-enable-windows-key-mode-of-mac-kotoeri.html)で確認してみてください。
(この設定は「F1,F2などのすべてのキーを標準のファンクションキーとして使用をチェックする」と合わせて使用します)
Linuxでのバックアップスクリプトのテンプレート


#はじめに
Linuxで何かのバックアップを取るシェルスクリプトをcronで回すというのはよくやると思います。

その際のシェルスクリプトってほとんど共通なので、自分のためにメモっておきます。

#仕様
- バックアップファイルはアーカイブされていること
- ファイル名にはホスト名と日付を入れる
- 世代管理する
- ログはsyslogに書き出す

#スクリプト
```Bash:backup.sh
#!/bin/sh

hostname=`/bin/hostname`
date=`/bin/date +"%Y%m%d_%H%M"`
path=PATH/TO/BACKUP
filename="${path}/${hostname}_${date}.gz"
filekeepdays=7

echo "XXX backup started." | logger -t xxx_backup

#BACKUP_COMMAND 2>&1 | logger -t xxx_backup

for file in `find ${path}/ -mtime +${filekeepdays} -type f -name \*.gz`
do
    echo "deleted: " ${file} | logger -t xxx_backup
    /bin/rm ${file}
done

echo "XXX backup finished." | logger -t xxx_backup

exit 0
```

#まとめ
ログをsyslogに吐き出すと、いちいち個別にログローテーションを考慮しなくて楽です。
Ubuntu で LWP::UserAgentでhttpsな通信するための環境構築


とりあえずこれだけやっていれば使えるようになっているはず。
Ubuntu 16.04.02で確認

~~$ sudo apt-get install openssl.*perl~~
↑2018/01/03 上記必要なさそうなので削除
<pre>
$ sudo apt-get install libssl-dev

$ sudo cpan -i LWP::UserAgent

//上手くhttps関連のモジュールが入らなかったら
$ sudo cpan -i YAML
$ sudo cpan -i Net::SSLeay
$ sudo cpan -i LWP::Protocol::https
</pre>

失敗例:
<pre>
SSLeay.xs:163:25: fatal error: openssl/err.h: そのようなファイルやディレクトリはありません
</pre>

libssl-devが入ってない。
Net::SSLeayのインストールの前にlibssl-devを入れないと行けない。
LWP::Protocol::httpsはNet::SSLeayに依存するので後で入れないと行けない。
RやRStudioでファイルをエディタ(Source)で開くコマンド

タイトルのまんまです。メモ。

## きっかけ

ファイルを自動的に作成する関数を準備したり，あるいはそんな関数を含むパッケージを作っていると，「作った後にそのまま開いて即編集モードにいきたいのに…」とよく感じます。でも`View()`だと編集モートにはなりません。そこで調べてみました。

## `utils::file.edit()`関数

Rに標準で組み込まれている*utils*パッケージには，`file.edit()`関数があります。これを利用するとそのシステムに依存したエディタが開くようになります。詳細は`?file.edit`で確認してください。

例えば，workind directoryに`kosaki.R`というファイルがあるとします。以下のコマンドを実行すると，その環境(システム)でひも付けらているエディタでそのファイルが開かれます:

```r
file.edit("kosaki.R")
```

私のUbuntuのTerminal上で起動させたRで実行した場合，vimでこのファイルが開かれました。これはterminalでのエディタとしてvimを設定していたからです。おそらく各種環境では対応したものが起動するでしょう。なお，RStudio上ではRStudioのSourceペインで開かれるはずです。

## `rstudioapi::navigateToFile()`関数

RStudio上であれば，*rstudioapi*という，RStudioと対話するためのパッケージが利用可能です。この関数はRStudio上でファイルを開くための関数です。詳しくはRStudioのConsole上で`?rstudioapi::navigateToFile`で確認してください。

例えば，working directory上に`kosaki.R`というファイルがあるとします。以下のコマンドを実行すると，RStudioのSourceペインで編集モードとして開かれます:

```r
rstudioapi::navigateToFile("kosaki.R")
```

なお，これはテキストファイルであれば大抵のファイルをテキストエディットモードで開きます。Rmdでもmdでもtexでもgvでも開きました。

## どちらがいいのか?

正直なところ，なんとも言えないです。なお*blogdown*パッケージの内部関数である`blogdown:::open_file()`関数は，[以下のように定義](https://github.com/rstudio/blogdown/blob/a3678355e7255a63226caf532d275fb685bb521c/R/utils.R#L237-L240)してありました:

```r
# use RStudio to open the file if possible
open_file = function(x) {
  tryCatch(rstudioapi::navigateToFile(x), error = function(e) file.edit(x))
}
```

まあ*blogdown*はその内容から考えてもRStudioで使うことが前提と思ってもいいので，こんな感じなのかなとは思います。私自身は98%くらいRStudio上で作業するのでこれでもいい気がしますが，RStudioを利用しない方も多くいます。なので公開パッケージで組み込む際は気をつけたいなと思いました。

**Enjoy**
mysqlでAlter Tableがうまくいかなかった話

### 症状
nullを許可していないカラムにnullを許可したい。

で、以下のエラー
#### 流したSQL
ALTER TABLE users MODIFY email varchar(255);

#### エラーメッセージ
Error Code: 1067. Invalid default value for 'created_at'

なんでｗｗｗできないｗｗｗｗｗｗmyｗｗｗｗsqlさんｗｗｗｗｗ俺たちｗｗｗｗ
友達ｗｗｗｗだろｗｗｗｗ？ｗｗｗｗｗｗｗ


### 前提

| Field                | Type             | Null | Key | Default             | Extra          |
|:----------------------+------------------+------+-----+---------------------+----------------+
| id                   | int(10) unsigned | NO   | PRI | NULL                | auto_increment |
| name                 | varchar(255)     | NO   |     | NULL                |                |
| email                | varchar(255)     | NO   | UNI | NULL                |                |
| password             | varchar(60)      | NO   |     | NULL                |                |
| remember_token       | varchar(100)     | YES  |     | NULL                |                |
| created_at           | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| updated_at           | timestamp        | NO   |     | 0000-00-00 00:00:00 |                |
| confirmation_token   | varchar(255)     | YES  |     | NULL                |                |
| confirmed_at         | timestamp        | YES  |     | NULL                |                |
| confirmation_sent_at | timestamp        | YES  |     | NULL                |                |


### で、こうやったら治った
SET sql_mode = '';

MySQLにはSTRICT_ALL_TABLESなるsqlモードがあり、それが原因らしい

### 参考

[【MySQL】MySQL5.6ではsql_modeがSTRICT_TRANS_TABLESになる](http://qiita.com/kazu56/items/0663ff7dd8b86eb02df7)

https://stackoverflow.com/questions/36882149/error-1067-42000-invalid-default-value-for-created-at
Kotlin+Spring Bootにて「@Configuration class may not be final」的なエラーが出たとき

# Kotlin+Spring Bootにて「@Configuration class may not be final」的なエラーが出たとき

この記事の対象フレームワークなど

- kotlinVersion = '1.1.2'
- springBootVersion = '2.0.0.M1'

## 起こった現象

Spring Bootを起動すると

```
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: @Configuration class 'Application' may not be final. Remove the final modifier to continue.
```

みたいなエラーが出る。
当方では、kotlinでApplicationクラスを作成し、Java側でConfigurationクラスを作成している場合に発生した。


## 対応

詳細はPivotalのサイトを見てもらうと詳しい

http://engineering.pivotal.io/post/spring-boot-application-with-kotlin/

内容としては @Configuration をつける対象は open指定して下さいよゴニョゴニョ.. というような感じでしょうか。

直接的な対応としてはApplicationクラスのアノテーションを

`@SpringBootApplication → @EnableAutoConfiguration + @ComponentScan`

に変更すればOKであった。

```
@EnableAutoConfiguration
@ComponentScan
@EnableDiscoveryClient
@EnableCircuitBreaker
class Application

fun main(args: Array<String>) {
    SpringApplication.run(Application::class.java, *args)
}
```

※ Pivotalの記事中にも注意書きされているが、今回利用したバージョンでは `build.gradle` などの修正は必要なかった
GCPのセキュリティ

GCPのセキュリティについて調べたので、その概要を記載。

#1.暗号化
### 1.1. データの暗号化
Google Cloud Platform はデータを保存する際にデフォルトで暗号化する。データはストレージ用にサブファイルのチャンクに分割され、各チャンクは個別の暗号鍵（データ暗号鍵（DEK））でストレージレベルで暗号化される。DEK自体も鍵暗号鍵（KEK)で暗号化されている。
DEKを保護するKEKを管理する鍵管理ソリューションは顧客が選択(Default, Cloud KMS, CSEK)できる。
https://cloud.google.com/security/encryption-at-rest/

ストレージレベルでは暗号化アルゴリズムにAES256 または AES128 を使用。
https://cloud.google.com/security/encryption-at-rest/default-encryption/

<img width="615" alt="Screen Shot 2017-04-14 at 14.59.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/95399/d332ad7a-bbd7-a9ee-d4d2-e6d56f79b670.png">

<img width="620" alt="Screen Shot 2017-04-14 at 17.28.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/95399/28b423f2-1548-3576-7d7f-9caf3eac031b.png">


### 1.2.通信経路の暗号化
全てSSL/TLSで暗号化されている。
https://cloud.google.com/security/?hl=ja

#2.ファシリティ
生体認証、金属検知、カメラ、車両障害物、レーザーを使った侵入検知システムを利用してデータセンターのフロアを保護している。
また侵入者を検知し追跡できるカメラを屋内と屋外に設置して24時間365日監視し、インシデントがあればこれらのデータを利用可能である。
データセンターでは、厳正な身元調査とトレーニングを受けた経験豊富な警備員が定期的にパトロールを行っている。

https://cloud.google.com/security/security-design/#security_of_physical_premises
https://cloudplatform.googleblog.com/2016/03/Google-shares-data-center-security-and-design-best-practices.html

#### 2.1.ハードウェアのトラッキングと廃棄
データセンター内の全ての機器はバーコードやアセットタグを使用して追跡しており、金属探知機や動画監視システムにより持ち出せれないようにもしている。
ディスクは破砕機でドライブを変形させ、シュレッダーでドライブを細かく砕いて破壊する。
https://cloud.google.com/security/whitepaper#hardware_tracking_and_disposal

#3. 不正アクセス防止
多層防御の原則に基づいている。
https://cloud.google.com/security/whitepaper#technology_with_security_at_its_core

#4.　データアクセスと制限
- 顧客のデータはそれぞれ論理的に隔離されている。
- 顧客のプライバシーを保護し、過剰な要求を抑えているが、一方で司法当局が定める義務は遵守してる。
https://cloud.google.com/security/whitepaper#data_access_and_restrictions

#5. インシデント管理
インシデントが発生した場合、セキュリティチームがインシデントを記録して、重大度に応じて優先順位を設定する。
セキュリティインシデント管理プログラムは、NIST ガイダンス（NIST SP 800-61）に基づいている。セキュリティチームは、24時間体制で問い合わせに対応できるようにしている。
インシデントで顧客データが影響を受ける場合、Google またはそのパートナーは顧客にその旨を通知し、Google のサポートチームを通じて調査活動に協力する。
https://cloud.google.com/security/whitepaper#incident_management

#6. ルール/文化
採用活動や新人教育の段階からセキュリティ教育を行い、従業員全員がセキュリティに高い意識がある。

- 従業員に対してバッググランドのチェック行っている。
- 全従業員に対してセキュリティ研修を行っている。
- セキュリティとプライバシーを向上させるために議論するイベントを定期的に行っている。
- セキュリティ専任のチームが品質を保証するための活動(ペネトレーションテスト、脆弱性チェック、新しいセキュリティ研究など)を行っている。
- 製品開発部門やセキュリティ組織とは独立したプライバシー専任のチームがレビューに参加しプライバシー要件を満たしているかチェックしている。
- 監査専任のチームがコンプライアンスをチェックしている。

https://cloud.google.com/security/whitepaper#google_has_a_strong_security_culture
https://abc.xyz/investor/other/google-code-of-conduct.html

#7. 第３者機関の監査など
- SSAE16 / ISAE 3402 Type II
- ISO 27001、ISO 27017,ISO 27018
- PCI DSS v3.1
- FedRamp ATO for Google App Engine
- HIPAA
- CSA STAR
- Google Cloud Platform と EU データ保護指令
- 個人情報及びマイナンバーの保護
- FISC 安全対策基準<br>
　　　　対応状況の詳細が以下に記載されている。<br>
　　　　https://cloud.google.com/files/FISC_guide_JP.pdf
- MPAA
https://cloud.google.com/security/compliance
Zabbix Agent Install & Zabbix Server Settings

#Env
OS: CentOS6.x
Zabbix: 3.0

#Zabbix Agent Install 
```bash:terminal
rpm -ivh http://repo.zabbix.com/zabbix/3.0/rhel/6/x86_64/zabbix-release-3.0-1.el6.noarch.rpm
```
```bash:terminal
rpm -qa | grep zabbix
// zabbix-release-3.0-1.el6.noarch
yum -y install zabbix-agent
```

```vim:/etc/zabbix/zabbix_agentd.conf
# Server=127.0.0.1
Server=zabbix.hoge.com // ZabbixServerドメインでもOK
```

```vim:/etc/sysconfig/iptables
-A INPUT -p tcp -m tcp --dport 10050 -j ACCEPT
```

```bash:terminal
service iptables restart
service zabbix-agent start
```

#Zabbix Server Settings
+ /zabbix/hosts.php
+ ホスト作成

あとは適当に設定してください。
任意のテーブルをダンプした後、別DBに新しいテーブルを作りつつ、ダンプしたデータをインポートする方法

仕事上以下の作業が必要になるため、自分用メモ

# 概要
任意のテーブルをダンプした後、別DBに新しいテーブルを作りつつ、ダンプしたデータをインポートする

# 使用する知識
* mysqldump
* mysql インポート
* 置換

# 手順
任意のテーブルをダンプ

```
$ mysqldump -u ユーザ名 -p -h ホスト名 DB名A テーブル名A > /tmp/出力ファイル名.dump
```

ダンプした出力ファイルの『元のテーブル名A』を『新しいテーブル名B』に変更（Vimで置換する場合）

```
:%s/元のテーブル名A/新しいテーブル名B/g
```

ダンプした出力ファイルをインポート

```
$ mysql -u ユーザ名 -p -h ホスト名 DB名B < /tmp/出力ファイル名.dump
```

DBを確認し終了
Docker for Macでおこなっていることのまとめ（メモ）

# Docker for Macでおこなっていることのまとめ
※随時更新

今回は、最近Docker for Macを使い初めて以前のDocker ToolBoxを使った構築とどう違うのか整理したいと思い、Dockerの仕組みも含めてまとめてみた。

## Dockerのアーキテクチャ
Dockerの構造について添付しておきます。
![docker.png](https://qiita-image-store.s3.amazonaws.com/0/178576/c3d03ea7-66b3-eebc-c0c6-b125c4b6387d.png)



## Docker for Macでインストールしているもの
Docker for Macでは、Docker Engine、Docker Compose、Docker Machineがインストールされます。では、それぞれがどのようなものなのかを説明していきます。

### Docker Engine
Docker Engineとは、3つの主な構成要素を持つクライアント・サーバ型アプリケーションです。

#### 1. Docker デーモン
Dockerデーモンとは、Dockerイメージ、Dockerコンテナ、Dockerネットワーク、DockerボリュームなどDockerの構成要素の管理者的な位置づけです。そのため、Dockerオブジェクトを作成・管理します。Dockerオブジェクトには、イメージ、コンテナ、ネットワーク、データ・ボリュームなどが含まれます。

#### 2. REST API
インターフェースを規定する REST API は、プログラムがデーモンと通信に使うものであり、何をするか指示するものです

#### 3. コマンドライン・インターフェース（CLI）クライアント
アーキテクチャの図でいうクライアントのことで、ユーザがDocker（Docker デーモン）とやりとりするためのものです。CLI は Docker REST API のスクリプトもしくは直接 CLI コマンドを使い、Docker デーモンを制御または対話します

### Docker Compose
Docker Compose とは、複数のコンテナを使う Docker アプリケーションを、定義・実行するツールです。

#### Docker Composeを使用するための3つのステップ
1. アプリケーションの環境を Dockerfile ファイルで定義する
2. アプリケーションを構成する各サービスを```docker-compose.yml```ファイルで定義します
3. 最後に、```docker-compose up```を実行することで定義したアプリケーション全部が起動・実行される

### Docker Machine
Docker Machine は仮想マシン上に Docker Engine をインストールするツールであり、 ```docker-machine```コマンドを使ってホストを管理します。
また、```docker-machine```コマンドで、管理ホスト（Dockerホスト）の起動（start）、調査（inspect）、停止（stop）、再起動（restart）ができます。

#### どのような時に使用するのか？
1. Mac や Windows 上で Docker を実行したい
2. リモート・システム上に Docker ホストをプロビジョンしたい

※ Docker for Macからは不要に？
Dockerは、Linuxカーネルの機能である「名前空間、コントロール・グループ、ユニオン・ファイル・システム」を使用しています。そのため、Linux環境でないと動きません。
しかし、Docker for Macでは、Macにデフォルトで入っている仮想化ツール「HyperKit」を使ってMacで仮想マシンを立ち上げ、Linuxを起動しています。それによって、Mac上にDockerホストを作成しています。
Docker for Macが出る前は、Docker ToolboxをインストールしてDocker Machineを使ってVM上にDockerホストを作していました。それが、Docker for Macになることで不要となったのか？ここは、ちょっと確証がないです...

## Dockerの処理内容・流れ
```docker run```コマンドでコンテナ起動した際の処理内容・流れ

1. ***イメージ取得***  
まずローカルホストにイメージがないか確認して、なければDocker Hubからダウンロードする
2. ***新しいコンテナ作成***  
Dockerがイメージを入手したあと、それを使ってコンテナを作成する
3. ***ファイルシステムを割り当て、読み書き可能なレイヤをマウント***  
コンテナを新しいファイルシステム上に作成し、読み込み可能な（イメージの）レイヤをイメージに追加する
4. ***ネットワークとブリッジインターフェースの割り当て***  
Docker コンテナがローカルホストと通信できるようにするため、ネットワーク・インターフェースを作成する
5. ***IP アドレスを設定***  
プールされている範囲内で利用可能な IP アドレスを探して（コンテナに）追加する
6. ***指定したプロセスを実行***
アプリケーションを実行し、そして
7. ***アプリケーションの出力を収集・表示***  
コンテナに接続し、アプリケーションを実行したことによる標準入力・標準出力・エラーを記録・表示する

※ ブリッジインターフェース
複数のインタフェースを1つの仮想インタフェースに収容し、収容したインタフェース間でブリッジング（2つのネットワークを1つの大きなネットワークにすること）を行う機能です。
※ ネットワーク・インターフェース
プロトコルで実現/実装されている機能を呼び出すための仕様のこと
※ プール
必要なくなった資源を回収してすぐに再利用できるように一時的に貯めておく仕組みや保管領域のこと

## 参考
http://docs.docker.jp/engine/understanding-docker.html 
http://www.memotansu.jp/2016/08/docker/377/
python3で周波数変調、位相変調

#概要
python3で周波数変調、位相変調、やってみた。

#写真
上　sin
中　周波数変調
下　位相変調
![fm2.png](https://qiita-image-store.s3.amazonaws.com/0/18104/f4cfa288-2cf7-79b2-d406-1a88a01b9797.png)


#サンプルコード

```
import scipy.signal as sg
import numpy as np
import matplotlib.pyplot as plt

sample_rate = 44100.0
nsamples = 320
F_1 = 440.0
F_2 = 5000.0
t = np.arange(nsamples) / sample_rate
vin = np.sin(2 * np.pi * F_1 * t)
vfm = np.sin(2 * np.pi * F_2 * t + 6.0 * -np.cos(2 * np.pi * F_1 * t))
vpm = np.sin(2 * np.pi * F_2 * t + 6.0 * -np.sin(2 * np.pi * F_1 * t))
fig = plt.figure(1)
ax = fig.add_subplot(311)
ax.plot(vin[1: 300])
ax = fig.add_subplot(312)
ax.plot(vfm[1: 300])
ax = fig.add_subplot(313)
ax.plot(vpm[1: 300])
fig.set_tight_layout(True)
plt.savefig("fm2.png")
plt.show()
```
jQueryの意外に知られていない仕様　セレクタの絞込方法（第二引数にcontext ありの場合）

第三者のコード解析中にあまり見かけない記述方法がありましたので、書き留めておきます。
以下のようなコードです。（実際はもっと複雑な記述でしたが、問題箇所に言及します）

```$( ".hit", "#btnA" ).addClass( "active" );
```

「$( ".hit", "#btnA" )」の記述が？？？？？となりました。

ちなみにHTMLは以下の構造です。

```<div id="#btnA">
	<div class="hit">ボタン</div>
</div>
```

「$( ".hit, #btnA" )」の記述なら
セレクター".hit"と"#btnA"に"active"クラスをつけるということがわかりますが、
それとは違います。

いろいろと調べた結果、公式ドキュメントに記述がありました。
http://api.jquery.com/jQuery/#jQuery-selector-context

```jQuery( selector [, context ] )
```

>Selector Context
>By default, selectors perform their searches within the DOM starting at the document root. However, an alternate context can be given for the search by using the optional second parameter to the $() function. For example, to do a search within an event handler, the search can be restricted like so:
>When the search for the span selector is restricted to the context of this, only spans within the clicked element will get the additional class.

第二引数にコンテキストを入力した場合、その指定で限定されるのです。
要するに、findを使った以下と同じ指定になるのです。

```$( "#btnA" ).find(".hit").addClass( "active" );
```

これで納得！詳しくは公式ドキュメントをご確認ください。
Google Cloud Storageのファイルを指定したファイル名でダウンロードしたい

## 背景
- gcsのファイルをファイル名指定してブラウザからDLしたい
- signed_urlを発行してブラウザからダウンロードする前提
- rubyのlibrary(https://github.com/GoogleCloudPlatform/google-cloud-ruby/tree/google-cloud/v0.24.0/google-cloud-storage) を使用
- 今回以下2つのやり方を紹介

## 1. Upload時にDLファイル名を指定する方法
- upload時にcontent-dispositionでファイル名を指定する
  - https://cloud.google.com/storage/docs/xml-api/reference-headers#contentdisposition


```rb

@api = Google::Cloud::Storage.new(project: $PROJECT_ID)
bucket = @api.bucket $BUCKET_NAME
raise("bucket not exist. bucket: #{$BUCKET_NAME}") if bucket.nil?
bucket.create_file($FILE_PATH,
                   $STORAGE_PATH,
                   content_disposition: "attachment; filename=#{$DL_FILE_NAME}")

```


## 2. signed_urlの生成時に指定する場合
- signed_urlにresponse-content-dispositionクエリを追加する
  - https://cloud.google.com/storage/docs/xml-api/reference-headers#responsecontentdisposition

```rb

@api = Google::Cloud::Storage.new(project: $PROJECT_ID) bucket = @api.bucket $BUCKET_NAME
raise("bucket not exist. bucket: #{$BUCKET_NAME}") if bucket.nil?
file = bucket.file $STORAGE_PATH
raise("file not exist. file: #{$STORAGE_PATH}") if file.nil?
url = file.signed_url(method: "GET", expires: 60 * 60 * 24)
url + "&response-content-disposition=attachment%3B%20filename%3D%22#{$DL_FILE_NAME}%22"

# ex. https://storage.googleapis.com/$BUCKET/$PUT_STORAGE_PATH?GoogleAccessId=xxx&Expires=xxx&response-content-disposition=attachment%3B%20filename%3D%22$DL_FILE_NAME%22
```

- $PROJECT_ID: プロジェクトID
- $BUCKET_NAME: バケット名
- $FILE_PATH: アップロード対象ファイル
- $STORAGE_PATH: アップロード先のパス指定
- $DL_FILE_NAME: DL時のファイル名


# 参照

https://stackoverflow.com/questions/21026132/google-cloud-storage-download-a-file-with-a-different-name
ApacheTikaを使ってRubyからPDFの本文抽出

## やりたいこと

PDFの本文をページごとに抽出したい。
(将来的に、指定したキーワードにヒットするのは何ページか？といった使い方をする）

## コードなど

RubyGemsを調べてみると、既に[Tika-Client](https://rubygems.org/gems/tika-client/versions/0.2.0)というGemが存在していたのだけど、
やりたいことは決まってるしそこまで汎用的に作る必要も無いのでイチからサクッと書いてみた。
外部コマンドを実行してその結果をパースするだけ。


```ruby
require "nokogiri"

module Rtika
  class Core
  	attr_reader :tika_path

  	def initialize tika_path: ""
  		@tika_path = tika_path
  		raise "java was not installed!" unless system("java -version")
  		raise "tika was not found!" unless File.exists? tika_path
  	end

  	def exec document_path: ""
  		raise "document was not found!" if document_path == ""

  		command = "java -jar #{tika_path}"
  		type = "x"
  		encoding = "UTF-8"
  		ret = `#{command} -#{type} --encoding=#{encoding} #{document_path}`
  		html = Nokogiri::HTML.parse(ret)
  		body = html.css("body > div.page").map{|page| page.css("p").text  }
  		body.map.with_index{|r, i| {page: i+1, content: r} }
  	end
  end
end
```

tikaはJSONフォーマットで抽出することもできるのだけど、抽出したJSONをRubyでJSON.parseするとパースエラーを起こしてしまう。
原因が掴めなかったので、xml形式で抽出し、Nokogiriで各ページの内容を削り取ることにした。

[Enumerator#with_index](https://docs.ruby-lang.org/ja/latest/method/Enumerator/i/with_index.html)を知ったのが今回の収穫。


```ruby
Rtika::Core.new(tika_path: "./jar/tika-app-1.14.jar").exec(document_path: "sample_document.pdf")
```


## 実行結果


```ruby
[
    [ 0] {
           :page => 1,
        :content => "1ページ目のページ内容"
    },
    [ 1] {
           :page => 2,
        :content => "2ページ目のページ内容"
    },
    [ 2] {
           :page => 3,
        :content => "3ページ目のページ内容"
    },
    [ 3] {
           :page => 4,
        :content => "4ページ目のページ内容"
    },
```
MapR の Logging に関するオプションについて

MapRではYARNに関連するLoggingとして以下の3つのオプションを指定できます。
1. Local logging
2. YARN log aggregation
3. Centralized logging (MapRのみ)

各オプションの特徴は以下のようにまとめられます

| オプション | 対応アプリケーションのタイプ | ログ格納場所 | リアルタイム性 |
|:---------|:-------------------------|:-----------|:-------------|
| Local logging | MR1, MR2, Yarn applications (non-MR) | ローカル | YES |
| YARN log aggregation | MR2, Yarn applications (non-MR) | HDFS (MapR-FS) | NO |
| Centralized logging | MR1, MR2 | HDFS (MapR-FS) | YES |


本記事ではこの3つのオプションの簡単な説明とセットアップについて説明していきます。
ただし、MR はv2に関してのみの説明となります。

## 1. Local logging

デフォルトの設定となります。
この場合、ログはローカルのファイルシステムに出力されるだけで、アグリゲーションされません。
この場合、ログを見ようとする場合は、ResourceManagerのWebUIなどから実行されたホストを探して、そのログを見る、といったフローになります。
MR2のログの場所はデフォルトで以下のパスとなります。

```
/opt/mapr/hadoop/hadoop-<version>/logs/userlogs/<application ID>/
```

## 2. yarn log aggregation

yarn log aggregationではローカルにログを書き出した後に、HDFS(MapR-FS)上に移動されます。
こちらはapache hadoop で実装されている機能となります。
有効化する際には以下のファイルを編集する必要があります。

```yarn-site.xml```を編集して、log aggregationをenableします。

```
パス
/opt/mapr/hadoop/hadoop-2.7.0/etc/hadoop/yarn-site.xml

以下を追加
  <property>
    <name>yarn.log-aggregation-enable</name>
    <value>true</value>
  </property>
```

MapRのデフォルトであるノンセキュアなクラスタでは```yarn-env.sh```も編集する必要があります

```
パス
/opt/mapr/hadoop/hadoop-2.x/etc/hadoop/yarn-env.sh

以下を追加
export MAPR_IMPERSONATION_ENABLED=1

```

このあと、クラスタのNodeManagerを全て再起動してください。

デフォルトではアプリケーションの実行後にローカルからHDFS (MapR-FS)上の以下のパスにログが移動されます。

```
/tmp/logs/＜実行ユーザ＞/logs/＜アプリケーションID＞/
```

以下のコマンドでログを参照できます。

```
$ yarn logs -applicationId ＜アプリケーションID＞
```

HDFS上のファイルはwrite-onceなので、ログの参照はアプリケーションの実行後に可能となります。

ResourceManagerのWebUIからも参照可能にするためには、Job History Serverも再起動して下さい。

## centralized log aggregation

centralized log aggregationはMapR特有の機能となり、ログはアプリケーション実行中からMapR-FS上に格納されます。
そのため、ローカルのディスク容量を気にする必要がありません。
また、MapR-FSでは追記が可能なため、リアルタイムでの参照も可能となります。

ただし、centralized log aggregationが利用可能なのはMR, MR2に関してのみとなり、MR以外のYARNアプリケーションでは利用できません。

有効化する際には、yarn-site.xmlに以下の設定を追加します。

```
  <property>
    <name>yarn.use-central-logging-for-mapreduce-only</name>
    <value>true</value>
  </property>
```

追加後にnodemanager, resourcemanagerを再起動してください。

有効後にMR2アプリケーションを実行すると、デフォルトではMapR-FS上の以下のパスにログが記載されます。

```
/var/mapr/local/<host>/logs/yarn/userlogs/<アプリケーション>/<コンテナ>
```

上記のログをリアルタイムで参照しようとすると以下のようなコマンドになるため、パスが長くなり結構大変です

```
$ tail -f /mapr/<クラスタ名>/var/mapr/local/<host>/logs/yarn/userlogs/<アプリケーション>/<コンテナ>
```

これの対応として以下の用にシムリンクを作成出来ます。

```
$ maprcli job linklogs -jobid <アプリケーションID> -todir ＜参照先MapR-FSパス＞
```

参照先のMapR-FSパスを/tmp/centralにすると、ログの参照パスは以下のようになります

```
$ ls /mapr/<ホスト名>/tmp/central/<アプリケーションID>/hosts/<host>/<コンテナ>
```
phpで二分探索（binary search）

#概要
最近、CSを復習中で、とりあえずbinary searchを書いてみたので、メモっとく。
ログは時系列にソートされているデータ構造なので、ログの探索とかで使った記憶がある。

```php
<?php

$nums = range(1, 100);
$target = 13;

binarySearch($nums, $target);

function binarySearch($nums, $target) {

        $numsLength = count($nums);
        $halfNum = $numsLength / 2;
        $pivot  = (int)$halfNum;

        if ($nums[$pivot] === $target) {
                $format = "nums[%d] is %d\n";
                print sprintf($format, $pivot, $target);
        }

        if ($nums[$pivot] > $target) {
                binarySearch(array_slice($nums, 0, $pivot), $target);
        }

        if ($nums[$pivot] < $target) {
                binarySearch(array_slice($nums, $pivot), $target);
        }
}

?>
```
Pythonのロギング標準ライブラリでファイル出力をログレベル毎にする

#背景
・Pythonでログレベル毎にログファイルを分けたいという話があった。
・そもそもloggingライブラリをやっつけで使っていてきちんと理解していなかった。

では、手を動かして整理しつつ課題を解決してみよう。

#おさらい

```py3
import logging

logging.basicConfig(format='%(asctime)s   %(message)s', datefmt='%m/%d/%Y', filename = './basic.log')
logging.warning('basic.logに日付と共に記録される。')
logging.basicConfig(filename = './not-appeared.log')
logging.warning('basicConfigは起動後最初の一回しか機能しないので、not-appeared.logは生成されない。')

root_logger = logging.getLogger('')
root_logger.setLevel(logging.ERROR)
root_logger.error('ERROR レベル以上を記録するroot loggerが設定された。basic.logには引き続き現れる。ハンドラーを指定していないので、他には出ない。')

root_logger.addHandler(logging.StreamHandler())

root_logger.error('これでコンソールに現れる。basicConfigで指定したフォーマットは無視される。')
root_logger.warning('ログレベルが低いのでコンソールには出ない。無視されたらbasic.logにも出ない。')

critical_handler = logging.FileHandler('./critical.log')
critical_handler.setLevel(logging.CRITICAL)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
critical_handler.setFormatter(formatter)
root_logger.addHandler(critical_handler)

root_logger.critical('CRITICALのみ記録するハンドラーを追加。日付やレベル名も追加。')
root_logger.error('こちらはコンソールに出るものの、ログレベルが低いのでcritical.logには出ない。')

second_logger = logging.getLogger('second')
second_logger.setLevel(logging.WARNING)
second_logger.addHandler(logging.StreamHandler())

second_logger.warning('ロガーを追加してコンソールに出すように。basic.logに加え、rootロガーとこれでコンソールに二度出る。')

second_logger.propagate = False

second_logger.warning('propagateを否にすると上流には伝わらなくなり、こちらはsecond_loggerの一回分しか出ない。')
```
#ふりかえりと検討
・ルートロガーを元に多段階に継承できる。
・それぞれにハンドラーを複数設定できる。
・ロガーとハンドラーにはそれぞれログレベルを設定できる。
・但しいずれも下方の閾値なので、要件のように特定のログのみフィルタリングする事は出来ない。

#解法
フィルターを使えば、ロギングの都度ログレコード(ログメッセージのインスタンス)を引数に呼ばれて真偽値を返す事でフィルタリング出来る。

こちらのStackOverflowの投稿を参考にした。#1の方の言うように、特定のレベルだけ抜き出しても、人間が読めるようなものにはならないというのは同意するけど。

[python logging specific level only](https://stackoverflow.com/questions/8162419/python-logging-specific-level-only)

```log_file_by_level.py
import logging

class LoggingFilter(object):
    """特定のログレベルのみ残すフィルター"""
    def __init__(self, level):
        self.__level = level

    def filter(self, logRecord):
        #handlerへのレベル設定を外してここは== self.__levelとするのでも可のはず。
        return logRecord.levelno <= self.__level

def set_handler(loglevel, filename):
    #共通のログフォーマット
    log_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
    handler = logging.FileHandler(filename)
    handler.setLevel(loglevel)
    handler.setFormatter(log_format)
    handler.addFilter(LoggingFilter(loglevel))
    logger.addHandler(handler)

logger = logging.getLogger(__name__)
#アプリで記録すべき最低限のレベルを指定。
logger.setLevel(logging.DEBUG)
set_handler(logging.WARN, './warning.log')
set_handler(logging.INFO, './info.log')
```

```main.py
from log_file_by_level import logger

logger.warning('I warn you.')
logger.info('Please be informed that this is just a test.')
logger.error('Found error on your smile.')
```

#参考
・[python logging specific level only](https://stackoverflow.com/questions/8162419/python-logging-specific-level-only)
・[Logging HOWTO — Python 3.6.1 ドキュメント](https://docs.python.jp/3/howto/logging.html#handler-basic)
BigQueryを利用したアプリケーション作成時に理解しておくべきジョブの概念

BigQueryをログの保存先としていると、BigQueryを使ったアプリケーションを利用・作成する機会が増えてきます。アプリケーションを作成するために必要な「ジョブ」の概念について軽くおさらいします。

## BigQueryにおけるジョブとは

ジョブは簡単に言えばクエリの実行やデータのロードなどBigQueryで何らかの動作を実行させるための仕組みで、非同期で実行されます。ジョブは必ず１つのプロジェクトに紐づくので、どのプロジェクトに対して課金されるかを明らかにするのにも役立ちます。APIからジョブを実行する場合、プロジェクト内でユニークなIDを持たせて実行できます。そうすることで同じジョブを実行させてしまうことを防いだりそのIDを利用してジョブの結果を取得したりということができます。ジョブIDを指定しなかった場合はBigQueryが自動でユニークな値を割り当てます。

## BigQueryのAPI

BigQueryのAPIは REST API として用意されていて、`Projects`・`Datasets`・`Tables`・`Tabledata`・`Jobs`というコレクションがあります。REST API ですので`get`や`list`などおなじみのメソッドでアクセスできます（コレクションの特性上用意されていないメソッドもあります）。
https://cloud.google.com/bigquery/docs/reference/rest/v2/

### 低レベルのAPIを使ったクエリ実行と結果の取得

`Queries`のようなコレクションはありませんのでクエリを実行するには`Jobs`を使います。 `Jobs.insert`のパラメータにクエリを指定し、BigQueryに対してジョブを挿入します。 するとBigQueryはジョブを実行するので`Jobs.get`でジョブの結果が取得できます。そのジョブが成功している場合、クエリ結果の保存先として指定したdataset・table（指定しなかった場合は無名のIDが`Jobs.get`の Response Body に含まれている）に対して`Tabledata.list`を呼び出せばクエリの結果を取得することができます。このようにBigQueryではAPIを組み合わせることで**非同期的にクエリ実行と結果の取得**ができます。

#### `Jobs.insert` のリクエストパラメータの例

```
{
  "configuration": {
    "query": {
      "query": "select * from [project-id-001:dataset.table] limit 5"
    }
  }
}
```

#### `Jobs.get` のレスポンスの例

```
{
 // （一部省略）
 "kind": "bigquery#job",
 "configuration": {
  "query": {
   "query": "select * from [project-id-001:dataset.table] limit 5"
   "destinationTable": {
    "projectId": "project-id-001",
    "datasetId": "[_dataset_id...]",
    "tableId": "[table_id...]"
   },
   "createDisposition": "CREATE_IF_NEEDED",
   "writeDisposition": "WRITE_TRUNCATE"
  }
 },
 "status": {
  "state": "DONE"
 },
 "user_email": "test@example.com"
}
```

#### `getQueryResult`

おそらくBigQueryに挿入するジョブの多くはクエリの実行でしょうから、何度も別々のAPIを呼び出すのは少し面倒です。そこでBigQueryは`getQueryResults`という便利なAPIも提供してくれています。このAPIにジョブIDを渡せば`Tabledata.list`を呼び出さなくてもクエリの結果を返してくれます。

### `Jobs.query`によるクエリ実行と結果の取得

クエリ実行やその他の動作をBigQueryに指示するとき、結果取得にかなり長い時間かかってくることもあるのでジョブという仕組みは都合がいいです。しかし、ジョブを挿入してその結果を取得というプロセスを踏まなければならないのでやはり面倒です。

実はこれにも便利な方法があって、`Jobs.query`にクエリを乗せて呼び出せばAPI一発で**同期的にクエリの実行と結果の取得**ができます。ただし、指定したタイムアウト秒数（デフォルトでは10秒）が経過した時点で結果の取得ができなくてもリクエストが終了するという特徴があります。タイムアウトになってしまうのはそのリクエストだけで、ジョブは動き続けています。タイムアウト時にレスポンスで返ってきたジョブIDを使って`Jobs.getQueryResult`を呼び出せば結果を取得することができます。

## アプリケーションからAPIを呼び出すときの注意

アプリケーションからBigQueryのAPIを呼び出す際はこのジョブの仕組を理解していなければなりません。`Jobs.query`は便利なのですがジョブの仕組みを理解していなければ予期せずユーザーにタイムアウトエラーを見せてしまうことになります。

「クエリを実行して一定時間結果が返ってこなかったらタイムアウトになる」という仕様であれば`Jobs.query`で良いのですが、そうでないなら一度`Jobs.insert`でジョブを挿入してあとから`Jobs.getQueryResult`を呼び出すのが良いでしょう。もちろんこれは実装の問題なので`Jobs.query`を呼んで例外処理をするのでもいいしタイムアウトとして扱うのもいいと思います。

自分が実装するときだけでなく人が書いたコードをレビューする際は特に注意する必要があります。実装者がAPIの仕様を理解していない場合も考えられるで仕様と照らし合わせて指摘するべきポイントだと思います。特にAPIをラップする何らかのライブラリを使用している場合はおそらく`query()`のようにわかりやすいメソッドがあるので、何も考えずに実装すると`Job.query`を呼ぶ率が多くなることが予想できます。

## おわりに

以前pandasのコードを読んだときにどういうわけか`Job.query`しか呼び出していなかったと記憶しています。統計用ライブラリなのでわざとそういう設計にしているのか、あるいは自分が読んだときには単純に未実装だったのかはわかりませんが、pandasとBigQuueryを利用したアプリケーション作成時に苦労した記憶があります。BigQueryには非同期で結果を取得する仕組みがあるので、そのBigQueryを利用したアプリケーションでも非同期で実行する仕組みがある方が自分は好みです。
Visual Studio / WPF > UniformGrid > Provides a way to arrange content in a grid where all the cells in the grid have the same size.

```動作環境
Visual Studio 2017 Community (以下VS)
Windows 7 Pro (32bit)
```

http://www.atmarkit.co.jp/ait/articles/0904/03/news104_3.html
> Silverlight 2には存在せず、WPFでのみ利用可能なPanelとして、DockPanel、UniformGrid、WrapPanelなどが存在する。

UniformGridについて調べた。
https://stackoverflow.com/questions/6197646/understanding-uniform-grid-control

MSDN: https://msdn.microsoft.com/ja-jp/library/system.windows.controls.primitives.uniformgrid(v=vs.110).aspx
> Provides a way to arrange content in a grid where all the cells in the grid have the same size.

実装してみた。

```MainWindow.xaml
<Window x:Class="_170530_t1500_uniformGrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:_170530_t1500_uniformGrid"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="525">
    <Grid>
        <UniformGrid Rows="3" Columns="4">
            <Button Content="1" Height="40"/>
            <Button Content="2" Height="40"/>
            <Button Content="3" Height="40"/>
            <Button Content="4" Height="40"/>
            <Button Content="5" Height="40"/>
            <Button Content="6" Height="40"/>
            <Rectangle Fill="Aqua"/>
            <Button Content="8" Height="40"/>
            <Rectangle Fill="Aqua"/>
        </UniformGrid>
    </Grid>
</Window>
```

<img width="393.75" alt="2017-05-30_15h17_49.png (17.8 kB)" src="https://img.esa.io/uploads/production/attachments/6206/2017/05/30/21741/b057b80e-795a-43a9-83f9-8693fd4655e7.png">

Gridを使う場合と比べて、宣言順にインスタンスが配置されていく点は便利かもしれない。
PHP 5.4 から、PHP 7.0 への変換スクリプト

PHP 5.5 から、mysql_connect などが使えなくなったので、それらを、mysqli_connect に変換します。

```bash:mysql_to_php7.sh
#! /bin/bash
#
#	mysql_to_php7.sh
#
#						May/30/2017
#
ls $1/*.php > /tmp/tmp01
awk '{print "sed -i -f sed_to_mysqli",$1}' /tmp/tmp01 > /tmp/go_tmp
#
bash /tmp/go_tmp
#
```

```sed:sed_to_mysqli
#
#	sed_to_mysqli
#
#				May/31/2017
#
# ---------------------------------------------------
s/mysql_connect(/$link=mysqli_connect(/g
s/mysql_select_db(/mysqli_select_db($link,/g
s/mysql_query(/mysqli_query($link,/g
s/mysql_fetch_array/mysqli_fetch_array/g
s/mysql_fetch_row/mysqli_fetch_row/g
s/mysql_fetch_assoc/mysqli_fetch_assoc/g
s/mysql_close()/mysqli_close($link)/g
s/mysql_error()/mysqli_error($link)/g
s/mysql_num_rows/mysqli_num_rows/g
s/mysql_free_result/mysqli_free_result/g
s/<? /<?php /g
# ---------------------------------------------------
```

使い方

```text
./mysql_to_php7.sh フォルダー名
```

フォルダー内にある *.php が変換されます。
nGUI uGUIの比較＆選択

# nGUIとuGUI
　Unity 4.xの時代ではGUI系が標準のままだと不便なので、GUI系をNGUIで作成する方が多く存在します。
　また、Unity 4.6から新しいUIシステムuGUIが搭載されるようになって、Unity 5ではuGUIがさらに更新され、とても便利なツールになりました。以前のUIシステムと違って、かなり改善されていました。
　nGUIからuGUIに移行するプロジェクトがたくさんいます。

# nGUI VS uGUI
　わかりやすいようにテープルにまとめることにします。

|                  | nGUI             |       uGUI        |    結論             |
|:-----------------|:-----------------|------------------:|:-------------------:|
| Source           | 買ったら勝手に編集  |     Open Source   |        お金ですね   |
| 大きさ            | android:20.1MB & ios:15.4MB           |            android:19.4MB & ios:14.4MB |       ボタン一個の場合       |
| 開発言語             | 全部C#             |              コアの部分がC＋＋ |        C＋＋なので、性能いいだろう        |
| ライブラリー             | 以前のUIライブラリーnGUI対応するのが多い               |                ５．３以後ライブラリー対応 |         将来的にuGUI         |
| Layout             | grid             |             AutoLayout & CustomLayout |       uGUIの方が拡張しやすい       |
| Event処理             | collider          |           RaycastTarget |     　-       |
| zOrder             | Panel depth & RenderQueue          |           hierarchyの並び順 |      uGUIの方がわかりやすい       |
| 画像ソース             | 手動パケッジーグ          |           開発段階は普通のソース、リリース段階はパケッジーグ |      uGUIの方がコントロールしやすい、効率向上       |

　uGUIはunity側作っていた新生UIシステムのため、nGUIのものを吸収して、いろいろのフィードバックをもらった後に開発した。未来性はすごくあると思います。

# メリット＆デメリット（uGUI）
　uGUIはRectTransformを活用しています、UIパーツはスクリーンサイズに適用しやすくなる、コントロールしやすくなりました。
　uGUIは画像ソースとか入っていないため、ソースの管理はあんまに大変ではなかった。
　uGUIはTweenないです。
　uGUIはUIWrapでScrollViewを作成しない。
　NGUIはWebみたいに画像とテキストを一緒に並べることは可能だが、uGUIは対応する必要がある。

# 注意点
## nGUI
　アニメションを再生する場合、spriteではなく、panelです。
　SpriteのTypeができるだけ、tileに避けましょう。
## uGUI
　たくさんのcanvasがある場合、タッチイベントが下か上のcanvasで反応してしまうので、graphics raycaster、GameObjectなどの注意は必要。
　
# まとめ
　nGUIはuGUI出る前に、UIシステムを効率よくなるためのプラグインでした。uGUIはunityに合うUIシステムを作り込んでいました、その効率性、性能はかなり進んだと思います。新規のプロジェクトだと、uGUIを利用すべきかと思います。unityのチュートリアルも詳しい使いたかも乗っているのため、コスト的にもほぼないかと思います。

PR:[自分のブログ](http://zamberform.github.io/blog/)