OmniAICreator/Qiita-1.07M huggingface dataset:
Windows7+Apache2.2でSSLを有効にする

###1.作業フォルダーについて
Apacheのデフォルト作業フォルダーは「C:\Program Files\」ですが、いろいろ制限があるので、
Apacheアンインストールしてインストール場所を「C:\Apache2.2\」に変更します。

###2.秘密鍵、公開鍵、証明書の作成
server.key--秘密鍵の生成
`C:\Apache2.2\bin>openssl.exe genrsa -out ..\conf\server.key 1024`

server.csr--公開鍵の生成
`C:\Apache2.2\bin>openssl.exe req -new -key ..\conf\server.key -out ..\conf\server.csr -config ..\conf\openssl.cnf`

※[Common Name (eg, your name or your server's hostname) []:]は**ホスト名**を入力してください！
(例www.webdavTest.com等)
これをしないとWebDAVフォルダにPCで接続することができない。

server.crt--証明書の生成
`C:\Apache24\bin>openssl.exe x509 -in ..\conf\server.csr -out ..\conf\server.crt -req -signkey ..\conf\server.key -days 365`

###3.httpd.confの修正
`#LoadModule ssl_module modules/mod_ssl.so`
`#Include conf/extra/httpd-ssl.conf`
↓
`LoadModule ssl_module modules/mod_ssl.so`
`Include conf/extra/httpd-ssl.conf`

修正後、Apacheを再起動します。

参考サイト：
http://www.kyoji-kuzunoha.com/2012/04/webdavwindows7windows7.html
http://www.koikikukan.com/archives/2013/12/03-012345.php
S3Clientクラス(AWS SDK for PHP 3.x)


##下準備

AWS SDK for PHPを下記コマンドでインストール

```
php composer.phar require aws/aws-sdk-php
```

##設定

```php:S3Controller

use Aws\S3\S3Client;

public function initialize(array $config)
    {
        $this->config = [
            's3' => [
                'key' => 'key', //S3アクセスのためのキー
                'secret' => 'secret', //S3アクセスのためのシークレットキー
                'bucket' => 'bucket', //S3バケット名
            ]
        ];

        $this->s3 = S3Client::factory([
                    'credentials' => [
                        'key' => $this->config['s3']['key'],
                        'secret' => $this->config['s3']['secret']
                    ],
                    'region' => 'ap-northeast-1', //リージョンは日本
                    'version' => 'latest' //バケットのバージョニングは最新
        ]);
    }


```

##シンプルなサンプル

```php:ファイルアップロード

$result = $this->s3->putObject([
            'Bucket' => $this->config['s3']['bucket'],
            'Key' => 'test/img.jpg', //アップロード先のフォルダとファイル名を指定
            'SourceFile' => $imgData['tmp_name'],
            'StorageClass' => 'REDUCED_REDUNDANCY' //低冗長化モードを指定
        ]);

```

```php:リスト取得

//オブジェクト型で取得
$list = $this->s3->listObjects([
         'Bucket' => $this->config['s3']['bucket'],
         'MaxKeys' => 10, //最大取得数
         'Prefix' => 'folder' //フォルダ指定
        ]);

//下記コードでフォルダと画像名のみ取得する
foreach ($list['Contents'] as $img) {
      $result[] = $img['Key'];
}

```

```php:画像削除

$result = $this->s3->deleteObject([
            'Bucket' => $this->config['s3']['bucket'],
            'Key' => 'test/deleted.jpg']//削除対象を指定
          );

```

他にも様々な機能があるので、確認して見てください。
http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.S3Client.html#_factory
shell scriptでEC2インスタンス内から自分についているタグを取得する


```
ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
TAG_VALUE=`aws ec2 describe-tags --filter "{\"Name\":\"resource-id\",\"Values\": [\"$ID\"]}" --query 'Tags[?Key==\`TAG_NAME\`][Value]' --region ap-northeast-1 --output text`
```

**autoscalinggroupのtagを付ける設定で起動直後は取れないことがあるのでwhileとかで回そう**
■MacでiPhone iPadなどのシミュレータでブラウザログを見る方法 


目的：MacでiPhone iPadなどのアプリを開発して、
簡単なシミュレータ機能を利用して、iPhone/iPad操作動きのログを見たい場合の手順となります。


## 前提条件＆その他
xcodeのインストール
https://developer.apple.com/jp/xcode/

Safariバージョン
10.1.2 (12603.3.8)

Xcode Simulator Version 
10.0

## 手順
![スクリーンショット 2017-10-17 10.46.24.png](https://qiita-image-store.s3.amazonaws.com/0/181748/b18e73e7-fb7b-4fa8-9d06-49d73c27a647.png)

Xcode >Open Development Tool > Simulator
![スクリーンショット 2017-10-17 10.47.39.png](https://qiita-image-store.s3.amazonaws.com/0/181748/4eb9dfd1-ca4f-4a3d-32f7-8c647bbb0fd7.png)
下記の画面が出ています。そして、シミュレータでのsafariを起動します。
![スクリーンショット 2017-10-17 10.49.54.png](https://qiita-image-store.s3.amazonaws.com/0/181748/df843a14-6fe9-bb30-047a-f5a29dda0437.png)

シミュレータでローカル/web中のアプリページを開く。
例：localhost:6003
![スクリーンショット 2017-10-17 15.33.49.png](https://qiita-image-store.s3.amazonaws.com/0/181748/591b081f-72b4-1128-f1e4-141139171300.png)



同時に、Mac側のSafariを起動することが必要です。
Safari > 環境設定
![スクリーンショット 2017-10-17 15.24.06.png](https://qiita-image-store.s3.amazonaws.com/0/181748/60b5b85b-bbc4-cd67-77fb-49418223da13.png)

詳細　> 「メニューバーに"開発"メニューを表示」をチェックします！！
![スクリーンショット 2017-10-17 15.24.17.png](https://qiita-image-store.s3.amazonaws.com/0/181748/b5e29b5d-1df8-ee85-bb29-3b45e3ad666d.png)

そうすると、「開発」がメニューバーに表示されます。
![スクリーンショット 2017-10-17 15.28.07.png](https://qiita-image-store.s3.amazonaws.com/0/181748/d756fdf0-0c82-8930-610c-1d6785a5d0aa.png)

開発　> simulator >  simulatorで開いたページ(例：localhost:6003-admin)
![スクリーンショット 2017-10-17 15.36.01.png](https://qiita-image-store.s3.amazonaws.com/0/181748/33f7bad7-d558-c3ff-cc48-2ccdecfe25a9.png)

localhost:6003-admin　を押すと、development tool が起動されます。
普通のdevelopment tool のように、iPhone/iPadのconsole.log()が見えるようにできました！！
![スクリーンショット 2017-10-17 15.36.35.png](https://qiita-image-store.s3.amazonaws.com/0/181748/72409520-a4ff-6205-0327-3f5e4ca2bffb.png)


## デバイスの切り替え
![スクリーンショット 2018-03-19 9.54.04.png](https://qiita-image-store.s3.amazonaws.com/0/181748/30bfc0d7-ae64-d7f2-170c-76747568525c.png)


※要注意

xcodeが再起動しないと、更新/編集したコードはxcode simulatorに反映できなさそうです。。。。。これはちょっと面倒なところです。。。。。もっといい方法がご存知でしたら、教えてください。。。。！
export default ってなに？


javascriptに出てくる `export default` ってどういう意味があるのか調べた。

---
画像はvue.jsの.vueファイル内。
![スクリーンショット 2017-10-17 10.42.19.png](https://qiita-image-store.s3.amazonaws.com/0/206790/5ca9604d-95ac-aab0-0700-5138bd8f410b.png)

```js
export default function() {}

export default class() {}
```

#export
export 文は、指定したファイル (またはモジュール) から関数、オブジェクト、プリミティブをエクスポートするために使用
引用元：[MDN - Export](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export)

importする際に指定がなければそのクラスや関数を呼ぶもの
importする際にdefault以外のクラスや関数を呼び出したいときは、{}でクラスやファイル名を指定して呼びだすことができる。

```
export これをつけると、別のファイルから呼び出せるよ！！
ついてなかったら、別のファイルから呼び出せないよ！ Errorになるよ!!
```

理解できました。

エクセルとかでも、エクスポート、インポートってあるなぁ
ウィルスと闘ってみた。その2

#概要
開発用のXPが、どうにも調子が悪い。
ウィルスと闘ってみた。
デスクトップの方。

#症状
oeditが、起動に失敗する。
ネットが遅い。
タスクマネージャで知らないプロセス走ってる。
シマンテックとか、トレンドマイクロとか、カスペルスキーのサイトに行けない。DNSエラーでる。
publisherが無い、ドライバー、「amsint32」がある。

#salitykillerで駆除してみる。

ウィルスが、見つからない。
困った。

#駆除ツールを探す。

Kaspersky Virus Removal Tool 2015を見つけた。
また、カスペルスキーだ。

#結果

ビンゴ、25件、検知、駆除。
oeditも寄生されてた。
カスペルスキーすげー。

以上
Unityで作ったAndroidアプリがBackキー押下で終了できない場合の仮対応

# 修正前
これまでは、これで正常終了しているように見えた。

```c#
    void Update()
    {
#if UNITY_ANDROID
        // Backキー押下
        if (Input.GetKeyDown(KeyCode.Escape)) {
            // アプリ終了
            Application.Quit();
            return;
        }
#endif
    }
```

ところが、いつのまにかアプリは非表示になるが残っているようで、
再起動すると動作が不安定になるようになった。

# 修正内容

```c#
System.Diagnostics.Process.GetCurrentProcess().Kill();
```
を使うと解消するが、マズそうなので別の方法を調査。

```c#
Application.Quit()
```
の前に

```c#
Application.runInBackground = false;
```
を追加すると改善された。

詳細はこちら。
https://docs.unity3d.com/ScriptReference/Application-runInBackground.html

> Default is false

って書いてあるので、どこかでtrueに変わってしまっているということかな・・・
根本的な解決にはなってないような気がするけれど、
動作が不安定になるようなことは無くなった。

# 修正後
こんな感じ。

```c#
    void Update()
    {
#if UNITY_ANDROID
        // Backキー押下
        if (Input.GetKeyDown(KeyCode.Escape)) {
            // アプリ終了
            Application.runInBackground = false;
            Application.Quit();
            return;
        }
#endif
    }
```
GitLab.com上のリポジトリをTortoiseGitでクローンする方法

GitHubと同じ感じでHTTPS接続でクローンしようとしたら出来なかった(何故か認証が通らない？)ので、SSH接続でクローンする方法をまとめた。

## 検証環境
* Windows10 Pro 64bit
* TortoiseGit 2.5.0.0



## GitLab.comにリモートリポジトリを作成
既に作成済みとし、詳細は割愛する。



## TortoiseGit環境のセットアップ
既にセットアップ済みとする。セットアップ方法は以下のエントリを参照されたし。
https://qiita.com/SkyLaptor/items/6347f38c8c010f4d5bd2


## SSH鍵を生成する
TortoiseGitがインストールされているPCにて、公開鍵と秘密鍵を作成する。

TortoiseGitのプログラム一覧中の "PuTTYgen" を起動する。
![run_puttygen.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/ca8d6490-706e-bc10-c5ae-935c04e40f20.jpeg)


"Generate" を押し、鍵の作成を開始する。
![start_createkeypair.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/b9a91f8d-a944-937c-7da0-61866d8a6a90.jpeg)


緑のバーがいっぱいになるまで、空白の領域で適当にマウスをぐりぐり動かす。
![generate_fingerprint.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/26f492a3-8c66-6082-b111-b7823c321558.jpeg)


公開鍵と秘密鍵が作成されるので、 "Save private key" を押して好きな場所に秘密鍵ファイルを作成する。
なお秘密鍵にパスフレーズを設定していないため警告が表示されるが、"はい" でスルーする。
![save_seckey.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/93a2cfc8-f1d0-ce8e-ea5b-21fc12b48768.jpeg)

![warning_passphase.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/dfd86125-cdbd-e3f2-0989-c0e8b4d444d6.jpeg)


### 備考: CentOS上でSSH鍵を作成する

```shell-session:
# ssh-keygen -t rsa
# less .ssh/id_rsa.pub
```

## GitLab.comにSSH鍵を登録する
生成した鍵のうち、**公開鍵**をGitLab.comに登録する。

GitLab.comにログインし、ユーザー設定からSSH Keysを開く。
"Add an SSH key" にて、"Key" の入力欄には公開鍵文字列(PuTTYgenの画面に表示されているのを丸ごとコピペ)を入力し、"Title" には任意のタイトルを入力して "Add key" で登録を完了する。
![add_pubkey.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/d63d29b5-2785-55bb-4339-be789ebfcc75.jpeg)



## リポジトリのSSH接続パスを控える
クローンしたいリポジトリを開くと、SSH接続パスを確認することができる。
パスの隣にあるボタンでクリップボードにコピーできるので、コピーしておく。
![check_repossshpath.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/4123f504-d5f1-7349-d845-5e58594ddea2.jpeg)



## リポジトリをクローンする
パソコン側にて、クローンしたリポジトリを置きたいフォルダを開き、適当なところを右クリックして "Git クローン(複製)..." を選択する。

クローン時の設定が開くので、 "URL" には事前に控えて置いたSSH接続パスを入力し、"Putty認証キーのロード" では生成しておいた**秘密鍵**ファイル(*.ppk)を指定する。
正しく入力したら、"OK" でクローンを開始する。
![start_clone.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/31c82816-0805-566f-0645-a310a7beb76d.jpeg)


接続先のホストを信頼するかどうか聞かれたら、確認して "はい" を押す。
![trust_gitlabreposv.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/bb3e4264-4a62-2bf7-d469-314287dac1ac.jpeg)


クローンが開始されるので、完了まで待機する。
![wait_clone.jpg](https://qiita-image-store.s3.amazonaws.com/0/97774/96a64cc5-205d-418c-b6ba-7af7fc64dde7.jpeg)

以上
CAA: DNSサーバーを使って、サーバー証明書の発行を許可する認証局を指定する仕組みのメモ


CAA(Certification Authority Authorization)とは、DNSサーバーを使って、サーバー証明書の発行を許可する認証局を指定する仕組み出そうな。[RFC6844](https://tools.ietf.org/html/rfc6844)

## 1. DNS CAA

  * [CAAレコードについて(SureServer)](https://www.cybertrust.ne.jp/sureserver/productinfo/caa.html)
  * [DNS CAAとは(DigiCert)](https://rms-digicert.ne.jp/howto/basis/caa.html)

## 2. 各社の設定

  * [RapidSSL](https://knowledge.rapidssl.com/support/ssl-certificate-support/index?page=content&id=SO28449)
  * [Cybertrust](https://www.cybertrust.ne.jp/sureserver/productinfo/caa.html)
  * [DigiCert](https://rms-digicert.ne.jp/howto/basis/caa.html)
  * [Let's Encrypt](https://letsencrypt.org/docs/caa/)
  * [セコムトラストシステムズ](https://www.secomtrust.net/service/pfw/news/oshirase20170825.html)

## 3. digの例

```
dig caa rms-digicert.ne.jp
;; ANSWER SECTION:
rms-digicert.ne.jp.	85108	IN	CAA	0 issue "digicert.com"
rms-digicert.ne.jp.	85108	IN	CAA	0 issuewild "digicert.com"
```
C++ Builder XE4, 10.2 Tokyo > TMemo > TStringList型のリストをTMemoに割当てる実装 > TMemo.Assign()など | link:パフォーマンス

```txt:動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)
```

特定のフォルダにあるファイルリストを取得する。
その中で、TStringListに取得した文字列リストをTMemoに表示する方法が気になった。

見つけたのはTMemo->Assign()という方法。

使ってみた。

### 対象ファイル

[bash > Brace Expansionで日付のダミーファイルを作る | ファイル名失敗時: MinGW32でファイルを消す](https://qiita.com/7of9/items/078ff8702cbbb64e5d88)
にて作ったファイル。

### code

関連: [c++ builder / fileIO > 指定日付以降のファイルだけ見つける](https://qiita.com/7of9/items/082de92a61432592923c)

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <IOUtils.hpp>
#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

/*
v0.1 Oct. 17, 2017
  - 対象フォルダにあるファイルリストを取得
*/


String kTargetFolder = L"D:\\WORK\\filedelete_171017";
//String kDueDateTime = L"2017/02/28 12:00";

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
	String searchPattern = L"*.csv";
	TSearchOption option = TSearchOption::soAllDirectories;

	TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, searchPattern, option);
	int allcnt = fileList.Length;

	std::unique_ptr<TStringList> lst(new TStringList);

    TDateTime filedt;
    for(int idx = 0; idx < fileList.Length; idx++) {
//		filedt = TFile::GetLastWriteTime(fileList[idx]);
//		if ( filedt < VarToDateTime(kDueDateTime) ) {
//			continue;
//		}
		lst->Add(fileList[idx]);
	}

    String msg = IntToStr(lst->Count) + L"/" + IntToStr(allcnt);
	OutputDebugString(msg.c_str());

	Memo1->Lines->Assign(lst.get()); //********************
}
//---------------------------------------------------------------------------
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/22aaf19a-1f9a-0dc5-16e3-6ca145b95272.png)

### パフォーマンス

[リストに大量のアイテムを高速に登録するには](https://www.gesource.jp/weblog/?p=5831) by 山本隆さん

上記において以下の３つの方法の処理時間が比較されている。

- BeginUpdate, EndUpdate使用
- Assign使用
- AddItem使用

Assignが最速ではないが、コードが読みやすいのと、処理速度が許容範囲であると思われる場合はありうる。
Ubuntu 16.04.3にCUDA 8.0とcuDNN 6.0をインストールして、TensorFlow GPUの環境を作成する

# TensorFlow GPUの環境を作成する

- 計算機環境

```
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.3 LTS"
```

- Ubuntu 16.04.3にCUDA 8.0とcuDNN 6.0をインストールする
 - 最新のCUDA 9.0とcuDNN 7.0はTensorFlow GPU 1.3.0 に対応していないもよう
 - [Upgrade to CuDNN 7 and CUDA 9 · Issue \#12052 · tensorflow/tensorflow · GitHub](https://github.com/tensorflow/tensorflow/issues/12052)


# 1. NVIDIAドライバーを入れる

- 古いドライバの削除

```
$ dpkg -l | grep nvidia
$ dpkg -l | grep cuda
$ sudo apt-get --purge remove nvidia-*
$ sudo apt-get --purge remove cuda-*
```
- NVIDIAドライバーをインストール

```
$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt-get update
$ apt-cache search 'nvidia-[0-9]+$'
$ sudo apt install nvidia-384
$ reboot
```

# 2. CUDA 8.0を入れる

- [CUDA Toolkit Archive](https://developer.nvidia.com/cuda-toolkit-archive) から [CUDA Toolkit 8.0](https://developer.nvidia.com/cuda-80-ga2-download-archive) をダウンロードする
- `install` では `cuda-8.0` を指定する

```
$ sudo dpkg -i cuda-repo-ubuntu1604-8-0-local-ga2_8.0.61-1_amd64.deb
$ sudo apt-get update
$ sudo apt-get install cuda-8-0
```

# 3. cuDNN v6.0を入れる

- [cuDNN Download](https://developer.nvidia.com/rdp/cudnn-download) から `Download cuDNN v6.0 (April 27, 2017), for CUDA 8.0` をダウンロードする

```
$ tar xfvz cudnn-8.0-linux-x64-v6.0.tgz
$ sudo cp cuda/include/cudnn.h /usr/local/cuda-8.0/include/
$ sudo cp cuda/lib64/libcudnn* /usr/local/cuda-8.0/lib64/
$ sudo chmod a+r /usr/local/cuda-8.0/lib64/libcudnn*
```

- `.bashrc` などでパスの設定を行う

```
export PATH="/usr/local/cuda/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64:$LD_LIBRARY_PATH"
```


# 4. TensorFlow GPUを入れる

- インストール

```
$ sudo apt-get install libcupti-dev
$ sudo pip install tensorflow-gpu
```

- 確認

```
$ python -c "import tensorflow"
```




###（2018/01/25 追記）

最新の TensorFlow 1.4.1 に Python 3.6 向けのパッケージがないらしい

```
$ python -c "import tensorflow"
/usr/local/pyenv/versions/3.6.4/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: compiletime version 3.5 
of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6
  return f(*args, **kwds)
```

対策としては下記の通り（[参考](https://github.com/tensorflow/tensorflow/issues/14182#issuecomment-346132338)）

- 公式対応を待つ
- 警告を無視して使う
- 1.3.0 を使う

```
$ sudo pip install tensorflow-gpu==1.3.0
```
NginxとUnicornの連携でハマった所(On CentOS7)

Railsアプリを公開する際に、設定でハマった箇所があったので、備忘録を残しておきます。

# 環境
アプリケーションを公開するにあたり、下記を使用しました。
- さくらインターネット VPS
 - CentOS7を使用
- Rails:(5.0.1)
- Nginx:(1.10.3)
- Unicorn:(4.8.3)
- PostgreSQL:(9.2.18)

# 設定で参考にしたサイト
- [nginx + unicorn + Railsの設定方法](https://qiita.com/akito1986/items/56198edcafc222b320a8)
    ※決して参考元の設定が間違っているわけではなく、環境差異

# ハマったポイント
UnicornとNginxとを連携するためのソケットを/tmp配下に置くよう、サンプルではなっています。
ただし、CentOS7では/tmp配下で共有できないらしく、下記のエラーが発生する。
```
connect() to unix:/tmp/unicorn-example.socket failed (2: No such file or directory) while connecting to upstream
```
[CentOS 7でNginx、Unicornにハマる](http://blog.tnantoka.com/posts/49)

私は/var/run配下に変更しました。

# 色々と調べていて知ったこと
## UNIX/INETドメインソケットについて
参考にしたQiita記事に従い *.sock を使用して連携していた。これをUNIXドメインソケットというらしい。
他の方法にINETドメインソケットがあり、指定したPort経由で連携する。
下記掲示板を見る限り、INETドメインソケットの方がトラブルが少ないよう。
[Nginx で Unicorn起動時、白い画面にNot Found: / の表示　(Rails)](https://teratail.com/questions/52302)

## UNIXドメインソケット連携での動確
サイトにアクセスすればNginxのエラーかUnicornのエラーかの切り分けできると思うが、下記コマンドを使用してUnicornの動確ができる。
```
echo -e "GET / HTTP/1.0\n\n" | socat unix-connect:/tmp/unicorn.sock STDIO
```
xrdp-0.9.4をビルド

DockerはIPv6がデフォルトで無効。
xrdp-0.9.1ではIPv6が無効だと起動に失敗する。
xrdp-0.9.3でその問題が解決しているのと、せっかくなので最新版の0.9.4をビルドしてみた。

最新版: https://github.com/neutrinolabs/xrdp/releases

## 準備

```sh
wget "https://github.com/neutrinolabs/xrdp/releases/download/v0.9.4/xrdp-0.9.4.tar.gz"
```

```sh:Dockerfile
Dockerfile 
FROM ubuntu:17.10

RUN sed -i -e 's/archive.ubuntu.com/jp.archive.ubuntu.com/' /etc/apt/sources.list \
    && apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install -y \
       build-essential
RUN DEBIAN_FRONTEND=noninteractive apt-get build-dep -y xrdp

COPY xrdp-0.9.4.tar.gz /opt/

WORKDIR /opt
RUN tar xzf xrdp-0.9.4.tar.gz \
    && cd xrdp-0.9.4 \
    && ./configure

RUN apt install -y checkinstall

WORKDIR /opt/xrdp-0.9.4
RUN make install \
    && checkinstall -y -D --pkgname=xrdp
```

* /opt/xrdp-0.9.4/xrdp_0.9.4-1_amd64.deb が出来上がる


## 起動の前に xrdp-keygen が必要になった

```
sudo /usr/local/bin/xrdp-keygen xrdp auto

/etc/xrdp/xrdp.sh start
```
bash > Brace Expansionで日付のダミーファイルを作る | ファイル名失敗時: MinGW32でファイルを消す

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.4 #10132
SmartGit付属のMinGW32
grep (GNU grep) 2.24
head (GNU coreutils) 8.25
```

`X_20170131.csv`
のようなファイルをテスト用に作りたい。

### 参考

[Brace Expansionが便利](https://qiita.com/__nagamee/items/bec89945f70f5dffe9c5)
by @__nagameeさん

## v0.1
### code 

```bash:mkdmy_datetimefiles_171017_exec
#!/usr/bin/env bash

# on MinGW32

# X: prefix
filename=$(echo "X_"{2017..2017}{01..03}{01..31}".csv")
touch $filename
echo $filename
```

SmartGitからOpen Git-Shellして(MinGW32を起動し)、起動のフォルダにスクリプトを置いて実行する。

`
$ bash mkdmy_datetimefiles_171017_exec
X_20170101.csv X_20170102.csv X_20170103.csv X_20170104.csv X_20170105.csv X_20170106.csv X_20170107.csv X_20170108.csv X_20170109.csv X_20170110.csv X_20170111.csv X_20170112.csv X_20170113.csv X_20170114.csv X_20170115.csv X_20170116.csv X_20170117.csv X_20170118.csv X_20170119.csv X_20170120.csv X_20170121.csv X_20170122.csv X_20170123.csv X_20170124.csv X_20170125.csv X_20170126.csv X_20170127.csv X_20170128.csv X_20170129.csv X_20170130.csv X_20170131.csv X_20170201.csv X_20170202.csv X_20170203.csv X_20170204.csv X_20170205.csv X_20170206.csv X_20170207.csv X_20170208.csv X_20170209.csv X_20170210.csv X_20170211.csv X_20170212.csv X_20170213.csv X_20170214.csv X_20170215.csv X_20170216.csv X_20170217.csv X_20170218.csv X_20170219.csv X_20170220.csv X_20170221.csv X_20170222.csv X_20170223.csv X_20170224.csv X_20170225.csv X_20170226.csv X_20170227.csv X_20170228.csv X_20170229.csv X_20170230.csv X_20170231.csv X_20170301.csv X_20170302.csv X_20170303.csv X_20170304.csv X_20170305.csv X_20170306.csv X_20170307.csv X_20170308.csv X_20170309.csv X_20170310.csv X_20170311.csv X_20170312.csv X_20170313.csv X_20170314.csv X_20170315.csv X_20170316.csv X_20170317.csv X_20170318.csv X_20170319.csv X_20170320.csv X_20170321.csv X_20170322.csv X_20170323.csv X_20170324.csv X_20170325.csv X_20170326.csv X_20170327.csv X_20170328.csv X_20170329.csv X_20170330.csv X_20170331.csv
`

そのフォルダに2017年1月から2017年3月のファイルが生成される。
(2月31日とかできるが、今回の目的のためには看過する。I'll let the mistakes go）。

### 補足

なお、スクリプトを間違えておかしなファイル名のファイルが生成されると、Explorerから消せなくなる場合がある。
その場合は、MinGW32からrmで消すことができる。
参考: @muroさんに[以前、教えていただきました](https://qiita.com/7of9/items/9aa82ce970c2898da5d0/#comment-004ed69186ec10634924)

```
rm '%1s_%s%02d%02d.csv '
```
(rmでシングルクォーテーションから始めて、Tab補完でファイル名入力)

## v0.2

prefixを増やした。

```bash:mkdmy_datetimefiles_171017_exec
#!/usr/bin/env bash

# on MinGW32

# v0.2 Oct. 17, 2017
#   - add prefixes "Y" and "Z"
# v0.1 Oct. 17, 2017
#   - loop with year, month, and day with prefix "X"

# X: prefix
filename=$(echo {X..Z}"_"{2017..2017}{01..03}{01..31}".csv")
touch $filename
echo $filename
```
CloudWatchのログがS3にエクスポートされない


LambdaやBatchでCloudWatchに出力されたログのエクスポートを試みたところ一部のログがエクスポートされない状況にハマりました。

原因はログがエクスポートできる状態になるまでに最大12時間かかる事が原因でした。

[参考](http://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/S3Export.html)

次の日にエクスポートしたら正常にエクスポートされました。

結構ハマった。
Ruby の Array でまとめて pop / shift

Ruby の配列操作である `Array#pop` と `Array#shift` は引数を渡すことが可能で、渡した引数の値の数の要素を取得することが出来ます。（0 を与えた場合は空配列が返ってきます）

```rb
list = [1, 2, 3, 4, 5]

a = list.pop(5)

p list #=> []
p a    #=> [1, 2, 3, 4, 5]
```

```rb
list = [1, 2, 3, 4, 5]

a = list.shift(3)

p list #=> [4, 5]
p a    #=> [1, 2, 3]
```

気をつけないといけないのは、空配列に対する操作を行った場合に引数を与えている場合は `nil` ではなく空配列を返すので、下記のようなコードを書いてしまうと大変なことになります。

```rb
list = [1, 2, 3, 4, 5]

while a = list.pop(2)
  p a
end
```

結果

```console
[4, 5]
[2, 3]
[1]
[]
[]
[]
[]
[]
[]
[]
[]
.
.
.
以下無限ループ
```



## 参考サイト

https://docs.ruby-lang.org/ja/latest/method/Array/i/pop.html
https://docs.ruby-lang.org/ja/latest/method/Array/i/shift.html
Kotlin覚書 - by lazy

# by lazyとは
今長澤太郎さんの、[赤べこ本](http://www.ric.co.jp/book/contents/book_1039.html)を読んでおります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/151973/ccfb2a5b-661d-bb76-18ce-47e95fdfea9f.png)
※転載あかんようなら消します。すいません。

まだ全然読めてないんですが、ちらっと出てきた物体に「？？」となっております。

それが**by lazy !!!!!**

一応自分でKotlinのDocを参照してみました。
https://kotlinlang.org/docs/reference/delegated-properties.html

以下の場合にプロパティに対して移譲できるようです。
つまり移譲プロパティ（Delegated Properties）ってやつです（赤べこ本にも書いてありました。）

```
class Sample(n: Int, d: Int) {
    private val str: String by lazy {"初期化します"}
```

## byで移譲
`by lazy`でひとまとめに読んでましたが、そうではなくて、
`by`のあとに移譲するオブジェクトが渡せるようです。

## じゃあlazyって？
lazyってなんじゃってことになります。

リファレンスにも一応書いてあります。
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/lazy.html

```
lazy() is a function that takes a lambda and returns an 
instance of Lazy<T> which can serve as a delegate 
for implementing a lazy property: the first call to get()
executes the lambda passed to lazy() and remembers the result,
subsequent calls to get() simply return the remembered result.
```

lambdaがまだまだ理解できていないですが、雰囲気的に
- 初期化時に利用します。
- 一度getしたときの結果を返し、且つ結果を記憶します。
- 再度getした時は、最初にgetしたときの結果を返します。
- Synchronizedで遅延実行されます

と言った感じでしょうか。。

移譲プロパティは他にもあるようです。
もう少し勉強する必要がありそうですが、ひとまずby lazyをつかった場合はどんなもんなんやっていうのがわかったのでよしとします。

ツッコミがあったり、なにかいい例文などあれば教えてください
PythonでのHTTPクライアント

PythonでHTTP GET/POSTします

#1. PythonでHTTP GET/POSTするクライアント
- python環境で実行します
- 必要に応じ、`pip3 install urllib`します

```py3:get.py

import urllib.request
import urllib.parse

#リクエストパラメータをエンコード
params = {"moji_param": "おはよう", # 文字パラメータの例
            "suji_param": 123,     # 数値パラメータの例
            "nested": {
                "nested_param": "ごきげんよう" # ネストしたパラメータの例
            }
        }
encodedParams = urllib.parse.urlencode(params)

#エンコードしたリクエストパラメータを付加してGETリクエストを送付
with urllib.request.urlopen("http://localhost:1880/test12?" + encodedParams) as res:
    html = res.read().decode("utf-8")
    print(html)

```


```py3:post.py

import urllib.request
import urllib.parse

#リクエストパラメータをエンコード
params = {"moji_param": "おはよう", # 文字パラメータの例
            "suji_param": 123,     # 数値パラメータの例
            "nested": {
                "nested_param": "ごきげんよう" # ネストしたパラメータの例
            }
        }
data = urllib.parse.urlencode(params).encode('utf-8')

#リクエスト・レスポンスを用意してpost
request = urllib.request.Request('http://localhost:1880/test10', data)
response = urllib.request.urlopen(request)
print(response.getcode())
html = response.read()
print(html.decode('utf-8'))

```

#2. Node-REDフロー
- たとえば、ですけど、上記のクライアントからのリクエストを受けるNode-REDのサンプルフローは以下のような感じかと。

```
[{"id":"d8af2f1d.1179b","type":"http in","z":"b46bcde3.e9962","name":"","url":"/test12","method":"get","upload":false,"swaggerDoc":"","x":130,"y":100,"wires":[["83adb3c3.f5ff58","3e77f42e.8f1a44","58b3b826.c38f9"]]},{"id":"5a3973f4.c79c04","type":"http response","z":"b46bcde3.e9962","name":"","statusCode":"","headers":{},"x":630,"y":80,"wires":[]},{"id":"e3ed6338.fe56b","type":"template","z":"b46bcde3.e9962","name":"htmlを返す","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n    <body>\n        <h1>\n        祝！開通！！「{{payload}}」が送られました\n        </h1>\n    </body>\n</html>","output":"str","x":490,"y":80,"wires":[["5a3973f4.c79c04"]]},{"id":"83adb3c3.f5ff58","type":"debug","z":"b46bcde3.e9962","name":"","active":true,"console":"false","complete":"payload.moji_param","x":270,"y":240,"wires":[]},{"id":"3e77f42e.8f1a44","type":"function","z":"b46bcde3.e9962","name":"","func":"msg.payload = msg.payload.moji_param;\nreturn msg;","outputs":1,"noerr":0,"x":330,"y":80,"wires":[["e3ed6338.fe56b"]]},{"id":"58b3b826.c38f9","type":"debug","z":"b46bcde3.e9962","name":"","active":true,"console":"false","complete":"false","x":230,"y":180,"wires":[]},{"id":"e593b21f.fc8a1","type":"http in","z":"b46bcde3.e9962","name":"","url":"/test10","method":"post","upload":false,"swaggerDoc":"","x":130,"y":60,"wires":[["3e77f42e.8f1a44","58b3b826.c38f9","83adb3c3.f5ff58"]]}]
```

![スクリーンショット 2017-10-17 18.28.33.png](https://qiita-image-store.s3.amazonaws.com/0/125842/15603a2a-98f8-c5aa-0234-455eab529a0b.png)
ウィルスと闘ってみた。

#概要
開発用のXPが、どうにも調子が悪い。
ウィルスと闘ってみた。
三日、かかった。

#現状
世界レベルでは、8％がXPらしい。
開発用に、ノートとデスクトップがある。
フリーのソフトが、いっぱい入ってる。
全部あやしい。
ウィルスバスターの類は入れない主義。
ファイアフォールも、甘い甘い。

#症状
ネットが遅い。
タスクマネージャで知らないプロセス走ってる。
ブルースクリーンで、ＯＳが落ちる。

#軽く調査
msconfigで、スタートアップ、いじっても、あやしいプロセスは、動いてる。
あやしいプロセスは、3つ。
毎回の起動でプロセスの名前は変わるが、3つ。
プロセスの場所は、document and settings \ ** \localseting\Temp\にある。

#さらに調査
microsoft謹製、autorunsを使う。
普段使わない、ノートでリファレンスのリストをつくる。
compareで差分を見て、あやしいやつを探す。
![image](https://qiita-image-store.s3.amazonaws.com/0/18104/4ab97526-7b36-11bf-d548-8026666de5a5.png)

publisherが無い、ドライバー、「amsint32」があやしい。
て言うか、リファレンスにも、入ってるじゃん。


#敵が、判明
ググルと、salityと呼ばれるらしい。寄生型らしい。
さらに、おかしい症状が、確認できた。
シマンテックとか、トレンドマイクロとか、カスペルスキーのサイトに行けない。DNSエラーでる。
これも、ウィルスの仕業。
勝てる気がしないので、駆除ツールを探す。

#駆除ツール発見
カスペルスキーにその名も、「salitykiller」あった。
邪魔されて、ダウンロードできない。
７で落として、フロッピーで入れる。

![image](https://qiita-image-store.s3.amazonaws.com/0/18104/6c4b253b-0196-30a2-3d9c-9ca7595f50e2.png)

#結果

９８０件、検出、駆除。
ギネス級じゃね。
デスクトップは、０件となる。続く。
kube-awsのカーネルパラメータチューニング

## 背景
ホストOS(CoreOS)のデフォルトのカーネルパラメータがいくつか渋かったのでチューニングしたかった。
kubernetesのノードレベルでオートスケールする想定なので、スケール時にチューニングされている必要があった。
kube-awsの `customFiles` と `customSystemdUnits` で実装することでチューニング済みのノードが生成されるようになった。

## 現状確認
パラメータはこちらの記事を参考にした。
[Dockerホストのパフォーマンスを引き出すTCPカーネルパラメータチューニング](https://blog.stormcat.io/post/entry/docker-tcp-kernel/)

CoreOS Stable(1520.6.0)のデフォルトのカーネルパラメータはこんな感じ。
`sysctl -a` とか `sysctl net.core.somaxconn` で確認できる。記事で言われている値がけっこう渋い。


```
fs.file-max = 400143
net.core.somaxconn = 128
net.ipv4.tcp_max_syn_backlog = 128
net.core.netdev_max_backlog = 1000
net.ipv4.ip_local_port_range = 32768	60999
net.ipv4.tcp_tw_reuse = 0
```

## 設定
`customFiles` だけでは適用されないので `customSystemdUnits` の設定も使う。
実際のcluster.yamlの設定はこちら。clusterをアップデートしたらパラメータの反映を確認できた。

```
      # User defined files that will be added to the NodePool cloud-init configuration in the "write_files:" section.
      customFiles:
        - path: "/etc/sysctl.d/nf.conf"
          permissions: 0644
          content: |
            net.core.somaxconn = 65535
            net.ipv4.tcp_max_syn_backlog = 65535
            net.core.netdev_max_backlog = 16384
            net.ipv4.ip_local_port_range = 1024 65535
            net.ipv4.tcp_tw_reuse = 1

      # User defined systemd units that will be added to the NodePool cluster cloud-init configuration in the "units:" section.
      customSystemdUnits:
        - name: update-sysctl.service
          command: start
          enable: true
          content: |
            [Unit]
            Description=Update sysctl values written by customFiles
            [Service]
            ExecStart=/usr/lib/systemd/systemd-sysctl
```
rspecを実行した時にcannot load such file -- spec_helper (LoadError)が出る

[rspecを実行した時にcannot load such file -- spec_helper (LoadError)と言われる解決方法](rspecを実行した時にcannot load such file -- spec_helper (LoadError)と言われる解決方法)
を見ても自環境ではrails_helperが存在していた場合

※念のため、projectへのパスを変更しています

```bash:エラー発生
$ bundle exec rspec sales_targets_dashboard_spec.rb
bundler: failed to load command: rspec (/Users/admin/.rbenv/versions/2.3.1/bin/rspec)
LoadError: cannot load such file -- rails_helper
```

```bash:rspecをinstallしてみる
$ rails generate rspec:install
    conflict  .rspec
Overwrite /project/.rspec? (enter "h" for help) [Ynaqdh] n
        skip  .rspec
       exist  spec
    conflict  spec/spec_helper.rb
Overwrite /project/spec/spec_helper.rb? (enter "h" for help) [Ynaqdh] n
        skip  spec/spec_helper.rb
    conflict  spec/rails_helper.rb
```

存在してるな。。。

```bash:実際にspec_helper.rbが存在することを確認
$ ll spec/spec_helper.rb
-rw-r--r--  1 admin  staff  5058  6 20 21:07 spec/spec_helper.rb
```

実行権限がないからかな？

```bash:権限を変更してみる
$ chmod 744 spec/spec_helper.rb
```

これでテストができるようになった。

あれ？こないだテストできたんだけどな。。。
Basic認証でユーザを追加する

Basic認証でユーザを追加するコマンドメモ。

# 前提
- Apacheは`/usr/local/apache`にインストールされている。
- パスワードファイルは`/usr/local/apache/htpasswd/user`にある。
- Apacheの設定ファイルにパスワードファイルを設置したディレクトリ（AuthUserFile）は記載されている。

# コマンド
```
/usr/local/apache/bin/htpasswd /usr/local/apache/htpasswd/user ユーザ名 パスワード
```

オプション`-c`を付けると、パスワードファイルを新規作成し、同名のパスワードファイルがすでに存在する場合は、既存の内容が削除される。
Jupyter + Matplotlib > triangular van der Corput sequenceの描画 > v0.1: 数点打つだけ

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

参考: [Jupyter | Matplotlib > 2次元データの可視化 > imshow() | scatter()
](https://qiita.com/7of9/items/208e55caa6a9713030aa)

### code v0.1

上記のリンク先のコードを変更し、単色の点を打つコードにしてみた。

```python:triangularVanDerCorput_171017.ipynb
%matplotlib inline

# v0.1 Oct. 17, 2017
#  - branched from [test_scatter_170812.ipynb]

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm


def get_value(ax, ay):
    return ax + ay

# 1. get data
NUM_DATA = 10
x = np.random.rand(NUM_DATA)
y = np.random.rand(NUM_DATA)
#color = get_value(x, y)
color = [10 for idx in range(NUM_DATA)]

# 2. draw data
size = 25  # arbitrary
plt.scatter(x, y, size, color, cmap=cm.jet)
plt.colorbar()
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/6190559d-96fa-ac88-939a-a87f14e641db.png)

単色にすると中央の色の緑になり見えにくい。
Gulpプラグイン 用途別メモ


##gulp-wrapper
https://www.npmjs.com/package/gulp-wrapper

任意のコードをまるっと、wrapper（ラップ）したい時に

```gulpfile.js
const gulp    = require('gulp')
const wrapper = require('gulp-wrapper')

gulp.task('{task_name}', function() {
  return gulp.src({file_paths})
	// ...省略  	
	.pipe(wrapper({
	   header: '<{tag}>\n',
	   footer: '</{tag}>\n'
	}))
	// ...省略
	.pipe(gulp.dest({dest_paths}))
})
```

##gulp-header
https://www.npmjs.com/package/gulp-header

任意のコードの前に追記したい時に
EX.「charset」の追記
EX. ライセンス情報を挿入

```gulpfile.js
const gulp    = require('gulp')
const header  = require('gulp-header')

gulp.task('{task_name}', function() {
  return gulp.src({file_paths})
	// ...省略  	
	.pipe(header('@charset "UTF-8";\n\n'))
	// ...省略
	.pipe(gulp.dest({dest_paths}))
})
```
※「gulp-footer」もある
https://www.npmjs.com/package/gulp-footer

##gulp-replace
https://www.npmjs.com/package/gulp-replace

任意の箇所を、replace（置換え）したい時に
EX. 出力ファイル別に任意のパスへ書き換え
EX. 不要な箇所を「''」(空)にする
EX. 正規表現で置換

```gulpfile.js
const gulp    = require('gulp')
const replace = require('gulp-replace');

gulp.task('{task_name}', function() {
  return gulp.src({file_paths})
	// ...省略  	
	.pipe(replace('bar', 'foo'))
	// ...省略
	.pipe(gulp.dest({dest_paths}))
})
```

##gulp-rename
https://www.npmjs.com/package/gulp-rename

任意のファイル名を、rename（リネーム）したい時に
EX. minifyしたファイルを「.min.{file_name}」にリネーム

```gulpfile.js
const gulp    = require('gulp')
const replace = require('gulp-rename');

gulp.task('{task_name}', function() {
  return gulp.src({file_paths})
	// ...省略  	
	.pipe(rename('xxxx.min.css'))
	// ...省略
	.pipe(gulp.dest({dest_paths}))
})
```

##gulp-template
https://www.npmjs.com/package/gulp-template

簡易的なテンプレートとして利用
EX. 任意の箇所のテキストを変数として管理
EX. 読み込みのパスへパラメータを付与してキャッシュ対策

```gulpfile.js
const gulp    = require('gulp')
const replace = require('gulp-template');

gulp.task('{task_name}', function() {
  return gulp.src({file_paths})
	// ...省略  	
	.pipe(template({name: '{name}'}))
	// ...省略
	.pipe(gulp.dest({dest_paths}))
})
```
```xxxx.hrml
<h1>Hello <%= name %></h1>
```

##gulp-imagemin
https://www.npmjs.com/package/gulp-imagemin

画像ファイルの最適化
※「gulp-newer」は変更されたファイルをStream

```gulpfile.js
const gulp     = require('gulp')
const newer    = require('gulp-newer')
const imagemin = require('gulp-imagemin')
 
gulp.task('{task_name}', function() {
    gulp.src('src/images/*')
     .pipe(newer('dist/images'))
     .pipe(imagemin({ optimizationLevel: 5 }))
     .pipe(gulp.dest('dist/images'))
);
```

##gulp-sftp
https://www.npmjs.com/package/gulp-sftp

SSH経由でファイルをアップロードする

```gulpfile.js
const gulp = require('gulp');
const sftp = require('gulp-sftp');
 
gulp.task('{task_name}', function () {
    return gulp.src('htdocs/*')
        .pipe(sftp({
            host: 'website.com',
            user: 'johndoe',
            pass: '1234'
        }));
});
```
jbuilderのpartialを高速化する

かなり有名な話かと思うが、 **jbuilderのpartialは遅い**。
ActionViewの機能の `render partial: '...'` を内部的に呼び出しており、それが遅いからである。
そのため、数の多いレコードをjbuilderでレンダリングすると、だいたい数百msかかる。

```
# 内部でレコードごとにrender呼び出しているのが原因で遅い
json.posts('posts/post', collection: @posts, as: :post)
```

これを解決するために、 `partial!` を呼び出さずに直接埋め込むこともある。
しかし、せっかく構造化して切り分けられたテンプレートを埋め込むと、見通しが悪くなり残念である。

```
json.posts(@posts) do |post|
  json.call(post, ...)
end
```

というわけで、テンプレートを分割したまま高速化することを考えてみる。
効果の高そうな順に並べてみた。

## 1. partialのログをオフにする

デフォルトでは、Railsはレンダリングしたテンプレートの情報をログに書き出す。
下記のようなログは、見覚えがあるのではないだろうか？

```
INFO -- : Rendered api/posts/_post.json.jbuilder (8.0ms)
INFO -- : Rendered api/comments/_comment.json.jbuilder (0.2ms)
INFO -- : Rendered api/comments/_comment.json.jbuilder (0.8ms)
INFO -- : Rendered api/comments/_comment.json.jbuilder (0.9ms)
INFO -- : Rendered api/comments/_comment.json.jbuilder (0.3ms)
INFO -- : Rendered api/comments/_comment.json.jbuilder (1.0ms)
...
```

通常は軽微なものなのだが、数が多いとパフォーマンスに影響が出る。
なので、jbuilderの場合はログの出力を抑えるのを試みる。

```
# config/initializers/optimized_jbuilder_partial_rendering.rb
module OptimizeJBuilderPartialRendering
  def render_partial(event)
    # jbuilderの場合はログを書き出さない
    super unless event.payload[:identifier].end_with?('.jbuilder')
  end
end

ActiveSupport.on_load(:action_view) do
  ActionView::LogSubscriber.prepend(OptimizeJBuilderPartialRendering) if Rails.env.production?
end
```

これで、検証環境では倍ぐらい速くなった。

## 2. 探索の正規表現を簡素にする

テンプレートの探索は、複数のパス(prefix + view_path)の `Dir[Regexp]` を回して行われる。
端的に言えば、 `Regexpのコスト * 探索回数` がテンプレート探索のコストである。
そのため、Regexpの内容を改良することで、テンプレートの探索速度が速くなる可能性がある。

ちなみにRegexpの中身はこんな感じで、locale、format、handlersなどが考慮されている。

```
%r!app/views/api/posts/_post{.ja,}{.html,.json,}{}{.erb,.builder,.raw,.ruby,.slim,.coffee,.haml,.faml,.jbuilder,}!
```

`#details_for_lookup` を上書きして、自分にとって不要な要素を削ることで高速化を試みる。

```
class Api::PostsController < Api::ApplicationController
  ...

  private

  # 実はjbuilderはhandlersのみ最適化しているので、handlersはなくても良い。
  # ただし、初回にcontrollerがrenderを呼び出す際には効果がある。
  def details_for_lookup
    {
      locale: [],
      format: [:json],
      handlers: [:jbuilder]
    }
  end
end
```

巨大なアプリケーションでは、HTMLの探索が10倍ぐらい速くなったことがあるのだが、今回は効果がなかった。
検証環境は小さいアプリケーションなのと、jbuilderの最適化、ActionViewの探索パスのキャッシュが既に効いているからだと思う。

ちなみに、自分のアプリケーションを変更したい時は `YourController.new.lookup_context.instance_variable_get(:@details)` でRegexpの大体の予想ができる。

---

今後も検証することがあれば追記していく。

ベンチマークは、[APIアプリケーション](https://github.com/alpaca-tc/jbuilder_bench)を作って試しているだけなので、ぜひフィードバックください。 :pray:
開封確認を求めるメールヘッダ(Disposition-Notification-To:) をprocmailでブロックする

最近中国語の迷惑メールにて開封確認を求めるメールが多く届くようになった。

```ruby:メールヘッダー例
Disposition-Notification-To: hoge@fuga.com
```

procmailでブロックするの以下で良いと思う (Hは省略可　[Procmail の紹介とレシピの書き方](http://www.jaist.ac.jp/~fjt/procmail.html))

```rb:/etc/procmailrc
:0 H
* ^Disposition-Notification-To:.*@(126|hotmail|gmail|yahoo).com
/dev/null
```

## その他情報

* [中国のフリーメールでは割と有名な『126.com』](http://haaya.net/512)
* [中国のサイトで提供されているウェブメールアカウントを作成する。 | 中国語独学日記](http://cj.yadoku.com/archives/618)

> 知り合いの中国人を見ていると、QQのメアド以外では、ほとんどの人が「~@163.com」もしくは「~@126.com」というアドレスを使っています。

* プログラムから開封確認を求めるメールヘッダーを送る場合は以下
    * [開封確認をリクエストしてメールを送信する: .NET Tips: C#, VB.NET](http://dobon.net/vb/dotnet/internet/dispositionnotificationto.html)
ECDSA鍵をGitHubで使う

## 動機

[professional SSL/TLS](https://www.lambdanote.com/products/tls)を読んで、今後はなるべくECDSA鍵を使っていこうと思った。
先行記事の[GitHubでEd25519鍵をつかう](http://jnst.hateblo.jp/entry/2014/12/15/200542)も非常に面白いのでぜひ。

## ECDSAとは？

ECDSA(Elliptic Curve Digital Signature Algorithm)は楕円曲線暗号を使った公開鍵のアルゴリズムで、RSAよりも短い鍵長で安全性を担保できる。

短いということは、TLSなどで利用する場合は高速に鍵交換が行えるということである。
（後で示すが、256bitのECDSA鍵は、2,048bitのRSA鍵より安全かつ2倍早い）

ただし古いブラウザでは対応していない場合があることに注意。
参考（ちょっと古め）: [ウェブブラウザにおけるTLS/SSLの対応状況の変化](https://ja.wikipedia.org/wiki/Template:%E3%82%A6%E3%82%A7%E3%83%96%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8BTLS/SSL%E3%81%AE%E5%AF%BE%E5%BF%9C%E7%8A%B6%E6%B3%81%E3%81%AE%E5%A4%89%E5%8C%96)

とはいえNISTによると、2031年以降、RSA 2,048bitをはじめ強度の低いアルゴリズムはほとんどが使用禁止扱いになる。
ECDSAがスタンダードになるのは時間の問題。

## GitHubのSSH keysで使う方法

鍵作って登録するだけだが、若干ハマりどころがある。

まず確実にECDSA鍵を作るため、`openssl`コマンドのバージョンを最新にする。
（macの2018までのデフォだとTLSの証明書とか作れないためupgradeを勧める）

更新前（下記は`macOS Mojave v10.14.2 MacBook Pro (2018)`の結果）

```
$which openssl
/usr/bin/openssl
$openssl version
LibreSSL 2.6.5
```

更新

```
$ brew upgrade openssl
$ brew link openssl --force
```

更新後

```
$which openssl
/usr/local/bin/openssl
# brewfileなどで入れるとシンボリックリンクが自動で貼られなかったので手動で貼る
$ln -s /usr/local/Cellar/openssl/1.0.2q/bin/openssl /usr/local/bin/openssl
# Note: ttyのsessionも再接続させた方が良いことが多い
$openssl version
OpenSSL 1.0.2q  20 Nov 2018
```

鍵を作り、公開鍵の中身をGitHubの設定のSSH keysに登録。

```
$ssh-keygen -t ecdsa -b 256 -C "your_email@example.com"
Enter file in which to save the key (/Users/me/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
$cat .ssh/id_ecdsa.pub | pbcopy
```

結果をGitHubに登録したら疎通確認。

```
$ssh -T -i ~/.ssh/id_ecdsa git@github.com
```

ECDSAに対応していない環境が多い場合などはRSAと併用すると思う。
そうした事情で`~/.ssh/config`で`IdentityFile ~/.ssh/id_rsa`などと記載している場合もあると思う。
そしたらgit cloneでRSA鍵を使われてしまうが、git2.3以降であれば`GIT_SSH_COMMAND`という環境変数を使えるので、GitHubに対してだけECDSA鍵を使うという手もある。

```
$vi ~/.bashrc
export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ecdsa"
```

## 詳細データ

下表より、256bitのECDSA鍵の強度は128(bit)で、2,048bitのRSA鍵の強度112(bit)より安全である。

<img width="569" alt="NIST_SP_800-57.png" src="https://qiita-image-store.s3.amazonaws.com/0/100881/7cd61c03-cc09-8104-c1a7-f80b089fa1d7.png">

参考: [NIST Special Publication 800-57(2012/07)](https://www.ipa.go.jp/files/000055490.pdf)

また鍵交換の速度については、256bitのECDSA鍵は2,048bitのRSA鍵より2倍高速となる。

<img width="694" alt="tls.png" src="https://qiita-image-store.s3.amazonaws.com/0/100881/5ffab07f-e62c-9bb8-9319-804689491628.png">

参考: [professional SSL/TLS 第9章より](https://www.lambdanote.com/products/tls)
=> 1,000回のTLSハンドシェイクにおけるCPU使用時間のベンチマーク

## その他（雑記）

量子コンピュータ時代の暗号化対策としては、鍵長を伸ばす等よりも、そもそも素数に頼らない新たな方法を模索しているのだと小耳に挟んだ。
例えば、高次元の連立方程式にするなど。面白い。
case classリストのgroupBy

DBから外部結合したクエリーの結果を`case class`の`Seq`に格納し、その後のプログラムで扱いやすいように加工した時の備忘録です。

## case class定義
#### DBから取得時のcase class
```scala
case class DBItem(
  id         : Int,
  name       : String,
  optionId   : Option[Int],
  optionName : Option[String]
)
```

#### 加工後のcase class
```scala
case class Item(
  id      : Int,
  name    : String,
  options : Map[Int, String] = Map.empty[Int, String]
)
```

## groupBy処理
DBから取得したデータは、下記のような形式で`Seq`に格納されているとします。

```scala
val dbItems = Seq(
  DBItem(1, "item1", Some("1"), Some("opt1")),
  DBItem(1, "item1", Some("2"), Some("opt1")),
  DBItem(2, "item2", None, None)
)
```

最初に可読性も悪く、非効率なコードを書いてしまったので、前後のコードを載せておきます。

### リファクタリング後
```scala
dbItems.groupBy(_.id).mapValues {
  items => Item(
    id = items.head.id,
    name = items.head.name,
    options = items.collect {
      case DBItem(_, _, Some(id), Some(name)) => id -> name
    } toMap
  )
}
```

### リファクタリング前
```scala
dbItems.groupBy(_.id).map {
  case (id, item) =>
    id ->
      item.groupBy(_.name).map {
        case (name, options) =>
          Item(
            id = id,
            name = name,
            options = options.filter { opt =>
              opt.optionId.isDefined && opt.optionName.isDefined
            } map { opt =>
              opt.optionId.get -> opt.optionName.get
            } toMap
          )
      }.head
}
```

### 結果
```scala
scala.collection.immutable.Map[Int,Item] = Map(
  2 -> Item(2,item2,Map()),
  1 -> Item(1,item1,Map(1 -> option1, 2 -> option2))
)
```
どちらも同一の求める結果となりました。


## 振り返り
- `filter`と`map`を続けて書く時は、`collect`を適用できないか考える
- `map`後に`head`のように違和感がある時は、やはり良くない書き方になっている気がする
- パターンマッチと`case class`をもっと使いこなす

といったところが、自分の足りないところだと思いました。
go1.9のsyncmapを試してみた

# はじめに
go1.9で導入されたsyncmapを今更ながら試してみようと思います。

# syncmap?
golangの様に簡単に並列処理を行える言語の場合には、共有リソースにアクセスする場合にはロックなどの処理が必要です。
これまでmapを共有リソースで使う場合は、sync.RWMutex等を使って同期していました。
syncmapでは、その辺の同期処理を実装する必要なくなるメリットがあります。
デメリットも[公式](https://golang.org/pkg/sync/#Map)に書いてあります。

# サンプル
```go
package syncmap_sample

import (
	"fmt"
	"sync"
)

type syncMap struct {
	mapData *sync.Map
}

func NewMap() *syncMap {
	return &syncMap{mapData: new(sync.Map)}
}

// StoreMap mapにデータをストアする
func (thisMap *syncMap) Store(key, value interface{}) {
	thisMap.mapData.Store(key, value)
}

// LoadMap mapからデータを取得する
func (thisMap *syncMap) Load(key interface{}) (value interface{}, ok bool) {
	return thisMap.mapData.Load(key)
}

// LoadOrStore mapにデータがあった場合は取得、ない場合はストアする。
func (thisMap *syncMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) {
	return thisMap.mapData.LoadOrStore(key, value)
}

// Range 試しにkeyとvalueが同じものだけdumpしてみる
func (thisMap *syncMap) Range() {
	thisMap.mapData.Range(func(key, value interface{}) bool {
		if key == value {
			fmt.Println("key:", key, " value:", value)
		}
		return true
	})
}

// Delete mapにあるデータを削除
func (thisMap *syncMap) Delete(key interface{}) {
	thisMap.mapData.Delete(key)
}
```
コードは、[github.com](https://github.com/arihitohagiwara/syncmap_sample_go/blob/master/syncmap.go)に上げてあります。
個人的には、LoadOrStoreとRangeの使い道に悩みます。
Goの挙動をgo testで確認する

Goの挙動を確認するのにgo testが役に立ちそう。

go testの使い方は

go test package_name

とすると特定のパッケージのみユニットテストを実行できる。さらに、

go test package_name -run TestHoge

とすると特定のユニットテストのみ実行できる。

実行されるユニットテストは、インストールされたGo本体やgo getで持ってきたパッケージのものとなる。

なので、自分のユニットテストを追加して、適宜ソースを修正すれば自由に挙動を確認することができる。

どうように挙動を把握する手段としてdelveなどのデバッガを使うことも考えられるが、go testで任意のコードを実行できるのでより簡単に詳細を把握することができる。

(あとで加筆、整形します)
EC2のインスタンスタイプを変えて経費削減

# はじめに
EC2の料金が高かったので、EC2のインスタンスタイプを変えることによって、安くした体験談です。
実際に対応したのは2017年8月で、awsでは、頻繁に値段が変わるので注意してください。

# 元の環境のインスタンスタイプ
m3.medium(２００台ぐらい)

# 変更後の環境のインスタンスタイプ
m4.large(１００台ぐらい)

# スペック比較
|タイプ|vCPU|ECU|メモリ（GiB）|インスタンスストレージ（GB）|Linux/UNIX 料金|
|---|---|---|---|---|---|
|m3.medium|1|3|3.75|1 x 4 SSD|$0.096 /1 時間|
|m4.large|2|6.5|8|EBS のみ|$0.129 /1 時間|
スペックは倍以上にもかかわらず価格は1.3倍!!

# 結果(１時間あたりの単純計算)
__元の料金__
\$0.096×200=$19.2

__変更後の料金__
\$0.129×100=$12.9

__結果__
約33%削減

# 注意点
インスタンスのスペックを倍にしたところでCPUを使いきれないアプリケーションだと、意味がないので気を付けてください。
（アプリケーションの設計やautoscaleのルール等を見直た方が良いです）
今回実施したアプリケーションではマルチプロセスで動いておりCPUも使い切っていたので上手く行きました。
インスタンスタイプを変えることによって思わぬことが起きたりもするので、十分テストしてから移行して下さい。

# 最後に
検証は必要だったとはいえ、インスタンスタイプを変えるだけで、経費削減できたのは大きかったです。
台数が減ったことにより運用負荷や他のサービスへの負荷も減っていて経費削減以外のメリットもありました。
ROCK64のXenial Mate(Ubuntu16.04)上に日本語入力環境を構築する方法

PINE64からカードサイズでパワフルに派生したROCK64。
電源は専用なので、必ずボードと一緒に買ってください。

ソフトウェアは以下から選びます。
http://wiki.pine64.org/index.php/ROCK64_Main_Page

ここでは、
2.9 Community Build Xenial Mate Linux Kernel ver 4.4 [microSD Boot]
に日本語入力環境を構築する例を紹介します。

まず、Ubuntu16.04のarm64版は、Mozcパッケージが欠落しています。
なので、Anthyを使う方法と、Mozcをビルドする方法の二本立てにしました。

■とりあえずパッケージだけで日本語入力環境を実現する方法
fcitx-anthyを使います。
https://ameblo.jp/yamjp/entry-12313219218.html

■不足してるパッケージをビルドして日本語環境を実現する方法
fcitx-mozcをビルドします。
https://ameblo.jp/yamjp/entry-12318813732.html

コミュニティは、以下にあります。Jews Japで投稿しています。
https://forum.pine64.org/forumdisplay.php?fid=88
SudachiをElasticsearchで使用する手順#1


# Sudachiと私
はじめまして。自然言語処理エンジニアのまっちゃんです。秋も深まりサンマの美味しい季節になりました。サンマといえば塩焼き。塩焼きといえば美味しいお醤油。あと私はすだちが欠かせません。今日はそのすだちの産地、徳島にあるワークスアプリケーションズの研究所で開発している形態素解析器Sudachiの使い方をご紹介します。

Sudachiは、語句を適切な長さで抽出することができることが特徴です。解析速度はkuromojiに匹敵し、neologd譲りの豊富な語彙を備えた辞書に加えて、neologdが抱える語句の過剰な纏め上げや広すぎる固有名詞解釈などの問題の解消を目指しているようです。こちらに取り組みの解説資料があります。
https://www.slideshare.net/WorksApplications/ss-78025845

更新：正式に公開されて解説も揃ってきましたね。@soramiさんのこちらの解説はとてもわかり易いです。
[Elasticsearchのための新しい形態素解析器 「Sudachi」](https://qiita.com/sorami/items/99604ef105f13d2d472b)
コンパイル済みのアーカイブも公開されるようになりました。
https://oss.sonatype.org/content/repositories/snapshots/com/worksap/nlp/
ということで、下記は既に役に立たない情報です。何かのトラブルシューティングの助けになれば。

~~今のところは開発者向けにgithubでソースを公開している段階ですので、Elasticsearchで使用するためには一手間必要です。きっとそのうちyum等で楽々インストールできるようになると期待しています。~~
# @Deprecated ~~おおまかな手順~~
Elasticsearchで必要なのはanalysis_sudachiというpluginです。
このpluginを作るためにまずSudachi本体をビルドする必要があります。
analysis_sudachiはclone先ディレクトリ(以下ではSudachi/)配下のelasticsearchでビルドします。

1. githubからLFSを有効にしてclone https://github.com/WorksApplications/Sudachi
- Sudachi/pom.xml に対して mvn package を実行
 - Sudachi/target/sudachi-0.1-SNAPSHOT-executable.zip 等が作成されていれば成功
- Sudachi/elasticsearch/pom.xmlを編集
 - surefire plugin削除
 - worksのartifact削除
 - elasticsearch系のartifactのversionを適宜変更
- Sudachi/elasticsearch/src/main/extras/plugin-descriptor.propertiesを編集
 - 3と同様にelasticsearchのversionを適宜変更
- Sudachi/src/main/java/をSudachi/elasticsearch/src/main/java/にコピー
 - worksのartifactがないのでこのステップが必要です
- Sudachi/elasticsearch/src/test/を削除
 - testがうまく通らないようですが問題ないはず
- Sudachi/elasticsearch/pom.xml に対して mvn package を実行
- Sudachi/elasticsearch/target/releases/analysis-sudachi-1.0.0-SNAPSHOT.zip をElasticsearchサーバに転送
- Elasticsearchサーバで次を実行してpluginをインストール
 - sudo elasticsearch-plugin install file:///your_path/analysis-sudachi-1.0.0-SNAPSHOT.zip
 - インストールに成功すると analysis_sudachi というanalyzerを使用できるようになります

以上、今日のところはざっくりした流れだけご紹介しました。また次回、詳細に説明していきます。
NgForOfとNgFor、、、、ngFor let-~~~ [ngForOf]=""という書き方

Angularプロな同僚が書いたソースに見慣れない`ngFor let-~~~ [ngForOf]=""`というコードがあり、参考書に記載無かったので本人に聞いてみました。

![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/201155/0bea3315-a429-7aac-a8cc-1112609d22eb.jpeg)


***Angularのループ処理は、 `NgFor` がDEPRECATED(非推奨)になり、`NgForOf`が推奨になった***

馴染みのある`NgFor`、つまり`let a of b`は非推奨になっており、代わりに`NgForOf`、コードだと`ngFor let-a [ngForOf]="b"`が推奨されているようです。

例えばJavaScriptをNgForOfに変えるとこうなります

**JavaScript**
```
let i = 0;
for (let detail of details) {
	i++
}
```

**NgForOf**
```
ngFor let-detail [ngForOf]="details" let-i="index"
```

https://angular.io/api/common/NgFor
たしかにDEPRECATED(非推奨)と書かれていて、NgForOfのURLが埋め込まれています。

ご参考までに。