OmniAICreator/Qiita-1.07M huggingface dataset:
RancherでLDAPとRocket.Chatを構築する (3)Rancherを構築する

## はじめに

[前回](http://qiita.com/gldn/items/813e56722c6de3119e7f)の続きです。

今回は、Rancherを立ち上げます。

## Rancher
Dockerイメージは、rancher/serverを使用します。

ゲストOSで、docker-compose.ymlを作成します。

```
$ mkdir -p /vagrant/services/rancher
$ touch /vagrant/services/rancher/docker-compose.yml
```
docker-compose.ymlを編集します
rancherコンテナのdocker inspectの情報を元に、以下を作成しました。

```ruby:docker-compose.yml
version: 2
services:
  rancher-server:
    image: rancher/server
    container_name: rancher-server
    restart: always
    ports:
      - '8001:8080'
    volumes:
      - rancher-server-data:/var/lib/cattle
      - rancher-server-db-data:/var/lib/mysql 
    networks:
      - bridge
volumes:
  rancher-server-data: {}
  rancher-server-db-data: {}
```

## コンテナ作成＆開始
```
$ cd /vagrant/services/rancher
$ sudo su
# sudo docker-compose up -d
```
※Proxy環境下では、docker-composeコマンド実行前に環境変数の設定を行います。

しばらくすると、ホストOSからブラウザでアクセスできるようになります。

## Ranherにアクセスする
ブラウザで、以下のURLを開きます。
http://(ホストOSのIPアドレス):8001

以下が表示されます。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/194385/4b5588e0-888b-c10c-2eaa-e4bc049e75fd.png)

「Got it」をクリックします。

## ホストの追加
Dockerコンテナを動かすマシンを追加します。
今回は、Rancher Serverと同じマシン(仮想マシン上)にします。

![addhost.PNG](https://qiita-image-store.s3.amazonaws.com/0/194385/2a2b28c0-fd41-93ad-7181-650d51851645.png)

右上の"Add a host"をクリックします。

![ip.PNG](https://qiita-image-store.s3.amazonaws.com/0/194385/4f626955-7ab8-baf3-084d-09b675908d07.png)

base URLを指定します。
以下を入力します。

http://(ホストOSのIPアドレス):8001

【注意】(ホストOSのIPアドレス)がlocalhostや127.0.0.1の場合は、
　　　　次項のRancher Agentが起動できません。
　　　　上記以外のIPアドレスを指定します。

## Rancher Agent起動

Rancher Agent起動のコマンドが生成されました

![agent.PNG](https://qiita-image-store.s3.amazonaws.com/0/194385/6e166b1d-2d54-77b7-2b50-233baf702486.png)

枠内のコマンド(sudo docker run ...)をコピーして、仮想OS上で実行します。

```
# (枠内のコマンドを入力)
```

エラーが出なければ、起動成功です。

つづき→[(4)OpenLDAPサーバを構築する]
(http://qiita.com/gldn/items/19116548743a85c85ddf)

## 目次: RancherでLDAPとRocket.Chatを構築する 

[(1)仮想マシン構築](http://qiita.com/gldn/items/565adc5158a3c1d57ef3)
[(2)Dockerインストール](http://qiita.com/gldn/items/813e56722c6de3119e7f)
[(3)Rancherを構築する](http://qiita.com/gldn/items/f5168cf0e09fa8562e31)
[(4)OpenLDAPサーバを構築する]
(http://qiita.com/gldn/items/19116548743a85c85ddf)
[(5)Rocket.Chatを構築する](http://qiita.com/gldn/items/c611e2eb49c481f58a40)
AWSあれこれ

# はじめに
AWSでシステム構築に携わって約１年経ちました。
その中で苦労したことや注意点をまとめます。



# あれこれ
## 1.設定をきちんとしたのに、メールの送信がうまくできないことがある。

AWSでメールシステムを構築する方法は、EC2上に、MTAを構築するかAmazon SESを利用します。
**スパムメール対策で、AWS側がメールの制限をかけているため、このような事象が発生します。**
普通に送信する場合は不要かもしれませんが、バッチ処理等でメールを数百通送るようなシステムの場合、運用後に問題が発生する可能性もあります。
**AWSのサポートで、メール送信数の解除が可能です。**


## 2.cloud-init機能により、環境間（本番、stg、開発）で差異がでる。

Amazon LinuxのEC2インスタンスの場合、環境設定を自動更新できる「cloud-init」という機能があります。
この機能を使うと、インスタンス起動時に自動で```yum update```を行なってくれます。
インスタンス作成時の手間は省けますが、予期せぬパッチ適用で環境間で差異が発生する可能性があります。
**cloud-initの機能を無効にすることで対応可能です。**


## 3.インスタンスの起動台数上限により、新しくインスタンスを作成できない。
**AWSのアカウントに対して、インスタンスの起動台数上限があります。**
AutoScaleをしている際は、インスタンスが新規作成できなくなってしまいます。
**環境毎にアカウントを分けるか、サポートに起動台数の上限緩和申請をしましょう。**


## 4.S3のバケット名に「.」はつけてはいけない。

**S3のバケット名に「.」をつけると、アクセスできなくなる可能性があります。**
これは、S3でバケットを作成されるときに付与されるURLが関係しています。
S3では、httpまたはhttpsで通信を行いますが、SSL証明書には「*.s3-ap-northeast-1.amazonaws.com」というワイルドカードが用いられています。

**バケット名に「.」をつけるとサブドメインとみなされてしまい、通信エラーが起こります。**


## 5.RDSのパラメータグループの変更は、設定によって反映されるタイミングが違う。

**RDSの設定変更は、パラメータグループの変更を行うが、変更すぐに反映されるものと、再起動を必要とするものがあります。**
**再起動が必要かどうかは、各設定の「Apply Type」から確認できます。
「Static」になっているものは、再起動が必要です。**


## 6.RDSへの初回接続に時間がかかる。

**AWSの仕様で「ファーストタッチペナルティ」というものがあります。**
これは、初回接続時にデータが実ボリュームに格納されない時があるためです。
したがって、新規作成時に起こる事象というより、スナップショットから復元した際に起こる現象と言えるでしょう。
**事前ウォーミングを行うことで、回避可能です。**


## 7.デフォルトのVPCを削除してはいけない。

**デフォルトのVPCには特別な役割があるようです。**
画面に表示されるのが鬱陶しい時に、削除してしまうと予期せぬ不具合が発生することがあるようです。
削除後に、デフォルトのVPCと全く同じ設定を入れてもダメ見たいです。
**削除してしまったら、AWSのサポートに問い合わせて作成してもらいましょう。**


## 8.IAMの権限の強さは「Deny, Allow, デフォルトDeny」

Denyポリシーを適用しているときに、一部Allowポリシーを適用してもDenyポリシーが優先され実行できません。


## 9.全セキュリティーグループの作成上限は250個

上限を超える数は作成できません。


## 10.ネットワークACLはインバウンドだけでなく、アウトバウンドも許可が必要。

セキュリティーグループのようにインバウンドを許可しただけでは、通信ができません。
**アウトバウンドにウェルノンポートを許可する設定を入れましょう。**
[クイズ]javascriptと仲良くなるための一歩　第２３話「関数で不変オブジェクト 注意１」

#問題

##第1問

```js
var obj = {x:2, y:3};
Object.preventExtensions(obj);
Object.freeze(obj);
delete obj.y;
Object.keys(obj); //=> ?
```

##第2問

```js
var obj = {x:2, y:3};
Object.freeze(obj);
Object.preventExtensions(obj);
delete obj.y;
Object.keys(obj); //=> ?
```

##第3問

```js
var obj = {x:2, y:3};
Object.seal(obj);
Object.preventExtensions(obj);
delete obj.y;
Object.keys(obj); //=> ?
```


:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:


#答え

##第1問

```js
var obj = {x:2, y:3};
Object.preventExtensions(obj);
Object.freeze(obj);
delete obj.y;
Object.keys(obj); //=> ["x", "y"] (freezeの制約になっている)
```

##第2問

```js
var obj = {x:2, y:3};
Object.freeze(obj);
Object.preventExtensions(obj);
delete obj.y;
Object.keys(obj); //=> ["x", "y"] (freezeの制約になっている)
```

##第3問

```js
var obj = {x:2, y:3};
Object.seal(obj);
Object.preventExtensions(obj);
delete obj.y;
Object.keys(obj); //=> ["x", "y"] (sealの制約になっている)
```

制約の強い方へしか途中で変更できません:hugging_face:
スクリプトでユーザーのaliasを無効にする

作ったshellスクリプトはユーザーの環境で動作がおかしくなります。
原因はユーザーの環境でaliasを使って、スクリプト中のコマンドが正しく実行できません。

解決方法：
1. unaliasでユーザー環境のaliasを無効にする
2. bashのalias展開を無効にする
マストドンを v1.4.1 から v1.5.1 にバージョンアップした時のメモ

だいぶ前にさくらのクラウドのスタートアップスクリプトでセットアップして、 v1.4.1 でバージョンアップ止まっていたマストドンインスタンスを重い腰を上げてバージョンアップした時のメモ

↓まず、これに対応
さくらのクラウドのスタートアップスクリプトで作ったMastodonインスタンスをv1.5系にバージョンアップする際の注意事項 - Qiita
http://qiita.com/toshi__ya/items/7088ceefe5fa442f4e37

あと、↓にあるLet's Encryptがらみの対応も合わせてやった。
スタートアップスクリプト「Mastodon」の更新のお知らせ・2017/7/10 12:00以前にスクリプトを使用して作成されたインスタンス向けの作業のお願い | さくらのクラウドニュース
https://cloud-news.sakura.ad.jp/2017/07/10/mastodon-startupscript-update-4/

あとは、

ゼロからはじめるMastodon インスタンス運用編 - さくらのナレッジ
http://knowledge.sakura.ad.jp/knowledge/8683/

↑これの手順と、

Release v1.5.1 · tootsuite/mastodon · GitHub
https://github.com/tootsuite/mastodon/releases/tag/v1.5.1

↑これの手順を見ながらやったらいいのかな・・と思ってやって見たら、

天に召される（？）マストドンの画像が・・・ :innocent:
something が wrong なの・・？

あれやこれやと試行錯誤して見たところ、どうも、 v1.4.2 にアップデートするときに必要な、外部キーの準備コマンドをやらなかったことが問題だったようです。

https://github.com/tootsuite/mastodon/releases/tag/v1.4.2

バージョンアップにちゃんと追随してリリースノートを見ながらバージョンアップしていれば防げた問題でした。

反省して、今後はマメにバージョンアップするようにしたいと思います。
rancidのセパレータはセミコロン

# 内容
rancidの設定で悩んだことを共有

# ホスト情報(router.db)の記載方法
バージョン３以降は、セパレート文字は”；”(セミコロン)になったそうだ。
※昔は、":"コロンでした。

(昔(ver2時代))router01:cisco:up
(今(ver3時代))router01;cisco;up

理由は、ホスト情報(IPアドレス)にIPv6の記載を許可するためでした。
なるほどな〜

# 以下、本家の情報

http://www.shrubbery.net/rancid/man/router.db.5.html

> In RANCID releases prior to 3.0, router.db used colons (:) as its field separator. This was changed to allow IPv6 addresses to be used in router.db.


http://www.shrubbery.net/rancid/CHANGES
上記内の3.0のチェンジログより抜粋
> router.db,rancid.types.*: change field separator to ';' (semi-colon) to allow for IPv6 addresses in router.db and avoid conflict with :s in device commands and perl module names

※rancid.typesも変更対象ですって
機能テストの自動化ツールHPE Unified Functional Testingについて

# はじめに
- テスト現場で何万件ものデータを個人でテストするにはかなりの時間と労力が必要に
なります。そんな時にHPE Unified Functional Testing（略称はUFT）は便利です。
- 使用する言語は、VBscript、エクセルVBA、あとはUFT独自の処理の書き方があるのでそれを使います。
- 対応している環境は、Web環境以外にもエクセルやデータベースなども自動でテストすることができます。

# 使い方(Webとエクセルについて)
1.  Webページやエクセルだと、テストしたい画面やその画面のボタン等の情報（オブジェクト）を取得する必要があります。Webとエクセルのオブジェクトの取得には、違いがあるので注意する必要があります。
2.   次に情報（オブジェクト）の取得後、新しいアクションを作ります。
3.   新しいアクションにテストで流したい処理を書き込みます。
記録というボタンがあるのでそこを押してから、テストで流したい画面でボタン等を自分で押すとUFTに自動で処理が書かれるのでそれを参照してから書くと楽です。
記録には４種類あります。

# UFTでできること
- エビデンスを取得（画面ショットをしてWordに張り付けやPDFに変換等）
- デバック
- 画面の遷移、クリック、画面拡大など
- コーディングいらずのGUIベースで書くことも可能

#個人的に使ってみて
- エビデンス取得など、自分で行うより早く終わるので時間の短縮ができると思います。
- 初めての方でも記録を使えば難なく動かせると思います。

# 参照
- https://www.ashisuto.co.jp/product/category/quality/functional-testing/
(アシスト「お客様の最高」のために)
[クイズ]javascriptと仲良くなるための一歩　第２２話「関数で不変オブジェクト化～Object.freeze編～」

#問題

```js
var obj = {x:2, y:3};
Object.freeze(obj);

obj.z = 4;
Object.keys(obj); //=>?

delete obj.y;
Object.keys(obj); //=>?

//プロパティ値変更はできない
obj.x = 20;
obj.x; //=>?
```

:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:

#問題

```js
var obj = {x:2, y:3};
Object.freeze(obj);

//プロパティ追加はできない
obj.z = 4;
Object.keys(obj); //=>["x", "y"]

//プロパティ削除はできない
delete obj.y;     //=> false
Object.keys(obj); //=> ["x", "y"]

//プロパティ値変更はできない
obj.x = 20;
obj.x; //=> 2
```
[クイズ]javascriptと仲良くなるための一歩　第２１話「関数で不変オブジェクト化～Object.seal～」

#問題

```js
var obj = {x:2, y:3};
Object.seal(obj);

obj.z = 4;
Object.keys(obj); //=>?

delete obj.y; 
Object.keys(obj); //=>?

obj.x = 20;
obj.x; //=>?
```

:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:

#答え

```js
var obj = {x:2, y:3};
Object.seal(obj);

//プロパティ追加はできない
obj.z = 4;
Object.keys(obj); //=>["x", "y"]

//プロパティ削除はできない
delete obj.y;     //=> false
Object.keys(obj); //=> ["x", "y"]

//プロパティ値変更は可能
obj.x = 20;
obj.x; //=> 20
```
[クイズ]javascriptと仲良くなるための一歩　第２０話「関数で不変オブジェクト化～Object.preventExtensions～」

#問題

```js
var obj = {x:2, y:3};
Object.preventExtensions(obj);

obj.z = 4;
Object.keys(obj); //=>?

delete obj.y;
Object.keys(obj); //=>?

obj.x = 20;
obj.x; //=>?
```

:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:
:mouse:
:cow:
:tiger:
:rabbit:
:dragon_face:
:snake:
:horse:
:sheep:
:monkey_face:
:bird:
:dog:
:boar:

#答え

```js
var obj = {x:2, y:3};
Object.preventExtensions(obj);

//プロパティ追加はできない
obj.z = 4;
Object.keys(obj); //=>["x", "y"]

//プロパティ削除は可能
delete obj.y;
Object.keys(obj); //=>["x"]

//プロパティ値変更は可能
obj.x = 20;
obj.x; //=> 20
```
dyld: Library not loaded: /usr/local/lib/libjpeg.8.dylib - homebrew php


[dyld: Library not loaded: /usr/local/lib/libjpeg.8.dylib - homebrew php](https://stackoverflow.com/questions/32703296/dyld-library-not-loaded-usr-local-lib-libjpeg-8-dylib-homebrew-php)

最近ずっと仮想環境での作業なので、homebrewのphpとか久し振りに触るとぶっ壊れてることおおいですね。

brew updateとbrew upgradeやってたらlibjpeg見つからないって言われたので、

```
$ php -v
dyld: Library not loaded: /usr/local/lib/libjpeg.8.dylib
  Referenced from: /usr/local/bin/php
  Reason: image not found
Trace/BPT trap: 5
```

こちらを参考に、解決しました。
[homebrewで過去のバージョンインストールする方法](http://qiita.com/ShuntaShirai/items/c582c0acebe2dbf03fc3)

でも！[コメント頂きまして、](https://qiita.com/maimai-swap/items/9ba6e5f877274079d755#comment-eed508df925f170ffd6d)
これでかいけつできるみたいでしゅ…！

```
brew switch jpeg 8d
```

上記で解決できなかった場合を除いて、以下無駄です…！

libjpegのバージョン違いだったので、v8のjpegのライブラリがはいってるコミットを探します。

Formulaが置いてあるディレクトリで

```
cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/
```

ログ検索

```
brew log jpeg
```

最新のだと、これくらいしかログが出ないので、

```
Warning: homebrew/core is a shallow clone so only partial output will be shown.
To get a full clone run:
  git -C "$(brew --repo homebrew/core)" fetch --unshallow
commit 2cfb629ee82e4e3bced64d14669192b281b14055
Author: BrewTestBot <brew-test-bot@googlegroups.com>
Date:   Mon Aug 7 06:33:22 2017 +0000

    jpeg: update 9b bottle.

commit 1fee4a326dd7144e192027705fa82d86e4676837
Author: ilovezfs <ilovezfs@icloud.com>
Date:   Sat Aug 5 11:44:29 2017 -0700

    jpeg 9b

commit b23146936a3abb57aabb39017561e7b0c750abbf
Author: FX Coudert <fxcoudert@gmail.com>
Date:   Sun Mar 12 09:15:30 2017 +0100

    jpeg: drop universal

commit 8a07d55e33686dda515024cc69fe5c862ff30ad0
Author: BrewTestBot <brew-test-bot@googlegroups.com>
Date:   Fri Dec 2 12:16:30 2016 +0000

    libical-glib: update 1.0.4_1 bottle.
```

古いのもfetchします。

```
git -C "$(brew --repo homebrew/core)" fetch --unshallow
```

そしてもう一回、logをみると

```
brew log jpeg
```

対象のログが見つかりました。

```
commit 7f16e5aa9451ea391cbb7822a59d2bf702c5b834
Author: BrewTestBot <brew-test-bot@googlegroups.com>
Date:   Tue Sep 6 14:22:41 2016 +0100

    jpeg: update 8d bottle.

```

これをチェックアウトして、

```
git checkout 7f16e5aa9451ea391cbb7822a59d2bf702c5b834 jpeg.rb
```

jpegをインストール

```
brew install jpeg
```

すると、うごきました。

```
php -v
PHP 7.1.7 (cli) (built: Jul 19 2017 15:58:29) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
```

忘れそうなので、masterに一応戻しときましょう。

```
git checkout master
```
CakePHPのプロパティとローカル変数の見分け方。

CakePHPのソースコードを読んでいたら、プロパティの記法が面白かったので、tipとして書こうと思います。

```php
    protected $_config;
```
以上のような宣言により、プロパティを宣言することができます。重要なのは、$の後に_(アンダースコア）を入れることです。このようにすることにより、アクセス修飾子ごとの違いが記述できます。
ちなみに、PHPでは、ローカル変数はvarなどで型定義されることなくいきなり使われています。僕は最初、ローカル変数とプロパティを区別するためにアンダースコアを入れていると思ったんですよね。

```php
    public function getUser(ServerRequest $request)
    {
        $digest = $this->_getDigest($request);
        if (empty($digest)) {
            return false;
        }

        $user = $this->_findUser($digest['username']);
        if (empty($user)) {
            return false;
        }

        if (!$this->validNonce($digest['nonce'])) {
            return false;
        }

        $field = $this->_config['fields']['password'];
        $password = $user[$field];
        unset($user[$field]);

        $hash = $this->generateResponseHash($digest, $password, $request->env('ORIGINAL_REQUEST_METHOD'));
        if ($digest['response'] === $hash) {
            return $user;
        }

        return false;
    }
```
上のソースコードをみてください。DigestAuthenticate.phpの一部です。`$digest`はいきなり使われていますが、これはクラスのプロパティではありません。`$user`、`$field`、`$hash`も同じです。プロパティは以下のように参照されます。

```php
$this->_compiledGroupNames
```
では、(_)アンダースコアは、なぜ存在するのでしょうか？
では、実験的に以下のコードを作ってみました。

```php
<?php
// Here your code !

class TestClass{
     private $_property1;
     public function method1()
     {
         $this->_property1 = 1;
     }
     public function method2()
     {
         return $this->_property1;
     }
}
$test = new  TestClass;
$test->method1();
echo $test->method2()
```
この場合、プロパティを参照する、`$this->_property1;`においての、`$this->`　は省略が不可能でした。つまり、アンダースコアを、プロパティと、ローカル変数を区別するために付加しているという仮説は消えました。
では、なぜ(アンダースコアをつけているのか。
`public $OptionParser;`　このように、publicにはアンダースコアを入れないようです。
ちょっと謎ですが、PHPの場合、protectedのアクセス修飾子の場合は、アンダースコアを頭につけるということです。
ちなみに、privateの場合は、(__)アンダースコア二つです。
ちょっと人に聞いてみると、private、protected、publicなどのアクセス修飾子がPHPになかった頃に、それぞれを区別するためにつけられていたもののようです。
それがアクセス修飾子が使われるようになった今でも残っているようです。
いきなり切り替えると、色々支障があるため、「キーボードはQWERTY」とか、「車は左側通行」と同じような問題だと推測できます。

(追記）
ちなみに、protectedのメンバ関数も、アンダースコアをつけます。

```ph
    protected function _query($username)
    {
        $config = $this->_config;
        $table = TableRegistry::get($config['userModel']);

        $options = [
            'conditions' => [$table->aliasField($config['fields']['username']) => $username]
        ];
```

(追記）
ちなみに、Laravelのソースコードを調べると、protectedのプロパティにもアンダースコアは入っていませんでした。物によって違うんですね。

PHPのslackの皆さん助言ありがとうございます。
http://www.msng.info/archives/2016/02/phpusers-ja-on-slack.php
xdebug.file_link_format 使っていますか？ NetBeans + XDebug + Windows を使っているなら是非！

## はじめに

XDebug 関連の設定を探していたら [本家](https://xdebug.org/) で xdebug.file_link_format というディティクティブを見つけました。

[xdebug.file_link_format](https://xdebug.org/docs/all_settings#file_link_format)

## これはなに？

ブラウザに XDebug のエラーが表示された場合、それがテキストリンクになっていて、そのリンクをクリックすると IDE で該当する行へジャンプしてくれます。

NetBeans + XDebug で、または xdebug.file_link_format で検索しても、日本語説明のページがヒットしなかったので、ここに記します。もし Windows で NetBeans で XDebug を使っているなら、これを使わない手はありません。

## 設定手順

[本家](https://xdebug.org/) では「Firefox on Linux」と「Windows and netbeans」の設定方法が載っています。Windows + NetBeans の方をやってみたので記します。

手順は大きく３つあります。

1. バッチを作成し、Windows フォルダへ置く
2. レジストリを設定する
3. php.ini に設定を書く

### 1. バッチの作成

以下のテキストを `netbeans.bat` というファイル名で保存し、`C:¥Windows` などパスが通っているフォルダに置きます。

```bat:netbeans.bat
@echo off
setlocal enableextensions enabledelayedexpansion
set NETBEANS=%1
set FILE=%‾2
%NETBEANS% --nosplash --console suppress --open "%FILE:‾19%"
nircmd win activate process netbeans.exe
```

もし `nircmd` をお持ちでなかったら最後の行は削除してください。

### 2. 以下のテキストを `netbeans_protocol.reg` というファイル名で保存します。

```reg:netbeans_protocol.reg
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT¥netbeans]
"URL Protocol"=""
@="URL:Netbeans Protocol"

[HKEY_CLASSES_ROOT¥netbeans¥DefaultIcon]
@="¥"C:¥¥Program Files¥¥NetBeans 7.1.1¥¥bin¥¥netbeans.exe,1¥""

[HKEY_CLASSES_ROOT¥netbeans¥shell]

[HKEY_CLASSES_ROOT¥netbeans¥shell¥open]

[HKEY_CLASSES_ROOT¥netbeans¥shell¥open¥command]
@="¥"C:¥¥Windows¥¥netbeans.bat¥" ¥"C:¥¥Program Files¥¥NetBeans 7.1.1¥¥bin¥¥netbeans.exe¥" ¥"%1¥""
```

NetBeans へのパスは二回出てきます。これらは、ご自身の環境に合わせて書き換えてください。また `netbeans.bat` のパスも最初の手順で保存したパスと一致するよう確認しましょう。

作成した `netbeans_protocol.reg` をダブルクリックしてレジストリを登録します。

### 3. php.ini の設定

php.ini に以下のディティクティブを追加してください。

```ini:php.ini
xdebug.file_link_format = "netbeans://open/?f=%f:%l"
```

終ったら PHP（Apache）を再起動しましょう。

## ネタ元

https://xdebug.org/docs/all_settings#file_link_format
RancherでLDAPとRocket.Chatを構築する (2)Dockerインストール

## はじめに
[前回](http://qiita.com/gldn/items/565adc5158a3c1d57ef3)の続きです。

ゲストOSにDockerをインストールします。
インターネット接続にProxy認証が必要かどうかで、手順が変わります。

## Proxy認証不要な場合

ゲストOSを更新します。

```
$ sudo su
# apt-get update && apt-get upgrade -y
```

続いて、dockerとdocker-composeをインストールします。

```
# apt-get install -y docker.io docker-compose
```


以上でdockerのインストールは完了です。

続き→(3)Rancherを構築する


## Proxy認証が必要な場合

Proxy認証情報を環境変数に設定します。

```
$ sudo su
# export http_proxy="http://[ユーザ名]:[パスワード]@[ProxyIPアドレス]:[ProxyPort]/"
# export ftp_proxy="http://[ユーザ名]:[パスワード]@[ProxyIPアドレス]:[ProxyPort]/"
```

※:[password]に記号が含まれている場合、URLエンコードが必要な場合があります。
　　記号は、「%」＋アスキーコードに変換が必要です。
　　　例：my&password → my%26password

続いて、ゲストOS更新、docker.ioとdocker-composeをインストールします。

```
# apt-get update && apt-get upgrade -y
# apt-get install -y docker.io docker-compose
```

※以下はUbuntu 16.04の場合の手順です。旧バージョンでは、手順が異なることがあります

設定ファイルを作成します。

```
# mkdir -p /etc/systemd/system/docker.service.d
# touch /etc/systemd/system/docker.service.d/http-proxy.conf
```

http-proxy.confを編集します。

```:http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://[ユーザ名]:[パスワード]@[ProxyIPアドレス]:[ProxyPort]/"
```
http:// 以下は、URLエンコードを行います。

最後に、dockerサービスを再起動します。

```
# systemctl daemon-reload
# systemctl restart docker
```

以上でdockerのインストールは完了です。

続き→[(3)Rancherを構築する](http://qiita.com/gldn/items/f5168cf0e09fa8562e31)

## 目次: RancherでLDAPとRocket.Chatを構築する 

[(1)仮想マシン構築](http://qiita.com/gldn/items/565adc5158a3c1d57ef3)
[(2)Dockerインストール](http://qiita.com/gldn/items/813e56722c6de3119e7f)
[(3)Rancherを構築する](http://qiita.com/gldn/items/f5168cf0e09fa8562e31)
[(4)OpenLDAPサーバを構築する]
(http://qiita.com/gldn/items/19116548743a85c85ddf)
[(5)Rocket.Chatを構築する](http://qiita.com/gldn/items/c611e2eb49c481f58a40)
【Terraria】リフレクションにてゲーム内のオブジェクトを抜き出す

#はじめに
この記事はTerrariaでのMod開発を行うに辺り、既存のデータを流用するために、リフレクションを使用してTexture2Dオブジェクトを抜き出す方法です。
<font color=red>
※これを書き始めてから、あれ？そもそも、xnbとかいうファイルがあるから、これから抜き出せるのでは？っと思ったら、当然、そういったツールがあるようですね。直ぐに次のような記事が見つかりました。</font>
[MOD - Stardew Valley 日本語Wiki](http://stardewvalley.netgamers.jp/MOD)
[Terrariaのグラフィックを差し替える | Frea.Inventory](http://frea.in/ventory/2015/09/terrariaedit.html)

まぁ、今回のケースでは、実際のフィールド名でファイルを出力するので、イメージを確認してどのフィールドから取得すれば良いかがわかるようになります。

#コード

```C#
using Microsoft.Xna.Framework.Graphics;
using Terraria;
 :

Main.instance.GetType().GetFields().ToList().ForEach(x => {
    try
    {
        if (x.FieldType.Equals(typeof(Texture2D)))
        {
            SaveAsPng($@"c:\{x.Name}.png", (Texture2D)x.GetValue(Main.instance));
        }
        else if (x.FieldType.Equals(typeof(Texture2D[])))
        {
            Texture2D[] textures = (Texture2D[])x.GetValue(Main.instance);
            for (int i = 0; i < textures.Length; i++)
                SaveAsPng($@"c:\{x.Name}_{i}.png", textures[i]);
        }
    }
    catch (Exception e)
    {
        System.Diagnostics.Debug.WriteLine($"{x.Name} {e.Message}");
    }
});

```
`SaveAsPng`は前回、イメージ処理について記事にしましたが、その際に作っておいたメソッドで、パスとイメージデータを受け取って、ファイル出力するだけの処理です。

<font color=red>なお、これはTerrariaを起動して出力しているのですが、一部のテクスチャは、特定のメソッドを呼び出してロードするなどしないと取り込めないので、そういったケースは個別に対処が必要です。</font>



とりあえず、備忘録としてないので、話題としている部分のコードのみ抜き出しているだけです。

タブンその内、整理します・・・


以上
python で 画像のGPS 情報を削除する方法

python3 で、GPS 情報 (exif) を削除する方法です。
piexif を使います。

Arch Linux でのインストール方法

```bash
sudo pacman -S python-piexif
```

削除して、同じ名前で保存する場合

```py3:remove01.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#
import piexif
import sys
#
jpg_file = sys.argv[1]
piexif.remove(jpg_file)
#
```

削除して別名で保存する場合

```py3:remove02.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#
import piexif
import io
import sys
#
jpg_in=sys.argv[1]
jpg_out=sys.argv[2]
#
fp_in=open(jpg_in,"rb")
data_in=fp_in.read()
fp_in.close()
#
output = io.BytesIO()
piexif.remove(data_in,output)
image_jpg = output.getvalue()
#
fp_out=open(jpg_out,"wb")
fp_out.write(image_jpg)
fp_out.close()
#
```

Exif の確認方法


```bash
jhead sample.jpg
```

Arch Linux で jhead のインストール方法

```bash
sudo pacman -S jhead
```

コマンドで、Exif を削除する方法

```bash
jhead -purejpg sample.jpg
```
RancherでLDAPとRocket.Chatを構築する (1)仮想マシン構築

## はじめに

外部Webサービスの利用が禁止の場所にいることが多いです。
チャットすらできないので、うんざりです。
**...自分で作ればいいじゃん！**

## 本稿が目指すところ
* OSSで、Webアプリケーションを動かす基盤を作ります  
    ついでに、Webアプリケーションも動かします。
* インターネットに自由に繋げない環境での運用を想定します  
    インストール/アップデート時以外は、インターネット接続を不要にします。
* 簡単に構築する  
  なるべくコマンドコピペで構築できるようにします。  


というわけで、以下の環境を構築します。

| 用途       |       アプリケーション |
|:-------------|:----------|
| 仮想マシン作成| Vagrant + Vritualbox|
| 仮想OS       | Ubuntu16.04|
| コンテナ管理  | Rancher + Docker Compose |
| ユーザ認証管理    | OpenLdap|
| LDAP管理GUI  |  phpLDAPadmin|
| Webアプリ    |  Rocket.Chat| 

Webアプリは、用途に合わせて追加/削除します。
今回は試しに、Rocket.Chatを導入します

## 仮想化ソフトウェアインストール
公式サイトからインストーラをダウンロード→インストールします。
Vagrant
https://www.vagrantup.com/
Virtualbox
https://www.virtualbox.org/

## 仮想マシン作成

### Vagrantfile作成
Ubuntの仮想マシンの設定を記述します。
NAT接続なので、forwarded_port設定もしておきます。

```ruby:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-16.04"

  #Docker構成変更時は、forwarded_port設定を適宜変更する
  config.vm.network "forwarded_port", guest: 8001, host: 8001, id: "Rancher"
  config.vm.network "forwarded_port", guest: 8010, host: 8010, id: "phpLDAPadmin"
  config.vm.network "forwarded_port", guest: 3000, host: 3000, id: "Rocket.chat"

  #メモリとCPUの割り当てはホストマシンのリソースに合わせて調整する
  config.vm.provider "virtualbox" do |vb|
    vb.name = "vagrant-ubuntu"
    vb.memory = 4096
    vb.cpus = 2
    vb.customize [
      "modifyvm", :id,
      "--hwvirtex", "on",
      "--nestedpaging", "on",
      "--largepages", "on",
      "--paravirtprovider", "kvm",
    ]
  end
end
```
vb.customizeについては、下記を参考にさせていただきました。
http://qiita.com/hidekuro/items/385bcc4b9eb43945751d
https://www.virtualbox.org/manual/ch08.html#vboxmanage-modifyvm

### 仮想マシン作成＆起動

コマンドプロンプト or シェルで、vagrant upを実行します

``````Bash:
$ vagrant up
```

完了したら、statusを見てみます。

```Bash:
$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. ...(後略)
```

仮想マシンが起動しました！

※初回起動時のみ、インターネット接続が必要です。
　プロキシ環境下では、環境変数を設定するか
　ブラウザでboxファイルをダウンロードします。

## 仮想マシンに接続する
仮想マシンでコマンドを実行するには、以下の方法があります。

* VirtualBoxマネージャで仮想マシンを選択→表示
* sshクライアントを使用する

今回は、sshクライアントで接続します。

```Bash:
$ vagrant ssh
(省略)
vagrant@vagrant:~$
```
仮想マシンの中に入ることができました！

※sshクライアントがインストールされていない場合、エラーになります。
　ホストOSがWindowsの場合、open-sshやTeratermなどをインストールします。
　私は"Bash on Ubuntu on Windows"を使用しています。

つづく→[(2)Dockerインストール](http://qiita.com/gldn/items/813e56722c6de3119e7f)

## 目次: RancherでLDAPとRocket.Chatを構築する 

[(1)仮想マシン構築](http://qiita.com/gldn/items/565adc5158a3c1d57ef3)
[(2)Dockerインストール](http://qiita.com/gldn/items/813e56722c6de3119e7f)
[(3)Rancherを構築する](http://qiita.com/gldn/items/f5168cf0e09fa8562e31)
[(4)OpenLDAPサーバを構築する]
(http://qiita.com/gldn/items/19116548743a85c85ddf)
[(5)Rocket.Chatを構築する](http://qiita.com/gldn/items/c611e2eb49c481f58a40)
記事のソートを別の投稿タイプのカスタムフィールドの値でおこなう

##「本の一覧を出版元の50音順でソートしたい」
WordPressで「書籍」「出版社」をそれぞれ別のカスタム投稿タイプで登録してSmart Custom Fieldsの「関連する投稿」などで紐付けている場合に、書籍の一覧を出版社のカスタムフィールドに登録された“よみがな”でソートする。

```php:search.php
if ( have_posts() ) :
	
	while ( have_posts() ) : the_post();
		
		// 書籍に関連付けされた出版社のIDを取得
		$member_id = get_post_meta( $post->ID, 'member', true );
		// 出版社のよみがなを取得
		$member_yomigana = get_post_meta( $member_id, 'yomigana', true );
		// $postオブジェクトに“よみがな”を追加
		$post->member_yomigana = $member_yomigana;
		
	endwhile;
	
	/********************************
	* 取得した書籍情報を出版社の“よみがな”で並べ替える
	* 第一引数=ソートする配列, 第二引数=ソートに使う比較関数を定義
	* 比較関数から返された値の順にソート
	********************************/
	usort ( $posts, function ( $a, $b ) {

		$member_a = $a->member_yomigana;
		$member_b = $b->member_yomigana;
      
		if ( $member_a && $member_b ) :
			// 前者が大きければ正の値、後者が大きれば負の値、同じならゼロを返す
			$value = strcasecmp( $member_a, $member_b );
		else :
			// よみがながない場合は最後尾へ
			$value = 99999999;
		endif;	      
		
		return $value;
	} );
	
	// ループを巻き戻す
	rewind_posts();
	
	while ( have_posts() ) : the_post();         
	
		// 記事表示部分
	
    endwhile;
    
endif;
```

* 要点１ ループをrewind_postsで巻き戻して２度回し、ソートと表示の処理を分ける
* 要点２ “よみがな”を取得して \$post オブジェクトに突っ込む
* 要点３ usort関数で、“よみがな”を元に \$posts をソートする

“よみがな”がなかった場合に返す"99999999"という値は適切かわからないが、"ソート最高尾に持っていくのに十分に大きい値"という意味。

###降順（逆順）にソートする場合

\$valueに「-1」を掛けて、

```php
return ( $value * -1 );
```
とすればいい。

###参考
http://php.net/manual/ja/function.usort.php
http://php.net/manual/ja/function.strcasecmp.php
http://php-archive.net/php/kana-sort/
https://ja.wordpress.org/plugins/smart-custom-fields/
MariaDB コマンドまとめ その1

MariaDB使用時にSQLの構文が分からなくなったり、
早くもどの記事に載っていたかを探すのが面倒になりつつある(ストックせいや！)ので、
復習も兼ねて自分用にSQLをまとめていく。

Oracle用のSQLはノートに書き溜めていたけど、どこに何を書いたかとか分からなくなるし、
コピペ出来ないしで面倒だから、そっちもいずれ記事にまとめていきたい･･･。

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

#ユーザーを指定してのログイン
パスワードの入力を求められるので入力するとログインできる。
-uオプションでユーザー指定、-pオプションでパスワード入力を
求められる様になる。

```sql:MariaDBにログイン
mysql -u ユーザー名 -p
```

接続するDBも一緒に指定してログインする時は以下の様に、
特にオプションを付けずにDB名を付与して実行する。

```sql:DB指定でMariaDBにログイン
mysql -u ユーザー名 -p データベース名
```

#作成済みのユーザーの確認
存在するユーザーについての情報を確認する時は
mysqlデータベースのuser表を確認する。

```sql:ユーザーの確認
SELECT user,host FROM mysql.user;
```

#ユーザーの作成
新しくユーザーを作成する。

```sql:ユーザーの作成
CREATE USER 'ユーザー名'@'ホスト名' IDENTIFIED BY 'パスワード';
```
※MySQLのリファレンスに拠るとINSERT文でもユーザーの追加をできる模様だが、
　できればOracleDBと互換性のある形で使用したいので今のところ除外。

特権ユーザーを作成する場合は以下。
WITH GRANT OPTIONを付け加えると、他のユーザの権限を書き換えることが
可能になる様なので、rootとは別に管理者ユーザーを作成する時に使えると思われ。

```sql:特権ユーザーの作成
GRANT ALL PRIVILEGES ON *.* TO 'ユーザー名'@'ホスト名' IDENTIFIED BY 'パスワード' WITH GRANT OPTION;
FLUSH PRIVILEGES;
```

**MySQL8系だと上記の特権ユーザーの作成はできないっぽい**
MySQL8系の場合は以下で作成する。

```sql:特権ユーザーの作成(MySQL8)
CREATE USER 'ユーザー名'@'ホスト名' identified by 'パスワード';
GRANT ALL PRIVILEGES ON *.* TO 'ユーザー名'@'ホスト名' (WITH GRANT OPTION);
FLUSH PRIVILEGES;
```

※GRANT構文を実行した後は「FLUSH PRIVILEGES;」を実行して権限を反映させる必要有。

#ユーザーのパスワード変更
接続したいユーザーのパスワードを忘れた時など
パスワードを再設定する場合は以下コマンドでパスワードを変更する。

```sql:ユーザーのパスワード変更1
ALTER USER 'ユーザー名'@'ホスト名' identified by 'パスワード';
```

```sql:ユーザーのパスワード変更2
SET PASSWORD FOR ユーザー名@ホスト=PASSWORD('パスワード');
```

#ユーザーの削除
ユーザーを削除するコマンド。

```sql:ユーザーの削除
DROP USER ユーザー名@ホスト名;
```

#DBの作成
DBを作成する際のコマンド。
[]内は省略可能。
省略した場合はmy.cnfで設定しているデフォルトの値を使用する。

```sql:DBの作成
CREATE DATABASE データベース名 
[CHARACTER SET 文字コード]
[COLLATE 照合順序];
```

#DBの一覧を確認
現在作成してあるDBの一覧を確認する。
注意は「database」ではなく「database"s"」で複数系である点。
間違えても特に問題は無いけど･･･。

```sql:DBの一覧
SHOW DATABASES;
```

#DBの削除
DBを削除するコマンド。

```sql:DBの削除
DROP DATABASE データベース名;
```

#DBへの接続
ログイン時に接続するDBを指定していない場合、
以下コマンドでDBに接続する。
尚、USEでもDBの切り替えは可能な模様…

```sql:DBへの接続
USE データベース名;
```

#接続DBの切替

```sql:DBの切替
CONNECT データベース名;
```

#接続しているDBの確認

```sql:接続中のDB確認
SELECT database();
```

#CREATE DATABASE文の表示
指定したテーブル名のCreate Database文を表示。
文字コードはこれで確認ができる。

```sql:文字コードの確認
SHOW CREATE DATABASE データベース名;
```

#参考
・よく使うMariaDB か MySQLのSQLコマンドメモ
　http://qiita.com/pugiemonn/items/247dccb6dc56e373ba92
・MariaDB　はじめてのMariaDB　【第４回 ユーザを作成してみよう】
　http://www.sakc.jp/blog/archives/38222
・MariaDB　はじめてのMariaDB　【第５回 DBを作成してみよう】
　http://www.sakc.jp/blog/archives/38550
・MySQL 5.6 リファレンスマニュアル
　　6.3.2 ユーザーアカウントの追加
　https://dev.mysql.com/doc/refman/5.6/ja/adding-users.html
WebRTCでDTMFやってみた

# はじめに

この記事は [WebRTC入門者LT会 #2](https://webrtc.connpass.com/event/58506/) での発表資料です。

---

# 自己紹介

- 名前: なかゆうすけ（[@Tukimikage](https://twitter.com/Tukimikage)）
- 仕事:
  - [SkyWay](https://skyway.io)の中の人
  - [HTML5 Experts.jp](https://html5experts.jp)の運営
- コミュニティ：
  - [WebRTC Meetup Tokyo/Osaka/Japan](https://atnd.org/groups/webrtc)主催
  - [WebRTC Beginners Tokyo](https://webrtc.connpass.com/event/58506/)

---

# 今日のスライドの目的

- WebRTCで普段触れられることが少ないマイナーなネタに触れてもらう
  - ぶっちゃけ役立ち度ミニマムですｗ

---

# みなさん、DTMF知ってますか？

以下、[wikipedia](https://ja.wikipedia.org/wiki/DTMF)より…

- DTMF（英: Dual-Tone Multi-Frequency）は、0から9までの数字と、*、#、A、B、C、Dの記号の計16種類の符号を、低群・高群の2つの音声周波数帯域の合成信号音で送信する方法である。
- 別名「トーン信号」「プッシュ信号」とも呼ばれ、その信号音は人間の可聴域にあるため日本語では「ピ、ポ、パ」とも擬音語表記される。
- プッシュ式電話回線での電話番号の送出、その他音声回線での数字入力（例・コールセンターでの着信後の項目選択）などで用いられる。

---

# ようはあれです

コールセンターとかに電話して、音声ガイダンスが流れて番号入力を求められる時に使われている技術です。

---

# デモ

---

# WebRTCでもDTMFが考慮されています

- APIスペック
 - https://www.w3.org/TR/webrtc/#peer-to-peer-dtmf

---

# RTCDTMFSender

- 最新の仕様ではRtpSenderの中に、RTCDTMFSenderが包含されています

```
partial interface RTCRtpSender {
    readonly attribute RTCDTMFSender? dtmf;
};
```
---

# RTCDTMFSender

```
interface RTCDTMFSender : EventTarget {
    void insertDTMF(DOMString tones,
                    optional unsigned long duration = 100,
                    optional unsigned long interToneGap = 70);
             attribute EventHandler ontonechange;
    readonly attribute DOMString    toneBuffer;
};
```

- duration : 送出時間
- interToneGap : 周期

---

# RTCDTMFToneChangeEvent

```
[Constructor(DOMString type, RTCDTMFToneChangeEventInit eventInitDict)]
interface RTCDTMFToneChangeEvent : Event {
    readonly attribute DOMString tone;
};
```

---

# 対応ブラウザ

Chromeのみ

---

# 実装は？

## トーン送信準備

```js
var senders = peerConnection.getSenders();
var audioSender = senders.find(function(sender) {
    return sender.track && sender.track.kind === 'audio';
});
dtmfSender = audioSender.dtmf;
dtmfSender.ontonechange = dtmfOnToneChange;
```

---

## トーンの送信

```js
dtmfSender.insertDTMF(tones, duration, gap);
```

---

## トーン送信時のイベント

```js
function dtmfOnToneChange(tone) {
    if (tone) {
        console.log('Sent DTMF tone: ' + tone.tone);
    }
}
```

---

# どこで使うのか？

- コールセンター
  - IVRとWebRTCをつなぎこむときなんかに使われるはずです

---

# 試してみたい方は

https://webrtc.github.io/samples/src/content/peerconnection/dtmf/
commonlispの導入

#rowsellとは
  
   roswellとは、commonlispを快適にするために作られた統合ソフトウェアのことです。これをインストールすることで、commonlispのインストールから、commonlispのライブラリのインストールまでができます。commonlispの強い味方でもあります。絵を書くために、絵の具からキャンバスまでをすべてだしてくれたようなものだ。
　commonlispは強力かつ柔軟である言語であるため、避けられてきました。ですが、今は違います。roswellによって開発は断然に変わりました。どう変わったのかというと、今まではせっせと石切をしていたのが、いきなり現代建築に入ったほどの進化を遂げたのだ。言うなれば、神が人類にりんごを与えたのと同じ勢いの進化だ。
　ただ、導入にはかなり手こずる。初心者はまず導入の部分で挫折する。今のままでは初心者に受け入れられないままcommonlispは宇宙のはるかななたに追いやられたスペースノイドのような悲惨な結果が待ち受けているであろう。だから、あえて言おう。初心者にもわかりやすい記事が足りないと！
　というわけでとっとと記事を書こう。この記事を読んでcommonlispの入り口を叩こう！

#MAC

まず、
brew install roswell
をします。ダメだったら
brew update
とすれば大丈夫なはず。

これが終わったら、とりあえず、
ros run　とすると、sbclが動きます。
ros runしてみたら、一度
(defun add (x)
(+ x 1))
としてみてください。おそらく、2と表示されます。
　何だそのくらいかと言ってはいけない。ここにもcommonlispの奥ゆかしい作法があるのだ。というのも、commonlispのカッコはもともとどこでバグが起きているのかをわかりやすくするための目印なのだ。何じゃそりゃと思われるかと思うが、そういうことになっているんだ。簡便なものを作ろうとしたら、結局わかりにくいもの作ってしまったという典型なんだ。ジオンの精神を形にしたら、ヅダができたと思ったほうが話が早い。
　カッコが多いのは、そのわかりやすさと、マクロといういものをつけるためにやったものだ。ただ、マクロをつけるとみんながみんな自分仕様の言語が仕上がるから、ノウハウを構築しづらい。だから、どうすることもできないのだ！

　　　だが、初心者にはそういうこと一切関係ないから、ここは読まなくても良い！
　　　


　　　さて、quicklispも同時にインストールされていると思いますので、


　　(ql:quickload :clack)

　こうすると、clackというウェブサーバーのライブラリがインストールされます。
　　　

　そして、このclackはターミナルからでも動かせる仕様になっていて、commonlispをターミナルから動かせるようになるのです。
　　　
　　　それをするためには、roswellをexportしてパスを通さないといけません。
　　　

　　　そのパスは

　　　「$ echo "export PATH=\"\$HOME/.roswell/bin:\$PATH\"" >> ~/.bashrc
」
　
　です。これを通すと
          
  clackup app.lisp

   で起動します。

Windows

    windows?知らない子だな。というより、実家のwindows機が安定しなかったため、動かせませんでした。
　メタルマンの博士「本当にもしわけない」
Rails3＆MySQL5の組み合わせでidをintからbigintに切り替える

そもそもテーブル設計が〜云々の話は置いておくとして、
早急にタイトル通りの作業が必要なことがある。

先に結論からいうと
`users`テーブルのプライマリキーである`id`を`bigint(20)`にしたい場合。

```rb
class ChangeUserIdFromIntToBigInt < ActiveRecord::Migration
  def up
    # usersテーブルのidをbigintに
    connection.execute(
      <<-EOS.strip_heredoc
        ALTER TABLE users
        MODIFY COLUMN `id` bigint AUTO_INCREMENT;
      EOS
    )

    # 関連テーブルのuser_idをbigintに
    change_column :authentications, :user_id, :bigint
    change_column :content_stars, :user_id, :bigint
    ### ...以下略... ###
  end
end
```

完全にただのSQL。
でもこれしか方法がわからなかった。

なお、外部キーの`user_id`を`bigint`にするのを忘れた場合、
`int`の最大値以上の値は全て`int`の最大値で登録される。


# 補足
最初はRailsのメソッドのみで済ませたいと思っていた。

```rb
def up
  # usersテーブルのidをbigintに
  change_column :users, :id, :bigint
end
```

これで`data_type`は`bigint(20)`になってくれるが、
`Auto_increment`の値が`NULL`になるという問題がある。

ちなみに`Auto_increment`の値が`NULL`になると
`id`が`0`でレコードが登録されてしまう。
2件目以降はプライマリキーのユニーク制約でエラーになる。
この状態から復帰する方法も最初と同じで

```sql
ALTER TABLE users MODIFY COLUMN `id` bigint AUTO_INCREMENT;
```

このSQLを実行すれば`Auto_increment`の値が正しい値になる。

# 細かいバージョン情報
```
Rails 3.2.20
MySQL 5.5.43-37.2-log
```
CdataのExcel add in for Twitterを使ってみた

#Excel add in for Twitterとは
一言でいうと、、、
**Excelを使って、Twitterのデータを管理できるもの。**
自分のアカウントと連携して、フォロワーやツイートの表示・様々な条件での検索や書き出し、読み込みがすべてExcel上でできる。表示項目も自分で設定でき、ツイートの内容はもちろん画像のURLやツイートした人のIDから一言や場所までそのアカウントがもっている情報が一挙にみれる。


#準備

簡単にTwitterとの連携までの流れを。。

今回は評価版（＝無料のもの）をインストールしました。

  **1.Excel add in for Twitterをインストール**
　Dataの会社の[ホームページ](https://www.cdata.com/jp/default.aspx)から「[Excel add in for Twitter](https://www.cdata.com/jp/drivers/twitter/excel/)」をダウンロードし、操作手順にしたがってインストール。


![スクリーンショット (7).png](https://qiita-image-store.s3.amazonaws.com/0/178136/ec718761-0c92-6f9e-660b-bd6513953d19.png)



**2.自動で開かれるマニュアルを基にtwitterと連携**
　まず、接続の確立という設定を行う。「このアプリケーションとTwitterをつなげますよ」という操作。ここではUserとpasswordを入力するかOAuthのどちらかで行うことができる。
　すると、Twitterの情報の取得画面にはいり自分で条件を指定して取得することができる（この取得の条件はあとから書き換えることが可能）
　最後にTwitterのOAuth認証のためにアカウントを作り認証して完了。

詳しい手順は[こちら](http://cdn.cdata.com/help/GTB/xls/pg_startedintrox.htm)


#実際に使ってみた

使ってみた感想は、
**自分もデータ管理の業務をバリバリやっていけそう**

というのも、自分の場合はほんの小1時間でTwitterの新たな見方を発見できたなと思ったから。表示されている情報はスマホの画面から各アカウントの個別に飛んでいけば見れるものを一つの画面にまとめたというものだが、あのスマホの画面からでは見落としてしまう情報も平等に表示してくれるので新たな発見をした気分になる。

（もちろんユーザーが公開している情報しか見れないが、フォロワーのアカウントを丸裸にしてしまった感。。）

情報の検索などはSQLを使ってやっていくが、全くのド素人の自分でもマニュアルに書いているように打ち込んでいけばデータの抽出や追加などが行えて、データをしっかりいじくりまわしていけるので簡単なデータ管理の仕事ならやっていけそう。

##例えばこんなことも

###自分が送信したDMのみを抽出
データ選択の画面（画面中央）で自分が送ったDMのテーブル（現在のテーブル名）をワンクリックで選択。実際の画面をさらに右側に進めていくと、送った相手の情報（アカウントのIDからプロフィール画面のURLまでも）が表示される。
データを見ていくと自分のメッセージの特性とかがわかるしそれが自動返信のシステムとかにも応用できるなと思った。情報発信系のアカウントであれば、時期によって変動する相手や送信回数からマーケティングの戦略を立てる際に参考になる

![スクリーンショット (9).png](https://qiita-image-store.s3.amazonaws.com/0/178136/8d2286bf-4369-1e58-8b4c-9283310c4d81.png)




###自分がフォローしている人をいいねの数が多い順に並び替え
データ選択のクエリの部分に自分好みの条件（今回は自分がフォローしている人をいいねの数が多い順）を指定することで、データの抽出・並び替えができる。条件の指定の仕方はこちら（リンクを飛ばす）時系列に表示されるTwitterをいいね順で表示させることで人気のツイートから見ることができる。他にもリツイート順での並び替えや条件のさらに絞り込みで自分の見やすいTwitterにカスタマイズしていける。

![スクリーンショット (8).png](https://qiita-image-store.s3.amazonaws.com/0/178136/5de9992c-c1fc-1fdf-786b-b8a20753ce14.png)




Cdata Excel add in for Twitterのダウンロード↓
https://www.cdata.com/jp/drivers/twitter/download/excel/
サーバーを使わないアプリの保存機能

#初めに
せっかくアプリを作ってみたのに保存機能がサーバー借りないとできない。。。。
という悩みの解決案のサイト紹介

#IndeedDB
https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API
lamrongolさんより
http://qiita.com/lamrongol/items/55ce60576af2aa665f5a

#webストレージ
http://www.atmarkit.co.jp/ait/articles/1108/12/news093.html

(https://teratail.com/questions/78402を参考に)
[JavaScript] 一旦タスクをためて、後から順番に実行する [Promise|タスク処理]

様々な処理を行う中で、一旦タスクをためておいて、後から順番に実行したい。
という場面に出会ったので、そのときに実装した内容です。

エラーキャッチしたときに、その後のタスクをどうしたいかで、
rejectやcatch周りは書き方変わりそうです。

```js:Tasks.js
/**
 * タスク管理用親クラス
 */
class Tasks {

  constructor () {
    this.tasks = [];
    this.messages = [];
  }

  /**
   * タスク追加
   * @param {function} task
   */
  pushTask (task) {
    if (typeof task === 'function')
      this.tasks.push(task);
  }

  /**
   * メッセージ追加
   * @param {string} message
   */
  pushMessage (message) {
    this.messages.push(message)
  }

  /**
   * タスクの実行
   * @returns {Promise}
   */
  execTasks () {
    return this.tasks.reduce((prevTask, next) => {
      return prevTask
        .then(next)
        .then(msg => {
          if (msg) {
            this.pushMessage(msg);
          }
          return Promise.resolve()
        })
        .catch((err) => {
          return Promise.reject(err)
        })
    }, Promise.resolve());
  }
}

export default Tasks;
```

```js:SampleTasks.js
import Tasks from './Tasks';

/**
 * サンプルタスク用クラス
 */
class SampleTasks extends Tasks {

  /**
   * サンプルタスクの生成
   */
  createSampleTask (number) {
    this.pushTask(() => {
      console.log('START: ' + number);
      return new Promise((resolve, reject) => {
        // 非同期処理　(APIなりファイル操作なりの処理をここに記述する)
        setTimeout(() => {
          console.log('FINISH: ' + number);
          resolve('sample task ' + number + ' 終了');
        }, 1000)
      })
    })
  }

}

export default new SampleTasks();
```

```js:app.js
import SampleTasks from './SampleTasks'

// タスク作成
SampleTasks.createSampleTask(1);
SampleTasks.createSampleTask(2);
SampleTasks.createSampleTask(3);

// タスク実行
SampleTasks.execTasks()
  .then(() => {
    // 全タスク終了時
    console.log(SampleTasks.messages);
  });
```
bootsnapを使ってrailsの起動時間を10%くらい短縮した

[railsのデフォルトのGemfileにも追加されたbootsnap](https://github.com/rails/rails/pull/29313)を導入しただけでrailsの起動時間を10%くらい短縮できました。

この記事は個人ブログでも掲載しています。
http://tackeyy.com/blog/reduce-rails-boot-time-about-10-percent-with-bootsnap

# [Shopify/bootsnap](https://github.com/Shopify/bootsnap#quick-performance-overview)

> Boot large ruby/rails apps faster

大きいrubyやrailsのアプリを早くするGemです。
railsの場合、2行追加するだけなので[README](https://github.com/Shopify/bootsnap#usage)を見てください。

# 検証結果

railsの起動時間の計測用のコマンドとして ` time bin/rails runner "puts Rails.env" ` を利用しました。
[railsのデフォルトのGemfileにbootsnapを導入するPRのコメント](https://github.com/rails/rails/pull/29313#issuecomment-310535683)で上記のコマンドを見かけたのでそのまま利用しています。` rails runner ` は知らなかったのですが、ヘルプを引いて見たところまあ計測に使っても良いかなという感じだったので採用しました。

```
$ bin/rails runner -h
Examples:
    rails runner 'puts Rails.env'
        This runs the code `puts Rails.env` after loading the app
```

## 環境

```
macOS Sierra 10.12.6 メモリ 16GB
rails 4.2.0
ruby  2.3.4
```

## bootsnap導入前

```
$ time bin/rails runner "puts Rails.env"
development
bin/rails runner "puts Rails.env"  17.10s user 3.91s system 85% cpu 24.562 total

$ time bin/rails runner "puts Rails.env"
development
bin/rails runner "puts Rails.env"  16.77s user 3.08s system 88% cpu 22.546 total

$ time bin/rails runner "puts Rails.env"
development
bin/rails runner "puts Rails.env"  17.02s user 3.68s system 85% cpu 24.085 total

平均: 16.96s
```

## bootsnap導入後

```
$ time bin/rails runner "puts Rails.env"
development
bin/rails runner "puts Rails.env"  19.36s user 3.49s system 80% cpu 28.230 total

$ time bin/rails runner "puts Rails.env"
development
bin/rails runner "puts Rails.env"  14.79s user 1.81s system 79% cpu 20.918 total

$ time bin/rails runner "puts Rails.env"
development
bin/rails runner "puts Rails.env"  14.39s user 1.43s system 79% cpu 19.823 total

平均: 16.18s
```

bootsnapをGemfileに追加して ` bundle install ` を走らせた直後に1回目を計測したので遅かったのかな？と思っています。
（Gemの読み込みの問題なのか、bootsnapのキャッシュなどの処理の問題なのかはみてません）
3回目以降も計測したのですが、bootsnapを導入してからはだいたい13秒後半〜14秒後半に落ち着きました。

# 最後に

railsの起動が遅いとイライラするので、できるだけ早く起動したいですよね。
起動時のボトルネックを調査して対応するのも時間がかかるのでまずはサクッとbootsnapを入れてみることをおすすめします。
node-slack-sdkでslackのグループ作成、招待を自動化する

## はじめに

インターンの運営とかで社員のユーザとインターン生のユーザごとにグループ作成して招待するっていうのをやろうとなった時に、GUIでポチポチするの面倒ですよね。
そこで、今回は、node-slack-sdkというNode.jsのパッケージを使用してSlackのグループ作成などを自動化してみました。

## Slack API

SlackBotなどを作ったことがある人は馴染みあると思いますが、SlackにはRestAPIが用意されています。これらを使用すれば、Channel,Group(プライベートチャンネル)などの作成、取得、アーカイブなどの処理をやらせることができます。SlackAPIのURLは以下になります。

[Slack API](https://api.slack.com/methods)

## node-slack-sdk

このSlackAPIをNodejsで使いやすくしたものがnode-slack-sdkになります。GitHubのリポジトリは以下になります。

[node-slack-sdk](https://github.com/slackapi/node-slack-sdk)

## 導入

1. node-slack-sdkを使える状態にしていきます。まず何かしらのディレクトリを新規作成します。(例としてslack-utilsというディレクトリを作成しています)
2. npm installでnode-slack-sdkを入れます。
3. ソースファイルを作成(index.js)

```
$ mkdir slack-utils
$ cd slack-utils
$ npm install @slack/client --save
$ touch index.js
```

## SlackのTokenの取得

node-slack-sdkを使用する上で、SlackにアクセスするためのTokenが必要になります。これはアカウントごとに異なるTokenが発行されます。発行の仕方は以下のページを参照してください。

[Slack APIのTokenの取得・場所](http://qiita.com/ykhirao/items/0d6b9f4a0cc626884dbb)

取得したTokenは環境変数に設定しておきましょう。以下をbash_profileに記述。

```
export SLACK_TOKEN="取得したToken"
```

## Groupの作成

では、早速Slackのグループを作成していきます。
node-slack-sdkはPromiseに対応しているので、Promiseの形式で書きました。

```js:groupCreate.js
const WebClient = require('@slack/client').WebClient;
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);

const groupName = "hogeGroup";  //作成するグループ名

//グループの作成
web.groups.create(groupName)
  .then(val => {
　　　　  console.log(val);
  })
  .catch(err => {
    console.log(err);
  });
```

書いたら以下のコマンドでスクリプトを実行

```bash
$ node groupCreate.js
```

## Groupの取得

グループを作成したら作成したグループを取得します。ここで面倒なのが、SlackAPIが用意している検索キーはグループのIDのみです。したがって、特定のグループを取得したい時は全グループの情報を取得してから該当するグループ名が含まれるかで判定する必要があります。
実際に使う際は、CSVかなんかで取得したい複数のグループ名を読み込む形になると思います。
slack-utilsディレクトリに新たにgroupGet.jsというファイルを作成しました。

```groupGet.js
const WebClient = require('@slack/client').WebClient;
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);

let name = "group1";  //探したいグループ名
web.groups.list()
  .then(value => {
    for(let group of value.groups){
      if(name === group.name){
        //何らかの処理
      }
    }
  })
  .catch(err => {
    console.log(err);
  });
```


## Groupに招待

Groupの情報が取得できたら、チームにいるユーザを招待してみましょう。今回は、チームにいるユーザ全員に作成したグループを送るという形で実装していきます。

```groupInvite.js
const WebClient = require('@slack/client').WebClient;
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);

let groupName = "group1";   //招待したいグループ名
let userIds = [];
Promise.all([web.users.list(), web.groups.list()])
  .then(values => {
    let users = values[0].members;
    let groups = values[1].groups;
    let groupId;

    //groupのID取得
    for(let group of groups){
      if(group.name === groupName){
        groupId = group.id;
      }
    }

　　//groupに招待
    for(let user of users){
      web.groups.invite(groupId, user.id)
        .then(res => {
          //console.log(res);
        })
        .catch(err => {
          //console.log(err);
        });
    }
  })
  .catch(err => {
    console.log(err);
  });
```

## まとめ
node-slack-sdkを使うと退屈な事務的な作業も自動化できてしまいます。色々カスタマイズして使うこともできるので、各々の用途にあった使い方をしてみてください。

ps. jsまだまだ初心者ですので、お見苦しい点あったら恐縮です。
Rust製のls代替ツールexa。tree・Git連携機能付き

## <i class='fa fa-question-circle'></i> exa とは？
>exa is a modern replacement for ls.

## <i class='fa fa-list'></i> 特徴
### <i class='fa fa-check-circle'></i> 色分け
デフォルトで多くのファイルを色分け表示してくれる。

![exa_list.png](https://qiita-image-store.s3.amazonaws.com/0/43480/85040041-3dae-5bb1-d845-441a6db08134.png)

### <i class='fa fa-check-circle'></i> Git
ディレクトリの Git 対応状況を表示する

![git.png](https://qiita-image-store.s3.amazonaws.com/0/43480/84c44a10-49e9-8ca4-146d-c0bf5b544782.png)

### <i class='fa fa-check-circle'></i> tree view
ディレクトリのツリー表示をする

![tree.png](https://qiita-image-store.s3.amazonaws.com/0/43480/07ba1de2-07b2-627d-3f92-2e0d78a2a4e4.png)

## <i class='fa fa-download'></i> インストール
Mac 環境のインストール例です。

```sh
$ brew install exa
```

## <i class='fa fa-book'></i> 関連情報
* [exa - A modern replacement for ls](https://the.exa.website/)
ServiceNow初期設定 インスタンスの通貨を日本円で固定化する（単一通貨モデルの設定）

ServiceNowの開発者向けインスタンスは最初、マルチ通貨が有効化されており、またデフォルトの通貨はUSドルになっている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/c761d151-f6ee-344f-b013-dcb73c22feea.png)

今回はマルチ通貨を無効化し、インスタンス内の通貨を日本円で固定化する。

マルチ通貨は有効のまま、全ユーザのデフォルト通貨を日本円にしたい場合は[こちらの記事](http://qiita.com/Kisaragi13/items/d0ab1a0bf622b0803591)を参照して下さい。
マルチ通貨は有効のまま、日本ユーザは日本円、北米ユーザはUSドルを初期値にしたい場合は[こちらの記事](http://qiita.com/Kisaragi13/items/19c3b20ff20772f75188)を参照して下さい。

インスタンスのビルドタイプはJakarta。

# インスタンス内の通貨を固定する

インスタンスにログイン
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/3f5b1f4f-f158-35e5-8456-1ef466299c53.png)

アプリケーションナビゲータの中から、システムプロパティ → システムローカライズを選択（<font color="red">赤枠</font>）。　※<font color="red">システムローカライズは２つあるので注意</font>
（フィルタナビゲータ（<font color="blue">青枠</font>）に「**システムローカライズ**」と入力すると簡単です）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/43aecd03-af8a-e67e-cdaf-b7cd03316878.png)

システムローカライズのカスタマイズプロパティを以下のように変更する。

- 「**単一通貨モデルを使用します。ユーザーのロケール、国、言語コードにかかわらず、同じ通貨コード内のすべての通貨を表示します**」にチェックを入れる
- 「**単一通貨モデルを使用している場合、この通貨コードを使ってすべての通貨を表示します**」に「**JPY**」を設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/c8856491-11a2-9d79-c53c-68d0c98d7833.png)

保存後、レコードを見ると通貨を切り替えることができなくなっていることが確認できる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/67df27fd-e333-6d5a-45fc-afc4a1d9b2b6.png)

# 関連記事
> - [ServiceNow初期設定 インスタンスのデフォルトの通貨を日本円にする](http://qiita.com/Kisaragi13/items/d0ab1a0bf622b0803591)
> - [ServiceNow初期設定 ユーザによってデフォルトの通貨を切り替える](http://qiita.com/Kisaragi13/items/19c3b20ff20772f75188)
ServiceNow初期設定 インスタンスのデフォルトの通貨を日本円にする

ServiceNowの開発者向けインスタンスは最初、マルチ通貨が有効化されており、またデフォルトの通貨はUSドルになっている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/c761d151-f6ee-344f-b013-dcb73c22feea.png)

今回はこれを日本円に変更してみる。

マルチ通貨は有効のまま、日本ユーザは日本円、北米ユーザはUSドルを初期値にしたい場合は[こちらの記事](http://qiita.com/Kisaragi13/items/19c3b20ff20772f75188)を参照して下さい。
マルチ通貨を無効にし、日本円のみ利用可能にしたい場合は[こちらの記事](http://qiita.com/Kisaragi13/items/ba211ac6a5334f8c5d60)を参照してください。

インスタンスのビルドタイプはJakarta。

# インスタンスのデフォルトの通貨を日本円にする

インスタンスにログイン
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/3f5b1f4f-f158-35e5-8456-1ef466299c53.png)

アプリケーションナビゲータの中から、システムプロパティ → システムローカライズを選択（<font color="red">赤枠</font>）。　※<font color="red">システムローカライズは２つあるので注意</font>
（フィルタナビゲータ（<font color="blue">青枠</font>）に「**システムローカライズ**」と入力すると簡単です）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/43aecd03-af8a-e67e-cdaf-b7cd03316878.png)

システムローカライズのカスタマイズプロパティを以下のように変更する。

- 「**ローカライズに使用するロケールコード**」に「**ja.JP**」を設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/dba86293-68bd-e20e-e837-de56642de3a7.png)

保存ボタンをクリックし、**<font color="red">再ログインすると</font>**システムのデフォルト通貨は日本円となる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/175688/c5751159-b118-33f6-2e97-f74d875d5ad9.png)

# 関連記事
> - [ServiceNow初期設定 ユーザによってデフォルトの通貨を切り替える](http://qiita.com/Kisaragi13/items/19c3b20ff20772f75188)
> - [ServiceNow初期設定 インスタンスの通貨を日本円で固定化する（単一通貨モデルの設定）](http://qiita.com/Kisaragi13/items/ba211ac6a5334f8c5d60)
Python スクリプトをシュッとプロファイリングする

Python スクリプトが重くてどこがボトルネックになっているか調べたいときに、いつもプロファイリングのやり方を忘れて調べ直してしまっていたのでメモ。

## cProfile でプロファイリングする
Python 3 では標準でプロファイラが使える。

[Python プロファイラ — Python 3 ドキュメント](https://docs.python.jp/3/library/profile.html)

もっと高性能なプロファイラもあるのかもしれないが、今回はシュッとプロファイリングすることが目的なのでこれを使う。

### スクリプト全体をプロファイリングする場合
``` console
$ python -m cProfile -o profile.stats myscript.py
```

`-o <filename>` を指定すると、結果を標準出力に出す代わりにファイルに出力する。

### スクリプトの一部のみをプロファイリングする場合
``` python:myscript.py
import cProfile
import very_slow_function

cProfile.run('very_slow_function()', 'profile.stats')
```

`cProfile.run` でプロファイリングしたい処理をラップする。
第二引数でファイル名を指定すると、結果を標準出力に出す代わりにファイルに出力する。

## cProfileV でプロファイリング結果を閲覧する
cProfile で出力した結果ファイルはバイナリデータになっていてそのまま閲覧することはできない。
標準の pstats モジュールを使うと読み込めるのだが、使い方が覚えられないので今回は cProfileV というツールを使って閲覧する。

### cProfileV のインストール
``` console
$ pip install cprofilev
```

インストールすると `cprofilev` コマンドが使えるようになる。

### cProfileV を利用する
``` console
$ cprofilev -f profile.stat
```

`-f` オプションで結果ファイルを指定して `cprofilev` コマンドを実行すると HTTP サーバが起動するので、ブラウザから http://localhost:4000/ にアクセスするとプロファイリング結果を閲覧できる。

各メソッドの実行回数や実行時間などで並び替えることができるので便利。
eclipseからtomcat起動失敗した時にエラーログが出力されない

毎度忘れてしまうので備忘録

ウィンドウ→設定→TOMCAT→JVM設定

JVMパラメータへ以下を追加
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="%CATALINA_BASE%/conf/logging.properties"
spring boot初心者にありがちなこと（tomcat編）

#事象
　eclipseが異常終了したので、再起動してspring bootも立ち上げ直した。
　ところがtomcat起動で以下のエラーが発生し、spring bootを起動できない。

　ローカル・ホスト の Tomcat8 (Java8) で必要な幾つかのポート (8080, 8009) がすでに使用中です。サーバーはすでに別のプロセスで稼働中であるか、システム・プロセスがそのポートを使用中である可能性があります。このサーバーを始動するには、他のプロセスを停止するか、ポート番号を変更する必要があります。

#原因
　ポート8080を抱えたtomcatが起動し続けており、ルーティングに失敗する。

#対応
　ポートを持っているプロセスを調べて、タスクマネージャから終了させる。

　コマンドプロンプトで以下を実行
　netstat -ano

##コマンドについて
　netstatはポートのルーティングを確認できるコマンドで、network statisticsの略。
　-a：全てのTCPコネクションとlistenしているTCPポートおよびUDPを表示。
　-n：TCPコネクションのアドレスやポート番号を数値として表示。
　-o：TCPコネクションに対応するプロセスID（PID）を表示。

##プロセスの終了
　タスクマネージャを起動し、同一のプロセスIDを持つタスクを終了する。

#備考
　8080ポートを使うアプリケーションがあり、そのアプリが不明な場合、共通の方法でポートを開放できる。
　例：jenkinsはデフォルトで8080ポートを使用する。