OmniAICreator/Qiita-1.07M huggingface dataset:
TreasureDataのクエリでtimestamp値を含む週の月曜日を計算する

メモ。やりたいことはタイトルの通り。

前提

- timeカラムにbigint型で入っているunix timestamp値を、それを含む週の月曜の日付文字列（yyyy-MM-dd）に変換する
- 週は月曜日始まりとする
- 日付は日本のタイムゾーンで計算する

PrestoのDOW関数とTreasureDataのTD_TIME_FORMAT関数を使う方法があるがどちらにしても長くなってしまった。
もっとスマートに書く方法があれば知りたい。

```sql
-- DOW()を使用
TD_TIME_FORMAT(time - 86400 * (DOW(FROM_UNIXTIME(time) AT TIME ZONE 'Asia/Tokyo') - 1), 'yyyy-MM-dd', 'jst')

-- TD_TIME_FORMAT()を使用
TD_TIME_FORMAT(time - 86400 * (CAST(TD_TIME_FORMAT(time, 'u', 'jst') AS integer) - 1), 'yyyy-MM-dd', 'jst')
```

やってることはどちらも同じで、

1. timeを曜日の番号（月曜を1とする）に変換
2. 月曜までの差の日数分だけtimeからtimestamp値を引く
3. TD_TIME_FORMATで日付に変換
git bashにsolarizedのカラースキームの適用とエイリアス

# git bashにsolarizedを適用させる
solarizedのしろが目に優しいの感じがしていつも使ってるので、git bashにも使ってみる。

## solarizedのカラーコードをダウンロード
[mavnn/mintty-colors-solarized](https://github.com/mavnn/mintty-colors-solarized) ここから、sol.darkとsol.lightをダウロードまたはコピペして任意の場所に置く。

## ~/.bashrcに設定を書き込む
~/.bashrcの中に`source ファイルパス`を書き込む
###例
```bash:~/.bashrc
source d:/Desktop/color/sol.light
```
その後、`source ~/.bashrc`や`bash`とコマンドを打つか再起動すれば設定が反映される。

# 色を変更するエイリアス
```bash:~/.bashrc
alias light='sed -i "s/^source\sd:\/Desktop\/color\/.\+$/source d:\/Desktop\/color\/sol.light/" ~/.bashrc && source ~/.bashrc'
alias dark='sed -i "s/^source\sd:\/Desktop\/color\/.\+$/source d:\/Desktop\/color\/sol.dark/" ~/.bashrc && source ~/.bashrc'
```
これらのエイリアスでファイルパスを自分のものにすれば、`light`または`dark`と打てばsolarizedの色を変えることができる

気分や複数git bashを開いたときに気軽に色を変更できるので便利 :octocat:
DropboxAPIの利用（準備編）

Dropboxの提供するAPIを触る機会がありましたので、使用感などメモしておきます。
このAPIでは、Dropboxと連携し、ログイン、アップロード、ダウンロードなどが簡単にできるみたいです。

公式リファレンス
https://github.com/dropbox/dropbox-sdk-obj-c#xcode-8-and-ios-10-bug

##準備
###アプリの登録
まず、下記のサイトでAPIを利用する上で必要な開発登録を行います。

Dropbox App Console
https://www.dropbox.com/developers/apps

###インストール
Dropboxが提供するSDKのインストールを行います。
今回はcocoapodsにて行いました。

```
pod 'ObjectiveDropboxOfficial'
```

###info.plistの編集
以下ように項目を追加設定します。

```
<key>LSApplicationQueriesSchemes</key>
    <array>
        <string>dbapi-8-emm</string>
        <string>dbapi-2</string>
    </array>
<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>db-<開発登録後にもらえるapp key></string>
            </array>
            <key>CFBundleURLName</key>
            <string></string>
        </dict>
    </array>
```
以下のような設定になります。
![InfoPlistExample.png](https://qiita-image-store.s3.amazonaws.com/0/205256/8ad8d060-09c2-6421-7b41-ff95bc975c9f.png)
※公式リファレンスより引用

##まとめ
ここまでが、実際の利用前の準備になります。
具体的な利用方法に関しては、また別の記事にて書きたいと思います。
プロジェクト間のコメントの単語の類似度の測定


#プロジェクト間のコメントの単語の類似度の測定

Bash on Ubuntu on Windowsで動きます．

1.全てのコメントを抽出
2.コメントを形態素解析し，名詞を抽出
3.名詞それぞれをベクトル化し，コサイン類似度を測る


#必要なソフトウェアのダウンロード

全てのコメントの抽出
https://qiita.com/SatoshiTanoue/private/58d6662cb38505c901d

mecabのインストール

```
$ sudo apt-get install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8
```
numpyのインストール

```
$ sudo apt install python3-pip
$ pip3 install numpy 
```
プログラムのダウンロード

``` 
$ git clone https://github.com/SatoshiTanoue/CosineSimilarity.git
```
#実行

## 1．全てのコメントを抽出


ここで，プロジェクトごとに全てのコメントの解析結果のディレクトリを分ける必要がある．
例，プロジェクトAの全てのコメントを入れたディレクトリ
　　プロジェクトBの全てのコメントを入れたディレクトリ
　　
下記の方法では，コメントを全て同じディレクトリに入れてしまうので，プロジェクトごとに解析結果を別のディレクトリに手動で分ける必要がある．
　　
全てのコメントを抽出の方法は，下記を参照
https://qiita.com/SatoshiTanoue/private/58d6662cb38505c901de

## 2.コメントを形態素解析し，名詞を抽出

文字コードをutf-8に変更．

```
$ cd CosineSimilarity
$ mkdir UTF8
$ mkdir UTF8/projectA 
$ mkdir UTF8/projectB
$ sh converter.sh ディレクトリまでのパス #projectAのすべてのコメントを抽出したファイルがあるディレクトリまでのパスを入れる．
#例　sh converter.sh SampleResult/projectA
$ mv UTF8/*.txt UTF8/projectA/
$ sh converter.sh ディレクトリまでのパス #projectBのすべてのコメントを抽出したファイルがあるディレクトリまでのパスを入れる．
#例　sh converter.sh SampleResult/projectB
$ mv UTF8/*.txt UTF8/projectB/
```
コメントを形態素解析し，名詞を抽出

```
$ sh mecab.sh UTF8/projectA/ > resultA.txt 
$ sh mecab.sh UTF8/projectB/> resultB.txt 
```

二つの結果をマージして，result.txtを作る．
```
$ sh mearge.sh resultA.txt resultB.txt
```

ディレクトリまでのパスは，全てのコメントの抽出を記述する．

## 3.名詞それぞれをベクトル化し，コサイン類似度を測る

結果の例

```
$ python3 CosineSimilarty.py
[ 1.  0.  1.  1.  1.  1.  1.  1.  1.  0.  1.  1.  1.  1.  1.  1.  1.  1.
  0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  0.  1.  1.  1.  0.
  1.  1.  1.  0.  1.  1.  1.  1.  1.  0.  1.  0.  1.  1.  1.  0.  0.  1.
  1.  1.  1.  1.  1.  1.  0.  1.  1.  0.  1.  1.  0.  1.  1.  1.  1.  1.
  1.  1.  0.]
[ 0.  1.  1.  1.  0.  1.  0.  1.  0.  1.  1.  1.  0.  0.  1.  0.  1.  1.
  1.  1.  1.  0.  0.  0.  0.  0.  1.  0.  1.  1.  1.  1.  0.  1.  0.  1.
  1.  1.  0.  1.  0.  0.  1.  0.  1.  1.  0.  1.  0.  1.  0.  1.  1.  1.
  1.  0.  1.  0.  0.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  1.  0.
  1.  1.  1.]
0.640184399664
```

##よくわからなくなったとき

```
$ cd ..
$ rm -rf CosineSimilarty
$ git clone https://github.com/SatoshiTanoue/CosineSimilarity.git
```
をして，手順2に戻ってください

## コメント
限定公開で公開していました、せっかくなので全体公開にしました。
「ブロックチェーンEthereum入門1」の手順が動かないので補足

下記のコラムがWalletのGUIツール込みの説明でいいなと思い、手順通りやってみたら、
ツールの構成が変わっていたのでその補足をします

> ブロックチェーンEthereum入門
> http://www.intellilink.co.jp/article/column/ethereum01.html

以下、上記から引用します

> なお、現在（2016年3月）のところ、Ethereumの開発は活発に行われており、まだ機能や動作が安定していない。
 また、本コラムをお読みいただいたタイミングでは内容が古くなっている可能性があることをご了承いただきたい。

まさにこれ・・・

# Walletの導入

> https://github.com/ethereum/mist/releases
> ページを下にスクロールし、Downloadsからバイナリをダウンロードできる。
> zipファイルを任意の場所に展開する。展開されたディレクトリ配下は次のような構成になる。

``` 
Ethereum-Wallet-win64-0-5-1
│ Ethereum-Wallet.exe
├─locales
└─resources
    └─node
        ├─eth
        │      eth.exe
        └─geth
               geth.exe
```

下記をダウンロードして展開すると、フォルダ構成は下記のようになっている
https://github.com/ethereum/mist/releases/download/v0.9.2/Ethereum-Wallet-win64-0-9-2.zip

eth.exeとgeth.exeがない・・・。

``` 
Ethereum-Wallet-win64-0-5-1
│ Ethereum Wallet.exe
├─locales
└─resources
```

#gethの導入

しかたないので、別途、gethを導入する

下記からたどって、windows版gethをインストールします。
https://geth.ethereum.org/downloads/

geth-alltoolsのzip版をダウンロードして任意のフォルダに展開
https://gethstore.blob.core.windows.net/builds/geth-alltools-windows-amd64-1.7.2-1db4ecdc.zip

#プライベートネットワークの起動

記事内だと、"--genesis genesis.json"オプションでプライベートネットワークを起動しているが、genesisオプションがなくなったらしくエラーが出てうまくいかない。あと、genesis.jsonの構成まで変わってしまってる(>_<)

次のgenesis.jsonで2stepに分けて起動する必要がある。
(参考) https://github.com/ethereum/go-ethereum/wiki/Private-network

<pre>
{
    "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
    "difficulty": "0x200",
    "gasLimit": "2100000",
    "alloc": {
    }
}
</pre>

後は細かい違いはあるものの、おおよそ手順の通りです

test1は任意のフォルダで、中にいろいろできます。
<pre>
geth --datadir ./test1 init ./genesis.json
geth --networkid <任意のid> --port 50303 --datadir ./test1 --maxpeers 0 --nodiscover console 2>> node.log
</pre>

気が付いた点。

- 各所でcoinbaseはehterbaseという名称に変更になっているが、coinbaseという名称も残っている
- ローカルのフォルダ構成はいろいろ変わってる
- miner.stop()は数値を入れるとエラーになった。数値なしでＯＫ
- 同じＰＣで二つ目のgethを起動したいときは--ipcdisableを付けてRPCを無効に
Sugar.js を Vue.js アプリケーションで使用する

Original: [Sugar\.js を Vue\.js で使用する \| tail \-f pinzo\.log](https://pinzolo.github.io/2017/10/24/sugarjs-in-vuejs-application.html)

諸事情があって Vue.js のアプリケーションで [Sugar \- A Javascript utility library for working with native objects\.](https://sugarjs.com/) を利用することにしたので導入のメモ。  
アプリケーションは vue-cli を使って作成したもの。

## インストール

```sh
$ npm install sugar --save
```

## ロード

main.js でロードし Extended mode で使用する。

```js
import Vue from 'vue'
import Sugar from 'sugar'

Sugar.extend()
```

## ja ロケールのロード

デフォルトでは en ロケールしか利用できないので ja ロケールを設定する。

```js
import Vue from 'vue'
import Sugar from 'sugar'

Sugar.extend()
require('sugar/locales/ja')
Date.setLocale('ja')
```
youtube-dl を使ってInstagram の動画を保存する方法

youtube-dl を使えばInstagramの動画をmp4ファイルに録画して保存することができる

- この記事はmacOS想定
- ffmpegさえ利用可能にすればWindowsやLinuxでも使えるのでは

# Homebrew のインストール
必須ではないが便利

```:macOS
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

# youtube-dl のインストール

```:macOS
brew install youtube-dl
```

## インストールできたかの確認
```:macOS
youtube-dl --version
```

```
YYYY.MM.DD
```


# 録画したファイルを置く専用フォルダを用意して移動
```:macOS
$ cd Desktop
$ mkdir video
$ cd video
```

# 録画したいInstagram動画のURLを取得
```
https://www.instagram.com/p/hogehoge/
```


# 録画する
```
youtube-dl https://www.instagram.com/p/hogehoge/
```
録画が終わると自動的に終了する

# 確認する
フォルダ内を覗くと
```hogehogehoge.mp4```
ができているはず

# 高度な操作
[youtube-dl/README.md at master · rg3/youtube-dl] (https://github.com/rg3/youtube-dl/blob/master/README.md#options)
にたくさんオプションが説明されている
electronでニコニコ動画を垂れ流すプレイヤーを作った

#命名：ニコ動垂れ流しプレイヤー
なんかいい名前あったら教えてください
[nico_tare_player](https://github.com/violet2525/nico_tare_player)

##やりたかったこと
ニコ動の使い方は人それぞれだと思います
ランキング上位の動画を見る、ニコレポでシリーズもの動画や投稿者を追う、検索結果から飛ぶ、etc

特にランキングや検索結果から動画を探すときに、シリーズものの動画で面白そうなものを見つけることもありますよね
しかし検索結果に出てきたのはシリーズの途中…
まず検索結果に出ている動画に飛んで…動画説明文のマイリストに飛んで…マイリストのソートを古い順にして…連続再生

**ええいめんどくさい！！！！！**

#*パート途中の動画からでも1クリックでパート1から連続再生するプレイヤーが欲しい！！！！！*
というわけで作りました。
##できること

- ChromeのCookieでログイン
- 動画検索
- シリーズ途中の動画から1クリックでパート1から連続再生
- 動画プレイヤーのみを表示

##やっていること
###ChromeのCookieでログイン
[こちら](https://qiita.com/violet2525/items/2fdc053105aa2263c10f)に書いています

###パート1から再生
![検索結果.png](https://qiita-image-store.s3.amazonaws.com/0/190389/ff15b684-6988-666b-d079-c6c221374a48.png)
基本的にはひたすらニコ動のAPIを叩いているだけです
「パート1から再生」リンクをクリックすると、検索結果の動画の動画情報を見てその中のマイリストリンク（複数ある場合は最初のもの）を拾い、そのマイリストの中でいちばん古い動画からマイリストを連続再生します。
なのでマイリストがない場合は連続再生できませんし、マイリストの内容次第では視聴者側で想定している再生順で再生されないこともあります。

####使ったもの
動画検索：http://api.search.nicovideo.jp/api/v2/snapshot/video/contents/search
視聴履歴：http://www.nicovideo.jp/api/videoviewhistory/list
サムネイル表示：http://tn-skr[1-4].smilevideo.jp/smile?i=[動画ID]
動画情報：http://ext.nicovideo.jp/api/getthumbinfo/[動画ID]
（自分の）マイリストhttp://www.nicovideo.jp/my/mylist
（自分以外の）マイリスト：http://flapi.nicovideo.jp/api/getplaylist/[マイリストID]


###動画プレイヤーのみを表示
ウィンドウサイズをプレイヤーと同じにしてプレイヤーだけ見えるようにスクロールしてるだけ

##とりあえず公開
とりあえず動くものができた段階ですが公開します。
完全に自分用に作ったものなのでexeを配布とかはしないつもりです。
今後追加したい機能をちまちま実装していきます
Xcode 9以降のSimulatorで出しすぎたDeviceを消す方法

Xcode 9以降のSimulatorでは、複数のデバイスを同時に表示できるようになりました。
また、より実機のように見せるためなのか、デフォルト設定ではデバイスにベゼルが表示されるようになっています。
このベゼルを表示しているデバイスにMacのいつもの×ボタンが出ず消し方に少し手間取ったので、備忘録として。

## 特定のデバイスの消し方
1. 削除したいデバイスをクリックしてアクティブな状態にする
2. `File > Close Window` を選択、もしくはショートカット `⌘ + W` を押す
![スクリーンショット 2019-09-30 12.04.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149055/15fc79be-8f18-2aaa-e49a-862dd3869630.png)

## ベゼルを非表示にする方法
ぶっちゃけベゼルが邪魔なことも多いですよね。 ~~⌘ + Wを押そうとして誤って⌘ + Qを押してしまうこともあるし……~~
このベゼルは非表示にすることもできます。
`Window > Device Bezels` をクリックし、チェックマークを外しましょう。

![スクリーンショット 2019-09-30 12.04.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149055/259398a2-89f5-efbf-e011-a3dfff9db8a9.png)

これならデバイスの閉じ方に迷う必要もありません。ベゼル表示に戻したい場合は、上記を再度クリックしチェックをすればOKです。
DockerFileを元に環境を作るときに必要な最低限の知識


## Docker for macのインストール
* https://docs.docker.com/docker-for-mac/install/
* これにより、dockerコマンドとホストPCにDockerコンテナを立てられるようになる

## Docker全体イメージ
![Kobito.u8ZDd8.png](https://qiita-image-store.s3.amazonaws.com/0/33823/cf1f9999-dfa3-9430-2be8-053fd03f4990.png "Kobito.u8ZDd8.png")

## 各コマンド
### ビルド
* docker build -t image_name
	* -t(tag)をつけることでイメージの名前を指定する

### イメージの確認
* docker images

### コンテナの作成
* docker run [オプション] イメージ [コマンド] [引数]
	* 基本はこれ

```
# 実行例
docker run -i \
  -e ENV=hoge \
  -v $HOME/hoge:/user/local/hoge \
  -p 8080:80 \
  --name container:image:tag \
  image_name \
  [コマンド]
```
* こんな感じでコンテナを起動してアクセスするだけ
* DockerFileさえ用意してしまえば後は簡単
* コマンドで実行時に走らせたいスクリプトなどを実行する

#### オプション
* -e: 環境変数
* -v: ホストマシンのファイルをコンテナと共有
* -p: ホストのポート(8080)アクセスしたら、コンテナのポート(80)にポートフォワーディング
* -i: ホストの入力をコンテナの標準出力につなげる
* -d: バックグラウンド実行
* --name: コンテナの名前

* 参考リンク
  * docker run | Docker Documentation https://docs.docker.com/engine/reference/commandline/run/#specify-isolation-technology-for-container-isolation

### 例: MySQLコンテナの起動

```
docker run --name mysql_container -e MYSQL_ROOT_PASSWORD=mysql -d -p 3306:3306 mysql
```

* 上記で公式のmysqlイメージがpullされて、使うことができる

### コンテナに接続

```
docker exec -it [コンテナID] bash
```

### コンテナの確認
* 現在起動中のコンテナ

```
docker ps
```

* 起動していないコンテナも含めて全て表示

```
docker ps -a
```

### 一度作成したコンテナを再度起動

```
docker start [コンテナID]
```

### コンテナの削除

```
docker rm [コンテナID]
```
youtube-dl を使ってYouTube（ライブ・アーカイブ）を録画する方法

youtube-dl を使えばYouTubeライブ（生配信）・アーカイブ動画をmp4ファイルに録画して保存することができる

- この記事はmacOS想定
- ffmpegさえ利用可能にすればWindowsやLinuxでも使えるのでは

# Homebrew のインストール
必須ではないが便利

```:macOS
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

# youtube-dl のインストール

```:macOS
brew install youtube-dl
```

## インストールできたかの確認

```:macOS
youtube-dl --version
```

```
YYYY.MM.DD
```


# 録画したファイルを置く専用フォルダを用意して移動

```:macOS
$ cd Desktop
$ mkdir video
$ cd video
```

# 録画したいYouTubeのURLを取得

```
https://www.youtube.com/watch?v=hogehogehog
```
- アーカイブ動画、ライブ（生配信）のいずれにも対応


# 録画する

```
youtube-dl https://www.youtube.com/watch?v=hogehogehog
```

- ライブ（生放送）の場合、 ```^C``` を押して終了する
- アーカイブ動画の場合、自動的に終了する

# 確認する
フォルダ内を覗くと
``` hogehogehog.mp4```
ができているはず

# 高度な操作
[youtube-dl/README.md at master · rg3/youtube-dl] (https://github.com/rg3/youtube-dl/blob/master/README.md#options)
にたくさんオプションが説明されている
[Django]Djangoのget_or_createの接続先はdb_for_writeに従う

DjangoでバックエンドDBにMySQLを利用してMaster/Slave構成とした場合の話です。
たぶんトランザクションをサポートしているようなDBであれば同様です。

```settings.py
DATABASES = {
    'app_master': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'app',
        'USER': 'user',
        'PASSWORD': 'pass',
        'HOST': '192.168.33.50',
        'PORT': '3306',
    },
    'app_slave': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'app',
        'USER': 'user',
        'PASSWORD': 'pass',
        'HOST': '192.168.33.60',
        'PORT': '3306',
        'TEST': {
            'MIRROR': 'app_master',
        },
    },
}
```

```database_router.py
class DatabaseRouter(object):
    def db_for_read(self, model, **hints):
        """
        Read
        """
        
        return "app_slave"

    def db_for_write(self, model, **hints):
        """
        Write
        """

        return "app_master"
        
    ...
```

上記のようなコードを書いて、更新系は【app_master】に、参照系は【app_slave】に流すという設定とします。

アプリケーション内で、「ユニークキーに対応するデータがあればUPDATE、なければINSERT」というようなことをします。
MySQLの【ON DUPLICATE KEY UPDATE】のようなことです。

```python
@staticmethod
def upsert_item_num(user_id, item_id, num):
    try:
        # ItemModelはuser_id、item_idでユニーク
        item = ItemModel.objects.get("user_id"=user_id, "item_id"=item_id)
        item.num = num
        item.save()
    except ItemModel.DoesNotExist as e:
        item = ItemModel.object.create(user_id=user_id, item_id=item_id, num=num)

    return item
```

```python
@transaction.atomic(using="app_master")
def update(self, request, pk):
    # なんかいろいろやって
    upsert_item_num(1, 1, 10)

    # さらにいろいろやって追加で
    upsert_item_num(1, 1, 20)
```

最初こういうコード書いていたんだけど、Master/Slaveの設定を反映させたら急にエラーになった。
2回目のupsert_item_numでDuplicate entryというエラー。

Modelのgetは常にSlaveを参照するように設定しているので、コミットされていない状態だと、2回目のgetもDoesNotExistになっていた。
こういう問題はModelのget_or_createを利用するようにしておけば回避できる。

```python
@staticmethod
def upsert_item_num(user_id, item_id, num):
    item = ItemModel.object.get_or_create(user_id=user_id, item_id=item_id)
    item.num = num
    item.save()
    
    return item
```

get_or_createは更新系に対してクエリを投げるぽいです。
[Electron]ウィンドウの高さを制限する。



Electronでアプリを作っていたら、
ウィンドウの高さを制限することの重要性に気づきましたので、
メモとして。

難しい話はないので、
そう、
ウィンドウオブジェクトを作る際に最低の高さを指定してあげるだけです。

```
const winSetting = { width: 800, height: 600, minHeight: 500}
const mainWindow = new BrowserWindow(winSetting)
```

これしないと、
ウィンドウサイズの
レイアウトが崩れてしまったりするので、
設定するかどうかは検討した方が良いと思います。


BrowserWindowのパラメータはここに載っています。
https://xwartz.gitbooks.io/electron-gitbook/content/en/api/browser-window.html#new-browserwindowoptions
React tutorial(リアクト チュートリアル)やってみた！！(その1 環境構築・その他編)

### インターン先の課題で***react tutorial***(公式)をやることになりました。初投稿なので至らない部分は大目に見ていただければ嬉しいです:innocent:

npmコマンドが動く前提で話を進めます。npmって何？って方は
[Macにnodebrew（node.js, npm）をインストールする手順](https://qiita.com/oreo3@github/items/622fd6a09d5c1593fee4)
こちらでも読んで見てください。

 *react tutorial*ってどれ？
日本語版もありますが、僕は英語版をオススメします。
(どうしても英語ヤダという場合は日本語版でも良いと思います)
![googleでreact tutorialで検索した時の検索結果](https://qiita-image-store.s3.amazonaws.com/0/178746/8099d312-439a-9d6f-f354-32323374b593.png)

1, *tutorial*の進め方の選択
公式の*react tutorial*では、環境構築がされていてブラウザ上にコードを書けば良い、という大変親切な設計になっています。僕の場合は1周目をブラウザ上で、2周目をlocalでやるという形をとりました。ここに関してはどちらが良いとかいうことはなく、好きな方で良いと思います(あくまで個人の見解です)

2, 環境構築<<ブラウザ上で進める場合はこの部分は飛ばしてください>>
早速、適当なディレクトリに移動して
`npm install -g create-react-app`
をコマンドライン(僕はitermを使ってます)上で実行してみてください。
「-g」　はグローバル環境にinstallする際につけます。
続けざまに
`create-react-app my-app`
も実行してください。my-appのところは自分で好きに変更して大丈夫です。

すると、現在いるディレクトリの中にmy-appフォルダが出来ているのが分かります。
↓ lsコマンドでディレクトリの中身を表示した結果 ↓
![コマンドライン表示結果](https://qiita-image-store.s3.amazonaws.com/0/178746/c339fd30-dea6-8d78-bf5f-caa281b79b51.png)

ここまででひとまずの環境構築は終わりです。(もちろんこれだけではまだ何も動きませんが)
以後、このmy-appに対して変更を加えていきます。
Xcode 9 インストール後にphp-buildでエラーが発生する場合

# はじめに

Xcode9をインストールした後から、php-buildを使ってphpをコンパイルするときに
下記のようなエラーが発生するようになったのですが、[フォーラム](https://forums.developer.apple.com/thread/87829)でー時的な解決方法をみつけたのでメモしておきます。

```bash
ld: file not found: /usr/lib/system/libsystem_darwin.dylib for architecture x86_64
```

# 事象を確認した環境

- macOS Sierra 10.12.6
- Xcode 9.0.1 (Build version 9A1004)
- Xcode 9.1 (Build version 9B55) **2017/11/06追記**
- Xcode 9.2 (Build version 9C40b) **2017/12/08追記**

# 解決方法

> /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/lib/libSystem.B.tbd

上記ファイルのバックアップをとって下記のように(/usr/lib/system/libsystem_darwin.dylibの記述を削除する)編集します。

```diff
--- /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/lib/libSystem.B.tbd.bak     2017-08-31 15:33:43.000000000 +0900
+++ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/lib/libSystem.B.tbd 2017-10-24 18:47:53.000000000 +0900
@@ -15,7 +15,7 @@
                        /usr/lib/system/libquarantine.dylib, /usr/lib/system/libremovefile.dylib, 
                        /usr/lib/system/libsystem_asl.dylib, /usr/lib/system/libsystem_blocks.dylib, 
                        /usr/lib/system/libsystem_c.dylib, /usr/lib/system/libsystem_configuration.dylib, 
-                       /usr/lib/system/libsystem_coreservices.dylib, /usr/lib/system/libsystem_darwin.dylib, 
+                       /usr/lib/system/libsystem_coreservices.dylib, 
                        /usr/lib/system/libsystem_dnssd.dylib, /usr/lib/system/libsystem_info.dylib, 
                        /usr/lib/system/libsystem_kernel.dylib, /usr/lib/system/libsystem_m.dylib, 
                        /usr/lib/system/libsystem_malloc.dylib, /usr/lib/system/libsystem_network.dylib,
```
PyCharmのVagrantリモートデバッガ設定

先日Vagrant+VirtualBoxの仮想サーバーを自分のマシンに設定をする機会がありました。PyCharmは非常に便利ですが、仮想環境でデバッガを起動させるためにはローカル環境でデバッガ設定をするより大分複雑だったため記事に残しておきます。

作業環境:
PC : macOS Sierra バージョン10.12.6
IDE : PyCharm 2017.1.5
仮想サーバー  : OS : Ubuntu 14.04.5 LTS, Trusty Tahr
　　　　 　　: 言語 : Python 2.7.10, Django 1.6
　　　　 　　: DB : MySQL5.6

まず出発点となる大本の記事
https://qiita.com/masahiro-fukushima/items/67959a0dfede69c9d653

この記事では2つの方法がありますが、remote interpreter方式のほうを使いました。
途中から設定が変わるのでそこから説明していきます。

![スクリーンショット 2017-10-20 18.43.30.png](https://qiita-image-store.s3.amazonaws.com/0/187011/a2927996-4eb8-b04d-7419-aee64b103c66.png)

HOST:
ローカルホストのIPアドレスを指定します。Port:は仮想サーバーが使っているものを指定してください。

User name:
仮想サーバーに設定したユーザー名を入れてください。

Auth type:
パスワード認証だったのでPasswordにしてパスワードを入力します。

Python interpreter path:
これがデフォルトだと/usr/bin/pythonと入力されていてローカルのPythonのパスになっているので仮想サーバーのPythonのパスに変えてください。

次に
path mappings横のボタンをクリックして、ローカルのディレクトリとリモートのディレクトリのパスを合わせます。
OKを押して作成完了。

......なんですが、実はインタプリタ設定画面にVagrantのチェックボックスがあります。

![スクリーンショット 2017-10-24 11.10.44.png](https://qiita-image-store.s3.amazonaws.com/0/187011/b4a34b15-d4cd-c384-291c-dab6b55b506a.png)
こっちの設定だとVagratfileとVagrantfile.localが置いてあるフォルダを参照して、仮想サーバーのPythonパスを設定するだけで完了します。どっちを使ってもできるので特に心配はいりません。

次にRun→Edit Configurationsを選択してウインドウを開きます。
＋ボタンを押してDjango serverを追加します。
![スクリーンショット 2017-10-20 18.54.46.png](https://qiita-image-store.s3.amazonaws.com/0/187011/977d8692-fbba-bbdc-f226-073fca51da13.png)

デバッガの設定をします。
![スクリーンショット 2017-10-24 19.15.13.png](https://qiita-image-store.s3.amazonaws.com/0/187011/928887b4-0e93-d13d-016f-a31322e65beb.png)


Name: 
デバッガーの名前をつけます。

Host: 
ここはローカルホストのIPアドレスを入れたくなってしまうのですが、仮想サーバー環境なので、外部マシンからアクセスできるようなアドレスを入れないといけません。

Port: 
vagrantの場合開放されているポート番号はVagrantfileに書いてあります。

Environment variables: 
ここではDJANGO_SETTINGS_MODULEで設定を読み込んでおきます。
https://docs.djangoproject.com/ja/1.11/topics/settings/#designating-the-settings

Python interpreter: 
作成したリモートインタプリタを読み込みます。

Working Directory: 
作業しているディレクトリのパスを入れます。 

Path mappings: 
先程設定したので特に何も書かなくて大丈夫です。

Add content roots to PYTHONPATH: 
Add source roots to PYTHONPATH: 
今回の導入したプロジェクトでは外さないと動作しないのでチェックを外してあります。



設定するのに気をつけないといけないところはアドレスや、ポートあたりです。リモートデバッガは仮想環境によって設定が変わってくることが予想されるので全部が同じようにいかないとこが難しいところだと思います。
Ansible プレイブックの j2(jinja2) テンプレートの中で条件分岐したいときの書き方

## やりたいこと
- `hoge.env.j2` ファイル内の環境変数を環境(ローカルとか Stg とか)ごとに設定したい
 - けどわざわざファイルを別に用意するのは少し大げさ
- 今回はローカルのときだけ DB の環境変数を設定したかった

## 書き方の例

```hoge.env.j2
{% if stage == "local" %}
DB_CONNECTION=mysql
DB_HOST={{ mysql_db_master_host }}
DB_SLAVE={{ mysql_db_slave_host }}
DB_PORT=3306
DB_DATABASE={{ mysql_db_name }}
DB_USERNAME={{ mysql_db_user }}
DB_PASSWORD={{ mail_db_password }}
{% endif %}
```

## 参考
if 文の他にも色々使える。
http://jinja.pocoo.org/docs/2.9/
Mastodonブラウザ閲覧時のショートカット (古文書、だたし現在でも有効) 

## 注意

※2019/10/07 追記
だいぶ前から、Mastodonのショートカットは「?」キーで表示されるようになっております。

※2025/05/04 ここに追記
そもそも、今やMastodonでこんなヘビーな使い方してる人はいないはずですね…

## 主旨

Mastodon2.0.0以降からWebUIホットキーが実装され、キーボードから主要な操作ができるようになりました。mstdn.jpで公開したところ、そこそこ好評をいただいたのでこちらにも記載しておきます。

## 基本チートシート

|キー操作|コマンド|
|:--:|:----|
|Tab|カラム選択モード [^1] |
|1～9|トゥート作成エリアを除き左から1,2,3…番目カラムにフォーカス [^2] |
|jまたは↓|一つ下(前)のトゥート|
|kまたは↑|一つ上(後)のトゥート|
|r|返信(reply)|
|f|お気に入り(favorite)|
|b|ブースト(boost)|
|m|宛先トゥート(mention)|
|s|検索(search)|
|p|ブーストした人のトゥートを追う、プロファイル表示(profile)|
|oまたはEnter|リプライの流れを追う|
|BackSpace|戻る [^2] |
|n|トゥート作成エリア(今なにしてる？)|
|Alt+n|クリアしてトゥート作成|
|Ctrl+Enter(トゥート作成時のみ)|トゥート|
|gu|自分のプロファイル表示、素早く押す。多分go userprofileの意味|

## 画面で表すと

一度は記事を書いたものの、チートシート初版も[マストドンつまみ食い日記](http://www.itmedia.co.jp/news/articles/1710/19/news053.html)さんより1時間以上出遅れているので、図を入れて対抗します。

![ホーム画面.png](https://qiita-image-store.s3.amazonaws.com/0/103102/840d379c-70a9-7f45-0bd4-408895041bfa.png)

左側トゥート作成エリアに移り、Tab、数字キー、jと操作してフォーカス移動を確認しましょう。

## 応用チートシート

フォロー3桁になってきたり、あるいは某jpのLTLを追いかける場合はある程度効率よく操作しないと流速が凄くて捌くのが大変です。そこで、私も未熟ですが、よく使いそうなセットも書いておきます。
ここではカラム順「トゥート画面、ローカルタイムライン(LTL)、ホーム(HTL)、通知、スタート」を前提にしています。

(jk)は上下の意味です、他の意図は一切ございません。

|キーコンボ|技|
|:----:|:---|
|fr|お気に入り＆返信入力|
|fbn|お気に入り＆ブースト＆トゥート入力|
|2(jk)ogu|HTLからリプの流れを追って**閉じる**|
|3(jk)pgu|通知からブーストした人のトゥートを追って**閉じる**|
|3(jk)p(jk)fbnトゥートgu|ブーストした人のトゥートにトゥートして**閉じる**|

ここでの**閉じる**は無難なgコマンドの自分プロフィールを中心に動いた方がいいからです、少なくとも今は。
たとえば、Aさんがブーストしてきたからとpキーで表示すると、そのプロフィールには現状新しいトゥートが反映されません。なので改めてAさんからブーストされた時にpキーを押してもトゥートを追いかけられなくなる[^3]のを回避する動作です。

## 補足

- NSFWやCWで隠された記事を開く操作はまだ存在しないようです。
- 公開範囲変更は、実質存在しないようです。
- gと組み合わせたコマンドは、基本ここには書いていません。例えばgn(通知 go notificaton)、gf(お気に入り go favorite)、gp(ピン留めトゥート go pin...?)、gb(ブロックユーザー一覧 go blockuser)、gm(ミュートユーザー一覧 go mute)やgl(ローカルタイムライン go local略)、gh(ホームgo home)などは誤操作を誘発しやすいからです。

## 謝辞

基本チートシート部分は
https://github.com/tootsuite/mastodon/releases/tag/v2.0.0
こちらのリリースノート訳
http://k0ta0uchi.hatenablog.com/entry/2017/05/21/141238
を元に作成しました、こうたさんありがとうございます。
また、名前を挙げることはできませんが、Qiita投稿の背中を押してくれたあの人にも深い感謝を。


[^1]: プロフィールからBSキーなどでフォーカスを頻繁に失うので、敢えてこう書いてます。

[^2]: 「トゥート作成エリア、ローカルタイムライン、ホーム」のように、トゥート作成エリアを左端にしてください。左端に配置しない場合、たとえば「ローカルタイムライン、検索作成エリア、ホーム、通知」の場合ローカルタイムラインに飛べません。

[^3]: 本来ならマストドン側が無条件リロードか追記してくれるよう、修正してプルリクでも投げる話なのですが、Ruby on RailsもJavaScriptもGithubさえも使えないへっぽこなのでご容赦ください。誰かお願いしますホント。
iPhone Xとその他の画面で余白を切り替える

# 問題
[こちら](https://qiita.com/Tueno@github/items/a04385f94e4fa5a00065)にも投稿したように、Xcode9からはStoryboardにSafeAreaという概念が追加されており、比較的簡単にiPhoneXの画面に対応ができます。
しかし、自前のViewを画面の最下部に合わせて配置する場合、iPhoneXのSafeAreaに合わせたViewコンテンツ配置の場合と、その他の画面の場合で高さや縦方向のマージンを切り替えたい場合があったので、どうやって対応したかを記します。

まず、説明だけではわかりにくいと思うのでどういうことかを画像付きで説明します。

<img width="266" alt="スクリーンショット 2017-10-24 18.32.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/24765/4413783d-1ebb-cbf6-4c55-1fdfd31fa578.png"> <img width="251" alt="スクリーンショット 2017-10-24 18.32.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/24765/f1915668-bc99-b4e0-95d6-e0650fef1fbf.png">

オレンジのエリアは背景がBlurになっているViewです。
iPhoneXの場合は画面の端までBlurを引き伸ばしたいので、購入ボタンの下のマージンが増え、オレンジのエリアのViewの高さが高くなっています。

# 実装方法

ロジックから分岐するなどいくつか方法はあると思いますが、今回はStoryboard上だけで解決する方法を考えてみました。

## 0. コンテナとして使うViewの配置

コンテナとして使うViewは画面（SafeAreaではない）のLeading, Trailing, Bottomとmargin = 0でConstraintを接続して配置します。
この時点で警告が出ますが、Heightは設定しません。

## 1. コンテナとして使うViewにSafeAreaを表示する

まず、この例の場合だと購入ボタンなどが入っているコンテナViewにSafeArea表示を設定してConstraintを接続できるようにします。

<img width="294" alt="スクリーンショット 2017-10-24 11.49.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/24765/91cc287f-d833-6b26-80a9-4bdefc18345b.png">

## 2. コンテナとして使っているViewの高さをその中のSubviewに依存させるようにしつつ、最下部のViewはSafeAreaと接続する

コンテナViewの高さがそのSubviewだけで決定できるようにするため、SubviewのHeightとVertical Marginをよしなに設定します。
その時、一番下にあるSubview（例だと購入ボタン）は1.で追加したSafeAreaと接続します。（Constrain to marginsにチェックを入れればSafeAreaと接続されます。）　

これだけです。慣れてしまえば当たり前なのですが、最初なので少し手間取りました。

※追記
TabBarControllerの中に入れるViewControllerの場合、RootのSafeAreaに対して制約を設定するとTabBarの高さが自動的に考慮されますが、RootではないViewの中のSafeAreaに対して制約を設定した場合はTabBarの高さが考慮されないのでメモとして追記します。
TabBarの表示/非表示を自前のアニメーションで切り替えたい場合などは自動的ににTabBarの高さを考慮されると困ることもあるので、Rootではない場所のSafeAreaを使うのが良いかもしれません。
【GIT】recursiveをつけずにcloneした後に、平和にsubmoduleをcloneする方法

親プロジェクト内で、サブモジュールを使っていて、
新しくcloneした際に、recursiveオプションを付け忘れてしまったときのTIPS。


親プロジェクト直下で、

`git submodule update --init --recursive`

を実行すればOK
Unity | Rotation MatrixをUnity5.6で作成する

#World, View and Projection Transformation Matrices
Since `Matrix4x4.Rotate` does not exist in Unity5.6, you might need to make a rotation matrix from Matrix4x4. I found [this article](http://www.codinglabs.net/article_world_view_projection_matrix.aspx)  quite helpful. 
(Unity5.6には`Matrix4x4.Rotate`がないのでMatrix4x4から自作する必要があるだろう。
この記事[World, View and Projection Transformation Matrices](http://www.codinglabs.net/article_world_view_projection_matrix.aspx)が非常に参考になった。)

```csharp
        Matrix4x4 rotmat = Matrix4x4.identity;

        rotmat.m00 = Mathf.Cos((yRotationDegree * Mathf.PI) / 180);
        rotmat.m02 = Mathf.Sin((yRotationDegree * Mathf.PI) / 180 * -1.0f);
        rotmat.m20 = Mathf.Sin((yRotationDegree * Mathf.PI) / 180);
        rotmat.m22 = Mathf.Cos((yRotationDegree * Mathf.PI) / 180);
```

You could multiply other matrices and `rotmat`.
(`rotmat`と他のMatrixをMultiplyすると取得したい結果が得られるだろう。)

##Ref
 - [World, View and Projection Transformation Matrices](http://www.codinglabs.net/article_world_view_projection_matrix.aspx)
 - [https://docs.unity3d.com/ScriptReference/Matrix4x4.html](https://docs.unity3d.com/ScriptReference/Matrix4x4.html)
 - [Getting cosinus of an angle in degrees](http://answers.unity3d.com/questions/884104/getting-cosinus-of-an-angle-in-degrees.html)
 - [http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/](http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/)
Apatche2.4+MySQL5.6+PHP7をCentOS6にインストールする

＼\お茶の子さいさいささいのさい/／ (引用元:うさぎ強盗には死んでもらう/橘ユマ)
でも人に説明するのがハイパーめんどくさいのでドキュメント代わり、兼、忘備録。

 - Linux6系
 - Apatche2.4系
 - MySQL5.6系
 - PHP7

を目指して作って行きまっしょい！

#### Apache2.4インストール

```

# cd /etc/yum.repos.d
# wget https://repos.fedorapeople.org/repos/jkaluza/httpd24/epel-httpd24.repo
# yum install --enablerepo=epel-httpd24 httpd24

```

httpd24は入ったけどserviceコマンドで呼び出せなくてめんどうだったので

```
# cd /etc/init.d/
# mv httpd httpd.org
# mv httpd24-httpd httpd
```
こういう感じの理不尽をやった

#### PHP7インストール

```

# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
# yum install --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd php-xml php-mcrypt


```

#### MySQL5.6インストール

```

# yum install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
# yum install mysql-community-devel mysql-community-server


```

#### 息をするのもめんどくさい人向け、コピペで動くチートシート

息をするのもめんどくさい人はこれをコピーしてターミナルに貼り付けたら全部入る（責任は取れない）

```

#Apatche24install
cd /etc/yum.repos.d
wget https://repos.fedorapeople.org/repos/jkaluza/httpd24/epel-httpd24.repo
yum install -y --enablerepo=epel-httpd24 httpd24
cd /etc/init.d/
mv httpd httpd.org
mv httpd24-httpd httpd

#PHP7install
rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
yum install -y --enablerepo=remi,remi-php70 php php-devel php-mbstring php-pdo php-gd php-xml php-mcrypt

#MySQL5.6install
yum install -y http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
yum install -y mysql-community-devel mysql-community-server

#service
service httpd start
service mysqld start
service iptables stop

#chkconfig
chkconfig httpd on
chkconfig mysqld on
chkconfig iptables off

```
macOSでAWS Command Line Interfaceをインストールする

少し手間取ったので手順をメモで残します。

【追記】[anyenv](https://github.com/riywo/anyenv)とツールを最近知りました。pyenvの導入が楽になるのでお勧めです。

# 環境

* maxOS Sierra(10.12.6)
* Homebrewがインストールされていること

# pyenv-virtualenvインストール

awscliはpipでインストールしますが、デフォルトでインストールされているpythonはpipが導入されていないようです。
[pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)でpython環境を構築していきます。

```
$ brew install pyenv-virtualenv
```

~/.bash_profileに以下の設定を追加します。

```:~/.bash_profile
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"
fi
```

2017/10/24時点のLatestバージョンであるPython 3.6.3をインストールします。（minicondaなども同様にインストールできるようです）

```
$ pyenv install 3.6.3
```

インストールしたバージョンが利用されるようにします。

```
$ pyenv global 3.6.3
```

ここで指定したバージョンは、`${HOME}/.pyenv/version`というファイルに保管されます。
なお、以下のようにした場合は、

```
$ pyenv local 3.6.3
```

実行ディレクトリ直下の`.python-version`というファイルに指定したバージョンが保管されます。
このファイルがあることで、このディレクトリ配下では、そのバージョンが利用されるようになります。（私はうっかりホームディレクトリにこのファイルを作ってしまって、いくら`pyenv global`で設定を変えても反映されず、しばらく悩んでしまいました）

# awscliのインストール

以下のコマンドでawscliをインストールします。
私の環境では、`$HOME/.local`配下にインストールされましたので、`$HOME/.local/bin`にもパスを通しました。

```
$ pip3 install awscli --upgrade --user

$ aws --version
aws-cli/1.11.176 Python/3.6.3 Darwin/16.7.0 botocore/1.7.34
```

## aws configure

以下でmanページが表示されます。

```
$ aws configure help
```

Profileを使い分けるには、`--profile`オプションを指定するとよいでしょう。

```
$ aws configure --profile sls
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: ap-northeast-1
Default output format [None]: table
$ cat ~/.aws/credentials
・・・（中略）
[sls]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```
ウイルス対策ソフト設計時の注意事項

ウイルス対策ソフト(アンチウイルス)の設計担当になった時はこんなところに注意しよう。

# ウイルス検知時の一次処理
ソフトによって隔離・検疫・削除とか色々あるが、サーバだったらまずは隔離するのが無難。サーバには重要なファイルが大量にあるので、不用意に削除してしまうと取り返しのつかないことになる。一次処理で隔離して、その後は管理者が目で確認してどう対応するかを決める。

逆にPCの場合は基本的に一次処理で削除してしまってもいい(と思っている)。消えて困るものをPCだけに保管しておくべきではない。もちろん隔離でもいいが、その分管理者の手間が増えることは覚悟する。

# リアルタイムスキャンとフルスキャン
「リアルタイムスキャンしてるのにフルスキャンする必要あるの？」という人がたまにいるが、リアルタイムスキャンは基本的にファイルのI/O(読み書き)を契機にしてスキャンが走るため、リアルタイムスキャンのみでは感染したファイルにI/Oが起きるまで検知されない。
かと言って、フルスキャンを常に走らせ続けるのはサーバリソースを食いすぎるので、リアルタイムスキャンを有効にしつつ、定期的にフルスキャンをかけるのが良い。

# 検索除外
製品ベンダから検索除外の推奨リストが出ていたりするので、まずはそれを探す。
また、DBをはじめ各種ミドルウェアにも除外推奨になっているものがある。ミドルウェアのサポート契約があれば直接聞くのが確実。

同じ場所を複数サーバからスキャンしないように設計することも重要。
例えば、NFSサーバとクライアントがいる場合、両方からスキャンをかけるのはサーバリソースやネットワークリソースの無駄になる。NFSであればNFSサーバ側でスキャンし、クライアント側では除外する。

そしてうっかり忘れがちなのがマネージャサーバ上のウイルス隔離ディレクトリ。これを除外しておかないと、隔離したウイルスをマネージャで検知するという残念な結果になる。

# オフライン環境でのパターンファイルアップデート方法
一部の製品では、マネージャサーバが製品ベンダサイトに直接アクセスしないと最新のパターンファイルをエージェントに配布できない仕様になっており、オフライン環境にあるマネージャサーバとは別にオンライン環境にもマネージャサーバを構築する必要がある。
したがって、ベンダサイトへアクセスするためのFWの穴あけや、オフライン環境のマネージャサーバにどうやってパターンファイルを運ぶか等を考慮しないといけない。

なお、見積りの時点でこの辺の考慮が漏れていると「誰がオンラインのマネージャサーバを構築するのか」とか「そもそもオンラインのマネージャサーバ用の機器なんて買ってないよ」とか「ライセンスの扱いどうすんの」とか揉める。

# ウイルス検知テスト
"EICAR"というテストウイルスがあるので、これを使う。大体製品ベンダのFAQから辿れる(辿れなければググる)。

実際に検知テストをする場合、直接PCに落とすと大抵PCのウイルス対策ソフトが検知＆削除してくれて、サーバまで運べない。
EICARの中身は比較的短いテキストなので、対象サーバ上で直接作ってしまえばよし。
ただし、RHELやCentOSで
`# echo "EICAR文字列" > eicar.txt`
などとやってしまうと、.bash_historyにEICARの文字列が残ってしまい、.bash_historyが感染ファイルとして検知される場合があるので、
`# echo "EICAR文字列の最後一字削除" > eicar.txt`
`# echo "EICARの最後の一字" >> eicar.txt`
という流れで作成する。
※viで作成してもいいが、エビデンス的に微妙
cssアニメーションのパフォーマンスについて リンクメモ

ページを表示すると同時にスライドインしてくる要素が、なんかカクつく。
cssアニメーションのパフォーマンス改善どうしよう？という疑問に始まり、
GPU周りのこと調べ出したので、忘れないようにリンクだけでもメモしとく。
結局アニメーションはcssにまかせておけばいいのか、どうなのか。パフォーマンスについてもっと深堀

リンクまとめ

Webサイトのパフォーマンス改善を行うためにGPU処理を取り入れてみた
http://un-tech.jp/performance-gpu/

アニメーションとパフォーマンス
https://developers.google.com/web/fundamentals/design-and-ux/animations/animations-and-performance?hl=ja

ブラウザの描画関連プロファイリングツールと利用方法
https://qiita.com/damele0n/items/363d6e30b92ed0c75b02
ヨーダ記法

eslintrcの設定項目にyoda（Yoda condition）という項目があり、
知らなくて何これと思ったので調べました。

```js:js

if ("red" === color) {
    // ...
}
```

**「赤は色」**という記述がヨーダ風（目的語-主語-動詞）とのことで、
この記法には**「条件式のつもりで代入文を書いてしまう」**ような記述ミスを回避する利点がある。
可読性の欠如が上記利点を上回っているという批判もあるようです。
linuxサーバにスワップ領域を追加

EC2の検証環境に（rails）アプリケーションデプロイ時、メモリが足らなくなってbundle installでコケることがある(Cannot allocate memory)。
そのためスワップ領域を追加する。
ec2再起動時などにやる。
ec2にsshして行う。

```
# dd if=/dev/zero of=/swapfile1 bs=1M count=512
# chmod 600 /swapfile1
# mkswap /swapfile1
# swapon /swapfile1
```
確認

```
$ swapon -s
```

参考）

- [スワップ領域の操作 【mkswap、swapon、swapoff】](http://www.turbolinux.co.jp/products/server/10s/manual/command_guide/command_guide/swap.html)
- [逆引きUNIXコマンド/Swapのサイズを確認する方法 - Linuxと過ごす](http://linux.just4fun.biz/?%E9%80%86%E5%BC%95%E3%81%8DUNIX%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/Swap%E3%81%AE%E3%82%B5%E3%82%A4%E3%82%BA%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
- [メモリとSwap領域の確認: BlueEyesBlue](http://blueeyesblue.cocolog-nifty.com/technote/2010/03/swap-ad70.html)
画面外に配置した要素が表示されてしまうバグ (ios9系)

translate3dを使って画面外から要素がスライドインしてくるアニメーションを実装しようとしたら、
ios9.0.2で初期表示時に画面全体が縮小されてしまう。
もうios9なんて切り捨てたいところだけど、調べてみた。

ios 9.X 系だと、画面外に配置した要素が表示されてしまうバグがあるらしい。

```
body {
  position: relative;
  width: 100%;
  overflow-x: hidden;
}
```

これでOK

参考URL
https://qiita.com/OnederAppli/items/6a709dfa0063405455dc
http://shinimae.hatenablog.com/entry/2016/06/06/191704
Gitでブランチ名に使えない文字

表題の通り、Gitでブランチ名に使えない文字が何なのかを調べてみました。正確なところは`man git-check-ref-format`すると書いてあるんですが、自分用にざっくりまとめます。


# ブランチ名として常に使えない文字

* コントロールコード（0x00から0x1fと0x7fの33文字）
* 空白文字（0x20）
* チルダ `~`
* キャレット `^`
* コロン `:`
* クエスチョンマーク `?`
* アスタリスク `*`
* 開きブラケット `[`
* バックスラッシュ `\`

# ブランチ名として常に使えない文字列

* `..`
* `@{`
* `//`

# もうちょっとだけ使えないパターンがあるんじゃ…

* 先頭の`.`または`/`
* 末尾の`.`または`/`
* 末尾の`.lock`
* `@`1文字だけのブランチ名

グルーピングの先頭最後の話とかをすると面倒なので、詳細はman pageを見てください、ということで。

# 使っても良い文字

上記からわかる通り、8bit文字については特に制約がありません。「🍣🍻」のようなブランチ名を作っていきましょう。
Python3.6でKeras/Tensorflow環境構築

#実行環境（開始時点）

- macOS Sierra 10.12.5
- Python 2.7.10

#やりたいこと
- Keras/Tensorflowの環境を作る
    - KerasはTensorflowやtheanoと親和性が高いとのことなので、楽しそうと思ってやってみた
    - 途中で気づいたけど、2017/10/24時点でtheanoはpython3.6に非対応...
- virtualenvを使ってpythonの仮想環境を作成→OS直轄のpython環境をピュアな状態に保つ

#やったこと
- homebrewのインストール
    - `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`

- python 3.6.3のインストール
    - `brew install python3`
        - 3.x系のどれがインストールされるかはhomebrewに上がっているバージョンに依存
        - pip3も同時にインストールされる
- virtualenvのインストール
    - `pip3 install virtualenv`
        - pip3を指定しないとpython3.x系でvirtualenvが使えない
        - OSが使っているpythonのpipを使ってしまい、後々大混乱

- 仮想環境の構築
    - `virtualenv -p python3 py3`
        - python3を使った「py3」というpythonの仮想環境を作成
- 仮想環境の起動
    - `source py3/bin/activate`
- Kerasのインストール
    - `sudo pip3 install keras`
        - ここでもpip3を指定すること
        - [このサイト](https://keras.io/ja/)を参照


- TensorFlowのインストール
    - `pip3 install --upgrade tensorflow`
        - [このサイト](https://www.tensorflow.org/install/install_mac)を参照
- virtualenv用のmatplotlibの設定
    - **次の作業（Keras/Tensorflowのサンプルコード実行）でエラーが発生したため、[このサイトに記載の対処を実施](https://qiita.com/mas9612/items/0b482b768e4b5a79ffb2)**
        - ~/.matplotlib の中に matplotlibrc という名前のファイルを作成する
        - ~/.matplotlib/matplotlibrc に以下の行を追加する

```~/.matplotlib/matplotlibrc
backend: TkAgg
```
- Keras/Tensorflowのサンプルコード実行
    - [このサイト](https://qiita.com/ohisama@github/items/8a04cb6b01838a750c3b)を参照

#表示されたエラー
- RuntimeError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are Working with Matplotlib in a virtual enviroment see 'Working with Matplotlib in Virtual environments' in the Matplotlib FAQ
    - 備忘録として残す
    - virtualenv使いのみなさんも同じ経験をしている模様
暇つぶしにFizzBuzzしてみた

##有名なFizzBuzzちゃんを今さらやってみました。
一応ルールは

+ ３の倍数のときは「[数字]はFizz!」と出力
+ ５の倍数のときは「[数字]はBuzz!」と出力
+ ３の倍数かつ５の倍数の場合は「[数字]はFizzBuzz!!」

###ここから自己流特殊ルール

+ ３を含む数字は「３を含んだ数字、その名は[数字]そしてFizz!」
+ ５を含む数字は「５を含んだ数字、その名は[数字]そしてBuzz!」

てな具合でやってみた。

```php:study.php

for($i=1;$i<=1000;$i++){
	$check = checker($i);
	if(!empty($check)){
		echo $check;
		continue;
	}
	if($i % 3 === 0 && $i % 5 === 0){
		echo $i.'はFizzBuzz!!<br>';
	}else if($i % 3 === 0){
		echo $i.'はFizz!!<br>';
	}else if($i % 5 === 0){
		echo $i.'はBuzz!<br>';
	}else{
		echo $i.'<br>';
	}
}
function checker($i){
	$num = strval($i);
	$result = "";
	if(strstr($num,'3')){
		$result = '3を含んだ数字、その名は'.$i.'そしてFizz!<br>';
	}else if(strstr($num,'5')){
		$result = '5を含んだ数字、その名は'.$i.'そしてBuzz!<br>';
	}
	return $result;
}

```

一応できたがこれでよかったのか・・・
もっと綺麗な方法があったのでは・・
もっとイケメンに書ける方いたら共有して頂けると嬉しいです！
##まとめ
初心に戻ってこういう問題を久々にやるとあの頃を思い出しました。
マークダウンの練習も兼ての投稿でした！ありがとうございました！
JAVAで文字列の類似度スコアを算出する

apache lucene を使えばすぐできる。一行でできる。
レーベンシュタイン距離法とJaroWinkler距離法がある（他にもあるが）。

## レーベンシュタイン距離法

何回編集すればいいか ＝ 距離となる。
『BitCoin Core』を『BitCoin Cash』に置き換える場合

１回目：『BitCoin C[a]re』
２回目：『BitCoin Ca[s]e』
３回目：『BitCoin Cas[h]』

なので、距離は『３』となる。

文字数はこの場合は、１２文字。１２文字中９文字は編集不要なので
スコアは ９／１２ ＝ ３／４ ＝ ０．７５ で ７５点とする。

※ 比較する文字列の文字数が異なる場合は
   より文字数が多いほうをベースとしてスコアを計算する。

**一般的には、スペルチェックや剽窃のチェックに使いやすいと言われる。**

## JaroWinkler距離法

同じく類似度を測定するが
例する一定の範囲内に置換できる文字が存在するか、という感じで類似度を算出する。

加えて、接頭語がどれくらい一致するかも類似度を算出する際に考慮される。

- 『1234567890』と『0004567890』の場合、スコアは８０点くらい
- 『1234567890』と『1234567111』の場合、スコアは９４点くらい

**一般的には、スペルミスのチェック等に効果的だと言われている**

## 実装
Luceneに頼るのみ。Mavenで。

```xml:pom.xml
        <dependency>
            <artifactId>lucene-core</artifactId>
            <groupId>org.apache.lucene</groupId>
            <version>5.1.0</version>
        </dependency>
        <dependency>
            <artifactId>lucene-analyzers</artifactId>
            <groupId>org.apache.lucene</groupId>
            <version>3.6.1</version>
        </dependency>
        <dependency>
            <artifactId>lucene-spellchecker</artifactId>
            <groupId>org.apache.lucene</groupId>
            <version>3.6.1</version>
        </dependency>
```

```java:sample
import org.apache.lucene.search.spell.JaroWinklerDistance;
import org.apache.lucene.search.spell.LevensteinDistance;

/**
 * 文字列の類似スコアを算出するサンプル
 * @author ryutaro_hakozaki
 */
public class ExecStringSimilaritySample {
    
    public static void main(String argv[]){
        
        System.out.println(
                "レーベンシュタイン距離で『BitCoin Core』と『BitCoin Cash』を比較したスコア == " 
                        + getSimilarScoreByLevenshteinDistance("BitCoin Core", "BitCoin Cash"));

        System.out.println(
                "ジャロ・ウィンクラー距離で『BitCoin Core』と『BitCoin Cash』を比較したスコア == " 
                        + getSimilarScoreByJaroWinklerDistance("BitCoin Core", "BitCoin Cash"));

        
    }
    
    /**
     * レーベンシュタイン距離で文字列の類似度を判定
     * @param s1
     * @param s2
     * @return 
     */
    private static int getSimilarScoreByLevenshteinDistance(String s1, String s2){
        
        // 入力チェックは割愛
        LevensteinDistance dis =  new LevensteinDistance();
        return (int) (dis.getDistance(s1, s2) * 100);
    }
    
    /**
     * ジャロ・ウィンクラー距離で文字列の類似度を判定
     * @param s1
     * @param s2
     * @return 
     */
    private static int getSimilarScoreByJaroWinklerDistance(String s1, String s2){
        
        // 入力チェックは割愛
        JaroWinklerDistance dis =  new JaroWinklerDistance();
        return (int) (dis.getDistance(s1, s2) * 100);
    }
    
}
```

```:実行結果
レーベンシュタイン距離で『BitCoin Core』と『BitCoin Cash』を比較したスコア == 75
ジャロ・ウィンクラー距離で『BitCoin Core』と『BitCoin Cash』を比較したスコア == 95
```
自前でビルドしたAndroidソースをNexusに焼く

Nexusシリーズ(最近はPixelですね)は公式にBootloaderをアンロックして、自前で改造したAndroidのソースをビルドして焼きこむことができるので、それのコマンドメモ。
基本的には[公式サイト](https://source.android.com/source/)の抜粋です。
なお、焼き込みターゲットはNexus 9です。
※Bootloaderをアンロックするとメーカーの保証等は受けられなくなります。

#環境
Ubuntu 16.04 LTS
メモリ 16GB
CPU Intel® Core™ i5-4570 CPU @ 3.20GHz × 4
HDD 500GB
※HDDが公式で250GBも必要らしいので注意して下さい

#AOSPソースのビルド
```bash:bash
#JDKが入ってることを確認(1.8.0_131が入ってた)
java -version

#作業用ディレクトリ作成
mkdir androidAllBuild
cd androidAllBuild/

#もろもろインストール
sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip

#Repoをインストール
mkdir ~/bin
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

#ソースDL(時間かかる)
mkdir nexus9_1
cd nexus9_1/
#目的のブランチを指定(今回はandroid-7.1.1_r53)
repo init -u https://android.googlesource.com/platform/manifest -b android-7.1.1_r53
repo sync

#ソースを編集
#OSを改造したり、調査用のログを入れたり…

#ビルド(時間かかる)
make clobber
source build/envsetup.sh
#ターゲット端末を指定(今回はaosp_flounder-userdebug)
lunch
make -j4
```

#焼きこみ
[こちら](http://tabkul.com/?p=92582)を参考にブートローダーをアンロックする。
ちなみに当方の環境ではfastbootはsudoで実行する必要があったので↓のように実行

```bash:bash
sudo XXXXXX/androidAllBuild/nexus9_1/out/host/linux-x86/bin/fastboot oem unlock
```
次に実際に端末に焼きこむ。

```bash:bash
env | grep ANDROID_PRODUCT_OUT
sudo -E XXXXXX/androidAllBuild/nexus9_1/out/host/linux-x86/bin/fastboot flashall -w
```
以上で自分でビルドしたROMで検証等が可能となる。

#公式イメージへの戻し方
[公式サイト](https://developers.google.com/android/images)に工場出荷時のイメージが置いてあるのでそちらへの戻し方。
公式サイトからNexus9のイメージを落としてきてflash-all.shの中身を参考に↓のコマンドを実行。
※基本的にflash-all.shの中身をsudoで実行してるだけ。

```bash:bash
adb reboot bootloader
sudo XXXXXX/androidAllBuild/nexus9_1/out/host/linux-x86/bin/fastboot flash bootloader bootloader-flounder-3.50.0.0143.img
sudo XXXXXX/androidAllBuild/nexus9_1/out/host/linux-x86/bin/fastboot reboot-bootloader
sudo XXXXXX/androidAllBuild/nexus9_1/out/host/linux-x86/bin/fastboot -w update image-volantis-n9f27m.zip
```
コミュニティサイクルの利用履歴をスクレイピングv2 Headless Chrome版

#はじめに
Headless Chromeというモノがあることを知り、これまでに PhantomJS でやってきたことの移植に手を付けようと思いました。
とりあえず、過去に作った「コミュニティサイクルの利用履歴をスクレイピング」をそのターゲットにしました。

#やってみたこと
Python3 + BeautifulSoup4 + Selenium + headless Chrome です。
[ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/downloads)をインストールすることをお忘れなく。

```docomo-cycle-hc.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import urllib.request
from bs4 import BeautifulSoup
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
import csv
from selenium.webdriver.chrome.options import Options

MEMBERID = "(自分のユーザID)"
PASSWORD = "(自分のパスワード)"

options = Options()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--window-size=1024,768')

driver = webdriver.Chrome(chrome_options=options)

driver.get("https://tcc.docomo-cycle.jp/cycle/TYO/cs_web_main.php?AreaID=2")

mid = driver.find_element_by_name('MemberID')
mid.send_keys(MEMBERID)
password = driver.find_element_by_name('Password')
password.send_keys(PASSWORD)
password.send_keys(Keys.RETURN)

obj1 = WebDriverWait(driver,5).until(
    EC.presence_of_element_located((By.XPATH, "//*[@id='pc_bill']")))
obj1.click()

time.sleep(3)

data = driver.page_source.encode('utf-8')
soup = BeautifulSoup(data, "html.parser")

table = soup.findAll("table",{"class":"rnt_ref_table"})[0]
rows = table.findAll("tr")

csvFile = open("docomo-cycle-hc.csv", 'wt', newline='', encoding='utf-8')
writer = csv.writer(csvFile)
try:
  for row in rows:
    csvRow = []
    for cell in row.findAll(['td', 'th']):
      csvRow.append(cell.get_text().replace('\n',''))
    writer.writerow(csvRow)
finally:
  csvFile.close()


driver.close()
```
上記スクリプトを実行すると、利用履歴がdocomo-cycle-hc.csvというファイルに出力されます。
なお、Mac環境とWindows環境で動作確認済みです。

#今後のこと
とりあえず、PhantomJSでやってきたことをHeadless Chromeに移植することは難しくないので、移植に関する記事はこのくらいにして、別のことにチャレンジしたいと思います。

#参考
・[Windows環境下でHeadless ChromeをPython3とSeleniumで動作させるキモ](https://qiita.com/nuwaa/items/0d00b806d8a6be74a3fd)
・[コミュニティサイクルの利用履歴をスクレイピング v2](https://qiita.com/nuwaa/items/726170de5fefc05e82c9)
MacにcondaでOpenCVをインストールする



macにcondaを使ってOpenCVをインストールしようとしたらエラーが出た。
```
$ conda install -c https://conda.anaconda.org/menpo opencv3
```
※-cオプションはパッケージを検索するための追加チャンネルで、URLをここで指定した順序で検索してくれるらしい。

```
Fetching package metadata ...........
Solving package specifications: .

UnsatisfiableError: The following specifications were found to be in conflict:
  - opencv3 -> python 2.7* -> openssl 1.0.1*
  - python 3.6*
Use "conda info <package>" to see the dependencies for each package.
```
なんかよくわからんけど、condaくんがインストールしたいOpenCVのパッケージがPython3.6に対応してない？
pythonのバージョンを下げて環境構築しなおして無理くり対応させるみたいな記事があったけどうーん（やりたくない）

どうもconda-forgeからパッケージをインストールすれば使えるらしいのでインストール。
```
$　conda config --add channels conda-forge
$ conda install opencv
```
OpenCV3.3.0がインストールされた！

で、conda-forgeって一体ナニって感じなのであとで調べとくこと。
https://anaconda.org/conda-forge
SQLから任意のシェルをキックする（MySQL）

バッチ系システムの設計で
cron から定期実行
だけだとちょっとタイミング的に厳しいかも？
ということがあり
調べていたところSQLからシェルをキックできることが判明！

**User Define Function**
の頭文字から**UDF**と呼ばれてるものを使用すればイケるみたい
ということがわかったので
早速
どんなものなのかを試してみました。

そのときのメモを載せておきます。


##環境

MySQLが載ってるサーバです。

```
# cat /etc/issue
CentOS release 6.8 (Final)
Kernel \r on an \m

```

MySQLです。

```
mysql> SELECT version();
+------------+
| version()  |
+------------+
| 5.7.12-log |
+------------+
1 row in set (0.16 sec)

```

##流れ的なもの

MySQLに自作のファンクションを作成し、登録する。
そのファンクションからシェルをキックするという流れです。

自作するファンクションはストアド感覚な感じですが
c++で作成したプログラムを登録することが可能。

ｃにはsystem関数という実行環境のコマンドをキックできる関数があるので
それを利用するという感じになります。

ということで、
まずはｃ言語のソースを。。
コピペでOKです。

```cpp:exec.cpp
#include <mysql.h>
#include <m_string.h>

extern "C" {
    my_bool exec_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
    my_ulonglong exec(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
    void exec_deinit(UDF_INIT *initid);
}

// init
my_bool exec_init(UDF_INIT *initid, UDF_ARGS *args, char *message){
    if(args->arg_count == 1 && args->arg_type[0]==STRING_RESULT){
        return 0;
    } else {
        strcpy(message, "Expected exactly one string type parameter" );
        return 1;
    }
}

my_ulonglong exec(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error){
    return system(args->args[0]);
}

void exec_deinit(UDF_INIT *initid){
    // do nothing
}

```

次にこれをコンパイル。
ということでコンパイラーをインストール。
自分は以下のものを入れました。

- gcc-c++-4.4.7-17.el6.x86_64.rpm
- libstdc++-devel-4.4.7-17.el6.x86_64.rpm

yumでもokだと思います。
*自分の場合、このサーバは外部につながってなかったのでrpmになりました・・・*

コンパイラを入れたら上記ソースをコンパイルしてみます。
>g++ -Wall -I/usr/include/mysql -shared -o exec.so -fPIC exec.cpp

成功すると exec.so がカレントに出力されるのでこれをmysqlのpluginにコピーする
>cp exec.so /usr/lib64/mysql/plugin

あとはMySQLからcreate functionすれば完成です。

>mysql> CREATE FUNCTION exec RETURNS int SONAME 'exec.so';

***レプリケーションしている場合は要注意です！***

##実行

早速実行するため適当なシェルを用意する

```
# cat /work/catt.sh
#!/bin/sh
ls -al /work > /tmp/catt
```

で、実行。

>mysql> select exec("/work/catt.sh");
>+-----------------------+
>| exec("/work/catt.sh") |
>+-----------------------+
>|                 32256 |
>+-----------------------+
>1 row in set (0.01 sec)

あれ？戻り値おかしいぞ？
/tmp を覗いてもファイルがないし。。

念のため
/var/log/mysqld.logを覗いてみる。

>sh: /work/catt.sh: 許可がありません

え？シェルの実行権限あるよ！
一応chmodで777にしてみたけど結果は変わらず・・・

・・・ここでハマる事、数時間。
<br>
<br>
原因はコレでした

```
# getenforce
Enforcing

```

selinuxが有効だった・・・（ubuntu でいうところの apparmor）

ということでこれを解除します。

```
# setenforce 0
# getenforce
Permissive

```

>この後、/etc/sysconfig/selinux を編集。
>SELINUX=の右辺をdisabledに修正後、サーバーをrebootする。

ちと自分の場合、諸事理由ですぐにはrebootできなかったので
Permissive
のまま続行～

mysql> select exec("/work/catt.sh");
+-----------------------+
| exec("/work/catt.sh") |
+-----------------------+
|                     0 |
+-----------------------+
1 row in set (0.02 sec)

お、成功か？

```
# ll /tmp/catt
-rw-r-----. 1 mysql mysql 234 10月 24 16:18 2017 catt

```

ファイル出力できてました。成功です。

##最後に

シェルをキックするのはこれでいけますが
シェルをキックして、その戻り値をselectでそのまま表示
というのはコレではできないので
キックしたシェルからDBに結果を書き込むなどの処理が必要になってきます。

この調査途中でシェルの結果を得るのもできそうだったので
今度時間あるときに調べてみようかと思います。

以上ご参考になれば。