OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleAppEngineスタンダード環境のPython3サポートはもう少し話題になっていいと思う

# お知らせ
タイトルの通りですが、2018年7月にGoogleAppEngineスタンダード環境におけるPython3.7サポートがアナウンスされました。（まだベータですが）
https://cloudplatform.googleblog.com/2018/07/bringing-the-best-of-serverless-to-you.html

長らくPython2系のみのサポートだったため個人的には非常に喜ばしいニュースでしたが、特に話題になっていないようなので、念のためこちらでもお知らせしておきます。

伝えたかったことは以上なのですが、AppEngineは少しサービスとして分かりにくいところもあり、「スタンダード環境って何？」といった疑問もあるかと思いますので、AppEngineについてPythonとの関連を中心に簡単に説明したいと思います。

また、今回サポートされたPython3ランタイムは、これまでのPython2ランタイムとは仕組みが異なります。gVisorというテクノロジーが採用され、それによっていくつかの制限が緩和され、より自由な開発が可能になりました。

# AppEngineって何？
PaaSです。開発者がアプリを書いてデプロイすれば、インフラのことは気にしなくてもいいやつです。
AppEngineはGCPのサービスの中で最も歴史が古く（2008年プレビュー版）、看板サービスの一つです。

スケーリングが非常に速く大量のアクセスをさばける点に定評がありますが、これはAppEngineのスタンダード環境の特徴です。（スタンダード環境については後述）

# 今までPython3は使えなかったの？

フレキシブル環境で使えました。
https://cloudplatform.googleblog.com/2016/08/python-3-on-Google-App-Engine-flexible-environment-now-in-beta.html

# スタンダード環境とフレキシブル環境の違いは？
AppEngineにはスタンダード環境とフレキシブル環境の２つがあり、それぞれ違いがあります。

下記の公式ドキュメントをまとまっていますが、ポイントをしぼって説明します。
https://cloud.google.com/appengine/docs/the-appengine-environments?hl=ja

## フレキシブル環境
フレキシブル環境のほうが後発です。この環境では、ユーザが開発したアプリケーションはDockerコンテナにまとめられます。フレキシブル環境の特徴として、ランタイムの選択肢が豊富で、サードパーティライブラリも好きなものが使えます。（Dockerなので）

スタンダード環境にはないランタイムで、Googleがあらかじめ用意しているものでいうと.NETやRubyがあります。また、ユーザがDockerfileを持ち込むこともできます。

アプリケーションを起動するには最低１台以上のインスタンス（つまりDockerコンテナ）が必要になりますが、起動させるインスタンスごとにVM（仮想マシン）が起動します。その結果として、課金モデルもGCEと近くなっています。
ユーザはVMにSSHすることが可能であり、インフラレイヤの抽象度は高くないといえるでしょう。（`docker ps`を実行すると、デプロイしたアプリがコンテナとして起動しているのが見えます。）


## スタンダード環境
_* 下記はPythonランタイムについてであり、他のランタイムでは事情が異なるかもしれません。_

フレキシブル環境はDockerベースでしたが、スタンダード環境は技術的なアーキテクチャが公開されておらず、Google内部の技術が使われていると思われます。

フレキシブル環境に比べると制約が多くあります。たとえば、ランタイムの選択肢が限定的、一部のライブラリが使用不可、リクエストが60秒でタイムアウトする、ローカルディスクへ書き込めない、などです。（__あとで触れますが、Python3で一部の制限が緩和されています__）

このようにデメリットもありますが、インスタンスの起動がかなり早いという大きなメリットがあります。
GCPのドキュメントではフレキシブル環境が分のオーダーに対し、スタンダード環境はミリ秒とされています。

https://cloud.google.com/appengine/docs/the-appengine-environments?hl=ja

高速なスケーリングにより突発的なアクセス集中にも対応できます。また、あらかじめ多くのインスタンスを起動させておく必要がないため、コストの節約にもなります。

これは私の経験ですが、デプロイ時間についてもスタンダード環境のほうが優れています。フレキシブル環境では10分程度かかっていましたが、スタンダード環境に変更したところ1分半〜２分で完了するようになりました。（どちらもPython3ランタイムを使用）

# Python3での制限緩和
スタンダード環境のPython3ランタイムでは、Python2ランタイムと比較して、制限が緩和されています。
特にサードパーティライブラリが自由に使えるようになったのが大きいです。

requirements.txtに書くだけでOKです。（フレキシブル環境と同じですね）

以前はCloud SDK（GCPサービスと連携するためのSDK）が呼び出せないという冗談のような問題がありました。（特定のサービスだけかも）


その他の制限の緩和については、こちらを見てください。
https://cloud.google.com/appengine/docs/standard/python3/python-differences

これらの制限緩和については、gVisorによるところが大きいと思います。
https://cloudplatform.googleblog.com/2018/05/Open-sourcing-gVisor-a-sandboxed-container-runtime.html

# まとめ
GCPでWebアプリを提供するにはAppEngineが非常に便利です。しかし、今までPython3はスタンダード環境で使えなかったため、高速なスケーリングというAppEngineの恩恵を受けることができませんでした。

そして、Python2を選んだとしても、少なくない制限を受け入れる必要がありました。また、サポート切れが見えているPython2系を新しいプロジェクトで使うのも微妙です。

しかし、今回gVisorベースのPython3サポートが発表され、開発における制限が少なく、高速なスケーリングというAppEngineの恩恵を受けながらPython3を使うことができるようになりました。
Windows バッチファイルで格納先フォルダ名を取得

### 改訂

> 2018-08-13  call文の代わりにfor文の1ライナーで `%~` 構文を適用し、実質2行に洗練。

### まえがき

Windows バッチファイルってすでに過去の遺物にも思えるが、まだまだ使われてることも多い。でも、ちょっと凝ったことをしようとすると `%~dp0` とか書くことになり、手こずったりもする。

### ■ 課題

`%~` 形式の [バッチパラメータのオプション構文][batch-parameters] はそこそこ揃っているのだが、`%~dp0` でバッチファイルの格納先パスは取得できても、格納先フォルダ名を取得する方法は用意されていない。

[batch-parameters]:https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call#batch-parameters

|取得したい情報|構文|値の例|
|---|---|---|
|バッチファイルのフルパス| `%~f0` | C:\Users\someone\folder\mybatch.bat|
|バッチファイルの格納先パス| `%~dp0` | C:\Users\someone\folder\|
|バッチファイルの格納先フォルダ名| なし | folder |

そこで、バッチファイル内でバッチファイルの格納先フォルダ名を取得する方法を実装してみた。

### ■ バッチファイルでの実装

```bat
@echo off

rem このバッチファイルが格納されているフォルダ名を取得する方法

setlocal
set THIS_PATH=%~dp0
for %%1 in ("%THIS_PATH:~0,-1%") do set FOLDER_NAME=%%~nx1

rem テストコード

echo.
echo Current directory is "%CD%"
echo Full path is "%~f0"
echo %%~dp0 is "%~dp0"
echo.
echo Folder name is "%FOLDER_NAME%"
```

> 説明
> * 上記の例では `%FOLDER_NAME%` にバッチファイルの格納先フォルダ名がセットされる。
> * ポイントはパス末尾の \ の有無で `%~nx1` の結果が変わること。
> * フォルダ名に空白文字やピリオドが含まれている場合にも対応。

> 改良
> * call文の代わりに、for文を応用した1ライナーで `%~` 構文を適用。


### ■ 参考

> * [call | Microsoft Docs](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call)
> * [バッチファイルでの文字列抽出](https://qiita.com/kshibamo/items/9368b0b2a4a2f40b61f1#文字列の抽出)
> * [Windowsバッチ - フォルダ文字列をループし、最後のフォルダ名を解析する > Answers](https://code.i-harness.com/ja/q/44989)
サマータイム対応方法のメモ

# はじめに

2020年東京オリンピックを前に、サマータイムの導入が議論され、
ITジャーナリスト（笑）が、電源切って時刻を変更するだけ・・・などという妄言を公開して大顰蹙を買ったりしています。
http://blogos.com/article/317015/

個人的にもサマータイムの導入は反対。百害あって一利なしと思っているのですが、

* そもそもサマータイムを導入している諸外国のシステムはサマータイムをどう処理しているのか？
* 日本にサマータイムが導入された場合、どのような処理を変更しなければならないか？

が気になり、調べたことをまとめます。
ツッコミ、指摘歓迎です。お気づきの事があればコメントください。

# サマータイムの表現方法

サマータイムはUTC（協定世界時）との時差を変更することで実現するのが一般的のようだ。
時刻そのものを変更するのではなく、時差をずらすことで調整する。

例えば、JST（日本標準時）は協定世界時に9時間足すことで表される。

+9時間を、夏の間だけ+11時間とすることで、時刻を2時間進める。
（電源を切ってずらしたりはしない）

以下、
(1)3/11 2:00:00からサマータイムが始まり、
(2)11/4の2:00:00にサマータイムが終わると仮定して記載する。

それぞれの時刻の変わり方は以下のようになる。

(1)3/11 1:59:59の次は3/11 4:00:00となる（2時間飛ぶ）。
(2)11/4 1:59:59の次は3/11 0:00:00となる（2時間戻る）。


タイムゾーンがいつからいつまでで、何時間ずらせばよいか、という情報は
tz databaseと呼ばれるデータに集約されているとのこと。
https://ja.wikipedia.org/wiki/Tz_database


# サマータイムの反映方法

PC・サーバ・スマートフォンともに、OSに搭載されている時計自体は、
サマータイム版のタイムゾーンを適用すれば自動的に反映されるらしい。

https://www.nikkei.com/article/DGXMZO33991670Z00C18A8000000/

組み込み系でどうアップデートを適用するか・・・という問題は残るが、
OSレベルではサマータイムへの対応はそれほど問題はない(？）


# サマータイムの影響を受ける処理

思いつく限り並べてみる。

### 指定時刻に起動する処理  

「毎日午前3時にバックアップスクリプトを起動」など。


(1)のとき、
例えば午前3時に起動する処理があった場合、
午前3時が存在しないため、実行されるはずの処理が実行されない。

(2)のとき、
例えば午前1時に起動する処理があった場合、
午前１時が１日に2回来るため、2回処理が実行されてしまう。



こういった処理の実行に使われるものとしてはcronが一般的と思う。
調べたところ、cronはそもそもサマータイムの対応ができているらしい。
https://tmotooka.hatenablog.jp/entry/2012/10/07/195622

上記の例で言えば、
(1)のときは、午前4時に午前３時に実行するはずだった処理を実行する。
(2)のときは、２回目に訪れた午前１時には、処理が実行されない。

というわけで、単にcronで定期実行している処理であれば、それほど気にしなくても良いかもしれない。


### タイムスタンプから経過時間を計算する処理

出社時刻と退勤時刻を記録し、勤務時間を計算するようなアプリケーションを考えてみる。

(1)のとき、
3/11 午前９時に出社し、3/12の午前３時（サマータイムでの午前５時）に退勤した場合、
実際の勤務時間は１８時間だが、サマータイム非対応のアプリケーションでは２０時間と計算される。

(2)のときには、逆に１６時間となってしまう。


こうした処理は以下の手順で勤務時間を計算するのが一般的と思われる。
・出社時刻と退勤時刻をそれぞれUNIX時間に変換する。
・退勤時刻のUNIX時間　－　出社時刻のUNIX時間　＝　勤務時間


サマータイムに対応させるためには、一度サマータイムを持たないUTCに変換することで対応する。
・出社時刻、退勤時刻を、UTCに変換する。
・UTCに変換した出社時刻、退勤時刻をUNIX時間に変換する。
・退勤時刻のUNIX時間　－　出社時刻のUNIX時間　＝　勤務時間

https://qiita.com/sota2502/items/e8df68d9cfebd01af809

Java, Perl(DateTime::TimeZone), Python(pytz)では任意のタイムゾーンからUTCへの変換ライブラリが存在しているようである。
https://qiita.com/tinymouse/items/06706981f7bbdc8215fd

javascriptはタイムゾーン対応が甘い（？）。
https://qiita.com/tinymouse/items/06706981f7bbdc8215fd

いずれにしても、日本のサマータイムはどの言語にもまだ組み込まれていないから、自力で実装するか、言語に組み込まれるのを待ってアップグレードが必要になる。

これはかなり問題で、もしサマータイムの開始日・終了日・何日ずらすか・・・が変更されたら、その度に言語のアップデートが必要になってしまう。

もし今からアプリケーションを作るのであれば、データベース上など内部処理はなるべくUTCで持っておき、表示する際に変換したほうが良いかもしれない。そうすれば、サマータイム導入後にも変換ロジックのみの修正ですむ。



# 最後に

あまり他人が読んで役に立つような内容にはできませんでした。すみません。。。

以下、感想。

* サマータイムはやっぱり導入すべきでない、面倒すぎる
* これまでサマータイムについて意識したことはなかった。少なくとも使っている国はあるわけだから、海外展開などで気にしないといけない場合はある。その意味では良いきっかけになった。
Rメモ　ヒストグラムの層別可視化

営業数値やら各データを見る際に、まずは単純集計ですが、
代表格のヒストグラムは、何故かEXCELやスプレがポンコツで、
Rじゃないと作りにくいですよね。

（PythonとJupyterNotebookもありだと思いますが、
速攻！を目的にするならやはりRだと個人的に思っています。）

そんなhist機能ですが、層別で見る方法でちょっと検索に時間がかかったのでメモ。
（オプションも以外に逐次検索するので、ついでにメモ。）


#ヒストグラムの層別化
ここでは２つの方法を紹介しています。
一つはノーマルhistで色を変えて重ね合わせる方法。
２つ目はライブラリでlatticeを使った方法。

よく使うオプションを下に追記しておきますので、カスタマイズ用に。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244525/78d69be9-30bd-155d-65aa-8e96729ee07b.png)

```r:
> hist(d[d$性別=="W",]$カラム名,　breaks = 25, col = "#ff00ff40",ylim = c(0,5))
> hist(d[d$性別=="M",]$カラム名,　breaks =100, col = "#0000ff40",add = TRUE)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244525/483b72ca-0c0f-e365-3ed1-e03dccddeb2d.png)

```r
> library(lattice)
> histogram(~カラム名|性別,data=d,col=0)
```


#よく使うオプション
営業さん向けなので一応細かく書いときます。


```r:hist_command.R
#ノーマル
> hist(d$カラム名)

#切り数を追加：breaks
> hist(d$カラム名,breaks = 25)

#頻度（割合）ラベルを表示：label
> hist(d$カラム名,breaks = 25, label = TRUE)

#頻度を割合に変換：freq
> hist(d$カラム名,breaks = 25, label = TRUE, freq = FALSE)

#表示する範囲を指定：xlim、ylim
> hist(d$カラム名,breaks = 25, label = TRUE, freq = FALSE, xlim = c(0,1000), ylim = c(0,0.003))

#軸名と題名を追加（日本語だと表示されないので注意）：xlab、ylab、main
> hist(d$カラム名,breaks = 25, label = TRUE, freq = FALSE, xlim = c(0,1000), ylim = c(0,0.003), xlab = "x", ylab = "y", main = "Histgram")

#RGB値で色を追加(数字直接指定でも、"red"などもOK)：col
> hist(d$カラム名,breaks = 25, label = TRUE, freq = FALSE, xlim = c(0,1000), ylim = c(0,0.003), xlab = "x", ylab = "y", main = "Histgram", col = "#ff00ff40")

#”性別”列の”W”だけに絞る：d[d$性別=="W",]$カラム名
> hist(d[d$性別=="W",]$カラム名,　breaks = 25, label = TRUE, freq = FALSE, xlim = c(0,1000), ylim = c(0,0.003), xlab = "x", ylab = "y", main = "Histgram", col = "#ff00ff40")

#一つ前のグラフと重ね合わせる：add
> hist(d[d$性別=="W",]$カラム名, add = TRUE, breaks = 25, label = TRUE, freq = FALSE, xlim = c(0,1000), ylim = c(0,0.003), xlab = "x", ylab = "y", main = "Histgram", col = "#ff00ff40")

```
QNAP NASでRAID1を構築しているHDDがエラーを吐いたので交換する

# 環境
- QNAP TS-231でNASを運用している
- WD Red 4TB×2でRAID1を構築、全領域1ボリューム
- ファイルベースのiSCSIターゲットを200GB確保、残りはLAN内の共有フォルダとして運用

# 症状
- QNAPのNAS管理ツールQfinderで見たときに、異常ステータスが報告されていた
 - こんな感じ

![QNAP説明1.png](https://qiita-image-store.s3.amazonaws.com/0/262640/5034d6e5-8604-9f2f-05d7-2987a1247760.png)

- 管理コンソールにログインすると、Disk2にS.M.A.R.T.の警告が出ている
 - ID197の異常セクタ(Current Pending Sector) が1

![QNAP説明2.png](https://qiita-image-store.s3.amazonaws.com/0/262640/3fd8516e-b425-8b63-99e6-51f8aed6e550.png)

- ありゃ、死んでしまったか、と思って管理ツールのお勧め通りDisk2にフルスキャンをかけてみる。
 - 4TBでだいたい9時間くらい？らしいが寝て起きて会社行って帰ってきたら終わっていた。
- スキャンでID197が22に増え、これはいよいよ死亡かと思ったけどしばらく時間を空けたら6になっていた。
- ID197は読みに行って読めたらエラーでなくなるらしいので、意外とこのまま行けるかもしれない？が色々怖いのでディスクを交換することにする。
 - Disk2は以前もエラー吐いて交換しているのだが、ハズレを引いてしまったらしい。WDは信用しているのだけど・・・

![QNAP説明3.png](https://qiita-image-store.s3.amazonaws.com/0/262640/3719b632-edb9-4de2-cf9e-465453048b93.png)

# 交換
- TS-231はディスクのホットスワップに対応しているので、NASを運用したままディスクの交換→RAID再構築が可能。
- せっかくなので、今後の拡張に備えて大容量のディスク（8TB）を用意することにする

## 交換手順
1. Disk2をRAID1から切り離し
1. 一時的にRAID1がシングルドライブ運用になる（RAID的にはDegraded）
1. Disk2を物理的に交換（4TB→8TB）
2. RAID1を再構築
3. 以前と同じ容量のRAID1が復旧する（4TB）

## 今後の拡張（予定）
1. 8TBのディスクを用意する
2. 同じ要領で、Disk1を交換する（4TB→8TB）
3. RAID1を再構築（4TBのRAID1になる）
4. RAID1の容量拡張（4TB→8TBになる）

## 代替ディスク
- WD Red 8TBを購入
 - ヘリウム充填じゃないほうの256MBキャッシュモデル（WD80EFAX）
 - 地元のドスパラにて24,000
 - https://www.wdc.com/ja-jp/products/internal-storage/wd-red.html

## 実際の交換

### まずDisk2を切り離す。
- ここのメニュー階層がすごくわかりにくい
 - 「ディスク」の項目にあると思ったのに・・・
- ストレージマネージャ→ストレージ領域→ボリューム→管理→ディスクを1台ずつ交換する

![QNAP説明4.png](https://qiita-image-store.s3.amazonaws.com/0/262640/6d61dc6c-9678-00f1-ad20-62112821a758.png)

### おもむろに抜く。
![QNAP作業1.jpg](https://qiita-image-store.s3.amazonaws.com/0/262640/ffd84a74-0947-54ab-5ce1-49c9f622f1d1.jpeg)
![QNAP作業2.jpg](https://qiita-image-store.s3.amazonaws.com/0/262640/633a29a2-b2b2-d153-e0eb-e0f08c1e3031.jpeg)

### トレイから旧HDDを外して新HDDに換装
![QNAP作業3.jpg](https://qiita-image-store.s3.amazonaws.com/0/262640/738e90de-416f-5507-22e2-e5c8e0c4983f.jpeg)

### RAID1再構築
- NASが自動的にHDDの挿抜を検知して、再構築を開始する
- その間、該当ボリュームは「警告」状態（RAID1がDegraded状態）になるが、NASとしては普通にアクセス可能。
- 所要時間およそ26時間

![QNAP説明5.png](https://qiita-image-store.s3.amazonaws.com/0/262640/acab3c82-1fb4-bdab-11b1-6a2fc83b6023.png)

### 完了
- 交換完了！ついでにファームも最新にアップ。ここまでNASはずっと稼働したまま。そのうち8TBに拡張もやってみよう。

![QNAP説明6.png](https://qiita-image-store.s3.amazonaws.com/0/262640/47121cc5-a58c-02e0-96ff-07bf933df1e9.png)
openposeをpythonでサーバ化

# 実装したもの
openposeのpython APIを利用して、server化してみる
画像を投げると、骨格推定の情報が埋め込まれた画像が返ってくるという簡単なもの

# 試した環境
- Ubuntu 16.04.4
- python 3.5.2
- openpose revision: f49e18421da832ae441f75477035786126357401

# ソース
https://github.com/komorin0521/openpose_python_server

# 実行
1. openposeをpythonライブラリを利用するモードでインストール

    参考：[OpenposeのPYTHON API](https://qiita.com/komorin0521/items/5de414653cffb2633ae8)
    
2. 本repositoryをクローン
    `$ git clone https://github.com/komorin0521/openpose_python_server.git`

3. config修正
    モデルファイルのパスとホストやポートなど、必要に応じて修正

4. server起動
    `$ ./run_server.sh`

5. POSTして確認
    openpose公式のgitからダウンロードした時に含まれる画像で試す場合
    ```
    $ (time) curl -XPOST -F file=@(path_to_openpose)/examples/media/COCO_val2014_000000000328.jpg http://localhost:3001/get_predict_image > pred.jpg 
    ```
    
    ![res.jpg](https://qiita-image-store.s3.amazonaws.com/0/114699/5d5c9a19-3ff2-d64b-6b0f-990002a6e9b2.jpeg)


# 苦労した点
最初、openposeのインスタンスをmainファンクションで作成して、
その後、`OpenPoseServer`のメンバ変数で定義してみたが、
下記のエラーが発生

```
The CPU/GPU pointer data cannot be accessed from a different thread.
```

なんとなく頭でデバッグはできたので、(=説明はできない)、
`OpenPose`インスタンスを`get_predict_image`関数内で作成するようにしたら、案の定うまくいった。
レスポンスまでの時間も1秒程度だったから速度的には（個人的には）許容範囲かな。
メモリの観点では、250MBくらいメモリリークが発生するけど、
数回試したところ、それ以上は増えなかったので、これもまあ許容範囲かな
herokuでcssなどのstaticファイルが反映されない場合の対処法

ほんとにわたしの備忘録になるだけですが、
[Django and static assets](https://devcenter.heroku.com/articles/django-assets)
を参考にしたらいいです。

Django→herokuのデプロイ方法はそのうち、全体感をまとめよう！
nasneの共有フォルダにアクセスするために、PowerShellでWindowsの機能を有効化する

# 前書き

あるときWindows 10 の端末から、nasneの共有フォルダにアクセス出来なくなりました。

具体的には

- スマホからはアクセス可能
- PCでもメディアサーバーは見える
- IPアドレス直打ちでnasne HOMEにアクセス可能
- エクスプローラーにIPアドレスやnasneの名前を入れてもアクセス不可

という状況でした。

そのときは以下のページを参考に、
「Windowsの機能の有効化または無効化」から
「SMB 1.0/CIFS ファイル共有のサポート」を有効化して、無事共有フォルダにアクセスできるようになりました、

> [Windows10からnasneの共有フォルダにアクセスする（180811削除）](https://qiita.com/hons/items/33f0940c0dc49f308ddb "Windows10からnasneの共有フォルダにアクセスする")
> [Windows10からnasneの共有フォルダにアクセスする（キャッシュ）](https://webcache.googleusercontent.com/search?q=cache:Y8Osgp3WaIwJ:https://qiita.com/hons/items/33f0940c0dc49f308ddb+&cd=4&hl=ja&ct=clnk&gl=jp "Windows10からnasneの共有フォルダにアクセスする")

# PowerShellから設定

上記の設定をしたものの、端末移行時などに忘れそう……と思っていたところ、PowerShellから設定できることがわかったため、スクリプトとしてみました。

## 作成環境

Windows 10 Pro 64bit

```:$PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.17134.165
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17134.165
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
```

## スクリプト

[Get-WindowsOptionalFeature](https://technet.microsoft.com/ja-jp/library/dn376470.aspx "Get-WindowsOptionalFeature") コマンドレットで設定状況の確認
[Enable-WindowsOptionalFeature](https://technet.microsoft.com/ja-jp/library/dn376466.aspx "Enable-WindowsOptionalFeature") コマンドレットで機能の有効化が行えるため
`SMB1Protocol`・`SMB1Protocol-Client`・`SMB1Protocol-Server`の3つの機能の確認・有効化を行います。
また、上記コマンドレットの実行にはPowerShellを管理者権限で起動しておく必要があります。

`Online`スイッチでローカルマシンを対象にし、`FeatureName`に機能の名前を指定します。
`Get-WindowsOptionalFeature`の`FeatureName`は単一文字列しか受け取れませんが、
`Enable-WindowsOptionalFeature`は`FeatureName`に文字列の配列を受け取れます。

今回は`Enable-WindowsOptionalFeature`のパラメータセットに合わせてスプラッティング用のhashtableを定義し、それを使ってパラメータを指定しています。

```posh
# for access nasne file server
[hashtable]$param = @{
    Online = $true
    FeatureName = [string[]]@(
        'SMB1Protocol'
        'SMB1Protocol-Client'
        'SMB1Protocol-Server'
    )
}

# 設定状況の確認
$param.FeatureName | Get-WindowsOptionalFeature -Online -FeatureName {$_}

# 機能を有効化
Enable-WindowsOptionalFeature @param
```

# 参考

「SMB 1.0/CIFS ファイル共有のサポート」が無効化されたのは、以下の脆弱性があったためだと思われます。

> [マイクロソフト セキュリティ情報 MS17-010 - 緊急 | Microsoft Docs](https://docs.microsoft.com/ja-jp/security-updates/securitybulletins/2017/ms17-010 "マイクロソフト セキュリティ情報 MS17-010 - 緊急 | Microsoft Docs")

必要が無ければ無効化のままの方が無難かもしれません。
flask-httpauthを使って、FlaskでBasic認証を5分で実装する

FlaskでBasic認証つけて、簡易的な管理ページを作ってみました。

## flask-httpauthをインストール

```
$ pip install flask-httpauth
```

## app.pyを編集

```python
from flask import Flask
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
auth = HTTPBasicAuth()

users = {
    "user_name": "password123",
}

@auth.get_password
def get_pw(username):
    if username in users:
        return users.get(username)
    return None

@app.route('/')
@auth.login_required
def index():
    return "Hello, World"

if __name__ == '__main__':
    app.run()
```

これでbasic認証が現れるようになります。あっという間！！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/209160/45f1ae96-17b0-014c-3858-fe8062ca7b78.png)


## AWS ElasticBeansTalksにデプロイするときには要注意！

これだけでEBにデプロイすると、Basic認証画面ポップは出てきますが、正しいユーザー名、パスワードを入力しても正常に通りません。 `.ebextentions` ディレクトリをapp.pyと同じディレクトリに作成して、その下に `auth.config` を作成してあげましょう。

```:auth.config
container_commands:
  01_wsgi_pass_headers:
    command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
```

この状態で、デプロイするとBasic認証が正常に動くようになります。
herokuでPythonﾗｲﾌﾞﾗﾘ(pandas,sklearnとか)を使えるようにするための方法

#ローカル(開発)環境で使うには

これは、言わずもがなですが、コマンドからpipでインストールすればいいだけです。

#herokuで使うには

いくつか、ファイルを編集する必要があります。git pushはできたけど、ブラウザ開いたらModuleNotFoundErrorになった時は、これをする必要があるかもしれません。

まずは、

```Command
pip freeze > requirements.txt
```
でrequirements.txtを生成する必要があります。すると、例えば以下のようなファイルが生成されます。(あくまで、一例です)

```requirements.txt
beautifulsoup4==4.6.1
certifi==2018.4.16
chainer==4.3.1
chardet==3.0.4
cycler==0.10.0
dj-database-url==0.5.0
Django==2.1
django-heroku==0.3.1
filelock==3.0.4
gunicorn==19.9.0
html5lib==1.0.1
idna==2.7
jsm==0.19
kiwisolver==1.0.1
lxml==4.2.4
matplotlib==2.2.2
numpy==1.15.0
pandas==0.23.4
pandas-datareader==0.6.0
pipenv==2018.7.1
protobuf==3.6.0
psycopg2==2.7.5
pyparsing==2.2.0
python-dateutil==2.7.3
pytz==2018.5
requests==2.19.1
requests-file==1.4.3
requests-ftp==0.3.1
scikit-learn==0.19.2
scipy==1.1.0
six==1.11.0
sklearn==0.0
urllib3==1.23
virtualenv==16.0.0
virtualenv-clone==0.3.0
webencodings==0.5.1
whitenoise==3.3.1
wrapt==1.10.11
```

つぎに、Pipfileを編集します。例えば、pandasを使うなら、下記のようにpackagesに追加する必要があります。

```pipfile
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
dj-database-url = "*"
django = "*"
gunicorn = "*"
psycopg2 = "*"
whitenoise = "*"
requests = "*"
pandas = "*"
jsm = "*"
pandas_datareader = "*"
matplotlib = "*"
chainer="*"
sklearn="*"
scipy="*"

[requires]
python_version = "3.6"
```

Pipfileを編集した上で、コマンドから、Pipfile.lockを生成します。

```Command
pipenv install
```
pipenvが無ければ、pipからpipenv自体をインストールしましょう。

これで、git add→commit→pushでできるハズです。
トランザクション分離レベルまとめ

データベースの分離レベルについて纏めます。

#1 分離レベルとは

OracleやSQLServer等のリレーショナルデータベースはACID属性という概念を基に設計されているという話は聞いたことがある人が多いと思います。
それぞれ
#### Atomicity(原始性)  
データの処理はトランザクションという単位で制御されてcommitかrollbackすることで処理が終了するということです。
#### Consistency(一貫性)
データが書き換えられない限りいつ、どこから取得しても結果は同じになる。
updateのSQLを実行した後でその内容をselectしたら必ずupdateした内容が取得できるということです。
#### Isolation(独立性)
今回のメインテーマです。
詳しくは後述しますが、あるトランザクションで操作した内容はほかのトランザクションに影響を与えない(=独立している)ということです。
#### Durability(永続性)
データが失われることがないようにする。
障害などでデータが失われてもバックアップやログなどから復旧する手段を用意しておくべきということです。


このページの主題である分離レベルとはConsistencyを実現するための設定です。
分離レベルの設定によっては完全にほかのトランザクションから独立できたり他のトランザクションから影響を受けるようになったりするようになります。
この分離レベルを低くする(他のトランザクションからの影響を受けやすくする)と独立性は弱くなりますが、その分パフォーマンスは向上します。必要な独立性はどれなのかを考えてDB設計をする必要があるわけですね。


#2 分離レベルの種類
分離レベルは高い順から紹介すると

* serializable
* repeatable read
* read committed
* read uncommitted

の４つがあります。
この４つをそれぞれ説明するには先にトランザクションが他のトランザクションによって受ける現象の説明が必要です。
この現象には3種類あるので、それぞれ説明します。(覚えることが多いですね。。。)

#### Dirty read
他のトランザクションがcommitしていない情報を読み込む現象。
読み込んでしまった後で確実にcommitしてくれるならまだいいのですが、問題は他のトランザクションがロールバックしてしまったケースです。
他のトランザクションがinsertしたけどまだcommitしていないレコードを読み込んでupdateしようとするとします。
update実行前に他トランザクションがロールバックした場合、存在しないレコードをupdateしようとしてエラーになってしまいます。
update実行後にロールバックされると更新したはずのレコードが見当たらないということになります。
このようなことを防ぐためにこのDirty readだけは最低限防ぐようにするべきでしょう。

#### fuzzy read
Non-repeatable readとも呼ばれます。これはあるトランザクションの処理中に他のトランザクションが同一レコードに対して更新を掛けてcommitした場合、その内容がこちらにも反映されるという現象です。
つまり他のトランザクションとupdateの対象レコードが重複した時に発生します。
対策しなければ他のトランザクションの更新を上書き、もしくは自分の更新内容が上書きされてしまい、思わぬ不具合を生むことになります。
この場合、楽観排他や悲観排他といった排他制御を取り入れることで対応できます。
処理が競合した場合は自分の処理を一旦ロールバックして取りやめる方法です。

#### Phantom Read
これはトランザクションで更新予定のテーブルに他のトランザクションがレコードを追加・削除した場合にその内容がこちらにも反映される現象です。
個人的にこの現象は発生しないとマズいケースもあるのかなと思っています。
例えば、IDというカラムが主キーのテーブルでIDは1から順に連番が振られているとします。
あるトランザクションがこのテーブルにID=2のレコードをinsertしようとしている時に他のトランザクションが先にID=2のレコードをinsertしてcommitしてしまった場合、自分のinsertは主キーが重複してエラーになってしまいます。
Phantom Readが発生するなら事前にIDの重複を検知してロールバックすることができますしそもそもシーケンスなどを使用してIDを設定しているなら自分のinsertはID=3でcommitすることも可能になります。
勿論レコードの数によって結果が変わる処理等では想定外の結果になるので対策は必要になります。
~~ところでファントムリードって名前カッコいいですよね！~~

これら3つの現象を防ぐかどうかの設定値が上記で紹介したserializable、repeatable read、read committed、read uncommittedの4つです。
設定の効果は下記の表に示す通りです。

| 分離レベル\現象|Dirty read |fuzzy read|Phantom Read|
|:--|:--:|:--:|:--:|
|read uncommitted|発生する|発生する|発生する|
|read committed|発生しない|発生する|発生する|
|repeatable read|発生しない|発生しない|発生する|
|serializable|発生しない|発生しない|発生しない|

read uncommitedに設定してしまうとその名前の通りcommitされていないデータを読み込むDirty readが発生してしまうので基本的にこれは避けるべきでしょう。
自分は仕事でWEBシステムを扱っていますが、WEBシステムで使用するDBはread committedで設定することが多いようです。
WEBシステムは不特定多数の人が使用するのでパフォーマンスを重視しなければならず、あまり重い設定はできないのが大きな理由であとは排他制御等を採用してのロジック側で対応するケースが多いのかと。
ちなみにserializableについては全ての減少を防ぐ最強の設定ですが、実際にどうやって防ぐのかというとトランザクションの同時実行を不可能にするようです。あるトランザクションが処理中に他のトランザクションが～ということがそもそも発生しなくなるので不整合は発生しなくなりますがそりゃ処理も重くなりますね。。。

#　まとめ

トランザクション分離レベルによってデータの不整合の発生を段階的に防ぐことができる。
より多くの不整合を防ごうとするとその分処理に時間がかかるので許容できる不整合とできない不整合を考え、パフォーマンスとのバランスを考えて設定する必要がある。
centos7 ルートログインを無効にする

ルートの名前がrootであることは誰もが知っている常識です。

SSHでルートログインが有効だと
ログイン名がわかり、
セキュリティー上危ないです。

viを使ってルートログインを無効にしましょう。


vi /etc/ssh/sshd_config

PermitRootLogin no


編集したらSSHをリスタートして変更を反映させます。

systemctl restart sshd
AWSを使って3分でAPIを作り公開する

こんにちは！RHEMS技研のニシダです！
以前、[GAS](https://developers.google.com/apps-script/)を使って
[3分で API を作って世の中にデプロイするライブコーディング〜今日から君もスピードスターエンジニア〜](https://qiita.com/numanomanu/items/7bb6542961a2c567f05c)
という記事が公開されていました。(GASについては[こちらのQiita記事](https://qiita.com/t_imagawa/items/47fc130a419b9be0b447)がオススメです)
今回はAWSを使って、同じく3分でAPIを作っていきます。

#はじめに
あくまでAPI(getのみ)を作って公開するまで、です。
APIGatewayとLambdaをつないだだけです、ここからDynamoDBとつないだり、APIGatewayにHTTPメソッドを足していくと本格的なAPIが作れるようになります

#動画
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">AWSで3分で簡単なAPIサーバを立てる動画<br>あとはDynamoDBと繋げば簡単にCRUDを満たすAPIサーバを立てられます<br>ハッカソンとか、スピード勝負のときに使えるやつです<br>今Qiitaで記事にします<a href="https://t.co/GeyW7osRXa">https://t.co/GeyW7osRXa</a></p>&mdash; にし☁ (@cidr_nishida) <a href="https://twitter.com/cidr_nishida/status/1028263306044223489?ref_src=twsrc%5Etfw">2018年8月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
(YouTubeの動画って埋め込むことできないんですね・・・)

#説明
##1 (開始~26秒)
まずはLambda関数を作っていきます。
関数名や、ロール名はわかりやすく、今回はDynamoDBを使わない(使うとコード量的に3分じゃ終わらない)のでロールにアタッチするポリシーは初期のままです。Dyanmoを使うならAWSLambdaDynamoDBExecutionRoleとか与えておきましょう。

##2 (26秒~1分55秒)
APIGatewayの設定をしていきます。ここで発行されたエンドポイントに対してHTTPリクエストを送信していきます。
作成画面のLambda関数には先程作った関数の関数名を記入します。この時点で関数の作成が成功していれば予測候補にでてきます。
今回はGETメソッドでクエリ文字としてパラメータを渡しています。クエリ文字をLambdaでも扱えるように設定をしています。
メソッドリクエスト→URLクエリ文字パラメータ→名前を入力して作成→必須にチェック
統合リクエスト→マッピングテンプレート→Content-Typeにマッピングテンプレートを追加、`application/json`→テンプレートの作成に以下を入力

```json
{
  "id":"$input.params('id')"
}
```

状況に応じてidの所を変更しましょう。
また、動画では忘れて最後にやっていますが、この時点でアクションからAPIをデプロイして構いません。

##3 (1分55秒~2分24秒)
Lambda関数にコードを書いていきます。最初の方で一度IAMを開いていますが、今回は何も設定をしません。もし、このLambda関数内でDynamoDBを使いたければ、先程のポリシーを該当するロールにアタッチしていきましょう。
Lambda関数のeventに、APIGatewayのマッピングテンプレート通りのjsonが渡るので、`event.id`とすることで、今回の値を取得できます。以下が実際のLambda関数です。

```javascript:index.js
exports.handler = (event, context, callback) => {
    callback(null, event.id);
};
```

##4 (2分24秒~2分41秒)
先程しわすれた、APIのデプロイとエンドポイントの確認を行っています。


---
以上で、3分でAPIをAWS上で立てる手順でした。
もし要望が多ければ、この後考えられる、「DynamoDBでデータの書き込みや更新、削除、取得などを行うAPIの立て方」を書きます、が、コードの量やロード時間など含めて3分では終わりそうにないので、3分ハッキングとしてはこれで完結いたします。
ですので、もし次回があれば10分ハッキングとかって名前になってるんじゃないでしょうか。



特に理由があったわけでもないんですが、大急ぎで書いていたので動画内でも落ち着きのないマウスやタイプミスが目立ってます。。
あと記事内でもおかしな言い回しや誤字があるかもしれません。
PHP：array_diff, array_intersectで配列の比較を超高速に行う（脱foreach作戦）

DBやCSVファイルからデータを取得する際、配列として取得することはよくある。
例えば、DB上の大量のデータを配列として取得して、手元にある別のデータとの重複の照合を行うこともあるだろう。
ここでは、配列同士の比較をできる限り高速に行うことを主眼に置く。
実行速度は処理に要する時間を計測することで、遅い or 速いを判断する。
[【PHP】処理の速度を計測する方法](https://www.out48.com/archives/1719/)
[【PHP公式】microtime — 現在の Unix タイムスタンプをマイクロ秒まで返す](http://php.net/manual/ja/function.microtime.php)

##配列の準備

はじめに、１０万個の要素を持つ配列を２つ準備する。
`$data`には0〜99,999の100,000個の数字
`$randomData`には0〜500,000のうちランダムに100,000個の数字
が格納されている。

```php
for ($i = 0; $i < 100000; $i++) {
	$data[] = $i;
}

for ($i = 0; $i < 100000; $i++) {
	$randomData[] = rand(0, 500000);
}
```

#**1.** **重複する要素を取得する**
##1.1 `foreach`で普通に比較する

`$data`のうち`$randomData`に含まれるものを数え上げる際にまず思い浮かぶのは、次の方法だろう。それぞれの要素数が少なければ、すぐに終わるが１０万件同士の比較になるとそうはいかない。また、実際の業務ではもっと複雑な処理をしなければならないことも多く、あまり使い勝手は良くない。
何よりもコードが見づらい。

```php
foreach ($data as $i) {
	foreach ($randomData as $j) {
		if ($i == $j) {
			$result1[] = $i;
			break;
		}
	}
}
```

```terminal:実行結果
121.19333004951 seconds.
Count: 18016 //重複している要素の数
```

##1.2 `array_intersect`を用いる

（PHP4.0.1以上）
[【PHP公式】array_intersect — 配列の共通項を計算する](http://php.net/manual/ja/function.array-intersect.php)
`array_intersect`は、第一引数のうち第二引数以降に含まれるものが返り値になる。このとき、値の型とキーは保持される。また、値の比較はstring(文字列)にキャストした上で行われ、完全一致したものだけが返される。
実際に今回のコードに適用してみると、驚くほど簡潔で清々しいほどである。
そして実行時間は、1.1と比較して約５００分の１である。

```php
$result2 = array_intersect($data, $randomData);
```

```terminal:実行結果
0.24257612228394 seconds.
Count: 18016 //同じプログラム内で行ったので同じ重複数
```

#**2.** **重複しない要素を取得する**
##2.1 `foreach`で普通に比較する

`foreach`を使って、ある程度実行速度を速くするためには次のコードが思い浮かんだ。コードの見づらさは、ご容赦を。
**「foreachでも、もっといい方法あるよ」**って方は是非教えていただきたい。
このコードでは、`$data`のうち`$randomData`に含まれないものを取得している。
実行時間は1.1とほぼ同じ結果となった。

```php
foreach ($data as $i) {
	foreach ($randomData as $j) {
		if ($i == $j) {
			break;
		}
	}
	if ($i != $j) {
		$result1[] = $i;
	}
}
```

```terminal:実行結果
121.41330385208 seconds
Count: 82026 //重複していない要素の数
```

##2.2 `array_diff`を用いる

（PHP4.0.1以上）
[【PHP公式】array_diff — 配列の差を計算する](http://php.net/manual/ja/function.array-diff.php)
`array_diff`は第一引数のうち第二引数以降に含まれないものが返り値になる。このとき、値の型とキーは保持され、値の比較も`array_intersect`同様に行われる。
それでは、コードと実行結果を見てみよう。
実行時間は、なんと2.1の約４３００分の１である。

```php
$result2 = array_diff($data, $randomData);
```

```terminal:実行結果
0.02807092666626 seconds
Count: 82026
```

##まとめ

`array_intersect`と`array_diff`は、配列を高速比較できる素晴らしい関数である。
実際の業務では、もっとデータ量の大きいものを比較することは大いにあり得る。そのようなときは、PHPで準備されている配列用の関数を考慮しながら、実装方針を固めるようにしていきたい。
[【PHP公式】配列 関数](http://php.net/manual/ja/ref.array.php)
【Rails】最初に必要なSQL操作

# SQLの起動
ターミナルにてアプリのディレクトリへ移動。

```
$ cd [アプリディレクトリへのパス]


例
$ cd web/sampleapp
```
下記コマンドでSQLを起動

```
$ rails db

sqlite>
```
SQLを終了する際は、下記コマンド。

```
sqlite> .exit
または
sqlite> .quit
または
controlキー + D
```

#用語
<img width="954" alt="スクリーンショット 2018-08-11 22.04.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/180127/3b68e58c-1737-a582-49b9-cec17a4f35d2.png">


#基本操作コマンド
- テーブル一覧

```
sqlite> .table
```
- テーブルの構造を表示

下のコマンドで、全てのテーブルのスキーマ(構造)を表示することができる。

```
sqlite> .schema
```
もし特定テーブルの構造のみを表示したければ、下のコマンドを使用。

```
sqlite> select * from sqlite_master where type = 'table' and name='テーブル名';
```
- テーブルを作成

```
sqlite> create table テーブル名("カラム名" データ型 オプション, "カラム名" データ型　オプション, ...);
```
オプションとデータ型はなしでもテーブルを作成することができる。
よく使用するオプションやデータ型については記事の下部で紹介する。

#変更・更新

- テーブル名を変更

```
alter table 現在のテーブル名 rename to 新しいテーブル名;
```
- 値の更新

```
sqlite> update テーブル名 set カラム名 = 新しい値 where 条件式;
```
##追加・挿入
- レコードを1行挿入

```
sqlite> insert into テーブル名 values(値, 値, ...);
```

- レコードを複数行まとめて挿入

```
sqlite> insert into テーブル名 (カラム名, カラム名, ...) values (値, 値, ...), ..., (値, 値, ...);

#例
sqlite> insert into discography (name, artist, released_date, composer) values ("ももいろパンチ", "ももいろクローバー", "2009-08-05", NULL), ("ラフスタイル", "ももいろクローバー", "2009-08-05", NULL);
```

- カラムを追加

```
sqlite> alter table テーブル名 add column "カラム名" データ型;

#例
sqlite> alter table members add column "color" string;
```
##削除
- レコードの削除

```
sqlite> delete from テーブル名 where 条件式;
```
- テーブルの削除

```
sqlite> drop table テーブル名;
```
- カラムの削除<br>
sqliteには対応コマンドなし。


最後に rake db:migrate コマンドの実行も忘れずに。
RubyMineでrails始めたが、generateできずに詰まった話

大学の論文執筆などが忙しくて自分の時間があまり取れなかったけど、残るは発表練習だけになり時間ができたので思い切ってRubyを始めよう!と意気込んだ私です。
とりあえずWebアプリを作りたいと思いrailsをやりたかったのですが、RubyMineのgenerateで詰まったので備忘録。

#症状
RubyはPythonのpyenvと同じようにrbenvと言うものがあると知ってrbenv諸々を入れ、Rubyを入れて使えるようにしました。
その後、RubyMineでrailsアプリケーションのプロジェクトを作り、お試し...

controllerを作るために、プロジェクトのところで option+Gを押すと出てくるやつから生成して見ると、以下のメッセージ。

```
bash -c "RBENV_VERSION=2.5.1 /usr/local/bin/rbenv exec springまでのpath rails generate controller users say -s"

Process finished with exit code 1
```

そして何も起こらない。ここでかなり時間を持ってかれました。

#考えたこと、試したこと
とりあえず1行目のscriptがうまく動いていないことがわかるのでその辺りから、

1. springの再起動
2. railsコマンドをTerminalで打ってみる(これは動いた)
3. RBENV_VERSIONの部分を消してTerminalに(動かない)
4. /usr/local/bin/rbenvをrubyの場所にしてみたり(この時はrbenv execで一つのコマンドということを知らなかった、当然エラー)
5. rbenvのPathがおかしくないか確認
6. sdkやgemの確認

このあたりで微妙に諦め始める
エラーメッセージがなかったのが非常に痛い、google先生にもどう聞けばいいかわからない。

#最終的に
rbenvの導入から見直すかということになり、以下を参考にもう一度上から調べていった。
[rbenvおよびbundlerの基本的な使用方法](https://www.qoosky.io/techs/8a0f1d8d9e)

そして

```
$ rbenv exec gem install bundler
$ rbenv rehash
```
の部分を超えたあたりでgenerateが動くように!!
おそらくbundlerが上手く入っていなかったのだと思います(Overwriteしますか?と聞かれたので入っていなかった訳ではなさそう)

#まとめ
RubyMineでrailsプロジェクトを立てたがgenerateが使えない問題にぶち当たった。
色々を経て、rbenvを導入から見直したらbundlerが上手く入っていなかった模様。
正しいかはわからないが何とか動いた。

半日くらい潰してしまった...
コミットメッセージでどのコミットへfixup/squashするかを予め予約する方法

## ユースケース

過去のコミットへrebaseして混ぜ込みたいコミットがある(例えばtypo、軽微なバグ修正など)。
しかし今すぐにはしたくない(他の人とブランチ状態を共有している、レビュー中は修正したという経緯も残しておきたい、rebaseはプルリクをマージする直前にのみ行いたいなど)。
が、"Fix typo"など適当に書き残すとどのコミットへ混ぜ込むのか忘れてしまうのが辛い。

## ソリューション

gitのそれ向きの機能を使う。

#### 1. rebaseして混ぜ込みたいコミットを作成するとき、以下のようにコマンドを実行する

```bash
git commit --fixup ${混ぜ込み対象のコミットのSHA}
// または
git commit --fixup :/${混ぜ込み対象のコミットのメッセージに含まれるキーワード}
// ↑ 複数のコミットが該当する場合は直近のものが優先される

// fixupじゃなくてsquashしたいときはこう
git commit --squash ${混ぜ込み対象のコミットのSHA}
```

#### 2. rebaseするときに`--interactive --autosquash`オプションをつける

```bash
git rebase --interactive --autosquash master
```

すると、interactiveモードの初期状態が通常と変わる。
具体的には1で作成したコミットが混ぜ込みたいコミットの直後に移動して、かつ行の先頭のモード指定がpickからfixupへ変更される。

※ 現状では--interactiveなしに--autosquashは使用できないようなので注意

## おまけ

以下でautosquashオプションをデフォルト有効にできる

```bash
git config --global rebase.autosquash true
```

## 参考

* [git rebase \-\-interactive \-\-autosquash master](https://robots.thoughtbot.com/autosquashing-git-commits)
* [Git \- git\-commit Documentation](https://git-scm.com/docs/git-commit)
* [Git \- git\-rebase Documentation](https://git-scm.com/docs/git-rebase)
「世界最悪のログイン処理コード」を解説してみた

# 概要

　ところでこのツイートを見てほしい。このソースコードをどう思う？

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">世界最悪のログイン処理コード。<br>実際のサービスで可動していたものだとか……<a href="https://t.co/C2bG93ZCkj">https://t.co/C2bG93ZCkj</a> <a href="https://t.co/EfVNAEslrn">pic.twitter.com/EfVNAEslrn</a></p>&mdash; はっしー@海外プログラマ🇳🇿元社畜 (@hassy_nz) <a href="https://twitter.com/hassy_nz/status/1027890455940198400?ref_src=twsrc%5Etfw">2018年8月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

　**すごく……セキュリティーホールです……**
　一応は動いていますが、あまりに問題がありすぎるため、Twitterでも話題になっていました。
　問題点は片手に入り切らないぐらいある気がしますが、一つづつ解説していきます。

_※[元記事](https://www.reddit.com/r/programminghorror/comments/66klvc/this_javascript_code_powers_a_1500_user_intranet/)のタイトルに記載されていますが、このコードは<b>イントラネット内</b>で動作していたものです。_

# 問題点リスト

## 1. クライアント上のJavaScriptで書かれている

　**他の問題点を全部ぶっ飛ばす**ぐらいの**重大な不具合**です。
　クライアントと言うのはこの場合、サイトにWebブラウザ等でアクセスするユーザーのことを指します。
　こういったJavaScriptはHTMLやCSSと一緒にサーバーから送られてきますので、当然ユーザーに読まれます。
　すると、わざわざサーバーをハッキングせずとも**ログイン処理の全容がバレバレ**ということになります。

## 2. Cookieに書き込む認証情報がザル過ぎる

　1.により、568行目で「(jQueryにより)Cookieに『loggedin』キーに『yes』値を保存している」ことがバレます。
　つまり、**「手動でCookieに同じ値をセットすればパスワードを調べずともログインしたことにできる」**ことがバレます。
　それこそWebブラウザのInspectorで観測すれば一発でバレる**クソ**要素ですが、1.が無ければ発見が遅れたことでしょう。
　……ちなみに真っ当なログイン処理の場合、書き込む情報をランダムなログインIDにしたりJSON Web Token(JWT)にしたりします。

## 3. 任意のSQLを実行できてしまう

　1.によって露見してしまった、超重大な脆弱性です。
　544～546行から「apiService.sqlメソッドで任意のSQLを実行できる」ことが分かります。
　また、メソッド名から察するに、accoutsはSQLの実行結果を「連想配列の配列」で受け取れるのでしょう。
　つまり、JavaScriptのデバッグコンソールからデータベースに対して**任意のSQLを送れます**。

※「任意」と言いましたがその範囲は想像以上に広く、単に「usersテーブルから全部のデータを取り出せる」他、有名なRDBのコマンドを送って応答を見ることでどのRDBを使用しているかまで察せられます。すると、**他のテーブルの情報も根こそぎ取られる**だけでなく、**ユーザー情報を弄って完全に支配を奪ってしまう**ことも可能かもしれません。ｱｶﾝ……

## 4. パスワードを平文で保存している

　平文とは、暗号化されていない文のことです。つまり、データベースにパスワードの文字列がそのまま保存されています。
　すると、データベースがハッキングされた際、**ユーザーが入力したパスワードが全部漏れてしまう**ことになります。
　一般的なWebサイトだと、そうならないようにパスワードをハッシュ関数で暗号化することにより、仮にデータベースをハッキングされてもパスワードがバレないようにしますが、この場合はそうじゃないということですね。

　さてここで**1.と3.を思い出してください**。これらを合わせると、「`apiService.sql("SELECT username, password FROM users");`」とすれば**全ユーザーのユーザー名とパスワードが取得できます**。

## 5. なぜかユーザー情報を全部取得している

　4.までならまだ、「`SELECT count(username) FROM users WHERE username=${username} AND password=${password}`」とでもすればユーザーの存在有無は判定できるでしょう。しかし今回の場合、**毎回全ユーザーの全情報を取得**しています。
　ユーザー名とパスワードが一致したデータだけ取り出せばいいので**全ユーザーを取得する必要はない**ですし、ユーザー名とパスワードしか見ていないので**全情報を取得する必要もない**です。
　おまけに、1.により上記処理がクライアント(Webブラウザ)で実行されますので、**ユーザーに無駄なメモリを使わせる**ことにも繋がります。ゾッとしますね……。

## その他のおかしな点

- SQLを直接文字列を入力して実行→今回のケースでは**SQLインジェクションすらできない**ほどクソだったのでさほど影響はないですが、一般的に、「SQLに任意の文字列を入力できる」は**バグの温床**です
- `if ("true" == "true")`や`if (authenticated === true)`も相当トチ狂っていますが、重大な脆弱性ってほどでもないかと……
- どこからどこまでも**クソコード**な癖に、「===」演算子を使うことで暗黙の型変換をキッチリ回避しているのが**謎**です

# まとめ

　問題点1.が無くても簡単にハッキングできるログイン処理でしたが、**問題点1.が全部持っていった**感があります。
　また、問題点5.の処理が「あまりに脳筋なためにSQLインジェクションできない」といった意味不明な結果になったのは笑いましたｗ
　なお、元のソースコードをマシになるように手直ししていくと、たぶん**原形を留めなくなる**ので省略します。
PC-98 フロッピーIPLサンプル

Bドライブなら1、セクタ番号を指定し、フロッピーのセクタを読み込み表示します。

```secread.c
#include <stdio.h>
#include <dos.h>
#include <ctype.h>

#define SECBYTE 1024

void secread(unsigned char *buf, int drive, int n, int sec)
{
	_asm {
		push    bp
		mov     bx, buf
		mov     ax, drive
		mov     cx, n
		mov     dx, sec
		int     25h
		popf
		pop     bp
	}
}

int main()
{
	int i, j, drive, sec;
	unsigned char buf[SECBYTE];

	printf("drive no ? ");
	scanf("%d", &drive);
	printf("read sector no ? ");
	scanf("%d", &sec);
	secread(buf, drive, 1, sec);

	for (j = 0; j < 16; j++) {
		printf("%04x: ", j*16);
		for (i = 0; i < 16; i++) {
			printf("%02x ", buf[j*16+i]);
		}
		putchar('\n');
	}
	return 0;
}
```

IPLファイルを指定し、Bドライブのセクタ番号0に書き込みます。

```secwrite.c
#include <dos.h>
#include <stdio.h>
#include <string.h>

#define SECBYTE 1024

void secwrite(char *buf, int drive, int n, int sec)
{
	_asm {
		push    bp
		mov     bx, buf
		mov     ax, drive
		mov     cx, n
		mov     dx, sec
		int     26h
		popf
		pop     bp
	}
}

int main(int argc, char *argv[])
{
	int drive = 1;
	int sec = 0;
	char *fname;
	FILE *file;
	char buf[SECBYTE];

	if (argc != 2) {
		fprintf(stderr, "usage: secwrite filename\n");
		return 1;
	}
	fname = argv[1];

	file = fopen(fname, "rb");
	if (! file) {
		perror(fname);
		exit(1);
	}
	memset(buf, 0, SECBYTE);
	fread(buf, 1, SECBYTE, file);
	fclose(file);

	secwrite(buf, drive, 1, sec);
	return 0;
}
```

セクタ番号0が(1fc0:0000)に読み込まれ実行されます。

```hello3.asm
comment *
        hello3.asm for MASM32

path %path%;C:\masm32\bin
ml /c /AT /Fl hello3.asm
link16 /t hello3;
*
        .model  tiny

        .code
        org     0h
start:
        push    cs
        pop     ds
        mov     si, offset data
        mov     ax, 0a000h
        mov     es, ax
        mov     di, 0h
L1:
        mov     al, ds:[si]
        cmp     al, 0h
        jz      L2
        mov     es:[di], al
        inc     si
        inc     di
        inc     di
        jmp     L1
L2:
        cli
        hlt

data    db      'hello, world', 0h

        end     start
```

![98ipl.png](https://qiita-image-store.s3.amazonaws.com/0/257554/26b1dd0e-8564-2308-4e7e-6171c3249913.png)
proxy.pacを記述する際に気をつけること

`proxy.pac` を記述する際に気をつけることについてまとめたいと思います。

# proxy.pacについて
[プロキシ自動設定ファイル - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_(PAC)_file)をご覧ください。

# デバッグ方法
通常のJavascriptとは異なり、`proxy.pac`でデバッグ情報を出力する際には`alert`を用います。

```javascript:例
alert("url: " + url + ", host: " + host);
```

## デバッグ情報の閲覧方法
### Google Chrome, Vivaldi
chrome://net-internals/#events にアクセスします。

### Firefox
[メニューボタン] - [ウェブ開発] - [ブラウザーコンソール]をクリックします。

# FindProxyForURL関数のurlに渡されるURL
`FindProxyForURL`関数の`url`に渡されるURLは、HTTPとHTTPSで以下のように異なります。

|プロトコル|アクセスしたURL|`url`に渡されるURL|
|:--:|:--:|:--:|
|HTTP|http://example.com:1234/path/to/page?query=1|http://example.com:1234/path/to/page?query=1|
|HTTPS|https://example.com:1234/path/to/page?query=1|https://example.com:1234/|

なお、Google ChromeやVivaldiでは`PacHttpsUrlStrippingEnabled`を`false`に設定することで、Firefoxでは`network.proxy.autoconfig_url.include_path`を`true`にすることで、HTTPSでもHTTPと同じ挙動にできるようです (セキュリティの観点から見たとき、非推奨な設定となっているらしいので注意)。

# 複数の設定を指定する方法
以下のように複数の設定を指定したいとします。

1. 設定Aを試す
1. 設定Aで404が返されたら設定Bを試す
1. 設定Bで404が返されたら設定Cを試す
1. ......

このような場合、以下のように`FindProxyForURL`関数の戻り値を指定します。

```javascript:例
return "A;B;C;...";
```

# 参考文献
* [PAC URL データ除去を有効にする（https:// の場合）](https://getadmx.com/?Category=Chrome&Policy=Google.Policies.Chrome::PacHttpsUrlStrippingEnabled&Language=ja-jp)
* [proxy.pac のデバッグ](http://var.blog.jp/archives/74300162.html)
* [社内SEの徒然なる日記 proxy.pac（プロキシパック）対応　No.8　pac作成（デバッグ）](http://harikofu.blog.fc2.com/blog-entry-517.html)
matplotlibを使う

必要最低限の使い方を覚書き。

# pythonでグラフを描画
Pythonで計算結果をグラフなどで図表できると分かりやすい。そんな時にmatplotlibを使えばPythonでデータをグラフにプロットできるようになる。

１．ライブラリのインポート

```python:
import matplotlib.pyplot as plt
import numpy as np
```

２．データをプロットして描画

```python:
# 数値を生成し「x」にセット
x = np.arange(-5, 15, 0.1)

# （2次関数）y = X^2 - 10x + 10
y_2 = x**2 - 10*x + 10

# データをプロット
plt.plot(x, y_2, label="y = X^2 - 10x + 10")

# 縦横軸にラベル表示
plt.xlabel("X")
plt.ylabel("Y")

# 凡例を表示
plt.legend()

# プロットしたものを描画
plt.show()
```
# 描画結果
![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/170424/8f43d815-1dca-ddfd-0018-4e7a611ce774.png)
Shader Graph入門してみた

# はじめに
シェーダーはほとんど書いたことがありませんが、GUIでシェーダーを組み立てることができるらしいので、試してみました。

# 使用したバージョン
Unity 2018.2.0f2
Render Pipeline Core Library 3.0.0 - preview
Lightweight Render Pipeline 3.0.0 - preview
Shader Graph 3.0.0 - preview

# 導入方法
* Package Managerから以下の3つをインストールします。<br>
今までのバージョンの上がり方が同じになっているので、バージョン番号は合わせた方が良さそうです。
    * Render Pipeline Core Library
    * Lightweight Render Pipeline
    * Shader Graph

![package-manager.jpg](https://qiita-image-store.s3.amazonaws.com/0/111339/fe2e7597-0281-e431-3f03-b9bcf62b84eb.jpeg)

* Scriptable Render Pipeline Assetを作成します。

![create-scriptable-render-pipeline.jpg](https://qiita-image-store.s3.amazonaws.com/0/111339/a76d761a-106f-d008-3e86-89831e65af0e.jpeg)

* GraphicsSettingsに作成したScriptable Render Pipeline Assetを設定します。

![graphics-settings.jpg](https://qiita-image-store.s3.amazonaws.com/0/111339/8cda30d6-4de3-364b-2900-905717310c6e.jpeg)

これでShader Graphを作成する準備が完了となります。

# シェーダーの作成
今回は、Shaderとして作成したものとShader Graphで作成したものを比較してみたいと思います。

## Shader
以下のサイトを参考にトゥーンシェーダーを用意しました。

[【Unityシェーダ入門】トゥーンシェーダを自作してみる - おもちゃラボ](http://nn-hokuson.hatenablog.com/entry/2017/03/27/204255)

![shader.jpg](https://qiita-image-store.s3.amazonaws.com/0/111339/ccf116ac-e55c-bdac-257e-2d1513612145.jpeg)

Shaderを利用する場合は、Scriptable Render Pipelineを設定していてはダメなようでした。
（シェーダーを利用しているオブジェクトが紫色になってしまう。。。）
Scriptable Render Pipelineを設定していないとShader Graphを利用しているオブジェクトは紫色になります。

## Shader Graph
これをShader Graphを利用して再現してみます。

![shader-graph-asset.jpg](https://qiita-image-store.s3.amazonaws.com/0/111339/849f6267-7a75-57d7-b2c8-098e0cf71825.jpeg)

ライトの向きやライトの色などを取得する方法がデフォルトでは無かったため、プロパティとしています。
ツリーの上側は、サーフェイスシェーダー部分に似せた処理となっています。
ツリーの下側は、ライティングシェーダー部分に似せた処理となっています。

そして結果がこれです。

![shader-graph.jpg](https://qiita-image-store.s3.amazonaws.com/0/111339/6ac07efe-56cf-fe2c-ad2a-eae2ff5551dd.jpeg)

Scriptable Render Pipelineを設定しているため、Shaderを利用している方が紫色になっています。
若干、色味がShaderとShader Graphで異なってしまいました。

# まとめ
* ShaderGraphに必要なものはPackage Managerからインストールできる。
* Scriptable Render Pipelineの設定が必要になる。
* ShaderとShader Graphは共存できない可能性がある。
* Shader Graphにはデフォルトでは取れないパラメータ（ライトの向きなど）がある。

準備が少し大変でしたが、シェーダーの処理過程が見えるのでとてもわかりやすいと感じました。

この記事では、Shader Graphを導入してシェーダーを作成できるところまでできたということで、ここまでにしたいと思います。
「Scriptable Render Pipelineとは？」や、「ShaderとShader Graphは共存できないのか？」など、いくつか疑問が出てきましたので、いつか調べてみたいと思います。

# 参考URL
[PackageManagerからShaderGraphを追加する - デコシノニッキ](https://www.tattichan.work/entry/2018/03/30/PackageManager%E3%81%8B%E3%82%89ShaderGraph%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)

[GitHub - UnityTechnologies/ShaderGraph_ExampleLibrary: A library of Shaders created using Unity 2018.1's Shader Graph.](https://github.com/UnityTechnologies/ShaderGraph_ExampleLibrary)
メモ：Ruby on RailsアプリをHerokuへDeployするコマンド

1 Gemfile修正
```# Use sqlite3 as the database for Active Record
gem 'sqlite3', group: :development
gem 'pg', group: :production```

config/database.yml 加筆
```production:
  <<: *default
  adapter: postgresql
  encoding: unicode
  pool: 5```

``` bundle install```

2 アプリのフォルダに移動、herokuログイン
``` cd アプリ名前```
``` heroku login```

3 gitスタート
``` git init```

herokuダッシュボードでアプリ作成

4 リモートリポジトリを追加
``` git remote add heroku https://git.heroku.com/xxxxx-xxxxx-xxxxx.git```


5ファイルのコミット
``` git add *
 git commit -m "first deploy on heroku"
 git push heroku master```



6 db の migrate
``` heroku rake db:migrate```

7環境変数の設定
```heroku config:set ENV_NAME_1=value1 ENV_NAME_2=value2```

8 deployされたURLの確認
``` heroku open```

9 log確認
```heroku logs -t ```
直近250ログの確認
```heroku logs -n 250```

---
#余談：全てのレコードを空にする
pg＠Heroku
```heroku restart && heroku pg:reset DATABASE --confirm アプリ名前 && heroku run rake db:migrate```

sqlite＠ローカル
```rake db:reset```
- 全てのテーブルを drop
- "db/schema.rb" を元にテーブルを再作成

テーブル定義を変更した上で全てのレコードを空にする
```rake db:migrate:reset```
全てのテーブルを drop
"db/migrate/" 以下の全てのテーブルを再作成
SetLocal EnableDelayedExpansionの罠とその回避方法

以下は、カレントディレクトリにある`txt`ファイルについて、その内容を表示するというバッチファイルです（エラー判定で`ERRORLEVEL`を遅延展開させたいので、`setlocal enabledelayedexpansion`を呼出しています）。

```bat:簡単なバッチファイル
setlocal enabledelayedexpansion

for %%a in (*.txt) do (

    type "%%a" >nul 2>&1

    if !ERRORLEVEL! neq 0 (
        echo "[%%a] Error has occurred."
    ) else (
        echo "[%%a] is OK."
    )
)
endlocal
```

##SetLocal EnableDelayedExpansionの罠

上記のバッチファイルは作り的に考慮漏れです。なぜなら、カレントディレクトリに「`!xxx!.txt`」のような名前のファイルが存在するとエラーが発生するからです。

```bat:実行結果
>check.bat
"[.txt] Error has occurred."
```

エラー発生時に`%%a`に代入されていたのは`!xxx!.txt`という文字列ですが、`!xxx!`の部分が遅延展開と認識されてしまうようです。

つまり、`%%a`が`!xxx!.txt`に展開され、さらに`!xxx!`を展開しようとします。しかし`xxx`という変数は未定義であるため、`!xxx!`の展開結果はブランクとなります。そのなれの果てが`.txt`という文字列です。

パスワードやファイル名など、**含まれる文字をコントロールできない変数**を扱う場面では、事実上`setlocal enabledelayedexpansion`が使えなくなってしまいます。

では、どんな回避方法があるでしょうか。

##回避方法

以下のように、`SetLocal～EnableDelayedExpansion`のスコープを最小限にしたり

```bat:回避方法1：スコープを最小限にする
for %%a in (*.txt) do (

    type "%%a" >nul 2>&1

setlocal enabledelayedexpansion
    if !ERRORLEVEL! neq 0 (
endlocal
        echo "[%%a] Error has occurred."
    ) else (
endlocal
        echo "[%%a] is OK."
    )
)
```

`for`ブロック内の処理を関数に逃すというテもあります。こうすれば`SetLocal EnableDelayedExpansion`を使う必要がなくなります。

```bat:回避方法2：関数に逃がす
for %%a in (*.txt) do (
    call :func "%%a"
)
exit /b 0

:func
    type "%~1" >nul 2>&1
    if %ERRORLEVEL% neq 0 (
        echo "[%~1] Error has occurred."
    ) else (
        echo "[%~1] is OK."
    )
exit /b 0
```

`if ERRORLEVEL N`を使うのもよいです。

```bat:回避方法3：if_ERRORLEVEL_N
for %%a in (*.txt) do (

    type "%%a" >nul 2>&1

    if ERRORLEVEL 1 (
        echo "[%%a] Error has occurred."
    ) else if ERRORLEVEL 0 (
        echo "[%%a] is OK."
    ) else (
        echo "[%%a] Error has occurred."
    )
)
```

というわけですので、バッチファイル全体を`SetLocal EnableDelayedExpansion`で囲むなどという恐ろしいことをしてはなりません…。

##余談

なお、値を関数の引数に渡すときに以下のように値をダブルクォートしているのは「ファイル名に空白文字が含まれたファイル」対策です。ダブルクォテーションが無いと、**空白文字で区切られた複数の引数**として認識されてしまうためです。

```bat:スペースをエスケープ
call :func "%%a"
```
【小ネタ】Googleサービスのアカウント切り替え方法

こんにちわ

[グローバルセンス株式会社](https://gb-sense.com)のskanehiraです。
Googleアカウントを複数持っている方でアカウントの切り替えをしたりすると思います。

マウスとタイピングが早いかは人それぞれなので、
タイムを測ってみるのも面白いかもしれません！

# Googleメール
- デフォルトアカウント
https://mail.google.com/mail/u/0/#inbox

- 2つ目
https://mail.google.com/mail/u/1/#inbox

- 3つ目
https://mail.google.com/mail/u/2/#inbox

見て分かる通り、`/u/{index}`というふうになっているので、
番号をタイピングするだけで切り替えられます。

ちなみに、`ログイン中のアカウント数-1`以上の数を入力するとデフォルトアカウントに切り替わります。

# Googleカレンダー

https://calendar.google.com/calendar/b/0/r

https://calendar.google.com/calendar/b/1/r

https://calendar.google.com/calendar/b/2/r

# Googleドライブ

https://drive.google.com/drive/u/0/my-drive

https://drive.google.com/drive/u/1/my-drive

https://drive.google.com/drive/u/2/my-drive

# ハングアウト

https://hangouts.google.com/?authuser=0

https://hangouts.google.com/?authuser=1

https://hangouts.google.com/?authuser=2

# Google+

https://plus.google.com/u/0/`

https://plus.google.com/u/1/`

https://plus.google.com/u/2/`
Windows10のVSCodeでvenvを利用するときの注意点

#はじめに
Pythonでvenvを使い始めました。
Windows10,VSCode環境下で導入したのですが、
何点が引っかかったポイントがありました。

それぞれの対処法ついては、検索により比較的容易に情報が手に入りますが、
まとまったものはなかったため、メモとして残します。

#venvについて
Pythonの仮想動作環境を作成するための、Pythonの標準パッケージです。
これにより、作成したプロジェクトごとに、
pipの導入状態を、独立させ切り替えることができます。

詳細は、以下の記事が詳しいです。
[Qiita - venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)

#Windows10環境下では、PowerShellの実行ポリシーを変える
PythonはPowerShell上で動作します。

仮想環境をActivateするためには、
その機能を持つPowerShell Scriptを実行する必要がありますが、
**標準では実行できません**

これはPowerShellの実行ポリシー(Execution Policy)によるものです。

ポリシーを変え、PowerShell Scriptを実行する方法はいくつかあります。
[Qiita - PowerShellのExecutionPolicyのスコープとかについて詳しく](https://qiita.com/kikuchi/items/59f219eae2a172880ba6)

**「管理者権限でPowerShellを開き、実行ポリシーをRemoteSignedにする」**
がシンプルな方法となります。

具体的には、管理者権限でPowerShellを開いた後、以下を実行します。

```
Set-ExecutionPolicy RemoteSigned
```

##開いたPowerShellだけ、実行ポリシーを変えることは可能か
可能です。
コマンドラインのみでvenvを利用しているならば、不都合はないと思います。
PowerShellを開いた後、以下のコマンドを実行するだけです。

```
Set-ExecutionPolicy RemoteSigned -Scope Process
```

しかし、VSCodeを使用する場合、不都合があります。
・後述する拡張機能には対応していない
・ターミナル起動時に上記コマンドを強制的に実行することはできるが、
それをすると、「ビルドタスクの実行」でPythonを実行できない。

#プロジェクトのパス・フォルダー名には日本語を使わない
仮想環境作成時、
ActivateするためのPowerShellスクリプトに、
プロジェクトのフォルダが環境変数として記録されます。

**日本語をパス・フォルダ名に含めるとActivationスクリプトの中身が一部文字化けします。**
仮想化が正常に機能しないので、日本語の使用を避けます。

#VSCodeに入れる拡張機能
venvに必要な拡張機能は、Microsoft公式の「Python」拡張機能です。
>Linting, Debugging (multi-threaded, remote), Intellisense, code formatting, refactoring, unit tests, snippets, and more.

##VSCodeでのvenv環境使用方法
1.拡張機能インストール後、venv構築環境でVSCodeを開き、
コマンドパレット(CTRL + SHIFT + P)から、以下のコマンドを選択します。
「Python:インタープリターを選択」
ここから、venv環境のインタプリタを選択します。

2.同じくコマンドパレットから選択できる以下のメニューより、
仮想化されたPython環境を利用できます。
・「Python:REPLを開始」
・「Python:ターミナルでPythonファイルを実行」
・「Python:Pythonターミナルで選択範囲/行を実行」

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/230272/cbd5bb01-424a-a1de-ba8d-0572123d2b1a.png)
WHR-300HP2にDD-WRTを入れて失敗した話。+ 復旧方法(2020年版)

**2020/4/13 記事修正しました。**

私は、最近DD-WRTという無線LANルーター向け高機能OSを知り、入れてみたいなと思ってやってみた際に失敗した話です。
#DD-WRTとは
>DD-Wrtは、ゲートウェイ、無線LANアクセスポイントなどの組み込みシステム用ファームウェアとして開発されているLinuxディストリビューションの一種である。OpenWRTを元にして作られている。(出典：https://ja.wikipedia.org/wiki/DD-WRT)

#インストールの時点でアウトだった
私は、Googleで調べて出てきたサイトを参考に、WHR-300HP2に合ったDD-WRTをダウンロードしてインストールしようとしました。
しかし、あるサイトに**最新のバージョンでは起動しなくなるかもしれない**と書かれていたのです。
ですが、そのページに示されていたダウンロードリンクは切れていて、流石に今のバージョンでは起動できるようになっているだろうと思いこんで、最新版のものをインストールしてしまいました。
2分ほどPWRランプが赤点滅。文鎮化しないように・・・と願いながら書き込みが終わるのを待っていました。
そしてようやく書き込みが終わってPWRランプが緑点灯になりました。
しかし・・・
一向に無線LANの電波が飛ばず、おかしいなと思ってハードリセットをしてNVRAMの消去をしてみました。
でも変わらず。そこでONUルーター側のリンク状態LEDを見てみました。
すると、なぜか6秒ごとに点いたり消えたりしています。
ここで私は「あぁ・・・。文鎮化したんだ・・・。」と思い、がっくりしてしまいました。
#文鎮化から復旧させる
復旧方法は無いかと、焦りながら探しまくったところ、以下の成功例を見つけました。
http://koyama4284.blogspot.com/2016/10/whr-300hp2-tftp.html
WHR-300HP2もTFTPに対応しているようで、AOSSボタンを押しながら電源を入れるとTFTPの要求に答えてくれるようです。
早速やってみました。
##純正ファームウェアのヘッダをいじる
非常に紛らわしいですが、このまま純正ファームウェアを書き込んでも何も起こりません。
ファームウェアのバイナリを少しだけいじります。
FavBinEdit等のバイナリエディタでファームウェアを開いて、バイナリデータが16進数で27 05 19 56で始まるように編集します。27 05 19 56がある場所より前にあるバイナリデータは消して構いません。

完成したら、**firmware_WHR-300HP2.ram**というファイル名で保存します。
code.binとか、firm.binという名前にしていてもできません。
このファイルを保存したフォルダを**TFTPのルートディレクトリ**にしてください。

##手順 (上記サイトより)
1. 自分のPCのIPアドレスを**192.168.11.168**にする
2. 3cdaemonというTFTPサーバーを入手して起動する **※必ず3cdaemonを使わないと失敗します。**
3. AOSSボタンを押しながら電源を入れる
4. 5秒ほど経ったらAOSSボタンから指を離す（この時に上手く行けば転送が始まります）
5. 2～7分で純正ファームウェアに戻り、完了 
6. 
復旧できたらNVRAMの消去(ハードリセット)を行ってください。

#上手く復旧できない場合は・・・
ブートローダーが壊れているために、完全に何もできなくなっているかもしれません。
最低でも10回試せば行けます。

# 純正ファームウェア書き込み後の注意
復旧できた...と思ったら大間違い。
復旧したら**ファームウェアアップデートで最新版に**してください。この操作を行うことで、**確実にフラッシュメモリに純正ファームウェアを書き込む**ことができます。
筆者のルーターでは再起動したらDD-WRTがまた起動してしまいました。中にはルーターの動作モードを切り替えるスイッチをいじった瞬間にDD-WRTに切り替わることもあります。

この操作を忘れないで行ってください。

#まとめ
よく調べたら、DD-WRTをインストールするには、まずOEMファームウェアのバージョンを**1.40**以下にしなければならない。
危険なWordPressプラグインの作り方で紹介されていたプラグインのセキュリティチェッカー実行方法

##危険なWordPressプラグインの作り方
https://qiita.com/hissy/items/6b1f51a35b2267041ce8#%E6%9C%80%E5%BE%8C%E3%81%AB%E5%AE%A3%E4%BC%9Dwordpress-%E3%81%AE%E8%A7%A3%E8%AA%AC%E6%9B%B8%E3%82%92%E5%9F%B7%E7%AD%86%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F

##インストール
cd xxxx（どこかのフォルダ）
git clone https://github.com/hissy/php-code-scanner.git
cd php-code-scanner
composer install

##実行
php bin\console wp-code-scanner /path/to/your-plugin