OmniAICreator/Qiita-1.07M huggingface dataset:
Heroku上の1つのDockerコンテナでnginxとgunicornを動かす

Flaskアプリをgunicornで動かし、nginxの裏で動かしたい。これをDockerコンテナとしてHerokuで動かしてみたいので、Supervisorを用いて1つのコンテナ内でnginxとgunicornの両方を起動できるようにするということを、HerokuでDockerコンテナを動かす時の制約を解決しながらやってみた。

## nginxの設定
まずは、nginxを単体でHerokuで動くように設定していく。

gunicornのサイトにあるサンプルのnginx.confを元に作業したので、書き換えが必要な部分だけ記載していく。
http://docs.gunicorn.org/en/latest/deploy.html

### ログの出力先変更
Herokuではログをstdoutとstderrに出力したいのでそのように設定する。

```nginx.conf
error_log stderr;

http {
  server {
    access_log /dev/stdout;
  }
}
```

### temp_path設定の変更
Herokuではコンテナは非rootユーザで動作するため、client_body_temp_pathなどを書き込める場所に設定する必要がある。

```nginx.conf
http {
  client_body_temp_path /tmp/client_body;
  fastcgi_temp_path /tmp/fastcgi_temp;
  proxy_temp_path /tmp/proxy_temp;
  scgi_temp_path /tmp/scgi_temp;
  uwsgi_temp_path /tmp/uwsgi_temp;
```

### PORTの設定
Heroku上のDockerコンテナは環境変数PORTで実行環境から渡されるポート番号をlistenする必要がある。

nginx.confの設定に環境変数を渡す方法としてperl_setなどを使う方法があるが、listenのポート番号に対しては使用できないらしい（[参考](https://stackoverflow.com/questions/39442773/dynamically-listen-on-an-nginx-port)）。そのためDockerfileのCMDの中で、sedでも使って無理矢理渡すくらいしか方法がなさそうだった。

さらに、前述のとおり実行ユーザの権限によりsedで書き換えたnginx.confの出力先に注意が必要で、その影響で一部の設定変更も必要になる。

```:Dockerfile
COPY ./nginx.conf /opt/nginx.conf.temp

CMD sed -e "s/ENV_PORT/$PORT/g" nginx.conf.temp > /tmp/nginx.conf && \
    nginx -c /tmp/nginx.conf -g "daemon off;"
```

```nginx.conf
# nginx.confの位置が通常と変わるので変更が必要
#include mime.types;
include /etc/nginx/mime.type;
```

ここまでで、いったんnginxが立ち上がり、当然まだgunicornは動いていないのでエラーページが表示される。

## Supervisor
次にSupervisorを設定し、DockerfileのCMDをsupervisordの起動に変更する。
PORTのためのsedはCMD側に残ることになる。

```:Dockerfile
COPY ./supervisord.conf /etc/

CMD sed -e "s/ENV_PORT/$PORT/g" nginx.conf.temp > /tmp/nginx.conf && \
    supervisord -c /etc/supervisord.conf
```

supervisord.confでは、logfileやpidfileを設定しないと、デフォルト設定ではこちらも書き込み権限がなくてエラーになるところにだけ注意。

```supervisord.conf
[supervisord]
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/tmp/supervisord.pid

[program:nginx]
command=nginx -c /tmp/nginx.conf -g "daemon off;"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:gunicorn]
command=gunicorn --bind unix:/tmp/gunicorn.sock app:app
```

以上で、Herokuにデプロイして動作することが確認できた。
Raspberry pi 2BでAmazon Alexaを動かしてみた

Raspberry Pi 2Bを使ってAmazon Alexaを動かした際の備忘録
###今回使ったもの
+ Raspberry pi 2B　（Debian Jessie、SDは8GB)
+ USBマイク　UMF01 ￥1200円くらい
+ スピーカーはHDMIから出力

##作業手順
参考：[https://github.com/alexa/alexa-avs-sample-app/wiki/Raspberry-Pi](https://github.com/alexa/alexa-avs-sample-app/wiki/Raspberry-Pi)
上記サイトに記載の通り以下のステップで構築作業
###１：Raspberry piの設定
　　・[https://github.com/alexa/alexa-avs-sample-app/wiki/Setting-up-the-Raspberry-Pi](https://github.com/alexa/alexa-avs-sample-app/wiki/Setting-up-the-Raspberry-Pi)

###２：AmazonのAmazon developer accountを作成
　　・ [developer.amazon.com.](https://developer.amazon.com/login.html)

###3：デバイス登録とセキュリティプロファイルを生成
　　※このときに生成される以下３つはインストール時に必要なのでメモをしておく
   　　 + ProductID
    　　+ ClientID
    　　+ ClientSecret

###4：サンプルアプリの入手

```ruby:Gitを使ってゲット
cd Desktop
git clone https://github.com/alexa/alexa-avs-sample-app.git
cd ~/Desktop/alexa-avs-sample-app
nano automated_install.sh
```
最後のコマンドはautomated_install.shをnanoで加工するというものだが、ステップ３でメモしたProductID、ClientID、ClientSecretを書き換える。
※その際、値は””で囲む事

###5：インストールスクリプトの実行

```ruby:スクリプトの実行
. automated_install.sh
```
あとは３０分程度待てば完了

##実行
動作させるのには最低２つのターミナルを動かす必要があります。
ハンズフリーで使いたい場合にはもう１つのターミナルを立ち上げます。

Terminal Window:1 

```ruby:サービスの起動
cd /home/pi/Desktop/alexa-avs-sample-app/samples/companionService && npm start
```

Terminal Window:2

```ruby:JavaClientの起動
cd /home/pi/Desktop/alexa-avs-sample-app/samples/javaclient && mvn exec:exec
```
Terminal Window:3(Option)　２つのエージェントがありますがどちらか１つを実行

Sensory

```ruby:Sensory
cd /home/pi/Desktop/alexa-avs-sample-app/samples/wakeWordAgent/src && ./wakeWordAgent -e sensory
```
KITT_AI

```ruby:KITT_AI
cd ~/Desktop/alexa-avs-sample-app/samples wakeWordAgent/src && ./wakeWordAgent -e kitt_ai
```

##感想
+ 手順通りにインストールするだけで特に問題なく動かせることができた。
+ 時間や天気を聞くとシアトルの状況を回答するが設定が足りないのかもしれない。。。
+ スキルの設定についてはまだ良くわからないため、今後の課題とする
Keras(〜2.1.2)でtrainable=FalseをセットしてもBN層は完全に固定されない

**古い情報です(2018/02/18更新)**
**Keras 2.1.3(2018/01/16リリース)から、trainable=Falseで固定されるようになりました**
https://github.com/keras-team/keras/releases/tag/2.1.3
>trainable attribute in BatchNormalization now disables the updates of the batch statistics (i.e. if trainable == False the layer will now run 100% in inference mode).

以下、2.1.3より前のKerasについての情報です

---

Kerasで特定の層の重みを学習させないようにする場合は

```py3
layer.trainable = False 
```

としますが、BatchNormalization層は移動平均の更新は続くため、完全には固定されません。

バージョンは以下の通り
Python 3.5.2
Keras 2.0.8
tensorflow-gpu 1.3.0

#最も単純な構造で実験

```py3
from keras.models import Sequential
from keras.layers import InputLayer, Dense
model = Sequential([InputLayer(input_shape=(1,)), Dense(1, use_bias=False)])
```

入力・出力ともに値1つです。biasも使用しないので、式で表すと

```math
出力=入力\times x
```

となります。(これはニューラルネットワークと呼べるのだろうか)
このモデルをベースとします。

まず`model.trainable = False`によってモデル全体を固定し学習を止め、
そのまま入力=理想出力=1として学習ループを回して出力値の変化の有無を見てみました。

```py3
import numpy as np
from keras.models import Model, Sequential
from keras.layers import Input, InputLayer, Dense, BatchNormalization

def test(model):
  ones = np.ones((1, 1))
  model.trainable = False
  model.compile(loss='mse', optimizer='sgd')
  model.summary()
  #
  output = model.predict(ones)
  for i in range(5):
    model.train_on_batch(ones, ones)
    print(i+1, ':', np.linalg.norm(model.predict(ones) - output))
```

#BNなし

```py3
test(Sequential([InputLayer(input_shape=(1,)), Dense(1, use_bias=False)]))
```

```
Total params: 1
Trainable params: 0
Non-trainable params: 1
_________________________________________________________________
1 : 0.0
2 : 0.0
3 : 0.0
4 : 0.0
5 : 0.0
```
パラメータは1つあり、`trainable=False` によって Non-trainable です。
出力値は変化しませんでした。

#BNあり

```py3
test(Sequential([InputLayer(input_shape=(1,)), Dense(1, use_bias=False), BatchNormalization()]))
```

```
Total params: 5
Trainable params: 0
Non-trainable params: 5
_________________________________________________________________
1 : 0.00632572
2 : 0.0126196
3 : 0.018882
4 : 0.0251131
5 : 0.0313128
```
パラメータは5つあり、全てNon-trainableです。
しかし、出力値の変化が確認できました。

#なぜ？
これは意図された挙動で、`fit`や`train_on_batch`などで学習を行うとき、
`trainable=False`の層は逆伝播の重みの更新は停止されるものの、順伝播時の平均・分散の更新は続くために出力値が変化する
ということのようです。
`predict`や`test_on_batch`など学習を行わない順伝播であれば出力値の変化は起こりません。
https://github.com/fchollet/keras/issues/4762#issuecomment-299606870

モデルの出力側に重みを固定した内部モデルを接続し入力側へbackpropする場合はこの仕様を考慮する必要があります。
完全にBN層を固定するには、上のリンクではFunctional APIを使用して、`training=False`とする方法が推奨されています。

```py3
input = Input((1,))
x = Dense(1, use_bias=False)(input)
x = BatchNormalization()(x, training=False)
model = Model(input, x)
```
```py3
test(model)
```
```
Total params: 5
Trainable params: 0
Non-trainable params: 5
_________________________________________________________________
1 : 0.0
2 : 0.0
3 : 0.0
4 : 0.0
5 : 0.0
```
出力値の変化が起きていないことが確認できました。
EV3RTと（リンカスクリプトの）メモ [sh_link not set for section `.ARM.exidx']

#sh_link not set for section `.ARM.exidx' が出たのでそれについて調べたことをメモメモ

##!初投稿なのでご容赦!
（自分toppersにも低レイヤにも全く精通しておりません）

今回EV3のTOPPERSカーネル環境で使うCファイルのビルド時に発生（未解決？）
（恐らくプログラム実行に支障が出るわけでは
ないので対策する実益はあまりないようです）
環境はmacoOS Sierra/High Sierra, ev3rt-beta7-release
##追記:
printfを使用し、改行文字（\n）を用いない時には発生しない模様
（\nを用いるとエラー発生）
ちなみに\rでは発生しませんでした


---
調べたらsh_linkが".text"セクションを指定していないために起こるエラーのようです
リンカスクリプトの修正でいいということだそうで
->リンカスクリプトって何？
となったのでメモ（しかし現実はそんなに甘くはなかった）
#やってみたこと
EV3RTにおけるリンカスクリプトの拡張子は.ldらしい
ということなので

```
  _exidx_start = . ;
    .ARM.exidx ALIGN(4) :
    {
		*(.ARM.exidx* .gnu.linkonce.armexidx.* )
    }
	_exidx_end = . ;
```
とam1808.ldとcfg1_out.ld に追加しましたが挙動に変化はありませんでした

https://www.toppers.jp/docs/tech/macproc-spec-20100723.pdf
.tfファイルを追記しようか思案中

ニッチな分野ながら徐々に追記していく予定です
#参考中:
http://blog.kmckk.com/archives/4950141.html
http://nemuisan.blog.bai.ne.jp/?eid=155799
http://www.kumikomi.net/archives/2010/08/post_28.
http://kozos.jp/documents/linker_kernelvm5.pdf
http://hijiri3.s65.xrea.com/sorekore/develop/h8/00_aki-h8-usb.htm
http://d.hatena.ne.jp/sodex/20070407
https://ameblo.jp/osstudy/entry-10747755001.html
属人化を避ける

このQiitaは、マサカリや編集リクエスト歓迎です

# 属人化って？
「○○さんがいないとプロジェクトが進まない！」という状況

例えば…

- ある手続きについて、マニュアルがない、仕様書もない
- マニュアルなしで操作できるのが○○さん一人

より強い表現をすれば、○○さんが任意にプロジェクトの進行を止められる状態

# 用語
|用語|説明|
|---|---|
|プロジェクト|チーム全体で進めるもの|
|タスク|個人またはチームの一部で進めるもの|
|モジュール|プロジェクトの断片で、タスクは基本的にモジュールを作る|

# 属人化の理由
## 個人の問題
- 手抜きやバグを隠す  
たとえば、仕様書外の動作を実装し、それをプロジェクトで利用する
- 解雇されないための保険的行動

## チームの問題
- マニュアルを作る文化の欠如
- 他人のタスクに対する無関心
- 他人の監査なしにプロジェクトを更新可能

# どうやって属人化を避けるのか
## 間違った対策
- ○○さん以外にもマニュアルなしで操作できる人間を育成
 - 育成した人が全滅すればやっぱり同じ状況
 - 全員がすべてのプロジェクトに精通するとかはムリ

## 正しい対策
- モジュールごとに仕様書を用意
- 間違って使うことが難しい仕様とする
  - 即ち、仕様書を読まなくてもある程度正確に使える
- お互いにコードレビューさせる

## 具体的にはどうすれば良い？
### テスト・仕様書・利用例
- テストは仕様書のベースとなる
- 仕様書を見れば、深い動作がわかるようになる
- 仕様書を読まなくても、利用例を見れば使える

### 全員がテストできる環境を作る
- 前提条件の少ないテスト
  - たとえば、「テストしようと思ったら、DBが初期化されてなくてテストできなかった！」を避ける
  - この時、「データベースくらい自分で初期化しろ！」ではなく、テスト内で自動的にDBやテーブルを生成させるようにする
  - 一般に、テストは単体テストであるように作ること(依存性や、環境の前提条件が可能な限り少ない) (2017/10/23追記)

　

- モジュール化
  - モジュール単位でリポジトリが存在し、モジュール単位でテストが可能
  - プロジェクトの`Issue`や`Pull Requests`が混雑しなくなる
  - 気楽に問題を報告できるし、問題の原因がどこにあるかを特定しやすい

### 相互にチェックしあう体制
- コードレビューのルーチンワーク化
  - あるモジュールをレビューする人が複数存在する環境
- プロジェクトやモジュールの`master`ブランチへのアクセス権を限定し、マージの際に品質チェックが入るようにする
- このタイミングで、仕様書外の動作を弾くことができる (2017/10/23追記)

# やってはいけないこと
- 仕様書やマニュアルの**確定**
  - これらもしっかりとVCSで管理し、問題点を共有
  - コロコロ変わる仕様書はダメだが、全く変わらない仕様書は負の遺産を生みだす
  - 仕様書も、悪いと思ったら悪いといえるようにしよう

　

- 仕様書が大量に存在 (読むのが大変)
  - 間違って使うことが難しいようにする
  - モジュール間でインターフェースを統一
  - 利用例を充実させる

　

- プロを使わない
  - すなわち、「**質問するな、調べろ**」が徹底されてしまうのはよくない
  - 属人化の排除を行う目的は、「**誰でも、ある程度の短時間で理解ができる**」状況を作ること
  - ある程度調べて分からなければ、やはりその道のプロに聞くべき


# こっちも読んでね
[続・属人化を避ける](https://qiita.com/4kizuki/items/3b60443ccd473d192c21)
機械学習論文読みメモ_100


[The One Hundred Layers Tiramisu Fully Convolutional DenseNets for Semantic Segmentation](https://arxiv.org/abs/1611.09326), CVPR2017
従来のsemantic segmentationモデルはCNNをベースにして作られてきた．
その場合、convolutionを通した粗い特徴抽出と、その後に続くupsamlingに
よる解像度向上によってネットワークは成り立っていた．
またconditional random fieldなどを用いた後処理なども用いた改善も行われる場合がある．
一方で，最近提案されたCNNの一つであるDenseNetは各層が全てfeed forward接続を通して繋がっており，
それにより性能向上が確認出来ている．
本論ではこのDenseNetのアイデアをsegmentationへ適用する事で性能向上可能な事を示した．

[Overcoming catastrophic forgetting in neural networks](https://arxiv.org/abs/1612.00796)
逐次的な様々な学習を積み重ねていく能力は，汎用AIの作成において重要である．
しかしながらニューラルネットワークを始めとするconnectionistモデルは新たな学習によって
過去の学習が上書きされてしまう事のよる忘却が発生してしまう問題があった．
本論ではその問題に対して，過去の学習において重要な役割を果たしている部分に対する
学習速度を低下させる事で，忘却を抑制する事を可能にした

[FCNs in the wild:pixel-level adversarial and constraint-based adaptation](https://arxiv.org/abs/1612.02649)
Semantic segmentationモデルとして知られるFCNを用いたdomain adaptationを考える．
Domain adaptationは従来adversarial learningの設定で提案されている．
つまり，sourceとdomainの分類器を騙せるように特徴空間を学習させる正則化を加える．
本論ではこれをsemantic segmentationの文脈に合うよう改良した．
つまり，semanticsに関する空間的特徴を良く含んでいる，upsample前の
最終レイヤーの特徴を用いる事ととなる．
また加えてクラスごとのadaptationも考え，source domainにおけるクラスごとに占めるピクセルの割合を
制約としてtarget domainに対して適用する。
Pleasanterの導入環境を整える:Bluemix IaaS版

# Bluemix Infrastructure（Bluemix IaaS)でオーダーしたWindows Server 2016 環境の日本語化

シンプルに言いますと、オーダーしたサーバーが生成された直後は英語版になっていますので、コントロールパネルの「Add a language」から日本語のLanguage Packを追加できないため、"[ShinobiLayer: Window2012で直接多言語パッケージをダウンロードして日本語化する方法](https://qiita.com/testnin2/items/676b6e78075fb835d00c)"を参考に、レジストリエディタを起動しレジストリ変数をいじるやり方で、一時的にWSUSを無効化、サーバー再起動後に、日本語のLanguage Pack を追加し、再びWSUSの値を元に戻します。

今回は、CPU コア× 2 , メモリ 4GB でWindows Server 2016の仮想サーバーをオーダーしました。

## UseWUServerの値を変更
レジストリエディタを起動
![6b.PNG](https://qiita-image-store.s3.amazonaws.com/0/41414/84ec0621-2ee6-7ce0-1a64-a5c0c45f8411.png)

HKEY_LOCAL_MACHINE → SOFTWARE → Policies → Windows → Windows Update → AU にあるUseWUServerの値を1から0に変更し、サーバーを再起動します。
![7b.PNG](https://qiita-image-store.s3.amazonaws.com/0/41414/d60b8f25-5159-d445-d4cc-a27ea353adf0.png)

## 日本語 Language Packの追加
サーバー再起動後、スタートメニュー → Control Panel → Add a language をクリックし、日本語を追加します。
![9.PNG](https://qiita-image-store.s3.amazonaws.com/0/41414/9a19ebd0-286e-45e6-453d-2f4fd83d44d8.png)

次に"language pack"をインストールします。Download and install language pack をクリックします。
インストール後はサーバーを再起動し、先ほどのUseWUServerの値を1に戻します。
![10.PNG](https://qiita-image-store.s3.amazonaws.com/0/41414/717e71dd-8177-759a-2d97-81e177f8659f.png)

# Pleasanterの前提となるソフトウェアを整える
GithubのPleasanterマニュアル "[プリザンターをWindows Server 2012 R2にインストールする](https://github.com/Implem/Implem.Pleasanter/wiki/%E3%83%97%E3%83%AA%E3%82%B6%E3%83%B3%E3%82%BF%E3%83%BC%E3%82%92Windows-Server-2012-R2%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B)"に従ってすすめます。Windows Server 2016 の場合でも手順は同じです。

## IISのインストール
Windows Serverにリモートデスクトップで接続します。Windows Server 2016のためIISのインストール時にASP.NET 4.6になっており、マニュアルと若干異なりますので、説明します。

1. サーバーマネージャー → 管理 → 役割と機能の追加 をクリック。
2. "開始する前に画面"で次へをクリック → "役割ベースまたは機能ベースのインストール"を選択 → 次へをクリック → "サーバープールからサーバーを選択"が選択されていることを確認し、次へをクリック。
3. "サーバーの役割"画面で、Web Server(IIS)にチェックを入れます。管理ツールを含める"とともに機能の追加"をクリックし、次へをクリックします。
4. "機能"の選択画面では、既に.NET Framework 3.5 Featuresと.NET Framework 4.6 Features が選択されていますので、そのままにして、次へをクリックします。
5. "Webサーバーの役割(IIS)"画面が表示されますので、次へをクリックします。
6. "役割サービス"画面がで、Application Development → ASP .NET 4.6 にチェックを入れます。管理ツールを含める"とともに機能の追加"をクリックし、次へをクリックします。
7. "インストールオプションの確認"画面で、インストールをクリックします。完了後、閉じるをクリックします。

SQL Server 2016 Express with Advanced Services、SQL Server Management Studio、Web Deploy v3.5 は、前述のマニュアルに従ってインストールします。

# Pleasanterのインストール
GithubのPleasanterマニュアル "[プリザンターをWindows Server 2012 R2にインストールする](https://github.com/Implem/Implem.Pleasanter/wiki/%E3%83%97%E3%83%AA%E3%82%B6%E3%83%B3%E3%82%BF%E3%83%BC%E3%82%92Windows-Server-2012-R2%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B)"に従ってすすめます。

# Pleasanterによるアプリ開発
[顧客別ToDo管理の作成](https://qiita.com/kolinz/items/c37807b728a96ca855f6)をご覧ください。
機械学習論文読みメモ_99


[Universal Adversarial Perturbations Against Semantic Image Segmentation](https://arxiv.org/abs/1704.05712)
Deep learningモデルはadversarial perturbationに弱い事が知られている．
このperturbationは人にはほぼ違いが分からないようなノイズを加えて，
deep learningモデルの推論結果を大きく変える事を示す．
さらには，入力に依存しない幅広く適用可能なuniversal perturbationが
存在する事も分かっている．
従来研究は画像分類においてこうした問題を研究してきたが，
本論ではsemantic segmentationに対する適用を考える．
本論では望んだ出力をモデルに出させるようなuniversal perturbationの
generatorを提案する．
結果，人間の目にはほぼ分からないようなノイズを加える事で，
どのような入力に対しても同じ一定の出力を出させる事に成功した．

[Full-Resolution Residual Networks for Semantic Segmentation in Street Scenes](https://arxiv.org/abs/1611.08323)
Semantic segmentationは従来分類問題向けに設計されたCNNをベースにして設計されてきた．
しかしそうしたモデルは物体の場所を特定する事には特化しておらず問題であった．
本論ではそうした問題に対して，resnetライクな２つのパスを持つようなネットワークモデルを
提案する．
１つ目のパスは，フル解像度の情報を保持するようにする事で，クラス毎の境界を高精度に認識出来るようにする．
もう一つのパスでは，プーリングの処理を行っていく事で，ロバストな物体認識を可能にする．
この２つのパスはそれぞれの層においてresidual networkの構造として繋ぐ事で情報がやり取り可能である．

[Semantic Segmentation using Adversarial Networks](https://arxiv.org/abs/1611.08408)
Semantic segmentationの予測結果を見ると，予測ミスによって現実的にありえないような位置関係を持ったセグメントが得られる事が多い（例えば空に車があるなど）．
そこで，通常のセグメント損失に加えて予測結果と真の値の間で，それがどちらであるか判別するモデルを騙すようにする敵対的損失と組み合わせる事で，現実的にありえないような予測ミスを軽減可能にした
AnsibleのPlaybookのテストにDockerのコンテナを利用した話

今更感ありますが、Ansible触る機会があったので触って見ました。


## 開発環境について

```sh
$ docker -v
$ Docker version 17.06.0-ce, build 02c1d87

$ docker-machine -v
$ docker-machine version 0.12.0, build 45c69ad

$ ansible --version
$ ansible 2.4.0.0
```

## なぜAnsible?
プロダクションのデプロイに対して、Docker環境構築するのはちょっと重い(予算的にも規模的にも)ことはまぁあると思います。
ただ、development, staging, production とミドルウェアの環境構築はコードで管理したい。  
そこでの最適解が、現状Ansibleかなと考えます。

## なぜDocker Container?
色々見ていると古い情報が多いっていうのもありますが、Ansible PlaybookのテストはVagrantでVirtualbox立てるのがいいですと書いてあるところが多かったです。
まぁそこはしかし、Virtualboxのダウンロードがめちゃくちゃ時間かかります。
これ、今回CentOS7のPlaybookだけれど、次回CentOS6だったら？Ubuntu環境,Windows環境だったら？と考えると絶望的な気分になりました。  
そこでDocker Containerですよね。

## 実際にやってみた  
### Ansible構成  
CentOS: 7
Apache: latest
MySQL: 5.7
PHP: 7.1
redis: latest
git: latest

### 調査
早速調査したところ、感謝すべき先人達がたくさんいますね。
特に参考になったのは、GMOのAdachiさんが書いてくださった[こちら](http://techblog.gmo-ap.jp/2016/09/23/docker%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92ansible%E3%81%A7%E3%83%97%E3%83%AD%E3%83%93%E3%82%B8%E3%83%A7%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%97%E3%81%9F/)の記事です。
この記事通りやれば、問題なく立ち上がると思います。
私の場合は、先にコンテナを立ち上げていて、その立ち上げ方に問題がありいくらか時間を使ってしまいました。
以下にログとして残しておきます。

### service httpdがdocker containerで動かない
導入検証時、centos:7 コンテナを普通に
```sh
$ docker run --name testcontainer -it -d centos:7 
```
として立ち上げていたのですが、この立ち上げ方に問題がありました。
[こちら](https://qiita.com/yunano/items/9637ee21a71eba197345)の記事に詳しいのですが、centos7ではsystemctlがデフォルトで効かない都合上、httpdをserviceから起動させる箇所で
```sh
$ fatal: [testcontainer]: FAILED! => {"changed": false, "failed": true, "msg": "Could not find the requested service httpd: host"}
```
と言われ続けました。
```sh
$ docker run --name testcontainer --privileged -d centos:7 /sbin/init
```
と、特権モードでコンテナを作成して/sbin/initで起動しておくことで解決できます。
Docker Containerのplaybook動作確認時、service絡みで同様にエラーを吐く場合は、もしかしたらcontainerの起動方法で解決できるかもしれないです。

今回の[成果物の簡易版を置いておく](https://github.com/itaoyuta/ansiblewithdockersample)ので、よかったら参考にしてみてください。

## 改めてVirtualBoxとの比較
Playbook検証環境の用意、実は最初Virtualboxダウンロードをしようとしていたのですが  
**VirtualBoxのダウンロード60分くらいに対してDockerのimage pull30秒くらい**  
で終わりました(笑)
また、Playbookの設定ミスってOSのクリーンインストールからやり直したいって場合も、vagrant destoryからvagrant upと比較して、コンテナの再作成も相当差があるのではないでしょうか。  
せっかくDocker環境があるなら、手軽に再作成できるのでPlaybookの検証環境に最適かと思っています。
PostgreSQL10.0ロジカルレプリケーションが失敗するケースその1

**ロジカルレプリケーションの対象に巨大なカラムがあると、Publisher側でメモリの確保に失敗して、レプリケーションを継続できない。**

※この制約を確認したのはバージョン10.0。以降のバージョンでは解決済の可能性がある。

以下、ロジカルレプリケーション対象のテーブルに、600MBのBYTEAカラムを挿入して、レプリケーションが失敗するのを確認する。

## PublisherとSubscriberのPostgreSQLの起動
```bash
## Publisher側のPostgreSQLの起動
$ initdb -D pub
$ echo "wal_level = logical" >> pub/postgresql.conf 
$ echo "log_line_prefix = '%t pub [%p] '" >> pub/postgresql.conf 
$ pg_ctl -D pub start

## Subscriber側のPostgreSQLの起動
$ initdb -D sub
$ echo "port = 5433" >> sub/postgresql.conf 
$ echo "log_line_prefix = '%t sub [%p] '" >> sub/postgresql.conf 
$ pg_ctl -D sub start
```

## Publisher側でテーブルとPublicationの作成
``` bash
## Publisher側のPostgreSQLに接続
$ psql
```

```plpgsql
-- テーブルと、そのテーブルを対象とするPublicationの作成
CREATE TABLE test (key bigserial primary key, val bytea);
ALTER TABLE test REPLICA IDENTITY DEFAULT;
CREATE PUBLICATION mypub FOR TABLE test;
```

## Subscriber側でテーブルとSubscriptionの作成
```bash
## Subscriber側のPostgreSQLに接続
$ psql -p 5433
```

```plpgsql
-- テーブルと、そのテーブルへの変更を受け取るSubscriptionの作成
CREATE TABLE test (key bigint primary key, val bytea);
CREATE SUBSCRIPTION mysub CONNECTION '' PUBLICATION mypub;
```

## 600MBのバイナリデータのテーブル挿入
```bash
## 600MBのランダムバイナリデータをPublisherのDBクラスタ直下に作成
$ dd if=/dev/random of=pub/600MB bs=1048576 count=600

## Publisher側のPostgreSQLに接続
$ psql
```

```plpgsql
-- 600MBバイナリデータの挿入
INSERT INTO test (val) VALUES (pg_read_binary_file('600MB'));
```

Publisher側でのメモリ確保エラーと、それによるロジカルレプリケーション失敗のエラーメッセージ。

```
2017-10-21 02:54:24 JST pub [79878] ERROR:  invalid memory alloc request size 1258291203
2017-10-21 02:54:24 JST pub [79878] CONTEXT:  slot "mysub", output plugin "pgoutput", in the change callback, associated LSN 0/29837808
2017-10-21 02:54:24 JST sub [79877] ERROR:  could not receive data from WAL stream: ERROR:  invalid memory alloc request size 1258291203
	CONTEXT:  slot "mysub", output plugin "pgoutput", in the change callback, associated LSN 0/29837808
2017-10-21 02:54:24 JST sub [79830] LOG:  worker process: logical replication worker for subscription 16392 (PID 79877) exited with exit code 1
```
python3のvenvで作った環境でインストールしたjupyterが呼ばれない

#### venvで作った環境でpip installしたjupyterlabが何故か動かなかったのでメモ
`JupyterLab assets not detected in ~`
って言うエラーが出た.
これは/usr/local/binにjupyterを呼びに行って, これは/usr/local/binにjupyterは入っているけどjupyterlabが入っていなくてjupyterlabがないよって言われてただけでした.


```
$ which jupyter
```
したら/usr/local/binを呼びに行ってました.
LinuxでVPN Gate（闇の力）をもっと簡単に使おう

以前の記事 [VPN Gate(VPN over https)とかいう闇の力でVPNを使おう on Linux](https://qiita.com/onokatio/items/aa656c23e24d721eed31) でVPN GateにLinuxから接続する方法を書きましたが、それさえもめんどくさいので自動化するためにsystemd serviceとシェルスクリプトを書きました。

# 事前にやること

事前に、[VPN Gate(VPN over https)とかいう闇の力でVPNを使おう on Linux](https://qiita.com/onokatio/items/aa656c23e24d721eed31)の「ソースコードのダウンロード」と「ビルド」に従ってvpn clientのインストールを済ませておいてください。

# ダウンロード

https://github.com/onokatio/vpngate-utils

git cloneなりzipダウンロードなりで任意の場所にダウンロードしてください。

# 使い方

README.mdにも書いていますが、以下の手順を追ってください。

### systemd用のserviceファイルをコピーしてリロードしてください。

```bash
$ sudo cp ./vpngate-client.service /etc/systemd/system/vpngate-client.service
$ sudo systemctl daemon-reload
```

### VPN Gate Clientのサービスを起動してください。

```bash
$ sudo systemctl start vpngate-client.service
$ sudo systemctl enable vpngate-client.service
```

### 最後に、設定用のシェルスクを実行し、パスワードを入力してください。

```bash
$ sudo ./setup-client.sh -s vpngate-server.com:443 -b VPN -u user1

パスワード : ********
確認入力　 : ********
```

このシェルスクの使い方は以下のようになっています。

```bash:help
Usage: setup-client.sh [-h] [-s <server:port>] [-b <HUB>] [-u <USERNAME>] [-f]

  -h                このヘルプを表示
  -s <server:port>  VPNサーバーのアドレスとポートを指定
  -b <hub>          VPNのハブの名前を指定（大体の場合は'VPN'）
  -u <username>     VPNのユーザー名
  -f                既にVPNの設定があっても、それを削除して強制的に再登録する。
```

これで完了です。
ちょっとずつ読むドメイン駆動設計 第ニ部 モデル駆動設計の構成要素 第七章 言語を使用する:応用例2

[前回](https://qiita.com/YasuhiroKimesawa/items/c138a5eee50da59cdfd8)の続き

## [関連](https://qiita.com/YasuhiroKimesawa/items/71eab6a497599eaa38fa)を設計

問題は双方向の関連。

検索なんかで関連づけられているだけならRDBのクエリで実現すればよいので、関連は不要。

ビジネスをしっかり理解すれば減らせる関連もありそう。ビジネス上必要ないのに関連付けられているならば削除する。

あとは、循環参照になっている場合が問題。
例では、
[貨物]->[配送記録]->[荷役イベント]->[貨物]
という参照パターン。

解決策としては[配送記録]<>->[荷役イベント]と、配送記録に荷役イベントを含んだリストを与えることで循環参照はそのままだが、実装上問題ないようにしているようです。(これで問題起きないんだっけ？っていう疑問は残りますが・・・)

そして、将来的には、貨物をキーにデータベースを検索するようにするかもしれないとは言っています。
最初からそうしない理由は、記録を問い合わせることが多いとみられるから直接参照しているほうがよいということ。記録への問い合わせが稀であれば、データベースへの検索の方にしたほうが、オーバーヘッドは減るでしょう。
そこは設計におけるトレードオフということですね。

## [集約](https://qiita.com/YasuhiroKimesawa/items/1fdadb042d3b10265fd7)の境界

独自の同一性があるものをルートに選択しています。
そのルート(例では[貨物])からどこまでを境界にするかが検討されていますね。
基準としては、値オブジェクトはもちろん境界内、エンティティでも独自の同一性がない、グローバルにアクセスされないものは境界内に設定していますね。

明日も引き続き読んでいきます。
Where is iproute2 ?? （最新 iproute2 はどこ？）

(2019/01/13) Download Site 更新

最新の iproute2 が必要なのに「どこにあったっけ？」と言って見つからないというのは良くある事かと思います。（最新 Kernel では対応してる Segment Routing IPv6 (SRv6) 設定したい！！ とか）

例えば以下サイトは違います。

* https://github.com/shemminger/iproute2

というわけで download 場所と build/install 方法のメモ。

* download サイト
    * tarball: https://www.kernel.org/pub/linux/utils/net/iproute2/
    * 通常こちら：git://git.kernel.org/pub/scm/network/iproute2/iproute2.git
    * net-next patch: git://git.kernel.org/pub/scm/network/iproute2/iproute2-next.git

* (2019/01/13) アクセス不可
    * git: https://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
    * git: https://kernel.googlesource.com/pub/scm/linux/kernel/git/shemminger/iproute2/

今回は tarball をダウンロードした際の手順を記載。
（2017/10/21 時点での最新：iproute2-4.13.0.tar.gz を利用）

* そのまま make すると（不要な）arpd ビルドしようとしてうまくビルドできないので、以下サイトに従って前処理。
    * [How to build iproute2 from source](http://www.linuxfromscratch.org/lfs/view/development/chapter06/iproute2.html)
* 念のため上書きしないように DOCDIR を指定。
* `apt instal ...` は上記サイトには記載ないけど、無いと `make` でエラーになるので記載。

```
sed -i /ARPD/d Makefile
sed -i 's/arpd.8//' man/man8/Makefile
rm -v doc/arpd.sgml
sed -i 's/m_ipt.o//' tc/Makefile

sudo apt install bison flex

make
sudo make DOCDIR=/usr/share/doc/iproute2-4.13.0 install
```

以上
CSSOMとパフォーマンス

# はじめに
Webのパフォーマンスチューニングについて調べていたりすると、ちょくちょく見かける**CSSOM**という言葉。DOMのCSSバージョンなんだろうなぁと何となく理解したつもりになっていましたが、ふと気になって改めて調べなおしてみました。この記事ではCSSOMについての説明、そして、それに関連するパフォーマンスについてまとめてみます。

# CSSOMとは
CSSOMは、**CSS Object Model**を意味する略語であり、ブラウザでロードされたCSSのツリー構造を保持する仕組みです。例えば、`body`にはこのスタイル、`body`の下にある`div`には別のスタイル、というようなイメージですね。ブラウザは、このCSSのツリー構造をDOMに対して適用することで、上位のスタイルからより具体的な下位のスタイルへと連鎖的にスタイルを決定していきます。このようにして処理されたものはレンダリングツリーと呼ばれ、これに基いてレイアウトの計算処理と描画処理が行われます。

# パフォーマンスにどう関係するの？
CSSOMがどのようにウェブのパフォーマンスへと影響を与えるのでしょうか。それは、[CSSOMの構築はウェブページのレンダリングをブロックする](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css?hl=ja)という点です。言い換えると、CSSOMが構築されるまではウェブページには何も表示されず、ユーザの目にはただただ白い画面だけが映し出されます。そのため、CSSOMの構築に要する時間がUXへと影響を及ぼします。(より正確にはDOMとJavaScriptも含めてクリティカルレンダリングパスと呼び、コンテンツが描画されるまでに時間に影響します)

また、CSSOMはキャッシュという仕組みを持ちません。そのためCSSファイルをブラウザがキャッシュしていたとしても、リロードや別ページへの遷移が発生する度にCSSOMは再構築されることになります。なので、いくらキャッシュしていたとしても、巨大なCSSはCSSOMの構築に毎回時間をかけることになります。

# CSSOMの処理を最適化するには？
CSSOMの処理パフォーマンスを上げるためには、以下のような方法が取られます。

## 複数のCSSファイルを1つのファイルにまとめる
CSSファイルが複数に分割されている場合、ブラウザは(HTTP/2でない限り)それぞれのファイルをダウンロードしなければいけません。そこでCSSファイルの内容をバンドラなどを使用して事前にまとめておけば、ダウンロードに要する時間を短縮することができます。

## 他のCSSファイルをインポートしない
CSSファイルをインポートすることは、パフォーマンスの低下につながります。以下のCSSを見てみましょう。

```css
@import url("another-style.css")
```

この例では、CSSファイル内で`@import`を使用することにより他のCSSを取り込んでいますが、ファイルをダウンロードするためのリクエストが別途発生してしまい、レンダリングをブロックしてしまいます。そのため、`@import`を使用せず、上記と同じようにファイルをまとめておくのがベターです。

## mediaを使用して必要な場合だけファイルを取得する
CSSの中には、モバイル機器にしか使われないスタイル定義、印刷時にしか使わないスタイル定義のように、特定の状況下のみで使用されるものがあります。そのようなケースで使用できるのが、`<link>`要素の[`media`](https://www.w3schools.com/tags/att_link_media.asp)です。以下の例を見てみましょう。（[Web Fundamentals](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css)より引用）

```html
<link href="style.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">
```

この例では、`style.css`に基本的なスタイル定義がしてあり、`print.css`と`other.css`には、特定の状況下でページを閲覧している場合のためのスタイル定義が含まれています。それぞれの`media`で指定した条件を満たさない場合はレンダリングをブロックしないため、パフォーマンスを向上させることができます。


# 最後に
この記事ではCSSに焦点を当てて記述しましたが、パフォーマンス改善、つまりクリティカルレンダリングパスの短縮にはHTMLとJavaScriptを含めて総合的に判断する必要があります。

また、現状のサイトのパフォーマンスを簡易的に測定するには、以下のサービスやツールが役に立ちます。
- [PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)
- [Chrome Developer ToolsのAudits](https://developers.google.com/web/updates/2017/05/devtools-release-notes#lighthouse)

# 参考
- [Render Blocking CSS  |  Web Fundamentals  |  Google Developers](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css)
- [Constructing the Object Model  |  Web Fundamentals  |  Google Developers](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model?hl=en#document-object-model-dom)
- [What is CSSOM? | Performance glossary](https://varvy.com/performance/cssom.html)
- [How to optimize CSS delivery](https://varvy.com/pagespeed/optimize-css-delivery.html)
MySQLでLaravel標準のSoftDeletesを使った論理削除とユニーク制約を両立させる方法

# スキーマの最適化

## Before

```php
Schema::create('users', function (BluePrint $table) {
    $table->bigIncrements();
    $table->string('screen_name')->index(); // ←論理削除があるので ->unique() にはできない
    $table->softDeletes();
});
```

## After

MySQL5.7から使える**生成カラム**と，**ユニーク制約がNULLには適用されない**ことを利用します。**アプリケーション側のコードには，一切手を加える必要がありません。**

```php
Schema::create('users', function (BluePrint $table) {
    $table->bigIncrements();
    $table->string('screen_name');
    $table->softDeletes();

    // 論理削除されていれば NULL， されていなければ 1 になる生成カラムを定義
    $table->boolean('existence')->nullable()->storedAs('CASE WHEN deleted_at IS NULL THEN 1 ELSE NULL END');

    // screen_name と existence に対して複合ユニークインデックスを張る
    // （カーディナリティの低い existence を後ろに持ってくるべき）
    $table->unique(['screen_name', 'existence']);
});
```

カラムの命名に迷いますが， `exists` だと `1` か `0` を取りそうな雰囲気があるので，存在そのものを表す名詞形にして `1` か `NULL` っぽさを出すようにしてみました。 

# SELECTするSQLの最適化

## Before

```php
User::whereScreenName('mpyw')->first()
```

これだと

```sql
WHERE screen_name = 'mpyw' AND deleted_at IS NOT NULL
```

という条件がつくので，せっかく貼ったユニークインデックスがフルに利用されません。

## After



```php
User::whereScreenName('mpyw')->withTrashed()->whereExistence(true);
```

こっちなら

```sql
WHERE screen_name = 'mpyw' AND existence = 1
```

となり，理論上は最速のクエリになります。

# 参考資料

- **[論理削除と一意性制約を両立させる方法・DB製品別 - Qiita](https://qiita.com/yuba/items/70165875cfe02b03513d)** ←特に参考になった
- [MySQL 5.7で生成カラムを使ってCHECK制約もどきを実装する - Qiita](https://qiita.com/hmatsu47/items/ddf0fc74f2dc3bb7556f)
RailsプロジェクトをCircleCIで自動デプロイしCOVERALLSに連携してgithubにバッジをつける


タイトルがなんかくどい・・・やることは以下です

* githubにpushすると自動でCIでデプロイする
* テストしたカバレッジ結果をCOVERALLSに連携する
* COVERALLSで生成されたバッジをgithubのREADMEにつける

前提は以下

* githubアカウントを持っている
* CircleCIアカウントを持っている（githubがあれば簡単に作れる）
* COVERALLS（こちらもgithubがあれば簡単に作れる）

## CircleCIで対象のプロジェクトを選択する
1. PROJECTSより`Add Project`ボタンを押下する
![スクリーンショット 2017-10-20 22.24.05.png](https://qiita-image-store.s3.amazonaws.com/0/188887/fd5da669-904d-973c-bd45-7101f1b75963.png "スクリーンショット 2017-10-20 22.24.05.png")
1. 対象のプロジェクトの`SetUp project`を押下する
![スクリーンショット 2017-10-20 22.26.58.png](https://qiita-image-store.s3.amazonaws.com/0/188887/093ea7e6-476b-688e-ca85-4257d0b618a8.png "スクリーンショット 2017-10-20 22.26.58.png")
1. `Start building`ボタンを押下する
![スクリーンショット 2017-10-20 22.30.11.png](https://qiita-image-store.s3.amazonaws.com/0/188887/5f9e0cee-a34c-f02e-5112-b4ff47f1eb16.png "スクリーンショット 2017-10-20 22.30.11.png")
1. buildが行われる  
下の方にずらずらとログが表示されていきます。  
初回はテストエラーになるようにしてますのでエラーになりました。
![スクリーンショット 2017-10-20 22.48.39.png](https://qiita-image-store.s3.amazonaws.com/0/188887/c68dcb9b-3846-90a6-c6f3-2b4ed4408110.png "スクリーンショット 2017-10-20 22.48.39.png")
1. エラーを修正してpushしてみる
次は成功しました、前回エラーだったので`FIXED`と表示されています
![スクリーンショット 2017-10-20 23.00.51.png](https://qiita-image-store.s3.amazonaws.com/0/188887/cfb90cb6-005b-67ad-b7f7-4dc70029cc90.png "スクリーンショット 2017-10-20 23.00.51.png")

これでgithubにpushすると自動的にデプロイしてくれる状態になりました。

## COVERALLSに連携する
1. `ADD REPOS`より対象のリポジトリをONにする
![スクリーンショット 2017-10-20 23.08.25.png](https://qiita-image-store.s3.amazonaws.com/0/188887/ffa37b2e-213b-579c-fad2-31bd992af527.png "スクリーンショット 2017-10-20 23.08.25.png")
1. `DETAILS`ボタンを押下する
COVERALLSを利用するための手順が書かれているので内容を確認する。
1. トークンをCIに設定する  
 1. 2.で表示された中に`repo_token:`があるので値をコピーする
 1. CircleCIのPROJECTS > Settings > BUILD SETTINGS > Environment Variables を押下し、`Add Variable`ボタンを押下する
 1. `Add an Environment Variable`と表示されるので以下を各々入力する  
 Name：COVERALLS_REPO_TOKEN  
 Value：3-1. でコピーした値
1. gemを追加する
  
	```ruby:Gemfile
	gem 'coveralls', require: false
	```

1. `spec_helper.rb` か `test_helper.rb`の先頭に以下を追記する  

	```ruby
	require 'coveralls'
	Coveralls.wear!
	```
1. 4.、5.の内容をpushする
自動でCIのデプロイが走りますのでtestの箇所に`Coverage report sent to Coveralls.`とあればOK。
1. COVERALLSに遷移してみてカバレッジ情報が表示されて入ればOK
![スクリーンショット 2017-10-20 23.43.19.png](https://qiita-image-store.s3.amazonaws.com/0/188887/a5daf9ab-e69e-d7d2-2703-103780849116.png "スクリーンショット 2017-10-20 23.43.19.png")

## READMEにバッジをつける
1. カバレッジ結果画面の`EMBED`ボタンを押下する  
押下すると色々なフォーマットのコードが出てくるのでお好みのものをコピーする。
![スクリーンショット 2017-10-20 23.46.08.png](https://qiita-image-store.s3.amazonaws.com/0/188887/9bdf9892-1372-1eaa-2cc7-8e596e3599d6.png "スクリーンショット 2017-10-20 23.46.08.png")
2. コピーしたコードをREADMEに貼り付ける  
以下の表示がされて入ればOK。
![スクリーンショット 2017-10-20 23.50.18.png](https://qiita-image-store.s3.amazonaws.com/0/188887/2a0dbc1b-a6c7-041f-f915-c3a549637de7.png "スクリーンショット 2017-10-20 23.50.18.png")
[iOS] Twitter Kitでリソース見つからず落ちる時の対処

iOS 11, XCode 9.0,
Twitter Kit: 3.2.1

---追記
最新の3.3.0では、Manual Installでも、公式に書いてある通りのやり方で落ちずにうまく動くようになりました。

---追記

Manual Installで"TwitterKitResources.bundle resources file not found."で落ちる件、結論から書けば、cocoapodsを使えばうまく行った。

色々試行錯誤したがTwitter kitのManual Installはうちの環境では成功しなかった。自分のインストール方法が悪いのか原因不明なのですが、Manual Installで成功した方がいれば教えていただければありがたい。

以下の記事の対処は開発環境であれば動くのだけど、結局、iTunes Connectにアップロードが上手くいかない。（TwitterKitResources.bundleの署名がうまくいかずに図のメッセージのエラーとなる。）

<img width="729" alt="スクリーンショット 2017-11-03 11.05.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/138773/31ba3464-9cb5-060b-3721-161679f9f084.png">


---追記終わり

Twitter KitはCocoaPodsからと、マニュアルで入れられるが、今回はマニュアルインストールが前提で。

以下の通り、マニュアルでインストールする
https://dev.twitter.com/twitterkit/ios/installation

実行時に
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'TwitterKitResources.bundle resources file not found. Please re-install TwitterKit with CocoaPods to ensure it is properly set-up.'
で落ちた。

リソースがないんだなーと思い
TargetsからのBuild PhasesのCopy Bundle resourcesに
TwitterKitResources.bundle
TwitterShareExtensionUIResources.bundle
の２つを追加したら落ちずに動作した。
<img width="673" alt="スクリーンショット 2017-10-20 23.18.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/138773/8ea41695-e4dc-c893-7c8a-4e1f5d8b8100.png">
（そもそもTwitterKit.frameworkをEmbedded Binariesしてるのになんでそっちを参照してくれないのか）

動いたがマニュアルインストールについて何かお気付きの点があればお教えいただければ。
ChromebookのデュアルブートでGalliumOSが立ち上がらなくなった時の対処

何かの拍子に，起動画面の
`Booting from Hard Disk…`
から進まなくなった．
割と簡単に戻せたのでメモ．

#手順
マウントして更新しなおすというのが大きな流れ．

ChromeOSとして起動（起動画面で`Ctrl + D`）．　
ChromeOSで`Ctrl + Alt + T`を押しターミナル起動．
croshで`shell`と入力しbash起動．

```bash

sudo bash

mkdir /tmp/a

# 次のコマンドはChromebookのCPUによって変わる．
GALLIUMOS_ROOT=/dev/sda7       # Haswell, Broadwellの場合はこちら
GALLIUMOS_ROOT=/dev/mmcblk0p7  # Bay Trail, Braswell, Skylakeの場合はこちら

mount $GALLIUMOS_ROOT  /tmp/a
mount -o bind /proc    /tmp/a/proc
mount -o bind /dev     /tmp/a/dev
mount -o bind /dev/pts /tmp/a/dev/pts
mount -o bind /sys     /tmp/a/sys
mount -o bind /run     /tmp/a/run

chroot /tmp/a /bin/bash

dpkg-reconfigure grub-pc
# ここで出るダイアログはだいたいそのままでOK
# ただし適用対象を選ぶ場面で /dev/sda あるいは /dev/mmcblk0 のみ選ぶ．
# 選択はスペースキーで．

exit

reboot
```

起動画面で`Ctrl + L`すれば元通りになるはず．

#GalliumOS(Linux)はいい
とりあえずGalliumOS(+chrx)はいいぞ．
croutonはもっさりだし，効かないキーや操作もあったりと何とも．
本当はセキュリティ上devmodeなしが良かったけれど，ChromebookでもVSCodeが使えてしまうという利便性には勝てず（）
詳細はまた別の機会にでも．

#参考記事
https://www.reddit.com/r/GalliumOS/comments/5mhjd3/acer_14_wont_boot_after_grub_update/
ノンぷろぐらまーの経営者が全くの0からプログラミングを学んだら。

#全くの０から勉強する僕のスペック。
95年生まれの22歳。現在コーワーキング等の事業を運営する会社の代表。
プログラミングを学ぶ動機は
自分でワードプレスをイジってサイトのデザインを変更したいと思ったから。

学習環境
プロゲートでの学習がメイン。


このノートの主旨
僕と同じ学ぼうとしてもすぐに諦めてしまったり、時間を言い訳にして何もやらない人に見てもらいたい。

PHP

echo ←これがコマンドを呼び出すやつ

echo 'こんにちは'; しっかりと最後は;で締めること。。

【一日目】
一番悩んだこと。

$x=20
if ($x>60){
echo '$xは６０より大きい';
}

上のコマンドは本来表示されないものなのに、表示されてしまった。
色々と　調べた結果。

$x=20
if ($x>60);{    ←この間に;が入っていたことが判明。
echo '$xは６０より大きい';
}

それが原因で表示されてはいけないものが表示されてしまった。

-------------------------
Pythonの下位モジュールの扱い

聞かれたときに間違えて答えて恥しかったのでメモしておく。
事の発端はscipy.specialが参照できなかったという話。
つまりこういうことだった。

```py3
import scipy as sci

sci.special # AttributeError

import scipy.special
scipy.special # Not error
```

上のパターンでエラーが起きるとは思ってなかったので面喰らった。
調べてみた。

# 下位モジュール
Pythonではあるモジュールの内側に別のモジュールをネストさせられる。
いままで上位のモジュールをインポートしたら下位のモジュールも参照できるのが当然だと思っていたけどどうも違うらしい。
テストするために簡単なモジュールを作成した。

# テスト
こんな感じの構成になった。
使ったのはpython3.6.1。

```
test.py
test1/
    __init__.py
    test2/
        __init__.py
```

```py3:test.py
import test1

print(dir(test1))

# callable
test1.func_in_test1()

# not callable
try:
    test1.test2.func_in_test2()
except AttributeError as e:
    print("Error!")

import test1.test2
print(dir(test1))

# callable here
test1.test2.func_in_test2()
```

```py3:test1/__init__.py
def func_in_test1():
    print('test1')
    return
```

```py3:test2/__init__.py
def func_in_test2():
    print('test2')
    return
```

test.pyを動かしてテストしてみた、出力は以下のようになった。

```py3
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'func_in_test1']
test1
Error!
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'func_in_test1', 'test2']
test2
```

下位モジュールの関数を見れていないし、そもそも下位モジュール自体が名前空間(で合っているんだろうか？)に含まれていない。
下位のモジュールを使う場合には明示的にインポートしないといけないらしい。
おそらく、外部には公開しない内部向けのモジュールのためにそうなっているのだと思う。
ちなみに、`test1/__init.py__`内でインポートしたモジュールは問題なく参照できる。

知らんかった。
CircleCI2.0でDangerを使いPullRequestにAndroidLintをかけて学んだこと

# Dangerとは
http://danger.systems/ruby/

GitHub等のPullRequestをCI上から検査し、問題点をコメントするツール

## 例
* プルリクエストの内容が長すぎると注意をコメントしてくれる
* AndroidLintの結果をコメントしてくれる

参考: https://qiita.com/noboru_i/items/011fd5ef1808bea3d6ba

## 学び1: KotlinのAndroidLintはコマンドラインでは動かないのでDangerもコメントしない 

cf. https://developer.android.com/studio/preview/kotlin-issues.html 

```
Lint checks with Kotlin don't work from command line Lint checks on Kotlin files only work from the Android Studio IDE.
The currently do not run when you run lint directly from Gradle.
```

なので頑張ってセットアップしたのにxml系しかコメントしてくれない(辛)

### 追記
AndroidStudio3.1からコマンドラインからでも動くようになりそうです
https://developer.android.com/studio/preview/features/index.html

``` When you run lint from the command line, lint now also analyzes your Kotlin classes.
 ```


## 学び２: 複数のモジュールを管理している場合の設定方法

### 状況
以下のようなスタンダードな構成ではなく

```
(Project Root)
 |
 |--app
```

以下のように複数のモジュールを管理している状況

```
(Project Root)
 |
 |--app1
 |
 |--app2
 | 
 |--app3
```

### 問題点

DangerのAndroidLintプラグインが一つのlintレポートファイルしか参照しない
cf. https://github.com/loadsmart/danger-android_lint/blob/master/lib/android_lint/plugin.rb#L37 

```
    # Location of lint report file
    # If your Android lint task outputs to a different location, you can specify it here.
    # Defaults to "app/build/reports/lint/lint-result.xml".
    # @return [String]
    attr_accessor :report_file
    # A getter for `report_file`.
    # @return [String]
    def report_file
      return @report_file || 'app/build/reports/lint/lint-result.xml'
    end
```

なので https://qiita.com/noboru_i/items/2ad7c07d8b4266c9eb5b などを参考にしてDangerfileを

```
android_lint.gradle_task = "app:lint"
android_lint.report_file = "app/build/reports/lint-results.xml"
android_lint.filtering = true
android_lint.lint(inline_mode: true)
```

と設定しても一つのモジュールに対してしか動作してくれない。

### 解決法

DangerFileをモジュールごとに作成し、CIからモジュールごとにDangerを動かすようにした。

#### CircleCI(2.0)での設定の例
##### .circle/config.yml (一部)
```
###
# コメントが上書きされないように別々のdanger_idを付与。danger_idがないとapp1やapp2に対するDangerのコメントが、app3に対するDangerのコメントで上書きされてしまう。
###
     - run:
         name: Run danger for app1
         command: bundle exec danger --dangerfile="app1/Dangerfile" --danger_id=1
     - run:
         name: Run danger for app2
         command: bundle exec danger --dangerfile="app2/Dangerfile" --danger_id=2
     - run:
         name: Run danger for app3
         command: bundle exec danger --dangerfile="app3/Dangerfile" --danger_id=3
```

##### app1モジュールのDangerfileの例
```
# PRの箇所のみコメントする
github.dismiss_out_of_range_messages

# Android Lint
android_lint.gradle_task = ":app1:lintDebug"
android_lint.report_file = "app1/build/reports/lint-results-debug.xml"
android_lint.filtering = true
android_lint.lint(inline_mode: true) 
```
java.util.Arraysクラスのソートについて

#配列のソート
今さらな内容ですが、覚えるためにメモしておこうと思います。

#java.util.Arraysクラス
配列を宣言して、Arrays.sort(参照変数)とすれば、ソートの操作はおしまい。

※ちなみに昇順(値の場合は小さい順)でしかソートされません。
大きい順に数個値を取得したい場合などは、ソート後にfor()文を工夫して書いて値を取得するしかないと思う。

※[　]付きで文字列表現として出力したい時は下記のArrays.toString()を使うけど、戻り値はString型となる。
その後にソートされた配列の値を取得するには、lists[i]の操作が必要となる。

Arraysクラスのソート方法はDual-Pivot Quicksortという方法で、一般的なクイックソートよりも高速とのことなので、
自分でバブルソートとかを実装してミスをするよりは、迷わずこちらを優先して良いと思う。

```java:java
//仮に{3,9,2,7,5}だとすると
int[] lists = new int[5];

//この時点でソートが完了
Arrays.sort(lists);

//{2,3,5,7,9}となりlists[0]は2が得られる
System.out.println(lists[0]);

//[1,2,3,4,5]の様に文字列表現を返す
Arrays.toString(a);

//ソート後の配列を全て出力
for(int list:lists){
    System.out.println(list+",");
}

```
メモ: BIG-IP Application Connector Proxyのdocker runコマンド

Application Connector Proxy インスール

https://support.f5.com/kb/en-us/products/app-connector/manuals/product/f5-application-connector-setup-config-1-0-0/2.html

- F5 downloadサイトからDocker Imageのダウンロード
- Node.jsのインストール
- Dockerのインストール
- Dockerのスタート
- f5_ac.tar.gzのDocker Load



> -  Install the Application Connector Proxy
Before you can install the Application Connector Proxy, you need to download the installation package from downloads.f5.com.
To access the Application Connector Proxy, you install the Proxy Docker image onto your Linux instance.

> 1.Log in to the Linux instance in your cloud environment where you would like to install the Proxy.
> 2.Use SCP to copy the TGZ file to your Linux instance to the /home/\<user\>/cloud_vendors/aws directory.
> 3.Install the Docker image.
>
> ```
sudo docker load -i <file-name>.tar.gz
> ```
> 4.Start the Docker container.
>
> ```
sudo docker run -d -e httpPort=8090 --restart=always --net=host -e proxyName=<proxy-name> -e user=<user-name> -e passwd=<password> -it -v /home/<user-dir>/cloud_vendors/aws:/app/proxy/vendors/aws -v /app/proxy/log -v /app/proxy/config f5/acproxy:x.x.x-build.xx
> ```
>  5.Verify that the Docker container is running.
>
> ```
sudo docker ps
> ```
> You should now be able to log in to the Proxy using the public IP address, plus port 8090, for your Linux instance, using the username and password that you set when you started the Docker container.


####  docker run のオプションで指定している「**httpPort=8090**」は「**adminPort=8090**」のことかな
設計手法？なにそれおいしいの？雰囲気で設計していた自分にドメイン駆動設計がどう役に立ったのか

# おれたちは雰囲気で設計をしている

* 一応アプリケーションを一から作ることはできるけれども、疎結合とか単一責任の原則とかの戦術レベルの知識やいくらかの経験を頼りに雰囲気で設計をしていた。
* 設計手法について用語だけなんとなく聞いたことはあるけど、一応設計はできているつもりだしあんなのはスーツのおもちゃだろうくらいしか思っていなかった。

# ドメイン駆動設計に出会う

* Yuki Anzai さんの[ドメイン駆動設計についての発表資料をブログにまとめたもの](http://y-anz-m.blogspot.jp/2017/03/droidkaigi-2017_9.html)でドメイン駆動設計に出会った。
* 資料がわかりやすく、なんとなく経験則として感じていたことが言語化されたりよりよい方法を提示されたりした気がして楽しかった。
* ドメイン駆動設計についてちゃんと調べなければいけないと思い[エリック・エヴァンスのドメイン駆動設計](http://www.shoeisha.co.jp/book/detail/9784798121963)を読んだ。

# ドメイン駆動設計とは

* 入門として先のブログがわかりやすい。この記事では解説はしない。
  * この記事書くのにブログ見ていたら Anzai さんが[ドメイン駆動設計の入門本](https://techbooster.booth.pm/items/392260)を出していた。買って読んでみたけどこれもわかりやすくて入門によさそう。
* エリック・エヴァンスのドメイン駆動設計は分厚いけどガッツで読むといい。冗長でわかりづらいようなレビューがあるけど結構ユーモアもあって楽しく読めた。
  * Qiita とかでも解説記事がいっぱいあるので先にそっちを読んだり平行して読んでもいいかもしれない。
* [実践ドメイン駆動設計](http://www.shoeisha.co.jp/book/detail/9784798131610)はエヴァンス本とかぶっているところも多くて順番に読んだら飽きてしまって全部読めていない。ユーモアセンスも個人的に合わなくて辛かった。
  * こんな記事を書いて他人に紹介しておいて自分は知りませんっていうのはやっぱりない気がしてきたのであとでちゃんと読む。

# ドメイン駆動設計はどう役に立つか

## おじさんだって悩んでいる

### 問題

* 設計がうまくいかない時、自分が頭が悪いからうまくできないんだろうなーとか惨めな気持ちになることがよくあった。

### 解決

* ドメイン駆動設計ではソフトウェアが取り扱う問題が複雑である場合はソフトウェア自身も当然複雑になるということを言っている。
  * 複雑ではない問題を解決したい場合はそもそもソフトウェアを作る必要もあまりないので（手習いの Hello World なんかを除いて）ソフトウェアは本質的に複雑なものである。
  * ドメイン駆動設計ではここから続けていかにその複雑さをコントロールするかという流れになる。
  * ちなみにドメイン駆動設計の"ドメイン"とは"ソフトウェアが取り扱う問題領域"のこと。
* ベテランエンジニアのエリックおじさんも最初から完璧な設計ができるわけではなく、ドメインに詳しいひとと相談をしたり実装したりしながら分析してより良い設計へとリファクタリングを繰り返すという地道なことをしている。
* 「ソフトウェア開発は複雑だ」ということを誰かに言ってもらえることはとても救いになった。自分だけが苦しんでいるわけではなくみんなが苦しいのだということは一見悲観主義的だが、苦しいのを当然として立ち向かう覚悟を持つことができるようになった。大げさかもしれないがブッダが「一切皆苦」と説いて苦難についてよく分析しコントロールするすべを教えたことにも似ているように感じる。

## 修正は手戻りか

### 問題

* 仕様決めて設計して実装した後にやっぱりここはこうした方がいいということで修正をすることがある。
* 動かしてみて初めて気がつくことはあると思うので自分的には修正は問題ない。
* が、最初からそっちの仕様出せよとかモチベーション下げたり仕様決定者と対立したりする人はいるので、このしょうがないよねーという感覚をどうにか共有できたらいいなと思う。

### 解決

* ドメイン駆動設計では最初からドメインについて十分に理解できていないという態度を取り、不十分な理解でもモデリングをし実装をしながら分析を行うことでドメインについての理解を深めてリファクタリングをしていくというプロセスを経て完璧なモデルに近づけていくという方法を取る。
* 全知全能ではない以上すべての要件を最初から把握しておくことは不可能である。実装して初めて新しい要件に気がついたときには、手戻りではなくドメインへの理解が深まったのだととらえてポジティブに修正を進めていけるようになりたい。なるといいな。

### おまけ

* それでもやっぱり一旦実装しないとわからないというのは自分の能力に問題があるのかなーとか思っていたが、事前に設計をしっかりやるタイプの[ユースケース駆動開発実践ガイド](http://www.shoeisha.co.jp/book/detail/9784798114453)を読んでみて、設計しっかりやる人もユースケースモデルつくって、ロバストネス分析つくって、シーケンス図つくって、とコードではないが何らかの形での実装を実際に何度もやることで設計を固めているのだということがわかって安心した。
* 設計を一発で完璧にやるというのはやっぱり夢物語だ。それでなければサービス稼働率を 100% にしたりバグ発生率 0% をめざすようなコストに見合わない過度な目標設定だ。

## 良い設計とは

### 問題

* 自分で書いているコードやレビューしているコードでなんとなく筋が悪い設計な気がするがうまく言語化できないことがある。
  * 「これは早すぎる最適化ですよ」とかなんとなくの指摘はできるがどうして駄目なのかちゃんと説明できない。

### 解決

* 良い設計とは何かという軸がなかったのが問題。
* ドメイン駆動設計のテクニックは複雑さを解きほぐして小さくしうまくコントロールすることを目的としている。
  * エヴァンス本のサブタイトルは「ソフトウェアの核心にある複雑さに立ち向かう」。
* 設計の良し悪しとは複雑さをうまくコントロールできているかどうかという基準を持てるようになった。
  * 例えば早すぎる最適化については、ドメインについて理解が不十分な段階で過度に構造化をすることは後に発生するリファクタリングの妨げとなるので筋が悪い場合があると言えるようになった。

# おわりに

* ドメイン駆動設計はよく紹介されている実装テクニックも役に立つが根本の考え方もとても強力で役に立つものだと思っている。
* ぜんぜん知らない人にはテクニック部分の用語解説とかから入るのは厳しいと感じるので、ぜんぜん知らない人向けに詳細に触れずにふわっとどういう方面に役に立つのかを紹介されているものがあってもいいと思いこの記事を書いて見た。
LaravelでArtisanコマンドをCLI以外から(PHPファイルから)実行する

Laravelでアプリケーションを作っていて、メールを送信するArtisanコマンドを作成したのですが、
何故かCLIからコマンド実行すると、メールテンプレートに表示する画像にアクセス出来ない、というエラーが出ました。

そのため、テスト用にメール送信ボタンを作り、ボタンをクリックするとメール送信用のコマンドが実行されるようにしました。

その時に、コントローラーからArtisanコマンドを実行する方法を調べたのでメモしておきます。

#結論(コード)
コマンドに渡すパラメータが無ければ以下ようなコードをコントローラー等コマンドを実行したい場所に記述すればOK.

```php
use Artisan;//エイリアスに登録しいる場合
//use Illuminate\Support\Facades\Artisan;//エイリアスに登録して無い場合

Artisan::call('matching:email');//matching:emailはコマンド名
```

コマンドにパラメータを渡したければ以下のようにパラメータ名と値の配列を第２引数に渡します。

```php
Artisan::call('matching:email',['param1'=> 'value1','param2'=>'value2',...]);
```

#参考

リファレンス
https://readouble.com/laravel/5.4/ja/artisan.html
Laravelのタスクスケジュールで多重起動を防止する方法

Laravelの`Console/Kernel.php`に定期実行したい処理を記述していましたが、
どうも同じ処理が２~3度実行されてしまっているようだったので、多重起動を防止するやり方を調べました。

#結論
`Condole/Kernel.php`の`schedule()`メソッド内に以下のように、
`withoutOverLapping()`メソッドをメソッドチェーンで繋げて記述します。

```php
$schedule->command('emails:send')->withoutOverlapping();
```

#参考
リファレンス
https://readouble.com/laravel/5.4/ja/scheduling.html

Laravelでタスクをスケジュール実行する
http://takayukii.me/post/20160824836
(複数サーバーでの多重起動防止についても記述されていました(試しては無いです))
AWS ElasticsearchとlambdaをNAT Gateway経由で繋ぐ

## やりたいこと
Elasticsearch Service（ES）をIP制限だけで運用したい
Webhookをlambdaで受け取って（API-Gateway経由）からESにデータを取りに行って戻す

## 実装方法
lambdaにVPC設定をして、NAT Gateway経由でESにアクセス
NAT GatewayのIPアドレスをESのアクセスポリシーで許可する

### 注意点
lambdaはプライペートサブネットに設定する必要がある
パプリックサブネットを設定してしまうと、外に接続できなくなる
AWS Elasticsearch ServiceがVPC対応したので、lambda→ESをVPCで括ってみた


VPC Support for Amazon Elasticsearch Service Domains - Amazon Elasticsearch Service http://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/es-vpc.html

![FireShot_Capture_065_-_Amazon_Elasticsearch__-_https___ap-northeast-1_console_aws_amazon_com_es_home.png](https://qiita-image-store.s3.amazonaws.com/0/67717/59f3a7c2-4f78-8795-06d4-f482510d8854.png "FireShot_Capture_065_-_Amazon_Elasticsearch__-_https___ap-northeast-1_console_aws_amazon_com_es_home.png")



## やること

1. VPCの設定をする
2. Elasticsearch Serviceを新規作成してVPC設定する
（既存のドメインをVPC対応にする・VPCを切り替える方法はまだわからない）
3. lambdaにVPCを設定する
4. テスト

### VPC設定
1. プライペートとパブリックの2パターンサブネットを作成する
2. パブリックサブネット内でNATゲートウェイを作成する
3. NAT,インターネットゲートウェイをルートテーブルに割り当てる
4. ESに設定するセキュリティグループを設定する

### ES設定
1. 新しいドメインの作成
2. ネットワーク設定でVPC, サブネット（プライペート）, セキュリティグループを設定する
3. アクセスポリシーをVPC用に設定
![FireShot_Capture_066_-_Amazon_Elasticsearch__-_https___ap-northeast-1_console_aws_amazon_com_es_home.png](https://qiita-image-store.s3.amazonaws.com/0/67717/d6ab502d-6f19-c209-ef93-a441c2f57575.png "FireShot_Capture_066_-_Amazon_Elasticsearch__-_https___ap-northeast-1_console_aws_amazon_com_es_home.png")


### lambda設定
1. ロールにVPCアクセス権限をアタッチする
2. lambdaをプライペートサブネットに配置する

### API Gateway設定
（疎通確認だけなら、lambda関数に繋がればよいかと）

## 疎通確認
ESはVPC内なので、外のネットワークからはアクセスできない
そのため、Kibana見れない状態…
VPC内にWindows立ち上げるとかEC2入れてcurlで叩いてみるとか

lambda内のログに出力するなりで確認



## はまりどころ
lambdaにパプリックネットワークのサブネットを付けてしまっていた為、外に接続できなかった
原因をAPI Gatewayかと思い、メソッドを設定したものの解決せず時間がかかってしまった

## もしかして
ESへのアクセスを制限したいだけであれば、lambdaをVPC内に設置してNAT Gateway経由でESにアクセスすればIP許可だけで十分だったのでは…？
ジョブのアウトプットをリアルタイム(?)に取得する

`Start-Job` とか `Invoke-Command -AsJob` で実行したジョブは Completed になってから `Receive-Job` で結果を
受け取ることができるけど、処理途中で内容をつまみ食いする方法について。

## 利用するケース

CLIで処理に時間のかかるリモートジョブを実行中に結果を確認したい時とか？
→まさにこれがやりたくていろいろ試してみた。

スクリプトをタスク実行などではあまり意味なさそう。
~~ジョブでログを監視して該当ログ来たら止めるとかやる人いるのかな。。~~


## 対応方法

普通に `Receive-Job` で受け取ると一番最後にまとめて取得される。

```PowerShell:Reveice-Jobで受け取る
$job = Start-Job {
  (1..10) | % { sleep 1; (date).ToString() }
}

while ($job.State -ne "Completed") {
    Wait-Job $job -Timeout 1 > $null
}

"after wait"
Receive-Job $job
```

```:出力結果
after wait
2017/10/20 20:23:27
2017/10/20 20:23:28
2017/10/20 20:23:29
2017/10/20 20:23:30
2017/10/20 20:23:31
2017/10/20 20:23:32
2017/10/20 20:23:33
2017/10/20 20:23:34
2017/10/20 20:23:35
2017/10/20 20:23:36
```

途中で中身を見る場合は `$job.ChildJobs[0].Output` を参照する。

```PowerShell:途中で中身を見る
$job = Start-Job {
  (1..10) | % { sleep 1; (date).ToString(); }
}

sleep 1

# Outputのデータ型の確認
$job.ChildJobs[0].Output.GetType()

while ($job.State -ne "Completed") {
    ""
    $job.ChildJobs[0].Output
    sleep 1
}
```

```:出力結果
IsPublic IsSerial Name                                     BaseType                           
-------- -------- ----                                     --------                           
True     True     PSDataCollection`1                       System.Object                      


2017/10/20 20:24:00

2017/10/20 20:24:00
2017/10/20 20:24:01

2017/10/20 20:24:00
2017/10/20 20:24:01
2017/10/20 20:24:02

2017/10/20 20:24:00
2017/10/20 20:24:01
2017/10/20 20:24:02
2017/10/20 20:24:03
        :
```

`$job.ChildJobs[0].Output` は `PSObject` のコレクションでインデックスアクセスも可能なので、
中身を順次呼び出し元で垂れ流すことで、ジョブ完了前に出力経過を確認することもできる。

----

なんで `$job` 直下じゃなくて `$job.ChildJobs[0]` なのかとかはよくわかってないので、
この辺りは偉い人のツッコミ待ちです(●´ω｀●)
ClickOnce で CurrentDomain.FriendlyName を使っていると

# 環境

.Netframework 4.5
VB.Net

# ClickOnceでAppDomain.CurrentDomain.FriendlyNameを使っていると

ビルド実行では動いてたのに、配布したら動かなくて焦った。

結論。  
デザインモード時に処理を発生させないように下記プロパティで制限してた。
だが、配布時にデザインモードになっていた。

```vbnet
If AppDomain.CurrentDomain.FriendlyName = "DefaultDomain" Then '<- ClickOnceだと"DefaultDomain"になってた。
    Return 'デザインモードのときはなにもしないよ。
End If
```

`ApplicationDeployment.IsNetworkDeployed`プロパティでclickonceで配布しているか確認するようにした。

```vbnet
If Not ApplicationDeployment.IsNetworkDeployed Then
    If AppDomain.CurrentDomain.FriendlyName = "DefaultDomain" Then
        Return 'デザインモードのときはなにもしないよ。
    End If
End If
```