OmniAICreator/Qiita-1.07M huggingface dataset:
Jenkinsではまったエラー

## ERROR: Error fetching remote repo 'origin'

```
Started by user anonymous
Building in workspace /var/lib/jenkins/workspace/WebDriverTest
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url git@bitbucket.org:zakki1206/cook-project.git # timeout=10
Fetching upstream changes from git@bitbucket.org:zakki1206/cook-project.git
 > git --version # timeout=10
using GIT_SSH to set credentials 
 > git fetch --tags --progress git@bitbucket.org:zakki1206/cook-project.git +refs/heads/*:refs/remotes/origin/* # timeout=30
ERROR: Error fetching remote repo 'origin'
hudson.plugins.git.GitException: Failed to fetch from git@bitbucket.org:zakki1206/cook-project.git
	at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:825)
	at hudson.plugins.git.GitSCM.retrieveChanges(GitSCM.java:1092)
	at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1123)
	at hudson.scm.SCM.checkout(SCM.java:495)
	at hudson.model.AbstractProject.checkout(AbstractProject.java:1202)
	at hudson.model.AbstractBuild$AbstractBuildExecution.defaultCheckout(AbstractBuild.java:574)
	at jenkins.scm.SCMCheckoutStrategy.checkout(SCMCheckoutStrategy.java:86)
	at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:499)
	at hudson.model.Run.execute(Run.java:1727)
	at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
	at hudson.model.ResourceController.execute(ResourceController.java:97)
	at hudson.model.Executor.run(Executor.java:429)
Caused by: hudson.plugins.git.GitException: Command "git fetch --tags --progress git@bitbucket.org:zakki1206/cook-project.git +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout: 
stderr: Permission denied (publickey).
fatal: The remote end hung up unexpectedly

	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:1970)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:1689)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$300(CliGitAPIImpl.java:71)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:380)
	at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:823)
	... 11 more
ERROR: Error fetching remote repo 'origin'
Finished: FAILURE
```


### 原因

bitbucketに登録した公開鍵の秘密鍵のパスが正しくなかった。

/root/.ssh 配下の鍵を/var/lib/jenkins/.ssh 配下にコピー


```bash

[root@tk2-408-45235 /]# ls -la /var/lib/jenkins/.ssh/
total 20
drwxr-xr-x  2 jenkins root    4096 Nov 30 19:50 .
drwxr-xr-x 15 jenkins jenkins 4096 Nov 30 19:50 ..
-rw-------  1 jenkins jenkins 1743 Nov 30 19:50 id_rsa
-rw-r--r--  1 jenkins jenkins  416 Nov 30 19:50 id_rsa.pub
-rw-r--r--  1 jenkins jenkins 1199 Nov 30 15:43 known_hosts

```

## ビルドシェルの実行でsudoが使えない

sudo: /bin/sudo must be owned by uid 0 and have the setuid bit set

### やったこと

Jenkinsでsudo実行可能設定

```
    sudo visudo
```

下記を変更

```
    # Defaults !visiblepw
    Defaults visiblepw
```

下記を追加

```
    root    ALL=(ALL:ALL) ALL
    jenkins ALL=(ALL) NOPASSWD:ALL
```


jenkins リスタート


```
    service jenkins restart
```

### 回避

解決できなかったので
cronで行うことで回避した


どなたか心当たりがあれば教えてください。。。
kotlinでOpenCV(環境設定編)

最近openCV使う人ってpython使う人が多いらしく、参考記事読んでもぱっと見、何がMatなのかなんなのか型がわからないです。そこに一石投じたいのと、kotlinでopenCVて新しいんじゃね？と思ったので書いてみました。(実際はjavaのときとそう変わらないのですがまだ記事として書いている人がいなさそうということで)
長くなりそうなので3回ぐらいに分けて書こうと思います。

##環境設定

###OpenCV for Androidのダウンロード
Android用のOpenCVをダウンロードします。[ここから](https://opencv.org/releases.html)自分のほしいバージョンを選んで
(今回は[3.2](https://github.com/opencv/opencv/releases/tag/3.2.0)です)opencv-3.2.0-android-sdk.zipをダウンロードして解凍してください。

###プロジェクトの作成
MainActivityはBlankで適当にprojectを作ってください。
プロジェクトを作り終わったら「File > New > import Module」を選択して次の画面のSourceDirectoryに次の画面のSource Directoryに`(OpenCVを展開した場所)/OpenCV-android-sdk/sdk/java`と入力してください。

![すくりーん1.png](https://qiita-image-store.s3.amazonaws.com/0/192385/47be7d0f-e76d-8cdb-278d-3bc3f35f9b72.png)

ModuleNameは適当で大丈夫です。デフォルトで`openCVLibrary320`て感じの名前がつきます。

###OpenCVライブラリをプロジェクトに追加
解凍したOpenCVフォルダから`sdk > native > libs`をコピーして先程作ったプロジェクトの`(プロジェクト名) > app > src > main`にペーストしてください。またこのフォルダの名前を`jniLibs`に変更してください。うまく目的のディレクトリが見つけられない人はディレクトリの表示を`app`から`project`にして探してください。

###モジュールの依存関係を設定
Android Studioの`File > Project Structure`を開き、左側にある「app」を選択して、右上の「Dependencies」タブを開きます。右カラム右上の「+」ボタンを押して「Module dependency」選択すると先程取り込んだライブラリが表示されるのでそれを選択して「OK」を押して追加してください。

![スリーん2.png](https://qiita-image-store.s3.amazonaws.com/0/192385/300cd4ef-4fac-f65e-3e08-556252ba9e06.png)

###build.gradleの変更
最後にopenCVモジュールの中のbuild.gradleで指定されているcompileSdkVersionとbuildToolsVersionの値をappモジュールのbuild.gradleの値と合わせてください。例えばappの方でcompileSdkVersionが26とか書いてあればopenCVの方のbuild.gradleでも26て書いてやってください。

**app: build.gradleの切り抜き**
![appgradle.png](https://qiita-image-store.s3.amazonaws.com/0/192385/406a387c-f44d-8c47-bc2a-f0f01f5ce805.png)

**OpenCV: build.gradleの切り抜き**
![opencvgradle.png](https://qiita-image-store.s3.amazonaws.com/0/192385/37e7a503-af86-1110-e02e-ff2dde4c2a03.png)

ここまででOpenCVをAndroidで使う環境が整いました！
###kotlin環境を整えていく
[このサイト](https://www.usaco-pg.com/2017/04/11/kotlin-android-helloworld/)を参考にしてkotlin環境を整えてください。
今回は「kotlin Android Extentsions」(findViewByIdをほぼいらない子にするすごいやつ)を使用したいのでProjectのbuild.gradleに`classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"`の一行を追加してください。![appgradle.png](https://qiita-image-store.s3.amazonaws.com/0/192385/0371774e-e108-d8bb-cd11-78c8da7bded6.png)

これでやっと環境設定終わりです！お疲れ様でした！
次回は[画像同士の特徴量比較編](https://qiita.com/pokotsun/items/f5d9cdd2cca14fd85369)です！

明日は三千万さんが書いてくれるらしいので楽しみにしています。あの人のことだから素晴らしい記事でしょう。
５日後くらいにまた会いましょう。

###参考にしたサイト
環境設定に関しては[このサイト](https://qiita.com/kodai100/items/6c9e8a34d0714913c017)を参考にさせてもらいました、ありがとうございました！
【MarkLogic Server】XQueryチューニングメモ～チューニング補助ツール

はじめに
===
MarkLogicに関連してXQueryの性能チューニング記事を集中的に上げていこうと思っていたのですが、まず今回はMarkLogicに付随するチューニング補助ツールを紹介していきます。性能チューニングを始める段階で何がネックになっているかを把握する手助けとなるはずです。(画像がうまくアップロードできないのでとりあえずテキストだけですが→IE以外のブラウザでうまくいったので画像を上げました)

クエリコンソールのProfile表示
===
MarkLogicインストール時に標準的に作成される[クエリコンソール](http://docs.marklogic.com/guide/qconsole/walkthru#id_90500 "クエリコンソール")(ポート8000番)は、実際に自分のクエリを書いて戻り値を確認できる便利なツールです。今回はその中にあるProfile実行というものを紹介します。

通常、画面中央のテキスト部分にクエリを記述し、Runボタンを押すと検索結果が表示されます。

![通常実行.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/89710249-288b-1a07-7d68-466b11506cc9.jpeg)

今度は、画面下部の「Profile」を選択してから実行してみましょう。

![Profile実行.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/6fb70e0a-4f0a-4ae6-6317-91d8d1ee2232.jpeg)

画面下部には戻り値の代わりにどの記述がどのように使われたかが影響が大きかった順に表示されました。通常はDB検索を伴うcts関数がネックになことが多いのですが、手元ではループ内で文字列分離を行うfn:tokenizeが10万回も実行され上位に挙がりました。
チューニング対象としてこの上位に挙がっているものから解決すると効率よくなります。


監視画面のリソース利用履歴
===
簡易的ですが、DiskIO/CPU/メモリなどの利用状況をグラフ化して表示することが可能です。

☆DB設定
この結果を得るためには、DB設定の変更が必要です。ポート8001の管理画面を開いてConfigure→Groups→Defaultを選択し、以下のパラメータを変更します。

| パラメータ | 設定値 |
|---|---|
|metering enabled|true|
|performance metering enabled|true|

![Meters設定.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/4c4b0c11-8163-8367-fa7f-2f2052b09f9f.jpeg)


☆histroy画面
DB設定の変更後にMetersデータベースに取得結果が蓄えられはじめます。では実際に見てみましょう。クエリコンソール上部のMonitoringからHistroyを選択します。画面が開いたら左側の「TIME SPAN」を好きな範囲に調節したうえで、右上にある矢印ボタンを押してみましょう。すると設定した範囲にグラフ表示が変更されます。
＊グラフが出ない場合は、ブラウザを変えてみる、あるいは互換表示を変更してみる、などで表示されるようです。

![history.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/ee9c0fd2-3a41-fc28-a61f-bf1a8547f003.jpeg)

リソースにずいぶんと余裕があるようなら、並列処理をかけても問題なさそうです。逆にひっ迫している場合は、リソースの追加やクエリの改修方法の目途に役立ちます。

監視画面のダッシュボード
===
クエリコンソール上部のMonitoringからDashboardを選択します。すると「Query Execution」というタブの画面が出ます。これはDBに対して実行されているクエリの状況を一定時間ごとに表示更新する画面がでます。

![dashboard.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/6e71d667-4fdb-0285-a2a0-687f6b686e48.jpeg)

次に「Disk Space」というタブを選択してみましょう。ここでは空き容量と使用容量が表示されます。ディスクの空き容量はMarkLogicのマージ領域を脅かし性能低下につながるため監視は重要です。

![dashboard2.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/269ffd28-3ad5-3a5f-739f-f6a10543b3b9.jpeg)

棒グラフの青い部分が、実際に使っている部分とマージ領域として確保しておきたい部分です。

おわりに
===
今回はMarkLogicがインストール時から備えている性能・リソース監視ツールを紹介しました。グラフ化して表示してくれることから初心者でも問題点の把握に使えそうですし、熟練者でもトラブル対応にて迅速に状況把握するツールとして活用できるものだと思います。

```math
\def\textsmall#1{%
  {\rm\scriptsize #1}
}
```

------------------------------------------------------------------------

**免責事項**

​​​​​$\textsmall{当ユーザ会は本文書及びその内容に関して、いかなる保証もするものではありません。}$
​​​​​$\textsmall{万一、本文書の内容に誤りがあった場合でも当ユーザ会は一切責任を負いかねます。}$
​​​​​$\textsmall{また、本文書に記載されている事項は予告なしに変更または削除されることがありますので、予めご了承ください。}$
コミュニケータをメモリを共有するノードで分ける

https://adventar.org/calendars/2548

メモリ共有するプロセス間では共有メモリを使いたい場合、メモリ共有するノードだけでグループを作りたい場合などがある。

MPI ver3 以降なら、MPI_Comm_split_type で、メモリ共有するプロセスだけでcommを分けることができる。

```c++
#include <mpi.h>
#include <stdio.h>

int main(int argc,char **argv)
{
    MPI_Init(&argc, &argv);

    MPI_Comm shared_nodes;
    int all_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &all_rank);

    MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shared_nodes);

    int shm_rank;
    MPI_Comm_rank(shared_nodes, &shm_rank);

    int shm_head_rank = all_rank;
    MPI_Bcast(&shm_head_rank, 1, MPI_INT, 0, shared_nodes);

    if (shm_head_rank == all_rank) {
        printf("all_rank=%d, head_rank=%d, in_shm_rank=%d (HEAD)\n",
               all_rank, shm_head_rank, shm_rank);
    } else {
        printf("all_rank=%d, head_rank=%d, in_shm_rank=%d\n",
               all_rank, shm_head_rank, shm_rank);
    }

    MPI_Comm_free(&shared_nodes);

    MPI_Finalize();
}
```
かんたん、お手軽、TweetBot（Crystal編）

# お前 is 誰?

@msky026

---
# 切っ掛け

10月からブレンド・Sが始まりました。

---

ドリコムの者として（10月時点）何かせねば、、、

---

どうしようか、、、

---

そうだ、TwitterBotを作ろう！

---

というわけで、放映時間10分（くらい前）に放送開始を通知するBotを作ることにした。

---

いい機会だからCrystalでやろう

---

いい感じにCrystal版のクライアントがある

https://github.com/sferik/twitter-crystal
(Ruby版のと同じ作者)

---
```shard.yml
dependencies:
  kemal:
    github: sdogruyol/kemal
    branch: master
  db:
    github: crystal-lang/crystal-db
    branch: master
  twitter-crystal:
    github: sferik/twitter-crystal
    version: ~> 0.2.0
```

---

```crystal
require "twitter-crystal"

class TwitterClient
  @client : Twitter::REST::Client
  def initialize
    consumer_key                 = ENV["CONSUMER_KEY"]
    consumer_secret              = ENV["CONSUMER_SECRET"]
    access_token                 = ENV["ACCESS_TOKEN"]
    access_token_secret          = ENV["ACCESS_TOKEN_SECRET"]
    @client                      = Twitter::REST::Client.new(consumer_key, consumer_secret, access_token, access_token_secret)
  end

  def tweet(message)
    @client.update(message)
  end
end
```

```crystal
twitter_client = TwitterClient.new
twitter_client.tweet("hogehoge")
```

---

かんたん、お手軽

---

完

---

本当に？

---

```bash
heroku run bash
crystal run src/tweetbot/tweet.cr
```

---

```
--: 1: --: cc: not found
Error: execution of command failed with code: 127: `cc "${@}" -o '/app/.cache/crystal/crystal-run-tweet.tmp'  -rdynamic  -lz `command -v pkg-config > /dev/null && pkg-config --libs libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs libcrypto || printf %s '-lcrypto'` -lpcre -lm -lgc -lpthread /app/.platform_tools/crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/lib -L/usr/local/lib`
```

---

結論から言うと、Heroku上でスクリプト実行が出来ない。
（少なくともHeroku-16スタックでは）
ビルドしてバイナリ実行すればOK

---

ただし、Kemalのとバイナリを2つ作らなければならない
（BotなのでKemalのはいらないと言えばいらないけど）

---

Heroku ビルドパック(msky026製)
https://github.com/msky026/heroku-buildpack-crystal

---

```
crystal_version=0.23.0
always_rebuild=false
config_vars_to_export=(DATABASE_URL)
post_compile="pwd"
build_command=("crystal build --release ./src/tweetbot.cr" "crystal build --release ./src/tweetbot/tweet.cr")
```

---

build_command
ビルドコマンドを複数指定できる

---

これでKemalとTweetBotのを2つ作り
Herokuスケジューラで
```
./tweet
```

---

結論
Elixirベースのビルドパックはいいぞ
シンボルの succ は、文字列の succ よりも遅い

[文字列をキーにすると、シンボルよりも少し遅い](https://qiita.com/Nabetani/items/97ffef21cbcb67489d79)
という記事を書いたんだけど、なんで差があるのかと。思った。

シンボルは内部的には整数だと言われている。
ということは、シンボルは生成されるたびに、対応する整数を作る必要があるはずだ。

ならば。
似たような処理を文字列とシンボルで行ったら、整数を作る分、シンボルのほうが遅かったりするんじゃないかと思った。

シンボルと文字列で同じような処理といえば、`succ`。

というわけで、例によっていい加減なコードで比較してみた。

こんな

```ruby
require "benchmark"

N=1_000_000

print "ruby #{RUBY_VERSION}|"

k=("a"*1000)
print "%.3f|" % ( Benchmark.realtime do
  N.times do |n|
    k=k.succ
  end
end )

k=("a"*1000).freeze
print "%.3f|" % ( Benchmark.realtime do
  N.times do |n|
    k=k.succ.freeze
  end
end )

k=("c"*1000).to_sym
print "%.3f|" % ( Benchmark.realtime do
  N.times do |n|
    k=k.succ
  end
end )

puts
```

感じ。

実行してみると：

||通常文字列|frozen文字列|シンボル|
|:--|:--|:--|:--|
|ruby 2.4.2|0.438|0.477|8.760|
|ruby 2.3.5|0.423|0.443|13.615|
|ruby 2.2.7|0.456|0.469|12.952|

こんな感じ。

2.3 と 2.4 の間に何かあったらしい。
ありがとうございます。

それはともかく。
1000文字あると、シンボルは 20倍くらい遅い。

つまりやっぱり、生成時にコストを掛けることで比較を速くしているということなんだろう。

と思うと謎なのは frozen文字列。なんで比較が速くなるんだろう。そもそも速くなっているのかどうか。気になるけど今日のところはこれぐらいで。
Rin - Redshift data Importer by SQS messaging - のご紹介

この記事は[OSS紹介 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/favorite-oss) の 1日目の記事です。

## Rinとは

[fujiwara/Rin](https://github.com/fujiwara/rin)

Rinは、簡単に言えばS3にアップロードしたログをRedshiftに自動で取り込むためのミドルウェアです。私は会社でfluentdと組み合わせて以下の構成図のような形で利用しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/3629/fec12517-35fb-ed55-735a-7b046de559c7.png)

Rinが行っているのは実線で示している部分です。

1. log aggregatorと呼ばれるfluentdが起動しているインスタンスから`fluent-plugin-s3`でS3にアップロードします
2. アップロードをトリガーにSQSにキューが入ります。それをlog aggregatorで起動しているRinが受信します
3. RinはRedshiftで`COPY`クエリを発行します
4. `COPY`クエリを発行されたRedshiftはS3にアップロードされたログを取り込みます

## 解決される問題

* S3にアップロードされた後にイベントが発行されるため、バケットにファイルがなくて空振りすることが殆ど無い
* fluent-pluginですべてやらないため責務が分割され、さらにfluentdが刺さることもない

## 実際の活用例

[ソーシャルゲームのカスタマーサポートを支える行動ログとredash](http://techblog.kayac.com/2016/12/21/160000)

以上の記事ではユーザの行動ログをRedshiftにとり込み、Re:dashを用いて可視化と検索を行っていますが、ログの取り込みにRinが使われています。

---

明日12/2は @papix さんで、「最近発見してテンション上がったMackerel Pluginの紹介します」です。
Pythonのurllib2でプロキシを刺す

どうも、最近糞記事を量産して数を稼いでいる人です。

唐突ですが、如何わしい事をしたい人間は串を指したいものです。
なので、サンプルコードをここに置いておきます。
ちなみに、Python2系です。

```set_prox.py
from __future__ import with_statement
import urllib2

#送信パラメーターをセット
obj = {"actions" : "param"}
#タイムアウト設定の時間
timeout = 0.5

with open('/proxy.txt') as ip_list:
    for ip in ip_list:
        proxy = {'http':'http://{0}'.format(ip)}
        proxy_handler = urllib2.ProxyHandler(proxy)
        opener = urllib2.build_opener(proxy_handler)
        urllib2.install_opener(opener)

        #Request作成
        request = urllib2.urlopen(request,timeout=timeout)
        param = urllib.urlencode( obj )
        request = urllib2.Request(url,param)
        #User-Agentを設定
        request.add_header("User-agent", 'Mozilla/5.0')
        #refererを設定
        request.add_header('Referer', 'http://hoge.com')
        #エンコード方法を設定
        request.add_header('Content-Type', 'application/x-www-form-urlencoded')
        request.add_data(param)

        try :
            #URLを開く（送信）
            request = urllib2.urlopen(request,timeout=timeout)
        except :
            print("error")

```

こんな感じでプロキシーをぶっ刺して送信することが出来ます。
Exceptのエラーについては、色々用意されてるみたいなので各自で調べて設定してください。
バッチファイルで FizzBuzz

# はじめに

これは [FizzBuzz Advent Calendar 2017](https://qiita.com/advent-calendar/2017/fizzbuzz) 2 日目の記事となります。
Windows のコマンドプロンプトで走る bat ファイルで FizzBuzz をやってみました。
(動作確認は Windows 10 で行っています)

# コード

こうなりました。

```bat:FizzBuzz.bat
@ECHO OFF & CLS
SET /A I=0
:LOOP
  SET /A I=I+1, F=I%%3, B=I%%5, FB=F+B
  IF %FB% == 0 (
    ECHO Fizz Buzz
  ) ELSE (
    IF %F% == 0 (
      ECHO Fizz
    ) ELSE (
      IF %B% == 0 (
        ECHO Buzz
      ) ELSE (
        ECHO %I%
      )
    )
  )
IF %I% LSS 100 GOTO :LOOP  
```

SET /A を知っていれば難しくないですね。

# おわりに

ひょっとすると...というかこれよりスマートに書ける方法が間違いなくあると思うのです。
もっとスマートに書ける方法をご存知の方はコメントをお願いします m(_ _)m
11. FUJITSU K5 の価格について考える

このページは、
FUJITSU Cloud サービス K5 を使ってみる - Qiita
http://qiita.com/ynott/items/a256669c692625c5fd25
の「11. FUJITSU K5 の価格について考える」のページです。

今年(2017年)に、FUJITSU K5 クラウドについてテストしてみる機会を得ました。

使ってみた内容については、
FUJITSU Cloud サービス K5 を使ってみる - Qiita
https://qiita.com/ynott/items/a256669c692625c5fd25
をご参照いただきたいのですが、アドベントカレンダーネタとしてK5は価格的にどうなんだろう？と言う事を考えてみます。以下のアドベントカレンダー 1日目です

FUJITSU Cloud Service K5 Advent Calendar 2017 - Qiita
https://qiita.com/advent-calendar/2017/k5

K5の価格表は、以下のページにありますね。

料金表 | FUJITSU Cloud Service K5 : 富士通
http://jp.fujitsu.com/solutions/cloud/k5/price/
第59.0版を元に考えます。

比較対象として、AWSの価格を比較してみます。AWSの価格は以下を参考にします。

AWS 月額料金チートシート - Qiita
https://qiita.com/jyotti/items/d47b52fa13d12476406f

CPUをメインに比べてみました。

AWSの価格は、皆さんいつもの見慣れた「t2.micro」とかです。
「P-1」とかハイフンが入っているものが、K5の価格です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/15176/c5bd1a53-0521-d276-4aa6-5cd78e27c7ec.png)

ザクッと見ると、CPU1個のところのメモリー別仮想マシンはK5の方が多いですね。
CPU2個の仮想マシンの価格はけっこうK5も頑張っていると思います。
CPU4個の仮想マシンについてもメモリー32GBを越えたところでK5の価格がAWSよりも安くなっています。
CPU8個以上でも結構、戦略的な価格になっていてもっと差があるかと思ったのですが、そうでもないという印象です。

＃もちろん、仮想マシンの価格を単純に比較するのは愚かな事だとは思っています。
＃エコシステム的な部分や、単なるIaaSを越えているところにAWSの強みはあるはずなので、
＃そこの部分を考えないというのはフェアではないというのは分かっています。

じゃあK5をお勧めできるか？と言われると、「VMの価格では負けてませんね。」と言う事はできると思います。
ネットワークのダウンロード課金もK5にはないので、「単純なVMでよくてネットワーク課金がないのを探している」
という会社さんにはお勧めだと思います。
変数名やブロックパラメーターをアンダースコア1文字にするイディオム


## はじめに

この記事は書籍「[プロを目指す人のためのRuby入門](http://gihyo.jp/book/2017/978-4-7741-9397-7)」に掲載できなかったトピックを著者自らが紹介するアドベントカレンダーの1日目です。
本文に出てくる章番号や項番号は書籍の中で使われている番号です。

今回は変数名やブロックパラメーターをアンダースコア1文字にするイディオムを紹介します。

### 必要な前提知識

「プロを目指す人のためのRuby入門」の第4章まで読み終わっていること。

## 変数名やブロックパラメーターをアンダースコア1文字にするイディオム

「2.2.8 変数（ローカル変数）の宣言と代入」で説明したとおり、Rubyでは変数名をアンダースコアで始めることができます。
アンダースコアで始めることができるということは、アンダースコア1文字の変数名でも有効、ということです。

```ruby
# アンダースコア1文字の変数の宣言と参照
_ = 123
_ #=> 123
```

通常はこのような変数を使うことは滅多にありません。
ですが、ときどき「とりあえず代入はするが、使わない変数」の意味でアンダースコア1文字の変数が使われることがあります。

```ruby
str = "Alice,Female,20"
# 文字列を名前と性別と年齢に分割するものの、使うのは年齢だけ
_, _, age = str.split(',')
age #=> "20"

# ただし上のコードはあくまで説明用。本当はこう書いた方が明示的
age = str.split(',').last
```

ブロックパラメーターでも同じような用途で使われることがあります。

```ruby
currencies = { 'japan' => 'yen', 'us' => 'dollar', 'india' => 'rupee' }
# キーと値のうち、値しか使わない
currencies.map { |_, v| v.upcase } #=> ["YEN", "DOLLAR", "RUPEE"]

# ただし上のコードはあくまで説明用。本当はこう書いた方が明示的
currencies.values.map(&:upcase) #=> ["YEN", "DOLLAR", "RUPEE"]
```

ですが、このような変数を積極的に使うべきかというと、そうではありません。
上のコードでも示したように、アンダースコアを使わず明示的に書く方法があれば、そちらを使うべきです。

とはいえ、他の人が書いたコードの中にこうしたテクニックが使われていることはありえるため、頭の片隅に置いておくのは良いと思います。

## 次回予告

次回はメソッドの引数をアスタリスク1文字にするイディオムを紹介します。
Rails書きの僕が最低限やっているAtomの設定

何も設定しないと使い物にならないという噂のAtomにRails書きの僕が最低限やっている設定。

## Settings > Editor Settings

font family : Windowsなら consolas, Meiryo。Macなら空のまま。
Show Invisibles : ✓
Soft Tabs : ✓
Soft Wrap : ✓
Tab Length : 2 (デフォルト)

タブの設定はEditorConfigを利用しているのであれば**editorconfig**パッケージを入れることによって設定が不要になる。

## Packages > Core Packages

**Whitespace**
勝手に空白や改行が削除されたりしちゃう！というときに設定を確認。
Ignore White Space On Current Lineは不要なタブの入ったコードが残りがちなので気分によっては切る。

**metrics**
Google Analyticsに利用統計データを送信するパッケージ。
気になるならDisableに。

## 入れておくと便利なPackages

**auto-update-packages**
packageの自動更新

**open-recent**
最近開いたファイル

**file-icons**
無味乾燥なファイルアイコンを色とりどりにしてくれる。

**Sublime-Style-Column-Selection**
矩形選択ができるようになる。

**language-apache**
.htaccessに色がつく

**linter**
**linter-ruby**
**linter-rubocop**
Linter系。
linter-rubyはそのままだと日本語が含まれるファイル名を上手く扱えないので以下の設定が必要。

【Atom】linter-rubyが日本語文字列に「unexpected end-of-input, expecting keyword_end」という
https://qiita.com/moonsubaru/items/8ef31a5029f88bd20e1a

**language-haml**
**linter-haml**
Hamlを使うのであれば

**language-sass**
**linter-sass-lint**
Sassを使うのであれば

**language-coffee-script**
**linter-coffeescript**
CoffeeScriptを使うのであれば。

**minimap**
**minimap-git-diff**
Sublime Textとかにあるminimapのパッケージ。
幅広なディスプレイ使っていると右方向が寂しいときに入れる。
minimap-git-diffは名前通りminimapでgitの差分がわかりやすくなる。

**split-diff**
二つのファイルのdiffが見られる。

**pigments**
CSS上のカラーコードの色が文字の背景色として表示される。

**color-picker**
CSSとか書いてるときにカラーピッカーからカラーコードを引っ張ってこられる便利パッケージ。

## Settings > Core Settings

Allow Pending Pane Items : オフ

Atom 1.6あたりからファイルをシングルクリックしたときには現在のタブでプレビューがされるようになった。
挙動がわかりづらく、個人的にエディタのファイルは新しいタブで開いてほしいのでオフにする。

## Ctrl + Tab の挙動の変更

Atom1.7からCtrl + Tabの挙動がMRU (Most Recently Used)になっているが、ブラウザとかと同じ右左に移動してほしいので設定ファイルを少し修正する。

Atom 1.7からタブ切り替えが使いづらくてイライラするので従来式に戻す
http://qiita.com/takuchan9104/items/237dd39bf5987879b106

または**disable-mru-tabbing**パッケージの導入でも同様の修正が可能。

## おわりに

以上で挙げたパッケージの他にも便利なパッケージはたくさんあります。
Atomを使い慣れてきて「こんな機能はないのかな？」と思ったらググってみてください。
また何から設定を改善したら良いのかわからなければ「Atom Ruby(Rails)」などでググればたくさんの推奨設定が見つかるので参考にしてみると良いでしょう。

### おまけ

一気に全部インストール

```
apm install editorconfig auto-update-packages open-recent file-icons Sublime-Style-Column-Selection language-apache linter linter-ruby linter-rubocop language-haml linter-haml language-sass linter-sass-lint language-coffee-script linter-coffeescript minimap minimap-git-diff split-diff pigments color-picker disable-mru-tabbing
```
iOSで独自SSL証明を回避する方法

NSURLSessionを使っています。

NSURLSessionDelegateを使用します。

以下のメソッドを追加します。

```objc
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
    }
}
```


NSURLSessionを作る時 delegateを指定します。

```objc
NSURLSession* session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; 
```
ざっくりまとめたSSL/TLS

# "SSL"とは
多くの場合はSSL3.0/TLSの2つの事を指す
下位互換はないものの、ほぼ同じ機能を提供する為に呼ばれている。

# "https"とは
ご存知、
Web通信で使用されるHTTPプロトコルをSSL/TLSプロトコルで保証するプロトコル

## https通信をする上で重要な登場人物

| 種類 |説明 |
| ---- | ---- |
| 証明書 |  WEBサイトが安全であるという事を外部に示す電子証明書 |
| 公開鍵・秘密鍵  |WEBサーバで使用する暗号化・復号化の鍵 | 
| 暗号化アルゴリズム | データ転送時に用いる暗号化・復号化のルール |
| SSLライブラリ | SSLプロトコルを実装する暗号化・復号化モジュール | 

# "SSH"とは
ご存知の通り、リモートでコンピュータにログイン・操作プロトコル。
いつも使うコマンド。
アプリケーション層で実装される暗号化方式
SFTPやポート制御でも利用される

# "TLS" とは
SSLとの違いは、暗号アルゴリズムをサポートしたという点。
「SSL通信でxxする。」という会話も実際にはTLSだったりする事が多い。

DH,DSS,3DESなど。
3DES(トリプルデス)はDESで3回暗号化する方式。

# SSLハンドシェイク
## 方法
公開鍵暗号方式で共通鍵を交換などを行う
	
## ステップ
![スクリーンショット 2017-11-30 18.46.07.png](https://qiita-image-store.s3.amazonaws.com/0/75761/9d2336ca-53b8-952a-da89-354aed6d5303.png)
(※かなり簡略化しています)

1. 使用するアルゴリズムの合意
  クライアントが対応しているアルゴリズムのリストを送付
  クライアントに実際に使用するアルゴリズムを返す  
  　
  伝える情報
  - SSL version
  - サーバ認証アルゴリズム
  - 鍵交換アルゴリズム
  - データ転送で使用するデータ保護用の鍵共通方式アルゴリズム
  - データ転送で使用するデータの完全性を確認するためのMACアルゴリズム		
  - MACアルゴリズム　チェック
  - 圧縮アルゴリズム
  　  　　　
 
1. アルゴリズムの確定
　通信で使うアルゴリズムを確定し、
  自身の公開鍵を含む証明書を送付
  　　　
 
1. ランダムな文字列をserverの公開鍵で暗号化
  ランダムな文字列はクライアントで生成される
  serverの公開鍵で暗号化して送付する

1.  ランダムな文字列をserverの秘密鍵で復号化
  クライアントとサーバそれぞれで作成した２つの乱数を

1. 暗号化鍵とMAC鍵を作成
  鍵生成関数の入力に追加し、暗号化鍵とMAC鍵を生成
  　

# SSLで暗号化される範囲
全てのパケットを暗号化する訳ではない
SSL プロトコルはOSI参照モデルのセッション層に位置する為、
OSI参照モデルの上位3層
（セッション層、プレゼンテーション層、アプリケーション層）を暗号化する。
それ以下の層(レイヤ1-4)については暗号化しない。

![スクリーンショット 2017-11-30 17.38.35.png](https://qiita-image-store.s3.amazonaws.com/0/75761/52622b13-957e-9a3c-ed6b-fb73e7bd6b7e.png)

つまり、SSLを導入したからと言っても、誰宛かのパケットかは隠せない。
「AさんからBさんへ連絡した」という事を隠すことはできない。
当然会話の内容は暗号化される。
イメージ的には大勢の前で、暗号化された言葉で話しているような感じ。

# SSLで保証されるもの
- 転送中のデータ
  盗聴されても、解読する事はできない。
  仮に改ざんされても、MACという技術により検知することができる
  　
  
- 通信相手が正しいマシンであること
  サーバの公開鍵の証明書を確認することで
  「なりすまし」されても偽物だと気付ける
[Unity] VRのカメラトラッキングを切る

# はじめに

## カメラの動きを制限したい

HMDの動きをトラッキングされちゃうと困っちゃうときってありますよね．

回転トラッキングを切りたいんですが，位置トラッキングを切る記事はあれど回転トラッキングを切る方法が見つかりません．

「VR用のカメラの前にUIでRawImageを張り付けて，別のカメラで撮影したイメージを描写する」
なんてことをやってたんですが，カメラ位置の調整がとんでもなく面倒です．もしくは不可能です．

ということで探しました．


# 視点固定の方法

## XRDevice.DisableAutoXRCameraTracking()

### トラッキングをオフするコード

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;

public class CameraControlForVR : MonoBehaviour
{
    [SerializeField] Camera target;

    // Use this for initialization
    void Start()
    {
        XRDevice.DisableAutoXRCameraTracking(target, false);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown("a"))
        {
            XRDevice.DisableAutoXRCameraTracking(target, false);
        }
        if (Input.GetKeyDown("s"))
        {
            XRDevice.DisableAutoXRCameraTracking(target, true);
        }
    }
}

```

* インスペクタでCameraにVR用のカメラを指定してあげる
* aを押下するとトラッキングOn
* sを押下するとトラッキングOff


という単純なスクリプトです．

# 結果

きちんとカメラの姿勢・位置が固定されました．
描写自体が止まっているように見えますが，後ろで動いているものはきちんと動いて見えます．


# 結論

視点を強制的に固定する方法がわかった．

## 問題点

### 回転だけでなく位置トラッキングも切れる

位置だけはトラッキングしたいんだよなあというときには使えません．
工夫の必要がありそうです．

### 再開時に視点が飛ぶ

トラッキングを再開したときに向いている向きに視点が飛びます．
シームレスに変化させたいときはこれまた工夫がいりそうです．


ひとまず備忘録として．
暇があれば文章を整えます．
Fish for Kubernetes

## はじめに

みなさんShellは何を使われていますでしょうか?
私は**[Fish](http://fishshell.com)**です。もともとZsh派でしたが、起動の遅さにストレスを感じ乗り換えました。

最高なFishですが、Zshに比べてKubernetes周りの環境が整っていないという弱点があります。そこで、今回はFishユーザのための環境構築について書きつつ今後の発展を願っていきます。

## プロンプトでオペミスを防げ!

複数のクラスタを操作していると「別のクラスタのコンテナ消してしまった😨」ということが起こりがちです。そんなオペミスを防ぐためには、プロンプトにContextとNamespaceを表示させるなど常にチェックできる環境を作る必要があります。
Zshには[zsh-kubectl-prompt](https://github.com/superbrothers/zsh-kubectl-prompt)がありますが、残念ながらFishにはありません。

そこで、今回は[fish-kubectl-prompt](https://github.com/Ladicle/fish-kubectl-prompt)をご用意しました。
実際のプロンプトはこんな感じ。よろしければご利用ください。
![normal-prompt](https://user-images.githubusercontent.com/1159133/33415205-5f428d52-d5d8-11e7-9ecb-e78fa8c784e0.png)

## Kubernetesの便利コマンド

kubectlだけでも十分に操作できますが、なんでも操作できるが故にコマンド引数が長かったり数ステップ必要だったりと物足りなさを感じることがあります。そんなあなたにお勧めするのが[stern](https://github.com/wercker/stern)と[kubectx](https://github.com/ahmetb/kubectx)です。sternはログの閲覧、kubectxはContextやNamespaceの切り替えを楽にしてくれます。

kubectxはfzfと組み合わせるとより便利です。
![tty.gif](https://qiita-image-store.s3.amazonaws.com/0/26683/76481691-7733-9a9a-7cce-c0b2e66f44d1.gif)

> Fishは関係ありませんでした

## kubectlを補完するには

残念ながら本家にはFishのCompletionが入っていません。現在の議論の様子は下のIssueを見ると分かるかと思います。CobraにFish用のCompletion Generatorが入って欲しいところですが、まだ時間が掛かりそうです。

* [Add support for fish shell autocompletion](https://github.com/kubernetes/kubernetes/issues/30763)
* [Support for completion in other shells (fish, zsh, etc.)](https://github.com/spf13/cobra/issues/350)

公式ではありませんが、GitHubで公開されている[evanlucas/fish-kubectl-completions](https://github.com/evanlucas/fish-kubectl-completions)は一つの選択肢です。

## おわりに

Fishで快適Kubernetesライフを送りましょう。
Pythonでのファイル読み込み

最近Pythonで外部ファイルを読み込むことが増えており、
この記事を書こうと思いました。

外部ファイルを読み込む場合、基本的に渡されるテキストはひとまとまりになった物です。
なので、こうしてやると別々に配列に格納する事が出います。

```file_read.py
hogeio = open("hoge.txt")
reader = hogeio.read()
hogeio.close()
reader = reader.split("\n")
```
見たらわかると思いますが、一応説明。
１行目で、ファイルをOPENし、２行目でリードします。
３行目で、クローズし、４行目で、Split("\n")で分割を行っております。
この４行目で、配列化することによって、改行された文字列の様に扱えます。

呼び出すときは、

```python:get.py
for read_txt in hogeio :
    return read_txt
```

で受け取ることが出来ます。

そして、終端から受け取りたい場合もあると思いますので、そのサンプルコードも。

```endpoint.py
arr_len = len(reader)
for i in range(arr_len) :
    print("{0}".format(reader[arr_len - i]))
```
AWSの月額課金のタイムゾーンについて


グローバルなサービスが月額で従量課金する時、タイムゾーンってどうなってるんだろう？と気になったのでAWSについて調べました。
結論としてはUTCらしいです。
一応念のためにサポートに問い合わせたのですが、以下のような回答を頂きました。

>AWSの月額料金につきましては、UTCにて計算をしております。
>1か月の計算は日本時間(UTC+9)にいたしますと、毎月1日の午前9時から開始いたします。

異なるタイムゾーンで計算するの面倒すぎるので普通に考えれば当たり前か、と思いましたが、前まで特に何も考えずにJSTの0時からだと勝手に思い込んでいたのでメモ。
現在のところ、AWSに関してUTCと明確に記載されている資料はないらしいです。

# 参考
- https://forums.aws.amazon.com/thread.jspa?threadID=245493
- http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/awsaccountbilling-aboutv2.pdf
- http://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/enhanced-billing-columns.html
Ubuntuでログインループに陥ったときの対処法

# TL;DR

Ubuntuでログインループにハマってどうしようもなくなったときの対処法です。
悪い子はNVIDIAドライバです。

# 原因

様々な原因が考えられますが、だいたいが以下の二種類です。

- カーネルのアップデートに失敗していろいろなバージョンが混ざってしまった
- NVIDIAのドライバのバージョン不整合

順に対処法をご紹介します。

# 対処法

## NVIDIAドライバのバージョン不整合が原因の場合

これは、GPUカードに対する適切なバージョンが何らかの原因でインストールされていないときに発生します。

### 1. NVIDIA公式サイトで適切な最新バージョンを調べる

まず、[NVIDIAの公式サイト](http://www.nvidia.co.jp/Download/index.aspx?lang=jp)上で、使用しているGPUカードに対応するドライバの最新バージョンを調べます。

例：）`384.98`と出ている場合は、バージョンは`384`です。

### 2. インストールされているバージョンを調べる

GUIログイン画面上で、`Ctrl + Alt + F1`を押すと、仮想コンソールに入ることができます。

仮想コンソール上でログインしたのち、以下コマンドでインストール済みのnvidiaドライバのバージョンを調べます。

```bash
dpkg -l | grep nvidia
```

実行すると、`nvidia-xxx`といった形で表示されると思います。この`xxx`のバージョン番号が、先ほど調べたバージョン番号と同じ、あるいは小さい場合は問題ありません。

### 3. 適切なバージョンをインストールする

仮に問題がある場合は、正しいバージョンをインストールします。

```bash
sudo apt-get update && sudo apt-get install nvidia-xxx
```

## カーネルのアップデートに失敗した場合

カーネルのアップデートに失敗した場合、仮想コンソール上で`apt-get`関連のコマンドを実行しようとすると、依存関係のエラーが発生します。

どうしようもなかったので、僕の場合は強制アップデートしなおしたら直りました。

```bash
sudo apt-get autoremove -f
sudo apt-get autoclean -f
sudo apt-get update && sudo apt-get upgrade -fy
```

以上です。
SMOTEはデータを分割した後に実行する

# SMOTEを使うタイミング

今日、プログラムを書いているときに指摘されて、すべての工程をやり直しになるほどの失敗を犯しました。
ほぼ初心者であるための失敗なのかどうか分からないので、私のような不幸物を二度と出さないことを祈りつつ書きます。

##私の失敗例
陽性データと陰性データが偏っていたので、SMOTEを使って増やそうとしました。
普通にSMOTEを使って、陽性と陰性のデータ数を合わせて、データインバランスを解消しました。
その後、学習データとテストデータに分割しました。
学習データで機械学習にガンガン学習させて、テストセットで評価しました。

……ここですでに間違いがありました。

##SMOTEで作ったデータをテストセットに入れてはいけない
よく考えたら当たり前ですが、**実際に存在しないデータで評価したところで何の意味もありませんでした。**
テストセットは実際に実在するデータを用いてこそ、汎化性能を評価することができるのであります。

##つまり……？
**SMOTEを用いるときは、テストセットはインバランス状態になってもいいので、先にデータを学習データとテストデータに分割しておく。**
次に、インバランス状態の学習データをSMOTEで増やして、インバランスを解消します。

こうすれば学習データはちゃんと増えているし、テストデータは実際のデータのみで構築することができます。

さっさと気づいていればよかった。
kerasのよく使うやつメモ

## keras.utils.to_categorical
one-hotなベクトルつくるやつ
↓のようなの。識別系で使う。

```py3
>>> keras.utils.to_categorical(1, 5)
array([ 0.,  1.,  0.,  0.,  0.])

>>> keras.utils.to_categorical(4, 5)
array([ 0.,  0.,  0.,  0.,  1.])

```

## keras.layers.concatenate

レイヤーをマージする
複数の入力を取りまとめたりする。

```py3
hoge_input = Input(shape=(10,), name='hoge_input')
fuga_input = Input(shape=(2,), name='fuga_input')
x = keras.layers.concatenate([hoge_input, fuga_input])
```

## keras.layers.Dense

全結合のレイヤーをつくる。中間層を追加するときなどに基本使う。

```py3
x = Dense(128, activation='relu')(x)
```

## reluとかsigmoid

活性化関数。
以下などがわかりやすい。
https://qiita.com/hokekiyoo/items/bf7be0ae3bf4aa3905ef
https://qiita.com/namitop/items/d3d5091c7d0ab669195f

## softmax

活性化関数。最終レイヤーで識別系をするときに基本使う。

```py3
hoge_output = Dense(10, activation='softmax', name='hoge_output')(x)
```

## model.compileするときのoptimizerとかlossの選び方
公式をみるのがわかりやすい。
https://keras.io/ja/optimizers/
https://keras.io/ja/objectives/

## keras.utils.vis_utils.model_to_dot

モデルを図にしてくれる。

![SS_ 2017-11-30 17.18.46.png](https://qiita-image-store.s3.amazonaws.com/0/2648/6f30f502-552a-d4e9-e3bc-6371921735bd.png)

## 学習曲線の表示

```py3
batch_size = 128
epochs = 2000
stack = model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1)

x = range(epochs)
plt.plot(x, stack.history['acc'], label="acc")
plt.title("accuracy")
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()

plt.plot(x, stack.history['loss'], label="loss")
plt.title("loss")
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()

```

![SS_ 2017-11-30 18.00.22.png](https://qiita-image-store.s3.amazonaws.com/0/2648/80c6e343-6ad0-bc49-db71-bf9333750fce.png)


## テスト（model.evaluate）

```py3
score = model.evaluate(X_test, Y_test, batch_size=batch_size)
list(zip(model.metrics_names, score))
```

model.metrics_namesでscoreのラベルが取れるので、zipしてlistして見やすくしてる

## モデルの保存と読み込み

h5pyが必要。```pip install h5py```。

```py3
model.save('model.h5')
model = keras.models.load_model('model.h5')
```
Kotlinでnioを使ってhttp server

JJUG CCC 2017 Fallで「[新しいプログラミング言語の学び方](https://speakerdeck.com/todokr/xin-siihurokuraminkuyan-yu-falsexue-hifang-httpsahawozuo-tutexue-hu-java-scala-clojure)」のセッションでhttp serverを作っていました。自分でhttp serverを書いたのは遥か昔のことです。セッションを聞いてみて、久しぶりに自分でも書いてみるか、という気になり、勢いで書いてみました。あまり、ちゃんとしてはいないですが…。

生のソケットを扱うことは普通のWebアプリケーションの開発者にとってはあまりないことなので、少し新鮮でした。

[http serverのコードはこちら](https://github.com/liris/simple-http-server)。なるべく、発表で使われたソースコードの構造に合わせています。

で、自分用のメモです。


## 前提

まず、普通にブロッキングIOでソケットを扱うと、JavaやScalaと違いがないので、nioを使ってなるべくノンブロッキングで処理します。nioでサーバーソケットを扱うのはこれが初めてです。

nioに関する処理は[SimpleHttpServer.kt](https://github.com/liris/simple-http-server/blob/bd8f853dfb1b4d6fcf7c064bf994a3b9c8aaa086/nio/src/main/kotlin/SimpleHttpServer.kt)にあります。

## 大まかな構造

メインスレッドの中でselectします。acceptすると読み込みを開始します。

読み込みは、readableになると別のスレッドで読み込みをして、メインスレッドはブロックしません。

HTTPヘッダーの読み込みが完了すると、メインスレッドのselectでwritableになったら、別スレッドに通知します。ここはread用のスレッドと同じようなパターン。ただ、writeの時に、handlerを呼び出して、書き込みのデータを準備します。ここがブロックされるとボトルネックになるので、ここでさらに別スレッドを立ち上げてhandlerを呼び出して書き込みまで行います。

ここまでが大きな流れです。


## 初期化

nioでサーバソケットを扱うときは、グローバルにはSelectorとchannelを利用します(L15, L16)。
そして、チャネルをノンブロッキングに指定して(L19)、ソケットを初期化します(L22)。最後にチャネルでacceptのイベントを登録します(L23)。

# メインスレッド

runメソッド(L31)の中の無限ループでselectします(L37)。selectしてイベントがある場合は、イベントの種類に応じて処理して(L39-L48)、最後にキーを削除しています(L49)。ここではあとでまとめて削除していますが、イテレータでループしている最中にremoveしてもいいかも。

扱うイベントの種類は、accept/read/writeです。acceptのときは(L72)、ServerSocketChannelでacceptして、ソケットを取得します(L75)。ここでも、ノンブロッキングに設定して(L77)、読み込み可能な状態を待つように登録します(L81)。
各ソケットに対応したデータを紐づけて登録できるので、分断された処理も継続できます。

readableになったら、read用のキューにselectedKeyを登録しています。SynchronizedQueueなので、データが登録されたら別スレッドで処理が開始されます(L84-L86)。

writableになった場合も、メインスレッドの処理は同じです(L87-L90)。

## ReadWorker

ReadWorkerでソケットからデータを読み込みます(L127)。一度の処理ですべてのヘッダーを読み込めるとは限らないので、ここでは、\r\n\r\nが現れるまで読み込みが継続します。

読み込みが完了したら、読み込み終了の状態にしてwriteのイベントを登録します。

## WriteWorker

WriteWorkerでは、writableになったらExecutorでスレッドを生成して、実行します(L162)。handlerが処理した後(L173)、channelに書き込んで(L176)、チャネルを閉じています(L177)。ここのtry - catchは余分でしたね。

## パフォーマンスはどう?

__発表内容でのブロッキングIOでの処理とnioのノンブロッキングの処理と比べて、パフォーマンスは有意な差は見られません。(てへぺろ)__

ただ、それは接続数が少ない場合で、接続数がおおくなると、ノンブロッキングの方が処理を継続しやすいです。(ブロッキングする方だとエラーが発生)。でも、おそらく、OSの設定を変更すれば大丈夫なはず。
websocketとかhttp2とか永続的なコネクションを扱うようになると、ブロッキングIOでスレッドでとやると、ある程度のオーバーヘッドが発生したりしてしまいそう。また、メモリも貧乏人には勿体無いかも。


## おわり

とりあえず、ノンブロッキングはめんどくさいので、そういうことは若者にやってもらいましょう。
まじめに作ると結構大変そう。
Cognos Analytics 11.0.8の地図機能で領域に複数アイテム置く場合の注意

#概要
Cognos Analytics 11.0.8の地図機能は、ダッシュボードとレポートの両方にありますが、領域のデータアイテムに、国(Country)、州(State)、郡(County)という、親子関係のあるアイテムを3つ置くときに、置く順番に注意してという記事が公開されていましたので紹介します。
**Refining Map Locations in Cognos Analytics**
https://www.ibm.com/communities/analytics/cognos-analytics-blog/refining-map-locations-in-cognos-analytics/#_ftn1

#内容
ダッシュボードの地図の場合は、以下のようにデータアイテムを置きます。
こちらは違和感の無い置き方と思います。
国(Country) → 州(State) → 郡(County)
![Dash01.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/72b46fb6-8b8d-6dd0-82b7-f0fb0f2a8c15.png)

しかしながら、レポートの場合は以下のように置きます。
つまり逆です。
郡(County) → 州(State) → 国(Country)
![Report01.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/5f947bb7-f6ed-6210-002c-f9dd812c904a.png)

これは将来のバージョンでは解消されるが、今だけこうなってしまっているので注意して、という記事でした。

ちなみに、記事ではレポートの場合のアイテムの置き方を、
郡(County) → 国(Country) → 州(State)
と置くように指示されていましたが、そんな置き方をするとエラーになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147246/f6947d8b-f900-1000-dbc6-23b7113c3bfb.png)


レポートの地図をご使用される場合は、この記事を思い出して頂き、どちらの置き方も試してみて下さい。

#参考
地図機能に興味のある方は、こちらの記事もご参照下さい。
**Cognos Analytics 11.0.8 新機能 - 地図で緯度・経度サポート**
https://qiita.com/shinyama/items/6e1a783470ce69f02389
容量不足でMACが起動しなくなった時の覚書

[グレンジ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/grenge)  4日目の記事を担当しました、woki と申します。
グレンジでクライアントサイドエンジニアをしております。

今回は、容量不足でMACが起動しなくなった時に行なった対応の記事になります。

# 【事象】
MACを起動するとロゴが表示され進捗インジケータが半分ほど進んだところでシャットダウンしてしまう（この時点では原因不明）

#【結論】
バックアップとってOS再インストールしました

おわり

# 【過程】
### ■ PRAMリセットしてみる
起動時に option + command + P + R 起動音が2回なったら離す
→ 改善されず (´'ω'｀)

### ■ セーフモード起動してみる
起動音が鳴った直後に shift ロゴが見えたら離す
→ セーフモードで起動せず  (´'ω'｀)

### ■ リカバリーモードで起動してみる
起動時に command + R ロゴが見えたら離す
→リカバリーモードで起動できた ( 'ω' )

##### ▼ディスクユーティリティでFirstAid実行
→ エラーが表示される
> ファイルシステム検査の終了コードは8です
> ボリューム用のブート・サポート・パーティションは必要に応じてアップデート中
> ファイルシステムを検証または修復できませんでした
> 操作が失敗しました...

→ 再度試すも...FirstAidで修復できない模様 (´'ω'｀)

ディスクユーティリティで情報を探す
使用状況999.35GB、空き0
→これが原因かも？消そうと試みるもアクセスできず...

### ■ シングルユーザモードで起動してみる
起動時に command + s
→ 起動した ( 'ω' )

とりあえず修復してみる
`$ /sbin/fsck -fy`

エラー
`$ The volume Macintosh HD could not be verified completely.`
`$ /dev/rdiskOs2 (hfs) EXITED WITH SIGNAL 8`

dfコマンドでパーティションが表示されず...
→どうやらパーティションが壊れてる？

##### ■ 容量が一杯だったのを思い出し、消してみる

/Users/配下で不要なファイル消そうとしたらReadOnlyでマウントされているため消せなかった
書き込み権限で再マウントする
`$ mount –uw /`

消えてもいいファイルを10GBほど削除

シャットダウン
`sudo shutdown -h now`

リカバリモードで起動、ディスクユーティリティでFirstAid実行
が・・・駄目っ・・・

### ■ 修復を諦めてデータだけバックアップを取ることにした

シングルユーザモードで外付けHDDを繋ぐ
→マウントすべき外付けHDDの名前がどれか分からない
ので一旦外す
`$ ls /dev/`
外付けHDDのUSBさす
`$ ls /dev/`
で増えた名前が多分それ(今回は `disk1s1` だった)

バックアップ用のフォルダ作る
`$ mount -o update / `
`$ mkdir -p mnt/backup`

マウントする
`$ mount_hfs /dev/disk1s1 /mnt/backup`

バックアップ用のフォルダにコピーする
`$ cp -ipR /Users/Downloads /mnt/backup/Downloads`
> -i	上書きされるファイルがあれば、その可否を確認します。
-p	元のファイルの属性(タイムスタンプ等)を可能な限り保持します。
R 再帰処理(recursive)ディレクトリ配下全て

外付けHDDを別のpcで開いてファイルが読み込めることを確認

リカバリモードで起動して壊れたパーティションを消去、OSの再インストール、避難したデータを復元

今日が始まる٩( 'ω' )و
css/sass 備忘録

style関連の備忘録。随時追記。

### 縦に中央寄せしたい
※指摘頂いたように編集済。

```sass:hoge.sass
.parents {
  display: flex;
  align-items: center;
  justify-content: center;
}
```

##### 参考
- [flex\-direction: column;](https://mamewaza.com/support/blog/howto-use-flex.html)
- [CSSで要素を上下や左右から中央寄せする7つの方法 \| 株式会社グランフェアズ](https://www.granfairs.com/blog/staff/centering-by-css)
- [position: absolute; の指定で要素が上下左右中央配置になる理由 \| WWW WATCH](https://hyper-text.org/archives/2014/08/position_absolute_center_layout.shtml)

### ページ両サイドスペースの背景色を設定する。
```sass
body {
    background: #fff;/*背景色の指定*/
}
```

##### 参考
[MakeShopサポート │ ショップの背景や両端に好きな色や画像の設定方法](http://www.support.makeshop.jp/design/?p=2292)

### labelの文字列を途中で改行させない
チェックボックスやラジオボタンの文字列が、ウィンドウサイズの関係で途中で改行されるのを防ぐ。

```sass:sass
.hoge{
  label{
    display: inline-block;
  }
}
```
```slim:slim
.hoge
  = collection_check_boxes(:user, :something_ids, @obj, :id, :name) do |cb|
    = cb.label { cb.check_box + cb.text }
```

### css でボタン非活性
class に `is-disabled` をつけると非活性とする。

```css

@mixin btn-disabled-base() {
  cursor: not-allowed;
  opacity: 0.5;
  pointer-events: none;
}

  a.is-disabled{
    @include btn-disabled-base();
  }
```
使い方

```erb:xxx.html.erb  
<%= link_to 'submit', submit_path(model), method: :post, , class: "button is-register is-submit #{'is-disabled' if model.disabled?}" %>
```
rust-doc.vimでrust-doc-open: Failed to open URL, xdg-open: no method available for opening / WSLからrust-doc.vim

# エラー全文

```
rust-doc-open: Failed to open URL: Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/%{ <-- HERE (.*?)}/ at usr/bin/run-mailcap line 528.^@Couldn't find a suitable web browser!^@Set the BROWSER environment variable to your desired browser.^@Warning: program returned non-zero exit code #1^@/usr/bin/xdg-open: 771: /usr/bin/xdg-open: www-browser: not found^@/usr/bin/xdg-open: 771: /usr/bin/xdg-open: links2: not found^@/usr/bin/xdg-open: 771: /usr/bin/xdg-open: elinks: not found^@/usr/bin/xdg-open: 771: /usr/bin/xdg-open: links: not found^@/usr/bin/xdg-open: 771: /usr/bin/xdg-open: lynx: not found^@/usr/bin/xdg-open: 771: /usr/bin/xdg-open: w3m: not found^@xdg-open: no method available for opening '/home/miyagaw61/docs/rust-docs/share/doc/rust/html/std/vec/index.html'^@
```

# 環境

- WSL
- NeoVim

# 原因

- BROWSER環境変数が宣言されていなかった
- xdg-open が ローカルファイルからの読み込みに対応していない
- WSLから叩くchrome.exeがパスを解釈できない

# 解決方法

```bash
$ export PATH=$PATH:/path/to
$ cat << EOF > /path/to/chrome
/mnt/c/Program\ Files\ \(x86\)/Google/Chrome/Application/chrome.exe $@
EOF
$ export BROWSER=chrome
```

```bash
$ nvim /path/to/rust.vim/autoload/rust_doc.vim # 僕の場合は~/.cache/dein/repos/github.com/rhysd/rust-doc.vim/autoload/rust_doc.vim

# 以下の4行を該当部分に追記

function! s:open(item) abort
    echomsg printf("rust-doc: '%s' is found", a:item.name)

    let url = shellescape(a:item.path)
    if g:rust_doc#vim_open_cmd != ''
        execute g:rust_doc#vim_open_cmd url
        return
    endif

    if g:rust_doc#open_cmd != ''
        let output = system(g:rust_doc#open_cmd . ' ' . url)
        if v:shell_error
            call s:error("Failed to open URL: " . output)
        endif
        return
    endif

+    call system('cp ' . url . ' ./rust_doc.html')
+    call system('chrome rust_doc.html')
+    call system('rm -rf rust_doc.html')
+    return

    try
        call openbrowser#open(url)
    catch /^Vim\%((\a\+)\)\=:E117/
        if has('win32') || has('win64')
            let cmd = 'rundll32 url.dll,FileProtocolHandler ' . url
        elseif executable('xdg-open') && has('unix')
            let cmd = 'xdg-open ' . url
        elseif executable('open') && has('mac')
            let cmd = 'open ' . url
        elseif executable('google-chrome')
            let cmd = 'google-chrome ' . url
        elseif executable('firefox')
            let cmd = 'firefox ' . url
        else
            call s:error("No command is found to open URL. Please set g:rust_doc#open_cmd")
            return
        endif

        let output = system(cmd)
        if v:shell_error
            call s:error("Failed to open URL: " . output)
        endif
    endtry
endfunction
```

パスを解釈できないchrome.exeでもファイル名だけを引数に渡せば成功するので、無理矢理カレントディレクトリにhtmlファイルをコピーしてchrome.exe \<file_name\>を実行してその後ファイルを削除しているだけです。
PostgreSQLで一時的にtriggerを全て無効する方法


9.6で試しています。もっといえば、Dockerのオフィシャルイメージのタグ 9.6-alpineです。 

https://hub.docker.com/_/postgres/


Docker以降、OS上に直接 WEBやDBサーバーをインストールする機会がほとんど無くなりました。いいことです。


psqlで接続している時に、一時的にこのセッションでだけtriggerを無効/disableにしたい時ってあると思うんですが、日本語ではALTER TRIGGERの例しか見つからなかったので、共有です。

元ネタはStackOverflow

https://stackoverflow.com/questions/3942258/how-do-i-temporarily-disable-triggers-in-postgresql

psqlで以下を実行するだけです。

```sh
SET session_replication_role = replica;
```

なにかのお役にたてば。
Talend WebAPI データ取得時cookie保存するコンポーネントの解決案

Talend WebAPIでデータ取得する時、uniqidはどうやって取得できますか。

考え方：
・uniqidはcookieで保存している
・Talendはcookie取得するコンポーネントがないこと確認。
・手でcookie取得するjavaコンポーネント作成する。

画像：
![11.jpg](https://qiita-image-store.s3.amazonaws.com/0/213567/ecf67883-cce9-18de-3800-95485f756251.jpeg)

javaソース：
//変数を定義する
String strPonit ="{\"uniqid\":\"";
String domainurl = "xxxxxxxxxxxxxxxxxxxxxx";
String content_type = "application/x-www-form-urlencoded";
String apikey = "xxxxxxxxxxxxxxxxxxxxxx";
String login_id ="xxxxxxxxxxxxxxxxxxxxxx";
String login_password ="xxxxxxxxxxxxxxxxxxxxxx";
String udid ="xxxxxxxxxxxxxxxxxxxxxx";
context.put("udid",udid);
//画面請求のパラメータ
apikey =String.format(apikey, login_id, login_password,udid);
java.net.URL url = new java.net.URL(domainurl);
java.net.HttpURLConnection conn = (java.net.HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", content_type);
conn.setDoOutput(true);
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes(apikey);
out.flush();
out.close();
java.util.Map<String, List<String>> map = conn.getHeaderFields();
//画面のcookieを取得
context.put("Cookie",map.get("Set-Cookie").get(0));
java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
    int startPonit = inputLine.indexOf(strPonit) + strPonit.length();
    int endPonit = inputLine.indexOf("\"",startPonit);
    //請求の成功したら、画面のuniqidを取得する
    context.put("uniqid",inputLine.substring(startPonit, endPonit));
    //System.out.println(inputLine);
}
in.close();

画像：
![12.jpg](https://qiita-image-store.s3.amazonaws.com/0/213567/64ae2824-2b9c-21ee-13e9-d61aa5f0cfd2.jpeg)

HTTPボディ：
"action=list&table=products_class&limit=50000000&offset=0&udid="+(String)context.get("udid")+"&uniqid="+(String)context.get("uniqid")

メモ：ジョブは個人GITにupdateする（非公開）

以上
シェルスクリプトでトリムする

シェルスクリプトで標準入力から取り込んだテキストをfor ... in ... で回したい時などに、受け取ったテキストの先頭や末尾、あるいはデリミターに含まれている余計な空白を除去したい場合がありますが、今までは色々と苦労してsedやらawkやらtrを駆使して面倒な事をやっていたのですが、実はxargs一発で出来るという目から鱗w

```sh:
$ echo "  abc  def  ghi  " | xargs
abc def ghi
```
【Laravel5.4】DB処理時にトランザクションを使用する


2017/12/01:
コメント欄でご指摘受けた通りに実装すると期待していた動きになりましたので修正しました。
ありがとうございました。


## DBファサードのtransactionメソッドを使用する方法

```register.php
/**
 * DB登録処理
 * 
 * @param array $attributes
 * @return bool
 */
private function register(array $attributes)
{
    return DB::transaction(function () use ($attributes) {
        // クエリ処理
        return $this->fill($attributes)->save();
    });
}
```


## 手動トランザクション

```register.php
/**
 * DB登録処理
 * 
 * @param array $attributes
 * @return bool
 */
public function register(array $attributes)
{
    // try内に記述すると失敗した時にcatchに拾われてrollBackが走るのでtry前に記述
    DB::beginTransaction();
    try {
        $result = $this->fill($attributes)->save();
        DB::commit();
        return $result;
    } catch (\PDOException $e){
        DB::rollBack();
        return false;
    }
}
```
  
~~テストでもトランザクションを使っているとうまく動かなかった。（期待値boolなのにnullが返ってきた。）
手動トランザクションに変更するとうまく行った。~~


### 参考

- [データベース：利用開始 5.4 Laravel](https://readouble.com/laravel/5.4/ja/database.html)
- [Laravel5.4でデータベーストランザクション（Database Transactions） 一言多いプログラマーの独り言](https://programmer-jobs.blogspot.jp/2017/02/laravel-5-4-database-transactions.html)
- [php - Laravel Eloquent ORM Transactions - Stack Overflow](https://stackoverflow.com/questions/15105640/laravel-eloquent-orm-transactions#)
PythonでYoutubeの動画をダウンロードするまで（2017/11/30現在）

メモ書き程度に書いていくので参考になるのかは不明
(あとMarkdownの書き方よく知らんし調べるのも億劫なのでそのまま)

googleのAPIを導入（動画検索用）

```
pip install --upgrade google-api-python-client
```

pytubeを入れる（動画ダウンロード用）

```
pip install pytube
```

APIのページのサンプルそのまま使う
https://developers.google.com/youtube/v3/code_samples/python#search_by_keyword

この時GoogleAPIをコード内に書く場所があるのでそこを忘れないこと
（書かないと当然エラー）

動かす際に検索するクエリを指定する．
引数（デフォルト）
--q 検索欄に打ち込むキーワード，ダブルクォーテーションで囲めばスペース区切りの検索もできる

```
ex. python hoge.py --q "baseball fullgame"
```

--max-result 検索結果最大数を指定，デフォルトは25件（最大50）

```
ex. python hoge.py --max-result 50
```

結果として得られるのはYoutubeで検索した時に出てくるページの中身（リスト）
動画だけじゃなくチャンネルとかも入ってくるので，動画だけがほしいときはいじる必要あり
（ここ https://developers.google.com/youtube/v3/docs/search/list のtype欄にヒントあり）

取ってきたデータリストをpytubeのダウンロードに突っ込む
（書いてあるのは平文でうってあるので適当にリストを入力にして動くように直す必要あり）

```
from pytube import YouTube
YouTube('http://youtube.com/watch?v=ほげほげ').streams.first().download()
```

あとは待つだけ（多分）

一応自分のコードも貼り付けておく（ほとんどサンプルままだけど……）

```
# -*- coding: utf-8 -*-

#!/usr/bin/python

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.tools import argparser


# Set DEVELOPER_KEY to the API key value from the APIs & auth > Registered apps
# tab of
#   https://cloud.google.com/console
# Please ensure that you have enabled the YouTube Data API for your project.
DEVELOPER_KEY = "API_Keys"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"

def youtube_search(options):
  youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
    developerKey=DEVELOPER_KEY)

  # Call the search.list method to retrieve results matching the specified
  # query term.
  search_response = youtube.search().list(
    q=options.q,
    part="id,snippet",
    maxResults=options.max_results
  ).execute()

  videos = []

  # Add each result to the appropriate list, and then display the lists of
  # matching videos, channels, and playlists.
  for search_result in search_response.get("items", []):
    if search_result["id"]["kind"] == "youtube#video":
      videos.append("%s" % (search_result["id"]["videoId"]))

  # print "Videos:\n", "\n".join(videos), "\n"

  return videos


if __name__ == "__main__":
  argparser.add_argument("--q", help="Search term", default="Google")
  argparser.add_argument("--max-results", help="Max results", default=50)
  argparser.add_argument("--type", help="search type", default="video")
  args = argparser.parse_args()

  try:
    search_list =  youtube_search(args)
  except HttpError, e:
    print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)


from pytube import YouTube

for ID in search_list:
    query = 'https://www.youtube.com/watch?v=' + ID
    yt = YouTube(query)
    yt.streams.filter(subtype='mp4').first().download("./videos")

```