OmniAICreator/Qiita-1.07M huggingface dataset:
ElasticBeanstalkでhttp2対応

ElasticBeanstalkでは、ロードバランサーの種類がClassicロードバランサーとApplicationロードバランサーの2つが選べます。

Applicationロードバランサーの主な特徴としては、リクエストされるパスごとに複数のエンドポイントに振り分けるられることなのですが、ApplicationロードバランサーにはClassicロードバランサーではできないhttp2対応ができます。

Applicationロードバランサーを使うには、ElasticBeanstalkのアプリケーションを何故かeb cliで作らなければなりません。WebのGUIでは今のところできないようです。

事前にVPCとVPCに紐付いたサブネットを2作っておき、以下のようにコマンドを使ってアプリケーションを作成します。

```
eb create xxxxxxxx \
    --elb-type application \
    --vpc.id vpc-xxxxxxxx \ # 作成したVPC
    --vpc.elbsubnets subnet-xxxxxxxx,subnet-xxxxxxxx \ # 作成したサブネット
    --vpc.ec2subnets subnet-xxxxxxxx,subnet-xxxxxxxx \ # 作成したサブネット
    --vpc.elbpublic \
    --vpc.publicip
```

事前にVPCとサブネットを作らないで `eb create`だけでapplicationロードバランサーのアプリケーションを作るとVPC外のところにアプリケーションができてよくわからないことになります…
chatworkからslackに移行したのでGASを使ってメッセージ転送した話

# chatworkからslackに移行したとは言っても。。
どっちのツールがどうこういう話は別として、chatworkで連絡を取り合っていたお客様に
「今後slackでお願いします！」とは言いづらい。。
chatworkは特定のお客様用に部屋を残すこととなった。

でも個人的にはchatworkとslackを常に上げておくのもなんか嫌だ。
#chatworkのメッセージをslackに転送しよう
chatworkにちょうど良いapiがある。
http://developer.chatwork.com/ja/endpoint_rooms.html#GET-rooms-room_id-messages
前回取得分からの差分のメッセージが取れる
→ってことはそれをslackに流せば良い。

#準備するもの
●chatworkのAPIトークン
　参考URL:https://help.chatwork.com/hc/ja/articles/115000172402-API-Token%E3%82%92%E7%99%BA%E8%A1%8C%E3%81%99%E3%82%8B
●slackのWebhook
参考URL:https://qiita.com/ik-fib/items/b4a502d173a22b3947a0
●googleアカウント

#GASを書く

```gas.js
function myFunction() {
  
  var CHATWORK_TOKEN = '上記の準備するもののAPIトークンをここに記載';
  var ROOM_ID = ["チャットワークのルームIDを記載","チャットワークのルームIDを記載"];
  
  var params = {
    headers : {"X-ChatWorkToken" : CHATWORK_TOKEN},
    method : "get"
  };

  for (var i = 0; i < ROOM_ID.length; i ++) {
    
    var url = "https://api.chatwork.com/v2/rooms/" + ROOM_ID[i] + "/messages?force=0";
    var strRespons = UrlFetchApp.fetch(url, params);

    if (strRespons != "") {
      
      var json = JSON.parse(strRespons.getContentText());
      if(json == "") return;
    
      for(var i in json){
        var message = '';
        message = message + json[i].account.name + "\n```" + json[i].body + "```\n";
        postSlack(message);
      }
    }
  } 
}

function postSlack(text){
  var url = "ここにはslackのWebhookを記載";
  UrlFetchApp.fetch(url, {
  payload : JSON.stringify({
    channel : "#部屋名を記載",
    text : text,
  })
  });
}
```

これで自分が入っているいる複数のチャットワークの部屋のメッセージが取得できる。
※ちなみにチャットワークのルームIDはチャットワークの部屋を開いた時のアドレスでわかる。
以下の例でいうと「12345678」
`https://www.chatwork.com/#!rid12345678`
※さらにちなみに起動トリガーは1分毎に設定した。
#まぁまぁ便利
ただし、まぁまぁ。

今回はGAS使ってみようっていうのが実は動機にあった。
GASはとても簡単で便利。しかも無料。
武器（手段）が一つ増えたと思って、今回は満足。
Linuxサーバーのtimezoneを変更する

ログなどに表示される時間が日本時間になってなかったらtimezone変更します。

```
ln -f -s /usr/share/zoneinfo/Japan /etc/localtime
```

今回はElasticBeanstalkのサーバーに設定したので以下

```yaml:.ebextensions/timezone.config
commands:
  set_time_zone:
    command: ln -f -s /usr/share/zoneinfo/Japan /etc/localtime
```
[Docker]初心者がLaravelの開発環境をDockerでやってみた

#概要
簡単なアプリケーションを作成することがあり、せっかくであれば、触ったことがない技術にチャレンジしたいと思い、「Docker」で開発環境・本番環境を構築することにしました。
（全て新しい技術だと死んでしまうので、6:4=使い慣れた技術:触ったことのない技術ぐらいのバランスでやってみました。）

今回は、開発環境をdockerで構築してみました。
ただ、あまりにインフラ部分が苦手なので、わかりやすい記事を見つけたので、参考にしながら、わからない用語や仕組みなどを調べて、記事にしたいと思います。
[Dockerでいい感じにPHP(Laravel)のローカル開発環境を作る](https://qiita.com/IganinTea/items/aec8f2b15b203946a2c4)

#誰向けの記事か
とりあえず簡単なアプリケーションを作れるけど、インフラとかサーバーの話はあんまりわかっていない人向け（プログラミング学習始めて、半年ぐらいかな？）
初心者の僕が、わからない用語を解説するので、基本的な内容ばかりです。

#そもそもDockerとはなんぞや
[公式のサイト](https://www.docker.com/what-docker)にはこのように書かれていました。
> The Docker platform is the only container platform to build, secure and manage the widest array of applications from development to production both on premises and in the cloud

ざっくり訳すと、「Dockerは開発環境から自社施設やクラウド環境での本番環境で利用でき、ビルド、保守、運用を手がけることができます」って感じですかね？
自分は、環境構築が恐ろしく苦手なので、開発環境で動いたのに、本番環境では動かない！みたいなことは避けたかったので、dockerを使うことでリスクを軽減できればと思っております。
詳細な説明は[こちら](https://www.docker.com/what-container)をご覧ください。

#Docker Composeとは
DockerはDockerイメージからコンテナを取り込んで、そのコンテナ内に環境を構築するのですが、開発環境というのはさまざまなソフトウェアを入れる必要があるので、毎回コマンドを打つのはめんどくさいということで、Docker Composeというツールを使うことで、複数のコンテナを扱うことが可能となります。

#Nginxとは
Webサーバーの一種。Apacheと比較されることが多い。両者の違いについては、[こちら](https://academy.gmocloud.com/qa/20160616/2761)がわかりやすくまとまっていました。

#Webサーバー・・・？？
クライアント（PC,スマホ、タブレット）からブラウザーを利用して、ウェブページにアクセスする際に、ブラウザに対してデータを返すサーバー。うん、[この記事](https://eng-entrance.com/web-server-mechanism)見た方がわかりやすい笑

#感想
やはりまだ一つ一つのコマンドの意味がわからないことが多く、用語を理解するだけで精一杯でした。でも、自分みたいな状態になっている初心者の方は多いかなと思い、このような記事を書いてみました。（頭の整理にもなりました）

#追記（2018年3月18日現在）
「docker-compose exec」というコマンドがわからなかったので、下記のリンクに詳細がありました。
日本語のドキュメントがあるのはありがたい。
http://docs.docker.jp/engine/reference/commandline/exec.html
Web会議に参加しているOSX上で文字起こしするやり方

録画・録音済みのファイルを文字起こしする方法は出て来るが、リアルタイムのは見つからなかったので整理した。

# 概要

もともとPCから出力されていた音声に自分のマイク入力を加えたものをPCへの入力に繋げば良い。
Soundflowerの入力と出力が難しくて頭がこんがらがる・・・
その場で音声を聞く必要がなかったり自分の音声を入れる必要がなかったりすればSoundflowerだけでよい。
他のスピーカやマイクを使う場合は読み替えてください。

## 手順

1. Soundflowerを入れて出力を入力につなぐ。
2. Audio MIDI設定で出力先を内蔵出力とSoundflowerにteeする。
3. システム環境設定で出力を作ったやつにする。入力はSoundflowerでよい。
3. LadioCastでマイク入力をSoundflowerに合流させる。
4. おもむろにGoogle docsを開いて Command + Shift + S。

# 詳細

## Soundflower

https://github.com/mattingalls/Soundflower/releases/ からダウンロードしてインストールする。
High Sierra以上だとインストールしようとするとセキュリティ警告が出るので許可をしてから再度インストーラを走らせる必要がある。
これは入れるだけで良い。

## Audio MIDI設定

Command + Space から Audio MIDI設定.app を起動する。
左下の+マークから複数出力装置を選択し新規追加し、内蔵出力とSoundflower(2ch)を選択する。
下の記事にあった通り。
https://apple.stackexchange.com/questions/221980/os-x-route-audio-output-to-audio-input
![スクリーンショット 2018-03-16 17.15.17.png](https://qiita-image-store.s3.amazonaws.com/0/244115/6f78bf7d-51ab-0148-e521-6f2bb477731a.png)

## システム環境設定

出力はこのようにする。入力はSoundflower(2ch)に設定する。

![スクリーンショット 2018-03-16 17.17.48.png](https://qiita-image-store.s3.amazonaws.com/0/244115/8fe6ddab-9a40-33c2-6ed1-d878c57e676d.png)


## LadioCast

https://itunes.apple.com/jp/app/id411213048 からApp Storeに行ってインストール。
起動して、内蔵マイクをSoundflower(2ch)につなぐ。他の設定は不要。

![スクリーンショット 2018-03-16 17.18.42.png](https://qiita-image-store.s3.amazonaws.com/0/244115/36349a5f-8832-181d-378b-0f3b07734f12.png)

## Google docs

Command + Shift + S 又は ツール → 音声入力 で音声入力開始。
おそらく精度が他のよりいいが、入力中に編集できないしブラウザのフォーカスも外せないのが欠点。
共有にして他の人に校閲してもらうといい気がする。
他の音声認識できるツールでいいのがあれば使いたい。

# 注意

普通に無視される発言があったりする。もともと現状の音声認識に限界があるので諦めてください。
MACでアプリアイコンのアルファチャンネルを削除する。

#MACでアプリアイコンのアルファチャンネルを削除する。

Appceleratorstudio使っていて、以下のエラーが発生しました。
```
[WARN]: The default icon "DefaultIcon.png" contains an alpha channel and will be flattened against a white background
[WARN]: You may create an image named "DefaultIcon-ios.png" that does not have an alpha channel in the root of your project
[WARN]: It is highly recommended that the DefaultIcon.png be 1024 x 1024
```

えーと。

"DefaultIcon.png"はアルファチャンネルを含んでいるなりよ。
プロジェクトのルートにアルファチャンネルを含んでいない"DefaultIcon-ios.png" を作成できるなりよ。
DefaultIcon.png のサイズは 1024 x 1024 なりよ。


うん。
アルファチャンネルを含んでいるのがだめなのね。

教えてサポーター。
Q.
```
Can "DefaultIcon - ios.png" be created with the function of Appcelerator Studio?
```

A.
```
No, create it on your PC with the recommended size then place it. Make sure no alpha channel. You can do it in your mac photo application software (Preview).
Thanks
```

サンキューサポーター

画像開く → メニューバーから「ファイル」→「書き出す」→ フォーマット欄にある「アルファ」のチェックを外す

できた！
python3+scapy

`scapy`とはpythonでもネットワークプログラミングができるライブラリのことです。

今まで`scapy`はpython2のみ対応で、python3で使おうとすると有志が作った`scapy-python3`というライブラリを使う必要がありました。さらにこの`scapy-python3`、微妙に更新が遅いのかIPv6周りのバグが残ったままの様子……。

ですが2017年11月ごろにとうとう本家もpython3に対応、2018年3月16日現在ではrc版ではありますが無事に使えることを確認しましたので共有しておきます。

またこちら`Ubuntu 16.04`での話となりますのでご注意ください

## インストール方法
`pyenv+virtualenv`を使った場合で説明します。

先に説明しておくと、`scapy`は受信パケットの確認に`tcpdump`を使ったりする関係で`root`権限で実行したほうが良いです。

ただ`sudo`ですと今度は`pyenv`のパスが上手く引き継がれないなどの影響があります。もちろん上手く`sudo`にパス変数を引き継がせることも`visudo`などで可能ですが、今度は`tcpdump`へのパスが……などと複雑になっていくためオススメしません。

というわけで今回は`root`用に`pyenv`が既にインストールされている、という前提でやっていきます。

もっと手っ取り早く、`root`からでも実行できるようにシステムにpython3をインストールしてしまって、細かいバージョンは気にしない、というのも可能ですが、流石に乱暴な気がするので止めておきます。

```bash
cd test_scapy_python3
sudo su
pyenv local 3.6.4
python -V # 3.6.4と表示されるはず
python -m venv .venv
source .venv/bin/activate

pip install --pre scapy
# `--pre`をつけてrc版を使うようにしないと現状(2018/03/16)python 3.6.4では動きません
```

## コード
基本的にpython2の頃と変わりませんので、他の方の書いた記事などを見て回ると良いと思います。ここではUDPパケットを送る例をサンプルとして置いておきます

```python:send_udp.py
import scapy.all as scapy

packet = scapy.IPv6(dst='2001:1:1:11::2', src='2001:1:1:11::555')
packet.show()
scapy.send(packet/scapy.UDP())
```

## 実行方法
```bash
cd test_scapy_python3
sudo su
python -V # pyenvの設定が正しければ3.6.4と表示されるはず
source .venv/bin/activate
python send_udp.py
```

## まとめ
もちろんC言語でパケットを送るより自由度は減りますが、L2レベルでEthernetフレームの中身も指定できますし、極端に変なことをしないのであれば簡単にネットワークプログラミングができると思います。

また今後`scapy`もrc版ではなくて本リリースでpython3に対応すると思いますし。

後はMacで使う方法ですが……試したことはないですがsudoつけたりするだけで行けるんだろうか……？ もしコメントなどで教えて頂ければ幸いです。

## 参考
本家: https://github.com/secdev/scapy
python3対応に関するissue: https://github.com/secdev/scapy/issues/657
運用で作ったツールやら豆知識

# 目次
- [運用当番を決めるプログラム](https://qiita.com/shota-nekoneko/items/469b742b375a7d369355)
- [redmineのdbをlinuxからwindowsサーバにバックアップ](https://qiita.com/shota-nekoneko/items/a21d071d2c1993c3191e)
- [OracleのdumpファイルからDDLを抜き出す](https://qiita.com/shota-nekoneko/items/e6dea944349e7eab379b)
Laravelでパスごとにエラービューを出し分ける

Laravelではexceptionのハンドリングを `app/Exceptions/Handler.php`で指定できます。
このクラスの実装は大半が親クラスの`Illuminate\Foundation\Exceptions\Handler`にあるので、
参考にしながらメソッドをオーバーライドしていきます。

```php:app/Exception/Hander.php
    /**
     * Prepare a response for the given exception.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception $e
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function prepareResponse($request, Exception $e)
    {
        if (! $this->isHttpException($e) && config('app.debug')) {
            return $this->toIlluminateResponse(
                $this->convertExceptionToResponse($e), $e
            );
        }

        if (! $this->isHttpException($e)) {
            $e = new HttpException(500, $e->getMessage());
        }

        // パスごとにエラーのviewを分岐する
        return $this->toIlluminateResponse(
            $this->customRenderHttpException($request, $e), $e // ここがparentのものと差し替わっている
        );
    }

    /**
     * parentのrenderHttpExceptionを改変してrequestパスごとに分岐するようにしたもの
     * @param Request $request
     * @param \Symfony\Component\HttpKernel\Exception\HttpException  $e
     * @return \Symfony\Component\HttpFoundation\Response
     */
    private function customRenderHttpException(Request $request, HttpException $e)
    {
        $status = $e->getStatusCode();

        $paths = collect(config('view.paths'));

        view()->replaceNamespace('errors', $paths->map(function ($path) use ($request) {
            return $request->is('admin/*') ? "{$path}/admin/errors" : "{$path}/service/errors"; // viewを分岐
        })->push(__DIR__ . '/views')->all());

        if (view()->exists($view = "errors::{$status}")) {
            return response()->view($view, ['exception' => $e], $status, $e->getHeaders());
        }

        return $this->convertExceptionToResponse($e);
    }
```

今回は`admin/`以下にアクセスが来たときは`/views/admin/errors`にそれ以外のときは`/views/service/errors`に振り分けます。

親クラスに`convertExceptionToResponse`というメソッドがあってそこだけ書き換えられればよかったのですが、パスで分岐するためには`\Illuminate\Http\Request`が引数に必要で、それが無かったので、`prepareResponse`メソッドから書き換えています。
WSL導入時にしたこと

WSLを導入時に自分でやったことのまとめ
[参考サイト1](http://www.atmarkit.co.jp/ait/articles/1608/08/news039.html)
[参考サイト2](http://www.clear-code.com/blog/2017/11/8.html)
[参考サイト3](http://system-admin-girl.com/comic/begins/sp-wsl/)
多分専門的にやる方は2の方がWSLの利点が分かりやすいと思われます．


#WSLとは
Windows Subsystem for Linuxの略でLinuxのアプリをwindows上で実行することのできる機能．今までのCygwinなどといｔったソフトとの違いはLinux環境用のプログラムが動作するようになったこと．
LinuxのデスクトップやMacOsのように「普段の操作をGUIで行いつつ，定型的な処理を素早く済ませたい場合に端末を開く」といった操作をwindowsで可能とする．

#インストール手順
上記の参考サイト1を参考に．
[プログラムと機能]から[windowsの機能の有効化または無効化]を開き[Windows Subsystem for Linux]にチェックを入れ再起動．その後Microsoft StoreでLinuxと検索しディストリビューションの中からUbuntuを選択．
その後ユーザー名とパスワードを設定．

#初期設定
参考サイトに書いてあったような```sudo```の必要はなかった．
今回はrubyとgitをインストールする．
まず，

```bash
sudo apt-get install ruby
```

としたところ

```bash
E: Failed to fetch
```

というエラーが発生したので調べたところ```apt```のアップデートが必要とのこと．

```bash
sudo apt-get update
```

とすることにより解決．

```bash
sudo apt-get install ruby
sudo apt-get install git
```

インストール完了．

#Linuxディレクトリとwindowsディレクトリの場所関係
WSL上のLinux環境からはWindowsのファイルが```/mnt/c```という場所にある．WSLをそのまま起動した場合の初期位置は```/home/username```となっている．
Windows上で作成したファイルの確認をしたい機会も多いであろうし、めんどくさいのでシンボリックリンクを作成．

```bash
ln -s /mnt/c/Users/username ~/Home
ln -s /mnt/c/Users/username/Desktop ~/Desktop
```

#その他
複数のディストリビューションがある場合windowsのコマンドプロンプト上で

```cmd
wsl config /list
```

と打てばインストール済みのディストリビューションが確認できる．
またその中からwslというコマンドで実行される既定のディストリビューションを指定したい場合

```cmd
wslconfig /s ubuntu
```

と打てばよい．
その後windowsのコマンドプロンプト上で作業したいディレクトリに移動し

```cmd
C:\Users\username\Desktop\github> wsl
username@ubuntu:/mnt/c/Users/username/Desktop/github$
username@ubuntu:/mnt/c/Users/username/Desktop/github$ exit
C:\Users\username\Desktop\github>
```

という風にそのディレクトリ上ででWSLを起動することができる．
また，毎回WSL起動しなくても例えば```ls```コマンドのみ実行したい場合

```cmd
C:\Users\username\Desktop\github> wsl ls
test.txt
```

といったように```wsl```の後にコマンドを入れておけばその一瞬だけWSLが起動しコマンドを実行してくれる．
ただし，このとき実行できるコマンドは1つだけなのに注意すること．複数実行したい場合```bash -c```などの工夫が必要．

#まとめ
WSL導入時にしたことを自分用にメモ書きした．
windowsとファイルを行き来する場合において，仮想マシンより使いやすいと感じたので使いわけていきたい．
WebpackでXMLHttpRequestを扱う

`xmlhttprequest`を利用していると、Webpackのビルド中にエラーが起きる。

```
ERROR in ./node_modules/xmlhttprequest/lib/XMLHttpRequest.js
Module not found: Error: Can't resolve 'child_process' in '/path/to/node_modules/xmlhttprequest/lib'
```

検索してみるとWebpackのIssueで同じ問題を投げている人がいた。 [Cannot resolve module 'child_process' to build XMLHttpRequest #66](https://github.com/webpack/webpack-dev-server/issues/66)

そこで書かれている解決策は`webpack.config.js`に次の設定を入れるというもの。

```js
externals:[{
    xmlhttprequest: '{XMLHttpRequest:XMLHttpRequest}'
}]
```
redmineのdbをlinuxからwindowsサーバにバックアップ

# redmineのdbをバックアップ

```mysql_backup.sh
#!/bin/sh

dumpfile=/tmp/redmine_`date "+%Y%m%d%H%M"`.dump

find /tmp -mtime +14 -name '*_*.dump' -exec rm -f {} \; >/dev/null 2>&1
mysqldump --defaults-extra-file=/etc/redmine_my.cnf --single-transaction redmine > $dumpfile

exit 0
```

# 取得したdumpをwindowsサーバにアップロード

```send_file_srv.bat
set DATE_NOW=%date:~0,4%%date:~5,2%%date:~8,2%
set TARGET_DIR=\\Foo\hoge\redmine\%DATE_NOW%
mkdir %TARGET_DIR%

cd "%~dp0%"
start "send_dump"
cscript send_file_srv.vbs

timeout 5
cp *.dump %TARGET_DIR%
del *.dump

pause
```

```send_file_srv.vbs
set WshShell = WScript.CreateObject("WScript.Shell")
strScpCmd = "scp -P 4400 foo@hoge:/tmp/redmine_"+ Replace(Left(Now(),10), "/", "")+"*dump .~"
WshShell.AppActivate "send_dump"
WshShell.SendKeys strScpCmd
WScript.Sleep 10000
WshShell.SendKeys "PASSWORD~"
WScript.Sleep 1000
WshShell.SendKeys "exit~"
```
OracleのdumpファイルからDDLを抜き出す

# 参考サイト
[export した dump から DDL を作成する方法 with Perl ワンライナー](http://d.hatena.ne.jp/yohei-a/20100123/1264269784)

# 前提
Oracleのダンプファイルは事前に取得済みの状態

# DDLをダンプから抜き出し
```
imp system/{パスワード} file=oracle.dmp show=y log=imp.log FULL=y
```

# 実行可能なDDLに整形
```
perl -ple '/^ "/ or s/.*//;s/^ "(.+)"$/$1/;s/^(CREATE|ALTER|ANALYZE|GRANT|COMMENT|AUDIT)/\/\n\n$1/i;END{print "\/"}' imp.log > ddl.sql
```
#おまけ
```表領域の確認.sql
col OWNER   format A20
col s_bytes format 999,999,999,999
select TABLESPACE_NAME,OWNER,sum(BYTES) s_bytes from dba_segments group by OWNER,TABLESPACE_NAME order by TABLESPACE_NAME,OWNER;
```
```ユーザーのパスワード忘れちゃったら.sql
--DBA_USERSを参照し、ユーザ名とパスワードを取得します
--例としてSYSを使用します

SELECT USERNAME,PASSWORD FROM DBA_USERS;

USERNAME                       PASSWORD
------------------------------ ------------------------------
SYS                            hogehoge　(←適当な値にしてます)
・
・
・
--SYSのパスワードをここでは「test」に変更します
ALTER USER SYS IDENTIFIED BY test;

--SYSでログインします
CONNECT SYS/test@&接続文字列 AS SYSDBA

--何らかの作業を行う

--DBA_USERSを参照して取得していたパスワードに戻します。
ALTER USER SYS IDENTIFIED BY VALUES 'hogehoge';

--参考
http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=305
```
【簡単】EC2でのCloudWatchLogsの使い方

### CloudWatchLogs

> Amazon CloudWatch Logs を使用して、Amazon Elastic Compute Cloud (Amazon EC2) インスタンス、AWS CloudTrail、Route 53、およびその他のソースのログファイルの監視、保存、アクセスができます。 その後、CloudWatch Logs から、関連するログデータを取得できます。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html


## メリット
- 5分でログ出力まで確認できるぐらい導入が容易。
- 設定内容がシンプル。
- 保存期間が柔軟。（失効しないも可）
- S3にエクスポートできる。
- オートスケールも対応可。


## IAM
下記のキーが必要になりますので、IAMユーザを作成して取得しましょう。
既存のCloudWatchLogsFullAccess権限を付ければ動かせます。

```
aws_access_key_id
aws_secret_access_key
```

## インストール
エージェントを入れます。

```
$ yum install -y awslogs
```

次に認証情報を設定します。
IAMで取得したキーを設定しましょう。

``` /etc/awslogs/awscli.conf
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
aws_access_key_id = {aws_access_key_id}
aws_secret_access_key = {aws_secret_access_key}

```

ログ出力の設定をします。
awslogs.confの一番下に/var/log/messagesの設定がデフォルトで入っているので、
もし試したいだけならこのままでOKです。
デフォルト設定なら「/var/log/messages」グループの配下にインスタンス名のファイルが出力されていきます。

|項目|内容|
|:-----------------|:------------------|
|file|保存対象のファイル|
|log_stream_name|ファイル名|
|log_group_name|グループ名|

``` /etc/awslogs/awslogs.conf
[/var/log/messages]
datetime_format = %b %d %H:%M:%S
file = /var/log/messages
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/log/messages

```

サーバ起動時に自動で起動するように設定してスタートします。
すぐに反映されるので、CloudWatchの左側のメニューにある「ログ」を見てみてください。

```
$ chkconfig awslogs on
$ service awslogs start
```



## 最後に
fluentdも便利ですが、単純にログ保存だけならこれで事足りますし、
何より設定がほとんどなくて簡単に使えるので、用途に合ってる場合はどんどん使っていきましょう。
Let's Encryptがワイルドカード証明書(ACMEv2)に対応したので使ってみた

# はじめに
ACMEv2対応のアナウンスが来ていたので実験してみました。

- [ACME v2 and Wildcard Certificate Support is Live](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579)
- [ACME v2 Production Environment & Wildcards](https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578)

Let's Encryptで以前の形式（ACMEv1）の証明書を取得・設定する方法はこちらの投稿を参考にしてください。

- [Let's Encryptを利用してApache 2.4サーバをHTTPS化する - Qiita](https://qiita.com/ariaki/items/5680cb6da6223844af4e)

## 証明書の発行
前回の記事と同じく `certbot` を使い、以下のコマンドを使って証明書を発行しました。
v1の時と違いDNS TXTレコードを使ったACME認証が必要になりますので、設定中にDNSレコードを書き換える必要があります。

```shell:コマンド
certbot certonly --agree-tos --manual-public-ip-logging-ok --manual -d [ドメイン名] --preferred-challenges dns-01 --email [管理者のメールアドレス] --server https://acme-v02.api.letsencrypt.org/directory
```

```shell:実行例
certbot certonly --agree-tos --manual-public-ip-logging-ok --manual -d "*.yourdomain.jp" --preferred-challenges dns-01 --email admin@yourdomain.jp --server https://acme-v02.api.letsencrypt.org/directory
```

- `--manual-public-ip-logging-ok`オプションを使ってIPロギングを承認します。
- `--preferred-challenges dns-01`オプションを使ってDNS TXTレコード認証を承認します。
- `--server`オプションでACMEv2に対応したエンドポイントを設定してください。
- ドメイン名の箇所は「"*.yourdomain.jp"」のようにワイルドカードをつけダブルクオートで囲みます。

途中で以下のようなメッセージが表示されます。
指示に従いTXTレコードを設定してからENTERキーを押下します。
このレコード値はコマンド実行のたびにランダムな文字列が表示されます。
※DNS未波及等でコマンドが失敗する場合があるので、TXTレコードのTTLを短めに設定しておく方がよいです。

```
-------------------------------------------------------------------------------
Please deploy a DNS TXT record under the name
_acme-challenge.yourdomain.jp with the following value:

WFek9KSKZ2Hv7tVIHtmC3l41pdx36xOIglWOufYq_iw

Before continuing, verify the record is deployed.
-------------------------------------------------------------------------------
Press Enter to Continue
```

ENTER押下後にDNSレコードが確認され、問題なければ[v1と同じファイル構成](https://qiita.com/ariaki/items/5680cb6da6223844af4e#証明書の初回作成)の証明書が発行されます。
CentOS 6.X > 外部パッケージELRepoのrpmファイル名を見つける (2018-03-16版)

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
GeForce GT 730 1GB GDDR5
CentOS 6.9 (64bit)
NCAR Command Language Version 6.3.0
for WRF3.7.1, WPS3.7.1
  openmpi-1.8.x86_64 とその-devel
  mpich.x86_64 3.1-5.el6とその-devel
  gcc version 4.4.7 (とgfortran)
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

### 関連

- [CentOS6.x yum外部リポジトリまとめ(2014/01版)](https://qiita.com/m2wasabi/items/6d6a68da2e9dada92369#elrepo)

### ELRepoのrpmファイル

ELRepoのインストールとして以下のようなコマンドを実行する。

```bash
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm 
```

2つ目のコマンドの情報は月日が経過することで、obsoleteとなる（release-6-8の部分が変わっていく)だろう。

情報がobsoleteになった時、どのようにして取得するファイルを見つけるのがいいだろうか?

### ファイル名を見つける

#### 方法1 > elrepo.org/linux以下を確認

http://elrepo.org/linux/elrepo/el6/x86_64/RPMS/
以下に見つかるファイルで確認する。

```
elrepo-release-6-8.el6.elrepo.noarch.rpm                     23-Jul-2017 13:02  7.6K  
```

#### 方法2 > tikiを確認する 

http://elrepo.org/tiki/

> To install ELRepo for RHEL-6, SL-6 or CentOS-6:
> `rpm -Uvh http://www.elrepo.org/elrepo-release-6-8.el6.elrepo.noarch.rpm`
MacのRMagickのインストールでエラーになる件

手元の環境は以下

---

- Mac
    - `macOS High Sierra 10.13.3`
- Ruby
    - `ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin17]`
- Rails
    - `Rails 5.0.2`
- RMagick
    - `2.16.0`

---

ググってよくある方法としては、なんとかしてhomebrewでinstallしたimagemagickを`imagemagick@6`に`force link`させる等でglobalにimagemagickのバージョンを下げている例を見かけるが、
数あるrepositoryの一つに依存して全体のimagemagickのバージョン下げるとかやりたくなかったので何かいい方法ないかと模索したところ、
`imagemagick@6`をkeg onlyでdownloadした状態で、direnv等で以下を設定した上で`bundle install` 叩くとcompileうまくいきそうということが判明。
(ただし動作確認まではちゃんとしてないので要注意)

```sh
export PKG_CONFIG_PATH=/usr/local/opt/imagemagick@6/lib/pkgconfig
```

まぁぶっちゃけちゃんとdocker環境作ったりするのが今のトレンドだと正攻法な気もするが、
↑みたいなところでつまるプロジェクトは往々にしてdocker化も結構しんどかったりするので。
RPMからVespaをインストール(for CentOS7)

RPM向けのQuick Startが見当たらないので書いてみた。

# インストール

```bash
$ sudo yum-config-manager --add-repo https://copr.fedorainfracloud.org/coprs/g/vespa/vespa/repo/epel-7/group_vespa-vespa-epel-7.repo

$ sudo yum -y install epel-release centos-release-scl
$ sudo yum -y install vespa
```

# 起動

```bash
$ sudo systemctl start vespa
$ sudo systemctl start vespa-configserver
```

# サンプルを試す

deploy

```bash
$ git clone https://github.com/vespa-engine/sample-apps.git
export VESPA_SAMPLE_APPS=`pwd`/sample-apps

$ /opt/vespa/bin/vespa-deploy prepare $VESPA_SAMPLE_APPS/basic-search/src/main/application/

$ /opt/vespa/bin/vespa-deploy activate

```

データをFeed

```bash
$ curl -s -X POST --data-binary @${VESPA_SAMPLE_APPS}/basic-search/music-data-1.json \
    http://localhost:8080/document/v1/music/music/docid/1 | python -m json.tool
$ curl -s -X POST --data-binary @${VESPA_SAMPLE_APPS}/basic-search/music-data-2.json \
    http://localhost:8080/document/v1/music/music/docid/2 | python -m json.tool
```

クエリーを投げてみる

```bash
$ curl -s http://localhost:8080/search/?query=bad | python -m json.tool
```

参考URL
http://docs.vespa.ai/documentation/
http://docs.vespa.ai/documentation/vespa-quick-start.html
macOSのアップデートでBreakaway Boxが動かなくなった場合の対処法

## 概要
表題の通りの状態に陥り、簡単なことなのに無駄に時間を浪費したため、
同じ轍を踏む方(はいないと思いますが・・・)出ないように記録を残します。

macOS HighSierra 10.13.3
Sonnet Breakaway Box 350
GeForce GTX1080

## 経緯
macOSを10.13.3にアップデート後、eGPUが認識されない状態になった。

## 対処方法
**Nvidia eGPU用のドライバーを、OSのバージョンに合ったものにする。**
ただそれだけです。バージョンが合って無ければ動くはずがないです。

以下のページよりお使いのOSのバージョンに合ったドライバーをダウンロードし、インストールしてください。
https://egpu.io/forums/mac-setup/wip-nvidia-egpu-support-for-high-sierra/

## 参考
[Macで外付けGPU使用しTensorflow GPUをソースからコンパイル(1.4/1.5対応)](https://qiita.com/mm_sys/items/c169fe0ef37862c39a30)
Dart static

##static
class宣言の中の変数メンバにstaticをつけると、クラス変数になり、そのクラスのインスタンスに関係なくただひとつそのオブジェクトが用意される。
new ~~でクラスのインスタンスを生成せずに使用可能

```dart:static
class Name {
  static final TARO = 'Taro';
  static final JIRO = 'Jiro';
  final saburo = 'Sanro';
}

main(){
  print(Name.taro);// Taro
  print(Name.saburo);//No static getter 'saburo' declared in class 'Name';
}
```
SystemTests時の unknown error: call function result missing 'value' の対処法

Rails の System Tests で次のエラーがでるのは chromedriver が古いのが原因のようです。

```text
Selenium::WebDriver::Error::UnknownError:
  unknown error: call function result missing 'value'
    (Session info: headless chrome=65.0.3325.162)
    (Driver info: chromedriver=2.33.506106 (8a06c39c4582fbfbab6966dbb1c38a9173bfb1a2),platform=Mac OS X 10.12.6 x86_64)
```

コマンドラインで `chromedriver-update` を実行すると直ります。

chromedriver-update は chromedriver-helper gem に入っているコマンドです。

chromedriver-helper gem を使ってない場合は
https://chromedriver.storage.googleapis.com/index.html
から自力で取ってくる必要があります。

macでhomebrewを使っている場合はupgradeしましょう。

```bash
$ brew upgrade chromedriver
```

# 参照

unknown error: call function result missing 'value' for Selenium Send Keys even after chromedriver upgrade - Stack Overflow
https://stackoverflow.com/questions/49162667/unknown-error-call-function-result-missing-value-for-selenium-send-keys-even
mac の git-completion.* はどこにあるか

mac os x の git-completion.* はどこにあるか.

追記

https://qiita.com/sheercat/items/f952e892637a4da3aa4e



```shell
/Library/Developer/CommandLineTools/usr/share/git-core/git-completion.tcsh
/Library/Developer/CommandLineTools/usr/share/git-core/git-completion.zsh
/Library/Developer/CommandLineTools/usr/share/git-core/git-completion.bash
```

ここでした。(xcode の commandlinetools git の場合)
Project Euler 56「もっとべき乗の数字和」

かい…かん

# Problem 56 「もっとべき乗の数字和」
Googol (10^100)は非常に大きな数である: 1の後に0が100個続く. 100^100は想像を絶する. 1の後に0が200回続く. その大きさにも関わらず, 両者とも数字和 ( 桁の和 ) は1である.
a, b < 100 について自然数 a^b を考える. 数字和の最大値を答えよ.

```python
def hoge(num):
    return max(sum((lambda l: (int(x) for x in l))(str(a**b)))
               for a in range(1, num)
               for b in range(1, num))

print(hoge(100))
```

## カンニング後追記
こういう時にmap関数を使うんですね。
普段使ってないから全然出てきませんでしたわ。


```python
map(int, str(a**b))
```

```python
(lambda l: (int(x) for x in l))(str(a**b))
```

上の2つは同じことをやってる（つもり）。
cd ../../../../../が嫌いな人向けalias

#モチベーション
cd ../../../../../../../ってタイプするの死ぬほどめんどくさいじゃん。

pushd、popdである程度は解決できるが、解決できない時もある。例えばtmuxやscreenとか使ってペインを作った時。
カレントディレクトリは引き継ぐけどpushdのディレクトリスタックは引き継がないため、
上位ディレクトリに行く時はcd ../../../../打つしかない。

ぐぐってもこれを解決しようとしている人には出会ったことがなかったから、自分で解決することにした。

#コード
以下のコードをbashrcに貼って快適な生活を手に入れよう。

```sh:.bashrc
isNum() { 
  if [ $# -ne 1 ]; then
    return 1
  fi
  expr "$1" + 1 >/dev/null 2>&1
  if [ $? -ge 2 ]; then
    return 1
  fi
  return 0
}

dirUp () {
  hierarchy_path=""
  isNum "$@"
  if [ $? -eq 0 ]; then
    for i in `seq 1 $1`
      do
        hierarchy_path=${hierarchy_path}"../"
      done
      \cd $hierarchy_path
  else
    \cd "$@"
  fi
}

alias cd="dirUp"
```

#How to use

```shell
$ pwd
/home/hugashy/project/hoge/bar/foo/

$ cd 3
$ pwd
/home/hugashy/project
```

cdコマンドの引数として数字を与えるとその数字分だけ上位ディレクトリに移動できる。

#ダメな所
ディレクトリ名が数字のディレクトリに移動できない。
一応回避策は用意していて

```sh:数字ディレクトリ名への移動
$ cd 3 適当な文字列
```

と数字の後に１つ適当な引数を加えてやると正しく数字のディレクトリに移動できる。
というよりは「cdの引数が1個の場合、かつ数字の場合」という条件で上位ディレクトリに移動させているだけなので、その条件から外れる場合は普通のcdと同じ。

#最後に
あんまり綺麗な実装じゃないけど、../../../../../../のストレスから開放される喜びを皆さんにも体験していただきたい。
bundle exec rails generate devise:install で 「Could not find generator 'devise:install'.」とエラー

Gemfile に以下を加えて、
```gem 'devise'```
`bundle install`を実行したところ、以下のようなエラーが出た。

> Running via Spring preloader in process 5177
Could not find generator 'devise:install'. Maybe you meant 'assets', 'generator' or 'coffee:assets'
Run `rails generate --help` for more options.

調べたところ、以下のIssueに行き着いた。
https://github.com/plataformatec/devise/issues/4594

いったんdeviseをアンインストールし、
`spring stop`でspringを止めたうえで、再度Gemfileにdeviseを追加、`bundle install`したところ、generateが成功した。

いっときの不整合かなんかなのかな。。。？
[Python] Django 管理サイトのカスタマイズ（表示面）

##この記事について

Django の管理画面のカスタマイズ方法です。

表示面の修正方法となります。
機能のカスタマイズについては以下のエントリの方を参照してください。

[Django 管理画面逆引きメモ](https://qiita.com/zenwerk/items/044c149d93db097cdaf8)
 
###１．タイトルを変更する

見出し部分は軽微な修正で変更可能です。
プロジェクトのurls.pyに以下のコードを入れます。

```py:project/urls.py
from django.contrib import admin
from django.urls import path, include

# 追加
admin.site.site_title = 'タイトルタグ' 
admin.site.site_header = 'サンプルアプリケーション' 
admin.site.index_title = 'メニュー'

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]
```

**変更後の画面**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/217094/5c56b59a-3587-df01-a525-22c1e7a0955a.png)


### ２．CSSを変更する

adminのcssを上書き指定することでデザインの変更ができます。

手順１．staticフォルダを追加

プロジェクト直下にstaticフォルダを作成し、設定ファイルに以下の項目を追加します。

```py:setting.py

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),  
)

```

手順２．adminのstaticリソースをコピー

作成したstaticフォルダに`/contrib/admin/static`のadminディレクトリ以下を全てコピーします。Ver2.0.3ではこのような構造になります。

```tree
project-root
└─static
  └─admin
      ├─css
      │  └─vendor
      │      └─select2
      ├─fonts
      ├─img
      │  └─gis
      └─js
          ├─admin
          └─vendor
              ├─jquery
              ├─select2
              │  └─i18n
              └─xregexp

```

試しに`static/admin/css/base.css`を変更してみます。

```base.css 
/* 823行目付近*/
#header {
    width: auto;
    height: 40px;
    padding: 10px 40px;
    background: #ff69b4; /* 元は417690(青) */
    line-height: 40px;
    color: #ffc;
    overflow: hidden;
}
```

無事に色が変わりました。あとは変更したい部分を探して更新するだけです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/217094/82addd16-dbc7-b31e-4d5a-7b6d086dca50.png)


この設定方法は**「templateとstaticは、同名のリソースが定義された場合、先に定義された方を採用する」**というDjangoの仕様に基づくものです。管理サイトアプリが使うリソースを管理アプリより先に同名で定義することで読み込むリソースを変更させます。

*※同名とは「static」以下のパス名が同じことを指す。*

staticファイルの定義順はターミナルで`manage.py findstatic admin/css/base.css`と打ち込むことにより確認できます。


###３．テンプレートを変更する

同様の方法でテンプレートの変更も可能です。
プロジェクトの直下に「templates」フォルダを作成し、設定ファイルの`TEMPLATES`を修正します。

```py:settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], #★ここを変更
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

```

そしてtemplatesフォルダにstaticと同様に`contrib/admin/templates`以下のディレクトリをそのままコピーします。Ver2.0.3ではこうなりました。

```
project-root
└─templates
  ├─admin
  │  ├─auth
  │  │  └─user
  │  ├─edit_inline
  │  ├─includes
  │  └─widgets
  └─registration
```

試しに`/templates/admin/base.html`を修正してみます。

```base.html
<-- 39行目付近 -->
{% if site_url %}
     <a href="{{ site_url }}">アプリに戻る</a> /
{% endif %}
```

もともと「サイトを表示」という表示でしたが、「アプリに戻る」に変更されました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/217094/2f843b79-b652-676d-5983-09a788a010d2.png)


上の手順でstaticとtemplatesのファイルを丸ごとコピーしましたが、実際は変更するファイルだけでOKです。
createアクションからデータベースへ保存が出来ない

現在、ruby on railsにて、入力したフォームをcreateアクションを通して、データベースへの保存を試みています。

その中で、new.html.erbからcreateアクションを経由してデータベースに情報を保存したいのですが、以下のうち、**first_name**しか保存されません。

また、**company**については入力をするのですが、**/posts/31**とidに切り替わってしまいます。

createを通して、データベースに複数データを保存するにはどうすれば良いのでしょうか？

以下、それぞれの現在のプログラミング内容を記載します。


### posts_controller.rb
```
class PostsController < ApplicationController

  def index
  	 @posts = Post.all.order(created_at: :desc)
  end
  
  def show
  	@post = Post.find_by(id: params[:id])
  end
  
  def new
    @post = Post.new
  end
 
  def create
    @user = User.new(company: params[:compamy], first_name: params[:first_name], last_name: params[:last_name])
  end
    
end

```


### route.rb
```
Rails.application.routes.draw do
  get 'posts/index' => "posts#index"
  get 'posts/new' => "posts#new"
  post 'posts/create' => 'posts#create'
  get 'posts/:id' => "posts#show"

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```

### new.html.erb
```ここに言語を入力
<%= form_tag("/posts/create") do %>
   	 <table>
      <tbody>
      <tr>
        <th>会社名</th>
        <td><input type = "text" name="company" value="<%= @post.company %>"></td>
      </tr>
      <tr>
        <th>姓</th>
        <td><input type = "text" name="first_name" value="<%= @post.first_name %>"></td>
      </tr>
      <tr>
        <th>名</th>
        <td><input type = "text" name="last_name" value="<%= @post.last_name %>"></td>
      </tr>
      	<td colspan="2">
        <input type="submit" value="登録">
      </form>
      </td>
      </tbody>
    </table>
 <% end%>
```

以上となります。

よろしければ、ご教示よろしくお願い致します。
ACMの自動更新が行われたタイミングで画像や外部ファイルが読み込めなくなった

## はじめに

はじめに言っておきます。
この記事を読んでも事象の根本的解決は出来ません。（根本解決は出来なかったです。）
ただのメモです。

## 環境

* Ruby 2.4.0
* Rails 5系

##### AWS

* Elasticbeanstalk
* S3
* CloudFront
* ACM

関連がありそうなのはこの辺

## 起きた問題

Railsで構築されたアプリケーションがある日突然、画像やCSSが読み込めなくなっていた。
Webブラウザのコンソールを見てみると、以下のようなエラーが頻発していた。

```
ERR_CERT_DATE_INVALID
```

コミットを見ても怪しいものはないから、ソースに問題があるとは考えずらい。
心当たりがあるとすれば、最近ACMで発行されていたSSLの証明書が更新された旨のメールが来ていた。

## 調査したこと

同様に構築されているサイトの設定などと見比べつつ調査を行なった。
時系列に書くので、煩わしいことがあるかと思いますが、適宜読み解いてください。

### 静的ファイルの問題

#### Railsのproduction.rbを編集

image_pathとかで画像を表示させている部分などにもS3経由のパスがあたってしまっているので、`production.rb`を確認することにした。

`production.rb`内に

```
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
config.action_controller.asset_host = 'hogehoge'
```

という記述があったので、上記を以下のようにして、disableに変更

```
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'hogehoge'
```

これでひとまず、静的に読み込ませている部分のpathは、`/assets/`からよんでくれるようになった。

### 動的ファイルの問題

#### S3


まじはS3内の画像があるかどうかを確認した。
画像は格納されていた。

#### Amazon Certificate Manager

SSLの更新が弾かれてる...?
確認すると、問題なく発行されていることが確認できた。

#### Cloudfront

画像の配信をhttpsで行なっているので、Cloudfrontの設定を確認してみることにした。
すると。「SSL Certificate」の項目が「arn...」と表示されていた。

正しく動作しているサイトは、ACMで登録している「ドメイン名」が表示されていた。
明らかに怪しい....

#### またS3

確認し忘れていたけど、S3に格納されている画像のURLを見てみた。
画像などが、表示されていないサイトの画像のパスをみると、「https://s3のバケット名...」 となっていたけど、S3の管理画面で確認できた画像のパスは、「https://s3-リージョン.amazonaws.com/バケット名...」 のようになっていた。

#### またproduction.rbを確認する

あまり詳しくは書けないけど、画像をS3経由でやりとりさせるための設定が書かれていた。


以下例：

```ruby
# 変更前の記述
s3_host_alias: 'https://s3のバケット名...'

# 変更後の記述
s3_host_alias: 'https://s3-リージョン名.amazonaws.com/s3バケット名...'
```

以上でなんとか復旧することが出来たけど、根本原因はわかっていないし、今まで動いてた設定を変更しなければいけなくなったのも最悪の手段だった...

同様の問題に遭遇した方はコメントいただけますと幸いです。
オフラインPC（Windows10）にchainer環境構築(with GPU)

機密データを扱う都合でオフラインPCでchainerの環境構築を行いました。
あんまり同じような人はいないでしょうが、誰かのお役に立てば幸いです。
へなちょこプログラマーにつき、ミスの指摘もアドバイスも大歓迎です。

# 環境
Windows10 home
GeForce GTX1080
Python 3.6.3（Anaconda 5.0.1）
Visual studio 2015 or 2017
CUDA9.1
CuDNN 7.1
Chainer 4.0.0b4
Cupy 2.4.0

# 方法
### Pythonインストール
- オンラインPCでAnacondaのインストーラを入手し、オフラインPCに移動させてインストール

https://www.anaconda.com/download/

### visual studioインストール
- オンラインPCでvisual studioのisoファイルを入手(方法は割愛)してDVDに焼くなり、マウントしてUSBやHDDに入れるなりしてオフラインPCに移動し、visual studioをインストール（**必ずCUDAより先に**）
※今回2017の有償版を入れてますが、オンライン環境であればVS2015のC++BulidToolsのみでOK

https://www.microsoft.com/ja-jp/dev

### CUDAインストール
- オンラインPCでCUDAのインストーラを入手し、オフラインPCに移動させてインストール

https://developer.nvidia.com/cuda-toolkit

### cuDNN適用
オンラインPCでcuDNNのzipファイルを入手し、オフラインPCに移動させて展開し、以下のようにファイルを移動させる

- binに入っているファイル（cudnn64_7.dll）　→　C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin
- includeに入っているファイル（cudnn.h）　→　C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\include
- lib\x64に入っているファイル（cudnn.lib）　→　C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64

詳しくは以下参照 
http://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installwindows

### 環境変数の設定
以下を参考にしました
https://twitter.com/i/moments/820727312010252289

- コントロールパネル→システム→システムの詳細設定→詳細設定のタブの右したにある環境変数のボタンをクリック→システム環境変数のPathを選択し、編集ボタンをクリック→新規のボタンをクリックして以下の4つを追加

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.1\include
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin

### cupy と chainer インストール
オンラインPCでpypiからchainerとcupyのtar.gzファイルダウンロード
https://pypi.python.org/pypi/chainer
https://pypi.python.org/pypi/cupy

chainerを入れるときにfastrlockが必要というエラーが出たのでこれもオンラインPCでpypiからtar.gzファイルをダウンロード
https://pypi.python.org/pypi/fastrlock

- tar.gzファイルをオフラインPCの任意の場所に置く
- オフラインPCでコマンドプロンプト（AnacondaをAlluserで入れた場合は管理者権限）を立ち上げ、tar.gzファイルがあるディレクトリに移動
- ```pip install fastrlock-0.3.tar.gz```を実行（バージョンによって数字は異なる）←chainerより先に入れないとchainerのインストール時にエラー
- ```pip install chainer-4.0.0b4.tar.gz```を実行（バージョンによって数字は異なる）
- ```pip install cupy-2.4.0.tar.gz```を実行（バージョンによって数字は異なる）


※tar.gzファイルでうまくいかない場合、setup.pyを試す

- オンラインPCでGithubからzipファイルをダウンロード
chainer：https://github.com/chainer/chainer
fastrlock：https://github.com/scoder/fastrlock
cupy：https://github.com/cupy/cupy

- オフラインPCにzipファイルを移動させて展開
- コマンドプロンプトを立ち上げ、zipを解凍したファイルがあるディレクトリに移動
- 各パッケージのsetup.pyが存在するディレクトリまで移動
- ```python setup.py install```を実行

pipでのインストールでUnicodeDecodeErrorが出る場合は以下で対応できるそうです
https://qiita.com/ruteshi_SI_shiteru/items/be6a58276bdbd67dc096

## まとめ
Windowsかつオフラインという面倒×面倒ですが、ちゃんとGPUで計算できました！
GPUはやい。すごい。
Discord.pyで音声を流すbotを作る

# 概要
Bot自体の作り方は以下の記事を参考にどうぞ。
[Pythonで簡単なDiscord Botの作り方](https://qiita.com/PinappleHunter/items/af4ccdbb04727437477f)

タイトル通り、Discordにmp3を流すBotを作っていきます。
ざっくり検索した程度ですが、[Discord.py](https://github.com/Rapptz/discord.py)を用いて任意のチャンネルに音声を流す記事やコードが見当たらなかったので、
実際に動くコードも添えて、動作させるまでに自分が詰まったポイントなどを明記していきます。

# 環境
今回自分が使用したOSは**Ubuntu 16.04**です。
やろうと思えばMac, Windowsでもおそらく出来るのですが、動かすまでにコストがかかるイメージがあるので個人的にはLinuxをおすすめしておきます。
VirtualBoxとか使って仮想でもいいのでLinux環境を整えましょう。

# 必要パッケージ
Discord.pyには依存パッケージがあります。
公式に記載されているのは以下の4つ。
- aiohttp
- websockets
- PyNaCl
- libffi-dev

aiohttpとwebsocketに関してはDiscord.pyに依存関係があるためにpipが解決（同時に勝手にインストール）してくれるのですが、
PyNaclとlibffi-devに関しては音声を流すときのみ使用されるために手動でインストールする必要があります。

```sh:Ubuntu16.04でのインストールコマンド
$ pip3 install pynacl
$ sudo apt install libffi-dev
```

以上で必要パッケージのインストールは終了です。


とはいかないんですよね。
公式に記載はありませんが、もう１つ追加で必要なパッケージがあります。
- ffmpeg

ffmpegというコマンドが音声を流すために使用されます。これコードの中身を見ないと気づかないからかなり不親切。
Windows,Macで音声botを実行する場合、この「ffmpegコマンドインストール」する手順をそれぞれのOSでのインストール方法に置き換える必要があります。
ubuntuでは以下コマンドでインストール。

```sh:ffmpegのインストール手順
$ sudo apt install ffmpeg
```
そしてDiscord.pyにはYoutubeのURLを指定して、その音声を流す機能も実装されています。
その機能を使用するために以下のパッケージが必要となります。
- youtube_dl

```sh:youtube_dlインストール手順
pip3 install youtube_dl
```

名前の通り一度Youtubeの動画をローカルに落とすライブラリなので、ご利用は計画的に。。。

#コード

```python:bot.py
import discord

client = discord.Client()

@client.event
async def on_message(message):
    if message.author.bot:
        return

    voice = await client.join_voice_channel(client.get_channel("Discord voice channel ID"))
    if message.content == ("lecture"):
        player = await voice.create_ytdl_player('https://www.youtube.com/watch?v=aFI1SItR8tg')
        player.start()

    if message.content == ("bgm"):
        player = voice.create_ffmpeg_player('bgm.mp3')
        player.start()

client.run("Your discord token")
```

コード自体はとてもシンプルです。
"Discord voice channel ID" や "Your discord token" は皆さんの環境のIDやトークンに変更してください。
チャット欄にlectureと打てばYoutube上のbot作成のレクチャー動画の音声が流れ、
bgmと打てばローカル上に配置した（bgm.mp3を配置するディレクトリはbot.pyと同じところ）bgm.mp3が流れます。

```sh:実行コマンド
python3 bot.py
```

個人的にわからなかったのがボイスチャンネルのID周りだった。
デフォルトではボイスチャンネルIDは表示できなく、Discord側の設定でデベロッパーモードにする必要がある。
あとclient.get_channelに渡すIDの型について、[公式ドキュメント](http://discordpy.readthedocs.io/en/latest/api.html)に明記されていなかったのでコードを読まなきゃダメだったとか。
静的型付けがない弊害。

#最後に
正直な所使い道はあまりないです。。。
一緒にゲームする人の声を録音して、コマンドでその音声を再生するのが一番楽しいかな。
自分の仲間内だと人工音声で流す音声作ってる人もいたり。

Musicプレイヤーとして楽しむなら[既存のもの](https://github.com/Just-Some-Bots/MusicBot)を使用したほうが良いですし。。。
他に何か面白い用途があればコメントで教えてください！
Docker For WindowsをGit Bashで操作するときの改行コード設定

docker for windowsをgitbashで操作するときは、以下の設定にしておく。

![gitbash_line_ending.png](https://qiita-image-store.s3.amazonaws.com/0/38162/e022d15e-db21-02f5-b511-dd34ffdb6ae2.png)

でないと、git cloneしたプロジェクトをマウントしたり、docker buildファイルを転送したときに改行コードがCRLFになり、実行に失敗することがある。

```
-bash: /root/service.sh: /bin/bash^M: bad interpreter: No such file or directory
```
Crytocurrency Calendarをスクレイピング1


[Crytocurrency Calendar][1]という仮想通貨の情報サイトをスクレイピングします。


##ソースコード

```python
import requests
import lxml.html

r = requests.get("https://coinmarketcal.com/")
html = r.text
root = lxml.html.fromstring(html)

time_of_event = root.xpath(
    "/html/body/main/div[3]/section[1]/div[2]/div[3]/article[1]/div/h5[1]/strong")
print(time_of_event[0].text.strip())
#strip()で出力結果の前後の空白を抜け出す
title_of_event = root.xpath(
    "/html/body/main/div[3]/section[1]/div[2]/div[3]/article[1]/div/h5[2]/strong")
print(title_of_event[0].text.strip())
sort_of_event = root.xpath(
    "/html/body/main/div[3]/section[1]/div[2]/div[3]/article[1]/div/h5[3]")
print(sort_of_event[0].text.strip())
content_of_event = root.xpath(
    "/html/body/main/div[3]/section[1]/div[2]/div[3]/article[1]/div/div[1]/p[2]")
print(content_of_event[0].text.strip())
```

##実行結果
15 March 2018
Burst (BURST)
Hard Fork
Dynamic block size and transaction fees, PoC2 protocol, partial Dymaxion code... The fork is planned to happen around block 470 000.

##解説
XPathでHTMLから要素を抜き出しました。Google Chromeから指定のXPathを抜き出すことができます。  
![xpath.gif](https://qiita-image-store.s3.amazonaws.com/0/196215/283cd457-355f-0a41-8e9a-af4b4139a663.gif)
XPathを使う上で注意することは、配列の添え字が0からはじまることでなく1から始まることです。XPathはGoogle Chromeを使うことで抜き出すことができますが、完全なXPathでなく、そのまま使うことはできません。なので自分で補う必要があります。
　サイトでは数十個のエベントがありますが、このソースコードでは1個のエベントしか抜き出すことしかできません。次回ではXPathの指定を工夫して1つのページからすべてのイベントを抜き出してみます。

##参考にした書籍
*Pythonによるクローラー&スクレイピング入門 設計・開発から収集データの解析・運用まで*


[1]:https://coinmarketcal.com/
WordPressで踏み台にされたから対策をしてみた

パスワードの変更だけでなく、ログインURLも変えましょうというお話です。
WordPressならば、Login rebuilderを使えば簡単です。

# 設定しないで踏み台にされた例
この度、www●●●.sakura.ne.jp(●●●.sakura.ne.jp) から不正なメールを送信している状況が確認されました。
という怖い連絡がメールで届きました。

![mail.jpg](https://qiita-image-store.s3.amazonaws.com/0/204110/f4edcd6b-9955-b090-bd55-3d2724e75c76.jpeg)

確かに、不正なメールが大量にでていることがわかりました。

---
# メールの本文はこんな感じです
以下サクラからの連絡です。

弊社にて調査いたしましたところ、お客様にて運営いただいております
プログラムによるものと判明いたしました。

当該のプログラムは以下となります。

/home/●●●/www/blog/88tz3f.php
/home/●●●/www/wp-content/fdgnasi830fnsz.php
/home/●●●/www/wp-content/plugins/ultimate-faqs/Shortcodes/SubmitFAQ.php
/home/●●●/www/wp-content/plugins/wordpress-seo/admin/class-admin-asset-manager.php
/home/●●●/www/wp-content/plugins/wordpress-seo/admin/class-premium-upsell-admin-block.php
/home/●●●/www/wp-content/uploads/2016/01/abennfdr.php
/home/●●●/www/wp-includes/customize/class-wp-customize-upload-control.php
/home/●●●/www/wp-includes/registration-functions.php

上記につきましては、設置されたプログラムによって不正なメールを外部
サーバへ配信しておりましたため、当該プログラムの設置場所となる以下
ディレクトリのパーミッションを"000"へ変更することにより、実行を一時
的に制限いたしました。

# WordpressのログインURLを変更していますか？

デフォルトの場合、
http://www.●●.com/wp-admin.php
のような形になっているので、簡単にログイン画面にアクセスされてしまいます。

---
# プラグインで対応
「Login rebuilder」を利用すると、簡単にログイン画面まわりの制御ができます。
プラグインとして入れられるので、導入・設定は非常に簡単です。

---
# プラグインのインストール
- 管理画面＞プラグイン＞新規追加
- 「Login rebuilder」を検索→「今すぐインストール」
- インストール後、有効化

![log.jpg](https://qiita-image-store.s3.amazonaws.com/0/204110/1c663f96-e79f-6dd4-8de9-2a83327d2331.jpeg)

---
# Login rebuilderの設定
- 管理画面＞左メニューの「設定」＞サブメニューの「ログインページ」

![page.jpg](https://qiita-image-store.s3.amazonaws.com/0/204110/d1182c8e-7fe6-a207-6302-f6daba1fb3ce.jpeg)

---
# ログインページの設定
![setting.png](https://qiita-image-store.s3.amazonaws.com/0/204110/58b37744-a76e-e56a-19b2-98c578ac0b4f.png)


---
# ファイルのアップロード

- 古いファイルはそのまま
- 新しいphpファイルをwordpressのルートにアップする
【JavaScript】headタグ内のmeta情報(keywordsとdescription)を取得できるスクリプト


# そのページのkeywordsとdescriptionを取得できるスクリプト

このページのdescriptionって何設定してんのかな～とか思ったりしたんで作ってみました。
使いどころ？しらんです

# ソースコード
```js
var headChildren = document.head.children;
for (var i = 0; i < headChildren.length; i++) {

  if (typeof headChildren[i].getAttribute('http-equiv') !== "undefined") {
    var propertyHttpEquiv = headChildren[i].getAttribute('http-equiv');
  }
  
  if (typeof headChildren[i].getAttribute('name') !== "undefined") {
    var propertyName = headChildren[i].getAttribute('name');
  }

  if (propertyName === 'description' || propertyHttpEquiv === 'description') {
    window.prompt('description：',headChildren[i].content);
  }
  
  if (propertyName === 'keywords' || propertyHttpEquiv === 'keywords') {
    window.prompt('keywords：',headChildren[i].content);
  }

}
```

これをchromeだったらF12押してデベロッパーツール開いてコンソール画面に張り付けエンター押せばOKです。
設定していないサイトはとれないです。あとサイトによって調整いるかも・・・

# おわり
- jQuery使わないでつくってみました
住所一覧から到達予測時刻を計算する（Googleスプレッドシート＋Google Distance Matrix API）

# 目的
　**「ある時間・ある場所を起点として、複数の場所に行く場合のそれぞれの到着予測時刻」を一挙に計算したかった。**
　具体的に言うと、定時後に会社ビルから色んなところ（日によって異なる）に行く場合に、それぞれいつ頃到着するのか、Google Mapや駅すぱあとで一々調べていくのは面倒だったので、自動化できないかなーと考えたのが始まりです。

　**Google App Scriptの利用は初めて**だったので、学習を兼ねてコーディングしました。
　情報共有のため、本記事を作成しました。（ある程度）

#結論
　算出できました。
　出発時間に「求めた移動時間」を加算すれば、到着予想時刻を求められます。
![ss.png](https://qiita-image-store.s3.amazonaws.com/0/110901/d6809066-4979-551a-4757-069a2f3d1aa7.png)


#内容
　以下のコードによります。
　Google Distance Matrix APIのAPIキーは、[Google Maps Distance Matrix API - API をアクティベートして API キーを取得する](https://developers.google.com/maps/documentation/distance-matrix/start?hl=ja#get-a-key)で取得できます。

**※注: URLパラメータのうち "mode='transit'" だけは、なぜかシングルクォートでくくらないと正しい出力が帰ってきません。**

```javascript:gas1.gs
function calcDptTimeFromSpecificPlaces() {
  var colDst = 2;      // 住所列
  var colRes = 3;      // 結果出力列
  var APIKEY = "hoge"; // Google Distance Matrix APIのAPIキー
  
  var bk = SpreadsheetApp.getActiveSpreadsheet();
  var sh = bk.getActiveSheet();
  var rowLst = sh.getLastRow();
  
  for (var i = 2; i <= rowLst; i++) {   // 2行目から処理
    var org = "皇居"; // 起点となる場所
    var dst = sh.getRange(i, colDst).getValue();
    var url = "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric" + 
              "&language=" + "ja" +
              "&origins=" + org + 
              "&destinations=" + dst +
              "&mode=" + "'transit'" +
              "&departure_time=" + "1521220500" + // "2018/3/16 17:15:00" のUNIXタイム
              "&key=" + APIKEY;
    
    var res  = UrlFetchApp.fetch(url);
    var json = JSON.parse(res.getContentText());
    
    if (json["status"] == "OK") {
      var str_min = json["rows"][0]["elements"][0]["duration"]["text"];
      var min = str_min.replace("分", '');   // "分"を除去
      min = "00:" + min + ":00";             // hh:mm:ss の形式にする
      sh.getRange(i, colRes).setValue(min);
    }
  }
}

```

#課題・展望
- 移動時間1時間以上に対応していません。
- 住所は、ググって手入力しています。"皇居"はAPIで通りますが、お店や会社名などは通ったり通らなかったりなので。だから**「地名から住所を出力するAPI」**なんかがあったら、地名入力しただけで到着時間が算出できるようになるため、捗りそう。

#文献
- [Google Maps Distance Matrix API - スタートガイド](https://developers.google.com/maps/documentation/distance-matrix/start?hl=ja)
- [Google Maps Distance Matrix API -  デベロッパー ガイド](https://developers.google.com/maps/documentation/distance-matrix/intro?hl=ja#DistanceMatrixRequests)：URLパラメータ理解に有用です。
- [teratail - Google Maps Distance Matrix APIでmodeにtransitを指定すると徒歩で取得される](https://teratail.com/questions/74765)：'transit'をシングルクォートでくくる事はここで知りました。
- [Qiita - GoogleDriveSpreadSheet上の住所一覧を地図にプロット](https://qiita.com/tatesuke/items/899cfa6f85350752bc0e) @tatesuke ：似たようなことやってる人いるんやな～と思ったら、友人だった。
Laravelで多次元配列のバリデーション 

# 書き方

inputタグのname属性がcomment[数字][]の場合です。

```php
$validator = Validator::make($request->all(), [
    'comment' => 'required|array',
    'comment.*' => 'required|array',
    'comment.*.*' => 'nullable|string|max:255',
]);

if ($validator->fails())
{
    return redirect()->back()->withErrors($validator->errors())->withInput();
}
```

# 画面例

foreachで展開できなかったので仕方なくforで展開します。

```
@if (old('comment'))
    @for ($index = 0; $index < count(old('comment')); $index++)
        @for ($index2 = 0; $index2 < count(old('comment.'.$index)); $index2++)
            @if ($errors->has('comment.'.$index.'.'.$index2))
                <div style="color:red;">{{ $errors->first('comment.'.$index.'.'.$index2) }}</div>
            @endif
　　　　    <input type="text" name="comment[{{ $index }}][]" value="{{ old('comment.'.$index.'.'.$index2) }}" maxlength="255">
        @endfor
    @endfor
@endif
```