OmniAICreator/Qiita-1.07M huggingface dataset:
Apache & CentOS 7 超シンプル早見表


root ユーザー or sudo コマンドで実行の必要があります。

## 起動

```
systemctl start httpd
```

## 停止

```
systemctl stop httpd
```

## 再起動

```
systemctl restart httpd
```

## システム起動時の自動起動の設定

```
systemctl enable httpd
```

## システム起動時の自動起動を解除

```
systemctl disable httpd
```

## Configtest

```
service httpd configtest
apachectl configtest
apachectl -t
```

## Graceful 


```
service httpd graceful
systemctl reload httpd
apachectl -k graceful
```
スマホのWebでパスポートの旅券番号を抽出する

# スマホのWebでパスポートの旅券番号を抽出する

前提条件
- OS: macOS Catalina (10.15.3)

## Javascriptのみ

> WebCameraのAPIにアクセスするのにSSLが必要

### Homebrew インストール

```zsh
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

### nginx インストール

```zsh
$ brew install nginx
```

### letsencrypt インストール

```
brew install letsencrypt
```

### nginx に適用

```zsh
$ sudo certbot --nginx
```

### サンプルコードを使用
https://medium.com/@impaachu/passport-mrz-reading-with-tesseract-js-ocr-library-7732fa8b6c66

### 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26601/81d29d2f-5a44-6c2e-6489-c82548fbf803.png)

ご覧の通り精度はイマイチという感じ、時間もそれなりに掛かります。


## Google Cloud 

- Cloud Vision ドキュメント  
https://cloud.google.com/vision/docs?hl=ja
- 料金  
https://cloud.google.com/vision/pricing
- 支払いと請求に対するドキュメント  
https://cloud.google.com/billing/docs?hl=ja

### 準備
1. Google Cloud Platform にアクセス
2. プロジェクトを選択（あるいは作成）
2. ダッシュボード > ナビゲーションメニュー > お支払 で課金を有効にする
2. ダッシュボード > スタートガイド > 「API を探索して有効にする」 をクリック
3. 「＋APIとサービスを有効化」をクリック
4. 「Cloud Vision」で検索して「有効にする」
6. 「認証情報を追加」
    1. 必要な認証情報を調べる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26601/e3598778-03ad-4fec-3d01-8492edff3e83.png)
    2. サービスアカウントを作成
    3. Jsonを大切に保存

### プログラムを書く
> とりあえずphpで

```
$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
$ anyenv update
$ exec $SHELL -l
```

下準備
https://cloud.google.com/vision/docs/quickstart-client-libraries?hl=ja

```zsh
$ composer require google/cloud-vision
```

やってる最中・・・


## Amazon Web Service

https://aws.amazon.com/jp/rekognition/image-features/


ログインして Amazon Rekognition で Try demo

## Azure

https://azure.microsoft.com/ja-jp/services/cognitive-services/computer-vision/#features
HANA Information Viewの参照先を確認するためのSQL

## Attribute View, Analytic View の参照先オブジェクト

```
select 
	DEPENDENT_SCHEMA_NAME
	,DEPENDENT_OBJECT_NAME
	,DEPENDENT_OBJECT_TYPE
	,BASE_SCHEMA_NAME
	,BASE_OBJECT_NAME
	,BASE_OBJECT_TYPE
from SYS.OBJECT_DEPENDENCIES
where DEPENDENT_OBJECT_NAME not like '%/hier/%'
//and	DEPENDENT_OBJECT_TYPE = 'VIEW'
order by DEPENDENT_SCHEMA_NAME, DEPENDENT_OBJECT_NAME
```

```
SELECT
	ao.PACKAGE_ID
	,ao.OBJECT_NAME
	,ao.OBJECT_SUFFIX
	,ao.CDATA
	,od.BASE_OBJECT_NAME
FROM	object_dependencies	od
INNER JOIN
	_SYS_REPO.ACTIVE_OBJECT ao
ON
	SUBSTR_BEFORE(od.DEPENDENT_OBJECT_NAME, '/') = ao.package_id
AND	SUBSTR_AFTER(od.DEPENDENT_OBJECT_NAME, '/')	= ao.object_name
AND	ao.object_suffix in (
	'analyticview'
	, 'attributeview'
	, 'calculationview'
	)
WHERE
	ao.package_id like 'パッケージ名%'
and od.DEPENDENT_OBJECT_NAME = 'パッケージ/InformationView名'
and od.DEPENDENT_OBJECT_NAME not like '%/hier/%'
AND	od.DEPENDENT_SCHEMA_NAME = '_SYS_BIC'
AND	od.DEPENDENT_OBJECT_TYPE = 'VIEW'
order by ao.PACKAGE_ID, ao.OBJECT_NAME
```

## Calculation Viewを含むXML定義情報

```
SELECT
	ao.PACKAGE_ID
	,ao.OBJECT_NAME
	,ao.OBJECT_SUFFIX
	,ao.CDATA
FROM	_SYS_REPO.ACTIVE_OBJECT ao
WHERE
	ao.object_suffix in (
		'analyticview'
		, 'attributeview'
		, 'calculationview'
	)
AND	ao.package_id like 'パッケージ%'
order by ao.PACKAGE_ID, ao.OBJECT_NAME
```

参考URL：
https://blogs.sap.com/2016/10/24/sap-hana-base-columns-information-views-depend/
Chrome のダウンロードバーを隠すシンプルな拡張を作った

Google Chrome でファイルのダウンロードをしたときに、UI 下部に灰色のバーが出現します。このバー、大きいし自動で消えてくれないので、すごく邪魔に感じていました。

そこでこの問題を _修正_ するために Chrome 拡張を作りました。
(_修正_ という強めの言葉を使ったのは、現状のダウンロード UI は不具合と言っていい、と思えるほど私が不満を持っているからです。)

この拡張がすることは 4 つです。私が考える「Chrome が本来提供すべき UI」を実現できるようにカスタマイズします。そういう意図ですので機能は控えめです。

1. 画面下部のダウンロードバーを隠す
2. 拡張のアイコンをクリックするとダウンロード画面 (`chrome://downloads`) を開く
3. 現在のダウンロード中のアイテムの数をバッヂ表示
4. ダウンロードの開始と完了を通知 (デスクトップ通知) する

[Chrome ウェブストア](https://chrome.google.com/webstore/detail/chrome-download-fix/idbhobikghdkepjgcdiphdbofibbbbfh) からインストールできます。
ソースコードは [GitHub](https://github.com/KoharaKazuya/chrome-download-fix) にあります。
ngコマンドの中身を覗いてみる

<font color="DarkGray">Disclaimer: この記事を執筆現在私はGoogleで働いています。記事内でGoogleのプロダクトについて言及するため明確に所属を記載していますが、このことは私が記事内に登場するプロダクトについて特別詳しい知識を持っていることを**意味しません。**１ユーザーが書いた記事としてお読みいただければ幸いです。</font>

---
唐突に自作コマンドを作りたくなって、参考にngコマンドを開いてみたところ中身が気になったので読んでみました:dog2: 読んでいるファイルの全量は[こちら](https://github.com/angular/angular-cli/blob/master/packages/angular/cli/bin/ng)です。

## 第一部

```bash:ng
#!/usr/bin/env node
'use strict';
```
Shebangでインタプリタにnodeを指定して、strictモードを使う宣言をしています。

## 第二部
```js:ng

// Provide a title to the process in `ps`.
// Due to an obscure Mac bug, do not start this title with any symbol.
try {
  process.title = 'ng ' + Array.from(process.argv).slice(2).join(' ');
} catch (_) {
  // If an error happened above, use the most basic title.
  process.title = 'ng';
}
```
`ps`で使われるプロセスのタイトルを決めているようです。`process.argv`の２個目以降の要素(=コマンドライン引数)を取り出して結合したものを`ng `と繋いで`process.title`とします。[ちなみに０個目にはnodeのフルパス、１個目にはコマンドのスクリプトファイルのフルパスが格納されています](https://nodejs.org/docs/latest/api/process.html#process_process_argv)。エラーが発生した際には、一番普通のネーミングということで`ng`になります。

## 第三部

```js:ng
// This node version check ensures that extremely old versions of node are not used.
// These may not support ES2015 features such as const/let/async/await/etc.
// These would then crash with a hard to diagnose error message.
// tslint:disable-next-line: no-var-keyword
var version = process.versions.node.split('.').map(part => Number(part));
if (version[0] < 10 || version[0] === 11 || (version[0] === 10 && version[1] < 13)) {
  process.stderr.write(
    'Node.js version ' + process.verson + ' detected.\n' +
    'The Angular CLI requires a minimum Node.js version of either v10.13 or v12.0.\n\n' +
    'Please update your Node.js version or visit https://nodejs.org/ for additional instructions.\n',
  );

  process.exit(3);
}
```
[`process.versions.node`にはnodeのバージョンが`11.13.0`のようなフォーマットで入ってくるので](https://nodejs.org/docs/latest/api/process.html#process_process_versions)、`.`で区切って配列に詰め直します。そして、

- メジャーバージョンが9以下 or
- メジャーバージョンが11 or
- メジャーバージョンが10でマイナーバージョンが12以下

の場合には「AngularCLIはv10.13またはv12以上のNodeを必要とします。(意訳)」のメッセージを表示して終了します。

## 第四部

```js:ng

require('../lib/init');
```

手元で`which ng`すると`/usr/local/bin/ng`で、この相対パス通りに遡ってもinitというファイルがないので一瞬???となりましたが、[「Node.js スクリプトをコマンドのように使えるようにする方法」](https://neos21.hatenablog.com/entry/2019/01/01/080000)という記事をみて謎がとけました。
`ls -l`すると

```bash
$ ls -l /usr/local/bin/ng
lrwxr-xr-x ...(割愛)... /usr/local/bin/ng -> ../lib/node_modules/@angular/cli/bin/ng
```
となっていて実際は`../lib/node_modules/@angular/cli/bin/ng`にいることがわかります。
そこで`ls /usr/local/lib/node_modules/@angular/cli`してみると、確かに`lib`フォルダーがいてその中に`init.js`がいます。ということで、最後にこれを読み込んでいました。

---
おしまいです。最初の最初しか読んでいないのでそんなにAngular独特の内容はないですね。
気が向いたら最後に読み込んでいた[init.ts](https://github.com/angular/angular-cli/blob/master/packages/angular/cli/lib/init.ts)の中身ものぞいてみようと思います:sunny:
独自のコンテナを作り、ECRに登録する

SageMakerであらかじめインストールされていないライブラリを使いたい場合、
prophetなど。
ライブラリインストール済みのコンテナを作りたいときがあります。
（既存コンテナで起動時にインストールしてもよい？？）

どのようにカスタムコンテナの環境を用意し、ECRに登録すればよいのでしょうか？

1.EC2を作成する
AWSのEC2でインスタンスを作成する手順
https://qiita.com/Quikky/items/2897573a42fd71cfc47f

サブネット
IAMロール
セキュリティグループ
の設定は忘れずに！


2.コンテナイメージを作成する

https://tech.librastudio.co.jp/entry/index.php/2018/07/14/post-1924/
dockerコマンド実行時の「Got permission denied while trying to connect to the Docker daemon socket」


AmazonECRとEC2を使って手元でビルドしたDockerイメージをAWS上でサクッと動かす
https://qiita.com/shnagai/items/196c6affbddedebced5d
###再ログインをしてなかったからエラーになった？？





#EC2でdockerイメージを作成して、ECRに登録してみる


$ aws ecr get-login --region us-east-2 --no-include-email
出力された docker login -u AWS -p <長文> https://<AccountID>.dkr.ecr.us-east-2.amazonaws.com
をコマンド入力

Login Succeeded

＜参考＞
https://qiita.com/shnagai/items/196c6affbddedebced5d
https://qiita.com/harukisan/items/6f536e662b42ea2694a9


？？？
Dockerによる環境構築って、docker環境というコンテナの中に入っていって、
pip install とか自由にして環境構築したら
イメージ化コマンドでスナップショット作ってpushして終わり！
と思ってたけど違うのか？？？
dockerfileってなんだ？？？
わざわざ書くの？？？動作確認は？？

https://blog.codecamp.jp/programming-docker-image-container
なるほど、dockerコンテナとdockerイメージがあるらしい。
ファイル編集は、Dockerコンテナレイヤーが読み書き可能らしい。

イメージレイヤーは、Dockerfileを元に作成され、プログラム固定で追加は不可。
インフラ、ミドルはイメージ・レイヤー。
アプリはコンテナレイヤーというイメージだろうか。

# dockerイメージとdockerコンテナをしっかり区別せよ


やはりわからない？？？従来の環境構築のやり方と全く異なるのか？？

＜従来の環境構築＞
・実機にログインして
・インストールコマンドを連打
・ディレクトリを掘りまくる
・スナップショットを保存
・展開



#prophetを動かすためのdockerfile
https://qiita.com/zurustar/items/4ee2927cee73c63f8dbf

ど真ん中の記事がありました。


#ECRからコンテナイメージをダウンロードしてコンテナビルドして、中に入って状況を確かめる

1.ECRにログインする
$ $(aws ecr get-login --region us-east-2 --no-include-email)

2.dockerコンテナをビルドする


3.Dockerコンテナの中に入る
$ docker exec -it コンテナ名 bash

最新のコンテナに入るために、ローカルのゴミは綺麗にしましょう。
＜確認コマンド＞
$ docker ps -a
$ docker images


#神記事を発見！！
http://sagantaf.hatenablog.com/entry/2018/09/04/190801

$ docker run -ti ubuntu:16.04 bash


#以下のコマンドで入れた！
$ docker run -it <accountID>.dkr.ecr.us-east-2.amazonaws.com/sagemaker-tf2.0-example:latest bash

-itのあとは、<REPOSITORY>:<TAG>
の構成

こちらの公式サンプルで作られたコンテナ
https://github.com/aws-samples/amazon-sagemaker-examples-jp/tree/master/workshop/lab_bring-your-own-containers/tensorflow2.0

結論、dockerコンテナもディレクトリ構成をもっている。

#dockerコンテナへのファイル転送
https://qiita.com/bunty/items/04c3bdd93ac3520c53eb

#dockerコンテナの環境構築
こちらも丁寧にかかれていてよい
https://suwaru.tokyo/dockerfile%E3%81%A8%E3%81%AF%EF%BC%9Fcommand-%E6%9B%B8%E3%81%8D%E6%96%B9%E3%82%92%E3%81%BE%E3%81%A8%E3%82%81%E3%81%BE%E3%81%97%E3%81%9F/
PDFのブラウザ表示・ダウンロード

まず単純にボタンを押してPDFファイルをダウンロードする場合の
ダウンロードファイル名は以下のようにContent-Dispositionヘッダを
attachmentにし、filenameを設定することで可能です。

```PdfSample.php
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: ' . filesize($file_path));
readfile($file_path);
```

今回の要件では、
ブラウザで表示した上で、もしユーザによってダウンロードされた場合の
ファイル名を設定することなので、以下のようにattachmentをinlineに変更します。

```PdfSample.php
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Length: ' . filesize($file_path));
readfile($file_path);
```

これでブラウザでの表示はできましたが、
いくつかのブラウザでダウンロード時のファイル名が正しく設定されませんでした。

そこでいくつかリクエスト時の処理を変更していきました。

##1.POSTメソッドではなくGETメソッドを使用する。
もともとPOSTメソッドでファイルNoを渡してPHP側でそのファイルNoに紐づく
ファイルを表示させるという処理を行っていたのですが、
Chromeでダウンロード時のファイル名が上手く設定されませんでした。
そこでGETメソッドに変えることでChromeでの動作が確認できました。


##2.URLの最終の「/」以下をダウンロード時のファイル名にする
①でChromeは動作確認がとれましたが、
今度はIE、Edgeでダウンロードする時に「無題.pdf」のような名前になってしまいました。
IEやEdgeではどうやらContent-dispositoionをinlineにした場合に、
filenameでの設定が上手くいかない場合があるようです。
調べていくと、URLの最終の「/」以下の部分がダウンロード時に有効とのことでした。
Laravelを使用している場合は、以下のようにルーティングを行います。

```web.php
Route::get('/download/{download_name}', 'HoegeController@OpenPdf');
```

これでIEでの動作が確認できましたが、Edgeではやはり「無題.pdf」のようになりました。
この時GETパラメータとしてファイルNoを渡してPHP側で処理していましたが、
どうやらGETパラメータを渡すとEdgeでは正しくダウンロード名が設定できないようです。


##3.GETパラメータを使用しない
実装時点では一旦②まで対応してEdgeは対象外としていたのですが、
よくよく考えたらGETパラメータの代わりに、
ルーティングのURL途中にファイルNoを入れることで
PHP側での処理が可能だったな思います。時間があるとき直したい。。。

```web.php
Route::get('/download/{file_no}/{download_name}', 'HoegeController@OpenPdf');
```

以上になります。
ssh key

# generate keys
```
mkdir ~/.ssh
cd ~/.ssh

ssh-keygen -t ed25519
---
enter
enter
---
mv id_ed25519.pub authorized_keys
chmod 600 authorized_keys
cd ..
chmod 700 .ssh
cd .ssh
sudo systemctl restart sshd
```
# login test
```
ssh ユーザ名@マシンのIP -i 秘密キー
```
もし、失敗しましたら、
適宜に、configかfirewallをイジる。

 sudo emacs /etc/ssh/sshd_config
 firewall-cmd --list-all
 sudo firewall-cmd --permanent --add-service=ssh

sshdのsecurityも忘れないで。
https://qiita.com/testmemo/items/b81a27636b4af8815bd8
上記のstep 3


# winscpを使いたい場合 

##(windows側の操作）
1. winscpのツールのputtygenを実行＞loadで秘密キーをload
2. passwordを入力
3. 新しい公開キーとputtyの秘密キー（**.ppk）を保存。

##(centos側)
1. cat 上記の公開キー>> authorized_keys
2. sudo systemctl restart sshd

##(windows側の操作）
winscpのlogin ”新しいサイト”で指定項目を正しく入力したら、OK
注意、ログインをクリックする前に、設定で、SSH認証を選択、
ちゃんとputtyの秘密キー（**.ppk）をロードしなければならない。

# putty key 生成後のteraterm or mobaXterm などのログイン
キーはputtyの秘密キー（**.ppk）を使わなればならない。
他のセッティングは、書いている通りでOK。
【Java】Dependency Injection 覚書

Dependency Injectionの利点
・newしなくてもよくなる

@AllArgsConstructor
全メンバの値をセットする引数付きコンストラクタを自動生成する

@NoArgsConstructor
引数なしのコンストラクタを自動生成する

@RequiredArgsConstructor
finalのメンバの値をセットする引数付きコンストラクタを自動生成

@Compornent
インスタンスを Spring 管理下におくアノテーション。
レイヤに応じて@Controllerや@Serviceや@Repositoryなどを使う。
Python 配列でやってみたこと

```python
# 初期化
lst = []

for i in range(5):
    # 追加
    lst.append(i)
print(lst)  # [0, 1, 2, 3, 4]

# フィルターをかける
filtered = list(filter(lambda x:x == 1, lst))
print(filtered)  # [1]

# カウントする
print(len(filtered))  # 1
```
Laravel+Heroku+ClearDBを使った無料公開手順

GitにPushしてからHerokuで実際に動かすまでの手順をここに残す。
1.Gitにpush。
2.GitとHerokuを繋ぐ。
3.Herokuからデプロイを行う。
4.ファイル（Laravel）にProcfileを作る。
web: vendor/bin/heroku-php-apache2 public/
5.HerokuのSettingからConfig VariableにAPP_KEYを.envからコピペしてはる。
6.OverviewからConfigure Add-onsで下のQuickly add add-ons from ElementsにClearDB MySQLを使う。そうするとSettingのvalue（右）にUSERNAME、PASSWORD、HOST、DATABASEの値を確認する。
7.SettingのConfing Variablesに入力。
（MySQL://USERNAME:PASSWORD@HOST/DATABASE?reconnect=true）の順番
8.Heroku右上のmoreからRun Consoleで php artisan migrate
Linux Policy Base Routing


# Linux Policy Base Routing

## そもそも何が起きたか。

AWSでEC2を構築している時、複数NIC持つEC2に対してパケットが以下のような状況で到達しないことがあったので備忘録とする。
構成としては、EC2 インスタンスに複数のNICがついており、それぞれが別々のサブネットに所属。

<img width="631" alt="Screen Shot 2020-03-12 at 18.20.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245585/4301b505-a95a-737b-a067-104da6cd627e.png">

図引用) http://blog.serverworks.co.jp/tech/2018/02/16/rhel-pbr-setting/


ルーティングテーブル(main)は以下のような状況。デフォルトGWはサブネット(10.0.1.0/24)のルータとなる。

```
[root@ip-10-0-1-5 etc]# ip route show table main
10.0.1.0/24 dev eth0  proto kernel  scope link  src 10.0.1.5 
10.0.2.0/24 dev eth1  proto kernel  scope link  src 10.0.2.5 
default via 10.0.1.1 dev eth0 
 ```

この状況で、10.0.1.0/24に所属するNWから、10.0.2.xのNIC(eth1)に対してPINGを飛ばしてみたが戻りのパケットがない状態。
なぜかと調べた結果、PINGは当該EC2に対して届いてはいるが、戻りのパケットを返す時に、当該EC2のデフォルトGWからパケットを送出しており、結果的に送信元に対して届かないというものだった。

同一の通信に関して、受信するNICと戻りの通信をするNICが異なる通信を非対称ルーティングと呼ぶ。
Linuxではどこかのバージョンから以下のカーネルパラメータにより、戻りの通信をするNICが受信したNICと異なる場合パケットを落とす設定になっている。この設定がパケットの受信先で有効になっており、戻りの通信だけフィルタリングされるのである。

```ruby:戻り経路フィルター
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
```

上記を無効化する手もあるが、IP スプーフィングを防ぐためのOS全体のセキュリティ設定となる。
これを回避するためにPolicy　Base Routingという機能もあるため実装する。

## Policy Base Routing

標準のルーティングテーブルは、宛先アドレスをみて特定のルータやデフォルトゲートウェイにパケットをルーティングする。
一方で、Policy Base Routing(以下PBR)は、送信元IPアドレスやTCP/UDPポートも見てルーティングを決めてくれる機能である。
また、PBRを通常のルーティングよりもルールとして優先させる。

そのため、今回のケースで言えば送信元IPアドレスが10.0.2.0/24を基準のパケットは、10.0.2.1に飛ばすようにPBRを設定すれば良いという結論になる。(ここで言う送信元IPアドレスだが、PINGの戻りのパケットの部分をさす。tcpdumpすればわかるが、戻りのパケットは、10.0.2.x ==> 10.0.1.xとなっている。)


- こちらが現状のルールなので「32766:  from all lookup main」よりもpriorityを小さな値にする。priorityが小さいほど優先度が高いルール

```
[root@ip-10-0-1-5 etc]# ip rule show
0:	from all lookup local 
32766:	from all lookup main 
32767:	from all lookup default 
```

- PBR用のルートテーブル・ルール作成

```ruby:一時的
ip route flush table 2000
ip route add table 2000 to 10.0.2.0/24 dev eth1
ip route add table 2000 to default via 10.0.2.1 dev eth1
ip rule add from 10.0.2.0/24 table 2000 priority 200
```
```:永続的
cat << EOF > /etc/sysconfig/network-scripts/pbr02-eth1
from 10.0.2.0/24 table 2000 priority 200
EOF

cat << EOF > /etc/sysconfig/network-scripts/route-eth1
10.0.2.0/24 dev eth1 table pbr02
default via 10.0.2.1 dev eth1 table 2000
EOF
```

- 設定確認系

```
[root@ip-10-0-1-5 network-scripts]# ip rule show
0:	from all lookup local 
200:	from 10.0.2.0/24 lookup pbr02 
32766:	from all lookup main 
32767:	from all lookup default 

[root@ip-10-0-1-5 network-scripts]# ip route show table 2000
10.0.2.0/24 dev eth1  scope link 
default via 10.0.2.1 dev eth1 
```


`参考`
https://milestone-of-se.nesuke.com/nw-basic/routing/policy-based-routing/
MacOSのあまり知られていない無線LANユーティリティコマンドairportの紹介

# これはなに?
社内の無線LANの増設を行うにあたって`airport`というコマンドラインが便利だったので紹介します。
`airport`コマンドはMacOSに付属してるコマンドラインツールです。
(Linuxだと`nmcli`とか`iwconfig`を使うのかな？)


# どんなときに便利？

- WiFiの電波状況を見たい(BSSID,RSSI(電波強度), チャネル)
- 接続してるAPのBSSIID,RSSI(電波強度),チャネルを知りたい
- 接続してるAP（チャネル）を変えたい

WiFiネットワーク構築をするときに便利！

# 使い方

airportコマンドは以下に格納されてます。
パスを通すか、作業ディレクトリをRecourcesまで移動しましょう!

```bash
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
```

## 使い方を調べる
```bash
$ /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -h             
Supported arguments:
 -c[<arg>] --channel=[<arg>]    Set arbitrary channel on the card
 -z        --disassociate       Disassociate from any network
 -I        --getinfo            Print current wireless status, e.g. signal info, BSSID, port type etc.
 -s[<arg>] --scan=[<arg>]       Perform a wireless broadcast scan.
				   Will perform a directed scan if the optional <arg> is provided
 -x        --xml                Print info as XML
 -P        --psk                Create PSK from specified pass phrase and SSID.
				   The following additional arguments must be specified with this command:
                                  --password=<arg>  Specify a WPA password
                                  --ssid=<arg>      Specify SSID when creating a PSK
 -h        --help               Show this help
```
以下のことができます。
- 接続中の情報を見る `-I`
- 切断する `-z`
- WiFiをスキャンする `-s`
- 接続チャネルを変える `-c`
- XML形式で出力する `-x`
- PSKを生成する `-P`

（ググると-Aでネットワークに接続できるという情報もありますが、当方の環境ではそういった機能は見つけられませんでした。Version違い？）

# WiFiの電波状況を見てみたい(電波強度RSSI, チャネル, BSSID)

WiFiの電波状況を見るには`-s`オプションを使用します.
`-s`の後ろにSSIDを入力すると、同一SSIDのものだけ絞り込んで表示できます。 

無線APの電波状況やチャネルの干渉をチェックするのに便利です。


```bash
airport -s
```

<img width="856" alt="a.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/ba9f928d-c71d-8134-0822-edb58b1faca9.png">

<img width="866" alt="c.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/7637ac06-7b99-bd31-55a5-6c29a91ec54c.png">

### RSSIとは
無線機器の電波強度を表す値です。値が小さいと電波が強い。
 "Received Signal Strength Indicator"の略。

# 接続してるAPのBSSIID,RSSI(電波強度),チャネルを知りたい

`-I` オプションで現在接続してるWiFIアクセスポイントの情報を見ることができます。

ローミングの設定をしてる時は、PCがどのチャネルに繋がっているかが重要なのでこのコマンドが便利です。

<img width="809" alt="b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268801/80b74485-9d65-3537-e636-9bf5ae172ede.png">

# 接続してるAP（チャネル）を変えたい

`-c`オプションを使います。
あんまり使い所がわからないけど、どうしても接続AP変えたいときにはこのコマンドが使えます。

```bash
airport -c 36 
```

# まとめ

MacOSにはairportという無線LANユーティリティコマンドラインツールがあって
無線ネットワーク構築する際に便利でした。
PhpStormでよく使うショートカットまとめ(Windows版)


今回はPhpStormのよく使う機能をまとめています。
せっかくの高機能エディター:point_up:
使うとグンと生産性が上がっています。

#【コード系】
・入力中ステートメント補完
**CTRL + SHIFT + ENTER**
例えば、public funcion hogeまで書いて上記操作すると、
public function hoge(){}までフォーマットされて補完されます。
pubf + ENTERも使うかも。:thinking:

・コードフォーマット
**CTRL + ALT + L**

・リファクタリング
**SHIFT + F6**
クラスやメソッド、変数の名前に修正が発生し、変更箇所が多岐に亘って大変だった……なんてことがたまにあります。
そんなときはリファクタリング機能を使いましょう。
これを使うことで名前を使用しているすべての箇所を自動で一括変更してくれます、便利ですね！
変更し忘れた箇所があったためにエラーになることが何度かありましたが、この機能を使うようになってからはなくなったように思います。IDE の方が賢い 🙌
使用方法は以下です。
Header コンポーネントの名前を変えています。ファイル名と一致するコンポーネントなのでリネームする場合ファイル名まで追従してくれます。

#【移動系】
・定義元へジャンプ
**CTRL + B**

・参照元へ戻る
**CTRL + ALT ＋　←**

・行番号を指定して移動
**CTRL + G**

#【検索系】
・Find Action
Find Action では IDE で利用できる機能を名前から検索・実行することができます。
**CTRL ＋ SHIFT + A**

・クラス、ファイル名、シンボル(変数名、メソッド名、定数名etc)などで検索
**SHIFT + SHIFT**

・最近編集したファイルを開く
**CTRL + E**

**Emmet(旧ZenCoding) : Tab**
一時期はまってたけど今は使ってない

・テキスト検索
**CTRL + Shift + F**
プロジェクト内のテキストを曖昧検索

・使用箇所を表示する
**ALT + F7**
単純な文字列検索では同名のメソッドなどがあった場合に使用箇所が把握しにくいですが、
これを使うと全ての使用箇所を把握することができます。

#【Git系】
・git statusやdiffを見る
**ALT + 9**
gitの状況確認のため、git bashでコマンド入力することが多かったですが、
エディターで見た方がdiffはとくに見やすいので、こちらを知ってからはほとんどこっちで見ています。
commit前に確認がしやすい。

#【機能系】
・ポップアップを閉じる
**ESC**
phpstorm上で何かをポップアップで開いた場合に閉じることができます。
知っていると以外と便利。

こんな便利機能があるなどあればぜひ教えてください。

以上です。
System Specでブラウザのダイアログを操作する方法

どうもShota(@Mii4a2501)です。
System SpecでDestroyアクションを行う際、ダイアログを操作しようとしたところ、はまってしまったので備忘録。


<h2>alert_confirmとdismiss_confirm

pageインスタンスには、

**alert_confirm** => OKを押す用のメソッド
**dismiss_confirm** => キャンセルを押す用のメソッド

この二つの操作用メソッドが用意されています。
（accept_alertというOKボタンのみダイアログ用の操作メソッドもあるようです)

<h2>注意点

上記メソッドを使う際、若干の工夫が必要です。

```ruby:qiita.rb
expect{ 
  page.accept_confirm
  # expectブロック内に一つ以上のfind,expectが必要
  expect(page).to have_content "削除に成功しました"
}.to change(School, :count).by(-1)
```

このようにして、expectブロック内に一つ以上findやexpectがない限り、ダイアログが表示されacceptされる前に次に進んでしまい、結果がfailureとなってしまいます。
(ちなみに自分はまだ現場未経験の人間なのですがこのテクニックはおなじみだそうで....）

<h2>最後に

同じ状況に陥ってしまった方の助けになれば幸いです！
【PHPUnit】モックした関数の返り値を引数を元に求めるにはandReturnUsingを使う

# 背景

PHPUnit を使っていると、関数をモックにしたい場面があります。
一般には下記のように実装します。

```php
Mockery::mock('class name')->shouldReceive('method')->withArgs($param)->andReturn($returnValue);
```

こういった書き方では返り値が決め打ちになっています。
ほとんどの場面では、返り値は固定値で問題ないはずですが、今目の前で、動的に返り値が決まっていたほうが都合がいい場面が起こったので調べてみました。

# `andReturnUsing`を利用する

ありました。`andReturnUsing`という関数を使えばいいです。

書き方はコールバックを受け取り、コールバックの引数をモック化したい関数の引数と同じにします。
あとはそのコールバックの返り値を計算して`return`するだけで返り値を指定できます。

```php
Mockery::mock('class name')
    ->shouldReceive('method')
    ->withArgs(function ($params1, $params2) {
        // $paramsを使った処理・・・
        return true;
    })
    ->andReturnUsing(function ($params1, $params2) {
        // $paramsを使った処理・・・
        return $calculateResult;
    }
);
```

# 実例

ユースケースの中で、別のエンドポイントに通信して、得た結果で引き続き処理をするというものがありました。この場合は通信自体モックにするのがベターですが、どうしても通信先の処理も結合テストしたかったので、まとめてテストできるようにテストを書きました。

```php
$clientMock = Mockery::mock(Client::class);
$clientMock->shouldReceive('post')
    ->withArgs(function (string $uri, array $data) {
        // 省略
        return true;
    })->andReturnUsing(function (string $uri, array $data) {
        $response = $this->post('{テストしたいエンドポイント}', $data['form_params']);
        $mock = Mockery::mock('TestResponse');
        // GuzzleのResponse Interfaceをモック
        $mock->shouldReceive('getStatusCode')->andReturn(200);
        $mock->shouldReceive('getBody')->andReturn(json_encode($response->json()));
        return $mock;
    });
$this->app->instance(Client::class, $clientMock);
```

こうすると、`andReturnUsing`の中で、`$this->post`で実際の通信処理が走るので、別のエンドポイントの動作チェックも兼ねることができます。

また、引数で`$data['form_params']`を渡すことで、引数が正しく渡っていることがテストできます。

繰り返しますが、本当はこういった場合は個別にテストを書いたほうがいいですね。
AWS IoT のクライアントデバイス環境を簡単に作るスクリプト(Python v2 版)

ちょこっとテストするための、Python版のAWS IoT Device SDK v2のPubSubをすぐに試すスクリプトです。CLI上で数行でできます。
Node.js版は[こちら](https://qiita.com/tatsuhiroiida/items/8620ca1019ddf7a6f114)

Cloud9上での設定を想定しています。マネコンで作成するのが手間な場合に使います。
何をやっているか等は説明しません。。
あと、手動で何発かメッセージを送るだけであれば、IoT Coreのテスト機能を使うのがよいです。

### 準備
Cloud9の環境を作成し、以下をEnvironmentディレクトリ下に置きます。

```sh:setup.sh
mkdir $THING_NAME
cd $THING_NAME
POLICY_NAME=${THING_NAME}_Policy

aws iot create-thing --thing-name ${THING_NAME}

git clone https://github.com/aws/aws-iot-device-sdk-python-v2.git
pip install ./aws-iot-device-sdk-python-v2
cd aws-iot-device-sdk-python-v2/samples/

wget -O rootca.pem \
    https://www.amazontrust.com/repository/AmazonRootCA1.pem

aws iot create-keys-and-certificate --set-as-active \
    --certificate-pem-outfile    certificate.pem \
    --public-key-outfile         public_key.pem  \
    --private-key-outfile        private_key.pem \
    --query certificateArn

echo -n CERTIFICATE_ARN: 
read str 
CERTIFICATE_ARN=$str

aws iot create-policy                     \
        --policy-name ${POLICY_NAME}      \
        --policy-document file://../../../policy.json

aws iot attach-thing-principal             \
        --thing-name $THING_NAME           \
        --principal $CERTIFICATE_ARN

aws iot attach-principal-policy            \
        --policy-name $POLICY_NAME         \
        --principal $CERTIFICATE_ARN
```

ポリシーは適宜修正すべきですが、一旦なんでも有りで。

```json:policy.json
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action":["iot:*"],
    "Resource": ["*"]
  }]
}
```

## 実行

```sh

python3 -m pip install awsiotsdk

aws iot describe-endpoint --endpoint-type iot:Data-ATS 
export ENDPOINT=yourendpoint-ats.iot.ap-northeast-1.amazonaws.com
export THING_NAME=mything
./setup.sh
cd $THING_NAME/aws-iot-device-sdk-python-v2/samples/
python pubsub.py --endpoint $ENDPOINT --root-ca rootca.pem --cert certificate.pem --key private_key.pem
```

別のThingで試すときは、THING_NAMEを書き換えて実行します。
[小ネタ] Nuxt on AWS Lambda では serverMiddleware 使えばいいよねって話

かなりの小ネタです。

[aws-serverless-express](https://github.com/awslabs/aws-serverless-express) を使うと Nuxt が Lambda で動くというのは既出記事でたくさんあるんですけど、そのほとんどが公式の通りに以下の様な実装になってます。

```js
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
app.use(awsServerlessExpressMiddleware.eventContext())
```

`aws-serverless-express/middleware` のソースコードを読んでみたら、普通にNuxtの `serverMiddleware` で動きそうだったため、やってみたら動きましたとさ。

```js:middleware/aws-serverless.js
const middleware = require('aws-serverless-express/middleware')
module.exports = middleware.eventContext() // わずか 2 行
```

```js:nuxt.config.js
module.exports = {
  serverMiddleware: ['~/middleware/aws-serverless']
}
```

ちなみに、ローカルで動かしているときも「API Gateway からのリクエストじゃないよ」というログを吐くだけで悪さをしないので、「AWS 環境だったら読み込む」みたいな制御も不要です。

ちゃんちゃん。
【個人的備忘録】Windowsタスクスケジューラーの使い方-GUI編-

#記事の内容
　作業の自動化のために作成したWindows.batのスケジュールを登録する際に、いつもやり方を忘れてググっているので、備忘録として投稿しております。今回はGUIでのスケジューリング手順に関して、書いております。
（余力があればコマンドラインからの手順も書きたい...）

#手順

1.デスクトップ左下の[スタート]ボタンを右クリックし、[検索]をクリック
2."タスク"と入力し、[タスクスケジューラ]アプリを開く
3.画面右に表示されているサイドバーエリアの[タスクの作成]をクリックする
![step3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/bb7df972-134d-030b-bf57-042c1aa2ae27.png)
4.開かれた[タスクの作成]ウィンドウの[全般]タブで、タスクの①名前と②説明を入力する![step4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/64e6316b-58c8-e010-b6aa-33d133201baf.png)
5.[トリガ]タブを開いて、[新規]ボタンを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/f0b80baa-7f7c-f08a-5214-94c1b315c13d.png)
6.新規で開かれたウィンドウでタスクのスケジュール時間を設定する。
とりあえず、開始時間さえ入力すればいい。繰り返したい場合は、「毎日」や「毎週」を選んだり[詳細設定]セクションで繰り返し間隔を設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/aea44001-720a-790e-6443-b3462475b16b.png)
7.[操作]タブを開いて、[新規]ボタンを押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/590a6f10-7132-a47d-ead7-4a617cdbbdc8.png)
8.実行するタスクを選択する(ここでいつもやり方を忘れる)
①[参照]ボタンから実行したいファイルを選択する。
②上記①で選択したファイルがあるディレクトリを指定する。
 ※開始の入力欄には、ディレクトリの名前などにスペースなどが含まれている/いないに関わらず、ダブルクォートを使用しない
　※ファイルが置かれているディレクトリを指定する(ファイル自体を指定しまうことがよくある)

例.
①は["C:\Users\UserNamei\Desktop\execute.bat"]
②は[C:\Users\UserNamei\Desktop]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394418/264749b5-0916-b48f-3a08-94066c684cf0.png)

あとはOKを押していけば、スケジューリング完了
rbenv: no such command `install' となってinstallできない時の対処

# エラー内容
rbenvで違うバージョンのrubyをインストールしようとしたら以下のメッセージが出た

```shell:
$ rbenv install -l
rbenv: no such command `install`

$ rbenv install 2.5.1
rbenv: no such command `install'
```

# 解決

`ruby-build`が必要でそれをcloneしたら解決

```shell:
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
Cloning into '/root/.rbenv/plugins/ruby-build'...
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 10685 (delta 0), reused 3 (delta 0), pack-reused 10677
Receiving objects: 100% (10685/10685), 2.23 MiB | 705.00 KiB/s, done.
Resolving deltas: 100% (7027/7027), done.

$ rbenv install -l
1.8.5-p52
1.8.5-p113
1.8.5-p114
```
「自分用メモ」をトレンド記事に進化させる方法

「最新の投稿」ページはノイズが徘徊しています。**自分用メモ**というノイズが。

いや、メモを残すのは良いことです。でも、せっかく時間をかけて調べたのに、それを誰も読まないノイズとして世に出してしまうのは勿体無いことでしょう。**どうせなら、もう１手間かけて、「記事」の形で公開してはどうでしょうか？**さすれば、他人の役に立つ可能性が増しますし、上手くすればトレンドに載るかもしれませんよ？

この記事では、私が普段やっている「自分用メモ」を「記事」に進化させるプロセスを紹介し、もっと記事化をみなさんに提案します。

# 1. 公開しない

いきなり前提を覆しますが、そもそも自分用のメモに過ぎないのなら、世界中に公開する必要があるでしょうか？

記事がネット上に存在するだけで検索のノイズになります。内容に誤りがあれば初心者を惑わせてしまいます。また、「この人は随分雑な投稿が多いなぁ。きっと仕事も雑に違いない」と思われてしまう可能性も無きにしもあらずです。

単にメモをしたいなら、自分のPCに保存するか、[Gist](https://gist.github.com/)などを使いましょう。非公開なら気兼ねは要りません。

# 2. 利用シーンを想定する。公式でよくね？

さて、世間的にも需要がある内容であり、記事に仕立てればランキングに載って同僚の評価が上がることが期待できるとします。

まず、誰がどんなときに読むのか想像してみましょう：

- 初心者が全体像を掴むために読む
- 他言語から移ってきてギャップに苦戦する人が読む
- ベテランがド忘れした時に読む

ここで注意したいのがこれです：

> 「これって公式ドキュメントに載っているよね？公式でよくね？」

今どきのOSSはドキュメントやチュートリアルが充実しています。なぜ、あえて、あなたの記事を読むのでしょうか？ ここで利用シーンを上手く想像できないなら実は需要が無かったということです。Gistに書きましょう。

# 3. コミュニケーションを取る

**「記事」は人様に読んでいただくものです**・・・などと書くと大げさですが、「自分用メモ」と「記事」は文章の書き方が違います。

ありがちなのは、いきなり説明を始めること。

> ❌悪い例
>
> rbenv のインストール方法メモ

いきなり書かれても、読者は**この記事は何を言いたいのか？** **読み進める価値があるのか？** が分かりません。

> ⭕️良い例
>
> rbenv はRuby開発の標準的ツールですが、プラグインがいっぱいあって１個１個インストールするのは非効率です。そこで、よく使われると思われるプラグインとインストール方法をメモしておきます。

# 4. 突き詰める

「自分用メモ」を記事に進化させるに当たっては、方向性を突き詰めた方が良い記事になりやすいと思います。

**エモい記事**はコードを減らして、熱く語りましょう。

**チートシート的な記事**なら、全ての要素を網羅しましょう。例えば「Pandasのよく使う操作まとめ」ならば、「よく使う操作」は（自分が使わない物を含め）全て書きしましょう。さもなくば「暗記するほど使う機能は載っているが、調べたい機能は載っていない、中途半端なまとめ記事」になってしまいます。

# 5. 体裁を整える

- 語尾をですます調にする
- 解りやすいタイトルをつける
- 書き出し部分で概要を説明する
- 適当に節を区切る
- 誤字脱字を直す
- いつの時点の情報かを書く
- 処理系のバージョンを書く
- 情報元・公式ドキュメントへリンクを張る

などなど、体裁を整えましょう。特にタイトルや書き出しは大事（らしい）です。この辺りはすでに世間に解説がたくさんあるので、ググってください。

# むずび

あなたが困って調べたことは、きっと他の誰かも困っているはず。

みんなで、いい記事をいっぱい書きましょう！
boto3でs3にある複数オブジェクトを削除したかった


# boto3をインストール
```bash
$ pip3 install boto3
```

# s3にアクセスするための設定がファイル
```python:aws.py
import boto3

s3 = boto3.client(
    's3',
    aws_access_key_id = {access key},
    aws_secret_access_key = {secret_access_key},
    region_name = 'ap-northeast-1')
    
s3_bucket = 'sample-app'
```

# s3を操作するメソッドを作成
```python:services/s3_service.py
from aws import s3, s3_bucket

class S3Service:

    # オブジェクトの中身を取得
    def get_object():
        s3_dir = 'image/sample.json'
        sample_json = s3.get_object(Bucket=s3_bucket, Key=s3_dir)
        body = sample_json['Body'].read()

        print(body.decode('utf-8'))

    # 複数のオブジェクト取得
    def get_objects(id):
        s3_dir = 'image/{0}/'.format(id)
        image_objs = s3.list_objects_v2(Bucket=s3_bucket, Prefix=s3_dir)

        for image in image_objs['Contents']: 
            print(image['Key'])

    # 複数のオブジェクト削除
    def delete_objects(id):
        s3_dir = 'image/{0}/'.format(id)
        image_objs = s3.list_objects_v2(Bucket=s3_bucket, Prefix=s3_dir)

        for obj in image_objs['Contents']: 
            key = obj['Key']
            s3.delete_object(Bucket=s3_bucket, Key=key)
```

# serviceクラスを呼び出す
```python:controller/image_controller.py
from flask import Blueprint, make_response
from services.s3_service import S3Service

# set route
sample_controller = Blueprint('sample_controller_router', __name__)

@sample_controller.route('/delete/<id>', methods=['PUT'])
def delete_images(id):
   S3Service.delete_objects(id)
   return make_response(jsonify({'code': 200}))
```
LGTMとは

Qiitaを開いたら「LGTM」が「いいね」の代わりに表示されててビビった。

![スクリーンショット 2020-03-12 18.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183420/afac0708-db6e-6599-d278-cf66c0cd8d37.png)

LGTMとは**Looks Good To Me**、「いいと思う」に近い略語。

[3/12からの変更](https://blog.qiita.com/like-to-lgtm/)らしいです。
【bash】ファイルを1行ずつ連番ファイルに書き出すコマンド【ワンライナー(？)】

備忘目的のメモ程度で残します。

# 背景
・あるファイルを1行単位で、かつファイル名は連番で分割保存したい
・連番については、表示順が適切になるようにゼロパディングをかけたい
・分割対象のファイルは4000行程度であった
**・分割対象内の文字列には「\」が含まれており、これはそのまま残したい　←2020/03/13(Fri) 追記**

シェルスクリプトとしてファイルを残すのもなんだか面倒だったので、コマンドだけで完結するように書いてみました。
(結局シェルファイルに書き出す内容と何ら変わっていないような気もしますが…)

# 実行環境
```
$ bash --version
GNU bash, バージョン 4.4.20(1)-release (x86_64-pc-linux-gnu)

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04.4 LTS (Bionic Beaver)"
```

# 実行コマンド

```bash:改善前
count=1 ; load_target="hogehoge.txt" ; cat ${load_target} | while read line ; do echo ${line} > "${load_target}_`printf \"%04d\" ${count}`.txt" ; count=`expr ${count} + 1` ; done
```
上記では分割した文字列内に「\」が含まれていた場合、それはエスケープとして読み取られて消されてしまう
(json形式の値部分にHTMLタグ情報が入っているデータを扱っていて実際にそうなった…)

**消されたくない場合、`read`コマンドの`-r`オプションを使えば良い模様**

```bash:改善後
count=1 ; load_target="hogehoge.txt" ; cat ${load_target} | while read -r line ; do echo ${line} > "${load_target}_`printf \"%04d\" ${count}`.txt" ; count=`expr ${count} + 1` ; done
```

出力時の拡張子や0パディングの部分に関しては、もう少し工夫して変数展開や読み込み元ファイルの情報を抜き出しつつやった方が、読み込み元ファイル行数に合わせて潰しが効くし格好良さそうですが、とりあえず上記でも何とかなったので改良は後々できればいいかな程度です。

ワンライナーならもっともっとエレガントな書き方あるよ！！という方は後学のため是非ご意見頂けますと嬉しいです。。。
【Python3】paizaで標準入力からの値の受け取り方

# はじめに

pythonのお勉強がてらの自分メモです
動作環境は「paiza」でやってます。


## 入力値が1行に1つの場合

```python3:test.py
#文字列の場合
str = input()

#数値（int）の場合
num = int(input())
```

## 入力値が1行に2つ以上の場合
※ここでは便宜上入力値は2つ、区切り文字は半角スペースとする

```python3:test.py
#文字列の場合
strA, strB = input().split(' ')

#数値（int）の場合
num1, num2 = map(int, input().split(' '))
```


## 入力値が1行に複数ある場合　⇒　listで取得
※ここでは便宜上区切り文字は半角スペースとする

```python3:test.py
#文字列の場合
list = input().split(' ')

#数値（int）の場合1
list = list(map(int, input().split(' ')))

#数値（int）の場合2
list = [int(i) for i in input().split(' ')]
```
Shopifyで使う技術まとめ

#shopifyアプリを開発するための技術まとめ

- アプリのフロントはReactとnext.js(ReactのFW)で作る
- APIからデータを取得するにはGraphQLと[Apolloクライアント](https://www.apollographql.com/docs/react/)を使う
- 見た目をshopifyっぽく整えるのはPolarisというやつを使う
- アプリのサーバーサイドはRubyOnRails、DBはMySQLの予定
- shopify既存のフロントを変えるにはliquidというRubyのファイルをいじる

備忘録です。
event.preventDefault() を最低限理解する

# 背景
**event.preventDefault()** というものをよく見かけるけどコレ何？

# 一言で
**DOMイベントを止める**もの
Prevent : 防ぐ
Default : デフォルト
**デフォルトのイベントをさせないよ**

# 動作確認ファイル

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>preventDefault</title>
</head>
<body>
    <a id="google" href="https://google.com">Google</a>
    <script src="app.js"></script>
</body>
</html>
```

```app.js
const google = document.getElementById("google")

google.addEventListener("click", () => {
    event.preventDefault() /* これ */
    console.log("link先への遷移イベントを防いだよ")
})
```

# 今回のファイルで何を確認するのか
aタグをクリックすると**リンク先に飛ぶ**というイベントが起こる。これを止める。


![preventDefault.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520523/d8f0a6c0-8aae-b2aa-7296-40b5b7af4776.png)


こんな感じ




# 終わり
httpdのconfをより安全に


##close welcome page
```
cd /etc/httpd/conf.d/
sudo mv welcome.conf welcome.conf.org
```
##iconsフォルダ無効化
```
cd /etc/httpd/conf.d/
sudo mv autoindex.conf autoindex.conf.org
#check if error
sudo httpd -t
sudo systemctl restart httpd
#confrim http://サイトのURL/icons/README changed to be not found
```

##TLS1.0 と TLS1.1 を無効にし、TLS1.2 のみ利用する設定
```
#confirm  ciphers
openssl ciphers -v

sudo emacs /etc/httpd/conf.d/ssl.conf
---
#edit as below
#SSLProtocol all -SSLv2
#SLProtocol -all +TLSv1.3 +TLSv1.2
SSLProtocol -all +TLSv1.2

#SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
SSLCipherSuite HIGH:MEDIUM:!aNULL:eNULL:!MD5:!SEED:!IDEA:!3DES:!RC4:!ADH:!DH
#SSLCipherSuite TLSv1.3 TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305

#Perfect Forward Security
SSLSessionTickets off

SSLHonorCipherOrder on 

#turnoff compression
SSLCompression off
---

#restart sshd
sudo systemctl restart sshd
```
#Apache 環境変数を変更
```
emacs /etc/sysconfig/httpd
---
export OPEN_NO_DEFAULT_ZLIB=1
---
```

#ディレクトリ内容一覧表示off、バージョン表示offなど
```
sudo emacs /etc/httpd/conf/httpd.conf
---
# modified_as bellow
# index off
# Options Indexes FollowSymLinks
Options FollowSymLinks
# Apacheバージョン表示の無効化
ServerTokens ProductOnly
ServerSignature off
#HTTP TRACE of
TraceEnable off
#X-Frame-Optionsヘッダ
Header append X-FRAME-OPTIONS "SAMEORIGIN"

#set 404
ErrorDocument 404 /missing.html

---
#restart httpd
sudo systemctl restart httpd
```
jsonnet のメモ


## 基本文法

### リファレンス

```
// self = 現在の object 
self["buffers"]
self.buffers 

// $ = outer most object(= 通常は root?)
$["buffers"]
$.buffers 


```

フィールドが文字列の場合は ['bora'] を使う
identifier(識別子. 空白が無いなど)の場合は `.bora` と記載できる. 

### 外部変数(コマンドライン引数で設定したものとか)の参照

std.extVar("bora") でアクセスできる.

### 外部ファイルの参照

```
local lib = import 'path/to/file.jsonnet';
```
 
として, `lib.bora` などとしてアクセスできる.

ファイルパスの起点は, カレントディレクトリではなく, import のある jsonnet ファイルのパスが起点となる.

### 配列アクセス

`[10]` としてアクセス可能
python っぽい slice 対応
 
### comprehention(foreach 的な操作)

配列の各要素は, python のように記述できる

```
local arr = std::range(5, 8);
{
  item: [x + 1 for x in arr],
}
```
## tips

逆引き Jsonnet
https://qiita.com/ktateish/items/c07d76fb268575f5a8dc

基本的にはこちれあるもの以外の tips です.

### オブジェクトにフィールドがあるか確認したい.

T.B.W.

has("bora") みたいなのは直接には無いようです.

`std.isObject` や `std.length` を組み合わせて実現?
 
### 配列の数を求める

`std::length` を使う.
変数に対して使う.

```
local buffers = [0, 1, 2],
local len = std.length(buffers)
```

既存の JSON オブジェクトを扱うには, リファレンスを使う

```
"buffers": [0, 1, 2],
local len = std.length(self.buffers) // self = 現在の object
// local len = std.length($["buffers"]) // $ は root から

```

### 配列に対して処理を行う

`std.map` が使える.

### JSON の値を書き換える

入力データが素の JSON で, 特定のフィールドの値を書き換えたい.

T.B.W.

import してから処理すればいけるか?
(JSON で完結するなら, python や jq とかで処理するのも手)
jQuery

##jQuery（ジェイクエリー）
JavaScriptのライブラリです。短く記述することができます。
【例】JavaScriptでクリックイベント

```
var btn = document.getElementById("title");
btn.addEventListener("click", function() {
　　console.log("Hello");
});
```

【例】jQueryでクリックイベント

```
$(function() {
  $("#button").on("click", function() {
    console.log("Hello");
  });
});
```
##jQueryを導入
[jQueryへのリンク先](https://developers.google.com/speed/libraries/#jquery)
とりあえずバージョンは一番新しいのでいいと思います。
jQueryは他のJavaScriptファイルよりも先に読み込まないとエラーが出てしまいます。仮にJSがmain.jsだとしたらそのファイルより先に記述します。
【例】

```main.js
〜省略〜
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="./main.js"></script>
〜省略〜
 ```
##HTML要素を取得
HTML要素の取得します。

```
$("セレクタ")
```

```main.js
$(function() {
  console.log($(".menu_item"));
});
```
クラスがmenu_itemの要素を取得されます。
次はよく使用する4つのセレクタを紹介します。
##IDセレクタ
HTML要素のid属性で指定し、取得したいid属性の値に#を付けたセレクタのことです。
【例】

```
$("#idSelector") // idがidSelectorの要素を取得します
```
##クラスセレクタ
HTML要素のclass属性で指定し、取得したいclass属性の値に.を付けたセレクタのことです。
【例】

```
$(".classSelector") // classがclassSelectorの要素をすべて取得します
```
##要素セレクタ
h1やpのようなHTML要素を対象とし、取得したい要素名をそのままセレクタとして利用します。
【例】

```
$("h1") // h1要素をすべて取得
```
##属性セレクタ
HTMLのタグの属性値を指定したい場合、$("[ 属性 = '値' ]")で属性セレクタを取得できます。
【例】

```
$("input[ type='radio' ]");  // <input type="radio">のHTML要素を取得します
```
JavaScriptで書いていたDOM要素の取得を$("セレクタ名")で取得できるようになります。
##クリックイベントの取得
click()で使用できます。
【例】

```
tabs.click(Switch); 
```
##this
関数の中でthisを使用すると、イベントの発生元となった要素を取得することができます。
※thisは、使用する場面によって取得できるものが異なります。
【例】JSの場合

```
console.log(this);
```
jQueryで使う場合は、$(this)と指定します。
【例】

```
console.log$(this);
```
##removeClass()
タブのクラス要素を削除します。[0]と指定しなくても、最初の要素を指定してくれます。
##addClass()
タブにクラス要素を追加します。[0]と指定しなくても、最初の要素を指定してくれます。
##index()
配列に変換しなくても、集合したDOM要素から引数に指定したDOMと同じ要素番号を戻します。

```
index("セレクタ")  // セレクタと一致したDOMの要素番号を戻します
```
##eq()
引数に要素番号を取り、集合したDOM要素から選択できます。

```
eq()  // セレクタと一致したDOMの要素番号を戻します
```
##submit
フォームが送信される時に呼び出されるイベントです。
【例】

```XXXX.js
$(function() {
  $('form').on('submit', function(e) {
    console.log('送信ボタンが押されました');
    e.preventDefault();
  });
});
```
関数の引数のeはeventのeです。関数の第一引数には自動でイベントオブジェクトが渡されます。
##イベントオブジェクト
イベントに関する情報を持つオブジェクトです。イベントの発生元の要素や押されたキーの情報などが入っています。
##preventDefault()
ブラウザが最初から持っているアクションをキャンセルするメソッドです。
##find("セレクタ")
$(this)を使えばformタグに対して要素を取得できますが、inputタグの属性がcheckboxをという属性だけを取得したい場合、find()を使用します。
jQueryのfind()メソッドは、引数にセレクタを指定して、合致するセレクタを全て取得します。
##each()
引数に要素番号を指定することが可能です。
##prop()
要素のプロパティを取得するメソッドです。
##attr()
要素の値を取得することができます。
#var
変数を宣言し、任意で指定した値を初期化します。
【例】

```
var 変数名 = 値;
```
##val()
HTMLタグ内に記述されているvalue属性を取得したり変更することができるメソッドです。
ユーザーがフォームに入力した内容や選択した項目をjQuery側から把握できるようにします。
【例】

```HTMLの記述
<button id="btn-1" value="1">ボタン1</button>
```
```XXX.js
var btn $(#btn-1).val();
console.log(btn);
```
上記の記述でHTMLからvalue値1を取得できました。
No Rails found in SDKのエラーが発生

# `No Rails found in SDK`のエラーが発生

今まで使えてたのに急にですよ。
なになぜどうして。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533120/213f0525-c35f-efbf-e841-64f0e041e2b1.png)


## 解決策

RubyMine > Preference > Language & Frameworks > Ruby SDK and Gems
を見てみたら、右側のgem一覧が空っぽになってたんですよ。(画像は読み込み後なので出てるけど。。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533120/e75fbd8b-ad9d-6c10-82c8-c6f7ee8cb7fd.png)

で画像にある「Synchronize gems and RubyMine helper」ボタンを押す。
そして暫く待つ。
無事起動。

参考：https://forest-valley17.hatenablog.com/entry/2018/10/18/142222


原因はわからないけど直し方分かったからいいや的な。
東京都 新型コロナウイルス感染症対策サイトをVagrant環境で動かす

# はじめに

「東京都の新型コロナウイルス感染症対策サイト」についてローカルのVagrant環境で動作確認をする方法についてまとめました。

# 環境

以下の環境で確認しています。ホストOSはMacOSですが、ゲストOSが同じであれば大きくは変わらないと思います。

- ホストOS：MacOS Catalina
- ゲストOS：CentOS7
- 仮想環境：Vagrant2.2.7 + VirtualBox6.0.18

# 構築手順

前提としてVagrantとVirtualBoxのインストールは環境していることとします。

## 仮想環境（CentOS）

### CentOSのインストール

vagrantでCentOS7の環境を構築します。

```
mkdir tokyo-covid19
cd tokyo-covid19
vagrant init centos/7
```

ホストOSから接続できるように、ネットワークの設定をします。ここではVirtualBox用のプライベートネットワークを追加することにしています。

Vagrantfileの以下の部分をコメントアウトしてゲストOSのIPアドレスを指定します。

```
config.vm.network "private_network", ip: "192.168.2.100"
```

デフォルトではゲストOSのメモリが512MBなので2GBに増やします。

```
config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
     vb.memory = "2048"
end
```

ゲストOSを起動してSSHで接続します。

```
vagrant up
vagrant ssh
```

### 前提ソフトウェア（git、node.js、g++）のインストール

環境構築には、CentOS上に、ソースコードを取得するためのgit、フレームワークを実行するためのnode.js、パッケージのコンパイルのためのyarnとg++のインストールが必要です。

node.jsのインストール

```
sudo yum install https://rpm.nodesource.com/pub_12.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm
sudo yum -y install nodejs 
```

g++のインストール

```
sudo yum install gcc-c++
```

yarnのインストール

```
sudo npm install -g yarn
```

### ファイアウォールの停止

デフォルトではCentOSファイアウォールが起動しているため停止します。

```
sudo systemctl stop firewalld
```

### 新型コロナウイルス感染症対策サイトの構築

githubからソースコード一式を取得する

```
git clone https://github.com/tokyo-metropolitan-gov/covid19
cd covid19
```

※ ここでREADME通りだとyarn installとなるのですが、途中でnode.jsがOut of Memoryになってしまったので、ヒープサイズを拡張します

package.jsonのdevの箇所に、「NODE_OPTIONS=--max_old_space_size=2048」を追記し、ヒープサイズを2GBにします。

```
  "scripts": {
    "dev": "cross-env NODE_OPTIONS=--max_old_space_size=2048 NODE_ENV=development nuxt-ts",
    "build": "nuxt-ts build",
    "start": "cross-env NODE_ENV=production nuxt-ts start",
```

パッケージのインストールを行い、dev環境を起動します。
なお、ホストOSから接続するためには「--hostname 0.0.0.0」オプションを付ける必要があります。

```
yarn install
yarn dev --hostname 0.0.0.0
```

### ホストOSから接続確認

ビルドが完了したら、ホストOSから「http://192.168.2.100:3000」にアクセスします。
問題なければ、新型コロナウイルス感染症対策サイトが表示されます。
Spring Securityで403 forbiddenが発生する

Spring Securityを導入した環境でセッションタイムアウト後にアクセスしようとすると以下のエラーが発生する

![403.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377078/80a69589-cc1e-f21b-0a76-c74e4d067fd4.jpeg)

これはSpring SecurityのCSRF対策でCSRFトークンチェックをする際にCSRFトークンの保存先としてHttpセッションを使用しているために発生する。

これを防ぐためには、以下のコードのようにinvalueSessionUrl()にセッションタイムアウト時の遷移先を指定することで可能。

```
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().invalidSessionUrl("/timeout");
  }

}
```
Vue.js：ビルドしてサブディレクトリに置きたい

「公式リファレンス見たら書いてあるじゃん」って話ですが、

http://example.com/
例えば、こんな感じのURLがあるとして、
http://example.com/hoge/
ココの`hoge`ディレクトリ以下にビルドして置きたい。

デフォルトの設定だとドメイン直下「/」に書き出されちゃって、
フォルダをヒョイっと移動しただけではパスがズレてしまいます。
なのでどうするかというと

##vue.config.jsを作る
```
$ touch vue.config.js
$ open vue.config.js
```
```vue.config.js
module.exports = {
  publicPath: process.env.NODE_ENV === 'production'
    ? '/hoge/'
    : '/'
}
```
ちなみに自分の`vue-cli`は新しめです。
（バージョン3くらいからできるはず。）

ちなみに`vue-cli-ui`でも設定できますが、
条件分岐は書けないかも。

以上です。

■参考資料
https://cli.vuejs.org/config/#publicpath
Laravelで何か作ってみる〜Hello World〜

##概要
[前回](https://qiita.com/r24desgin/items/445ff3cdc5ad7aa8e9b5)、[前々回](https://qiita.com/r24desgin/items/445ff3cdc5ad7aa8e9b5)と設定したMac用のLaravel開発環境にて、とりあえず「Hello World」と表示するサイトを作る

参考：公式サイト
https://readouble.com/laravel/6.x/ja/routing.html


##前提
###環境
Laravel 7.0.8
Valet 2.8.1

###構成
Laravelルート [ parkコマンド実行ディレクトリ ]
　~/DIR/
サイトルート [ プロジェクトディレクトリ ]
　~/DIR/blog/ 


##設定
###ルーティング
サイトにアクセスしたURLによって行う動作を指定

今回デフォルトでは http://blog.test にアクセスすると、ビューから**welcome**を表示する記述あり（実行ファイルは **resources/views/welcome.blade.php** ）

```php:routes/web.php
Route::get('/', function () {
    return view('welcome');
});
```

http://blog.test/user にアクセスしてページを表示するには、次のルーティングを追加。コントローラー **UserController**の **index()** メソッドの処理実行を意味する。

```php:routes/web.php
//add
Route::get('/user', 'UserController@index');
```

`indexメソッドはコントローラーが処理するURIのルートに対応します。`
https://readouble.com/laravel/4.2/ja/controllers.html

###コントローラー
ルーティングを受けて処理する制御を定義。**artisan**コマンドにて、コントローラーにファイルを作成。サイトルートディレクトリにて実行。

```
$ php artisan make:controller UserController
Controller created successfully.
```

UserControllerファイルが作成されたことを確認

```
$ ls app/Http/Controllers/
Controller.php     UserController.php
```

ファイルを開く

```php:UserController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
  //
}
```

UserControllerクラスに **index()** メソッドを追加

```php:UserController.php
  //add index
  public function index()
  {
    return view('user');
  }
```

###ビュー

コントローラーで指定したuserビューファイルを作成。Laravelでは *.blade.phpを使用。新規ファイルを作成。

```php:resources/views/user.blade.php
<html>
<head>
<meta charset='utf-8'>
</head>
<body>
Hello World!
</body>
</html>
```

サイトが表示されればOK。

<img width="677" alt="hello.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599693/fd91b7b8-07f6-a839-323a-eaffb373a82a.png">
Pythonで毎日AtCoder #3

### はじめに
[前回](https://qiita.com/taxfree_python/items/0187e54f4f623cbbd54c)
三日目です。

### #3
[問題](https://atcoder.jp/contests/abc115/tasks/abc115_c)

**考えたこと**
1WA,4TLE   (WAはミス提出)
今回最大の敵は、TLEでした。自分が計算量のイメージがついていないというのもありますが、Pythonの内部的な実装を知りませんでした。
問題を見て、最大値や最小値を求める問題はとりあえずsortするという癖が出てsortしました。最初は、forで順番に引き算していけば最小値が出ると思って,

```python
l = [10,15,11,14,12]
l.sort(reverse=True) #l = [15,14,12,11,10]
ans = l[0]
for i in range(n-1):
    ans = min(l[i+1] - l[i],ans)
```
で動くと思いました。ですが、nからk本選んだ中の最小値を求める必要があります。
ですので、sortしたinputをk個ずつ抜いていって、そのなかでmax-minする必要があります。
どうやって、kずつ取るかを考えたときにPythonのlistはスライスがあるじゃんということでスライスを使いました。これが大失敗でした。どうやら**Pythonのスライスは大きなオブジェクトに対して行うと、ウルトラ時間がかかります**。
理由分かる方は、教えてください。オブジェクトへのアクセスに時間がかかってる?
ということで、スライスを使ってTLEしたやつは、

```python
n, k = map(int,input().split())
h = [int(input()) for i in range(n)]
h.sort(reverse=True)

seed = h[0]
for i in range(0,n-k+1):
    high = h[i:i+k][0] - h[i:i+k][k-1] #ここ
    seed = min(high,seed)

print(seed)
```
コメントの部分のスライスで時間を食っています。
意地でも、スライスしたいtax_freeは4回もTLEしました。今考えると、別にスライスしなくてもindexで指定すればいいじゃん

スライスが時間食ってるということが判明したので、indexで指定したのがこれ

```python
n, k = map(int,input().split())
h = [int(input()) for i in range(n)]
h.sort(reverse=True)

seed = h[0]
for i in range(0,n-k+1):
    high = h[i] - h[i+k-1]
    seed = min(high,seed)

print(seed)
```
スライスしてません。

### まとめ
Pythonの気持ちを理解していませんでした。今後はスライスを使用しないで直接indexで指定します。
では、また
cURLでPOSTするときにJSONのデータを持たせてステータスコードだけチェックする方法



```sh:endpoint_test.sh
#!/bin/sh

SUCCESS=200

# GET 
CODE=`curl -X GET -s -o /dev/null -w '%{http_code}\n' localhost:8000/endpoint
if [ $CODE -ne $SUCCESS ]; then 
  exit 1
fi

# POST w/ JSONファイル
CODE=`curl -X POST -s -o /dev/null -w '%{http_code}\n' -d @filename localhost:8000/endpoint`
if [ $CODE -ne $SUCCESS ]; then 
  exit 1
fi 
```
sshd設定 scp sftpトラブルシューティング

# scp packet_write_wait: Connection to  port 22: Broken pipe lost connection

多分、ディレクトリのパーミッションが怪しい

/etc/ssh/sshd_config

```
Match group sftp-testuser
  ChrootDirectory /hoge/fuge/data/testuser
  X11Forwarding no
  AllowTcpForwarding no
  PasswordAuthentication no
  PubkeyAuthentication yes
  ForceCommand internal-sftp
```
とした場合
> ちなみに　
　　　PasswordAuthentication no
　　　PubkeyAuthentication　yes
 は鍵認証の場合の設定で
　　　ForceCommand internal-sftp
 はsftpのみ ssh,scpは利用できません


パーミッション・ユーザは

```
ll /hoge/fuge/data
drwxr-xr-x. 3 root root 4096  3月 12 14:06 2020 testuser
 
ll /hoge/fuge/data/testuser/
drwxrwxrwx. 2 sftp-testuser sftp-testuser 4096  3月 12 16:03 2020 uploaddata
```

となるべき。
ChrootDirectoryで指定したディレクトリはrootでしか扱えないようにしなければならず
ChrootDirectory直下にはファイル・ディレクトリはsftpユーザは置けない


# Directive 'AuthorizedKeysFile' is not allowed within a Match block

AuthorizedKeysFileディレクティブはsshd_configファイルの中では１つだけっぽい
自分はMatchブロックにAuthorizedKeysFileを書いていたのでNGを食らってた
まあ、メッセージそのままなんですけどね
ChrootDirectoryを使うとユーザ.sshディレクトリは使えないっぽいのでAuthorizedKeysFileで指定するが必要

ただ、AuthorizedKeysFileで.sshディレクトリを変更してしまうとssh通常ユーザの鍵管理ディレクトリもAuthorizedKeysFileに指定したディレクトリになってしまうので悩みどころ