OmniAICreator/Qiita-1.07M huggingface dataset:
関数とオブジェクトメソッドでは、thisの参照先は異なる

#はじめに
オブジェクトメソッドと関数でthisを使用したときに、参照先が異なる。

+ オブジェクトメソッド
`this　⇒　呼び出し元オブジェクト`

+ 関数
`this　=>　グローバルオブジェクト`

#実例
説明だけだと、イメージしずらいのでコードを交えて確認していきます。

##オブジェクトメソッドの場合##

```
const car = {
    name: 'ベンツ',
    drive: function() {
        console.log(this.name + 'を運転する。');
    }
}

car.drive();
```

出力結果

```
ベンツを運転する。
```

##関数の場合##

```
window.name = 'ランボルギーニ';

const car = {
    name: 'ベンツ',
    drive: function() {
        console.log(this.name + 'を運転する。');
        sell();
    }
}

function sell() {
    console.log(this.name + 'を売りたい。');
}

car.drive();
```

出力結果

```
ベンツを運転する。
ランボルギーニを売りたい。
```

##おまけ
オブジェクトの中にオブジェクトメソッドを追加した場合

```
window.name = 'ランボルギーニ';

const car = {
    name: 'ベンツ',
    drive: function() {
        console.log(this.name + 'を運転する。');
        sell();

        const car = {
            name: 'プリウス',
            drive: function() {
                console.log(this.name + 'を運転する。');
                sell();
            }
        }
        car.drive();
    }
}

function sell() {
    console.log(this.name + 'を売りたい');
}

car.drive();
```

出力結果

```
ベンツを運転する。
ランボルギーニを売りたい。
プリウスを運転する。
ランボルギーニを売りたい。
```
Dockerコマンドまとめ

##目的
自分用のdockerコマンドメモ

##docker基本コマンド
```
$ docker images //docker image　一覧

$ docker run <image名>  // コンテナを作る　この時点ではコンテナはupではない ($ docker create <image名> + $ docker start -a <image名> コマンド
$ docker run -d <image名> //デタッチドモード　（そのバックグラウンドで動かす）
$ docker run --rm <image名> //一回限りのコンテナ
$ docker run --name <name> <image名>
$ docker run -it <image名> bash  //コンテナを起動してbashプログラムで上書き itはインプット可能にして画面見た目をprettyにする
$ docker run -it -v "ホストのfile元のパス:コンテナのパス" <image名> bash // ホストのファイルシステムをコンテナにマウントする（実際にはないはアクセスできる状態）例　docker run -it -v ~/Desktop/docker_test/mounted_folder:/new_dir f3a01f5a7b45 bash
$ docker run -it -p <hostのport番号>:<コンテナのport番号> --rm jupyter/datascience-notebook bash　　ホストとコンテナのポートをつなげる
$ docker run -it --rm  --cpus <コア数> --memory <メモリ> ubuntu bash // 例　docker run -it --rm  --cpus 4 --memory 2g ubuntu bash

$ docker restart<コンテナ名> //コンテナをexitからupさせる
$ docker exec -it <コンテナ名> bash //upしたコンテナに対してプログラム実行
:/# exit // プロセスを切ってコンテナをexitさせる
:/# デタッチ(ctrl + p + q) //コンテナのプロセスを残したままコンテナはupのまま
$ docker attach <コンテナ名>//デタッチ状態のコンテナのプロセスに再び入る

$ docker build <directoryのパス> //ディレクトリの中からdockerfileを探してbuildする 例 docker build .
$ docker build -t <name> <directoryのパス> //名前をつけてbuild
$ docker build <dockerfileのあるパスのdockerfile名> <dockerコンテクスト> // カレントディレクトの外からbuildしたい場合 
```

##消去関連
```
$ docker rmi <レポジトリ名> //image削除
$ docker rm <コンテナ名> //exit状態のコンテナ削除
$ docker stop <コンテナ名> //コンテナをup→exitへ
$ docker system prune // exit状態のコンテナを全削除

```

##docker hub関連

```
$ docker login // docker hubにログイン
$ docker docker pull <image名> // 例ubuntu
$ docker commit <image名> <repository名(新image名）: tag名> //imageを更新　　　（pushするにはイメージ名をレポジトリ名にする必要がある）
//dockerhubのレポジトリ名は　username/<レポジトリ名> の構成であり
//pushするときは　username/<レポジトリ名> = <image名 : tag名>　の関係にしておく
docker tag <sourceのimage名><targetのimage名> //イメージ名を変える 

```

##応用？1
```
$ id -u //ユーザIDを確認
$ id -g //グループIDを確認
$ docker run -it -u $(id -u):$(id -g) -v ~/Desktop/docker_test/mounted_folder:/reated_in_run <image id> bash //ユーザidを指定してrun  
$ docker inspect <コンテナID>   //cpuとかメモリの割当確認
```
注意　dockerfileでmkdirしたディレクトリはroot権限
2.3：バー(Bar)

#概要

この記事では、Dr. Marcos著「Financial Machine Learning」の２.3章、バーの内容の補足?を行います(自分がいまいち理解できなかった箇所について調べたことをまとめています)。内容そのものを読みたい方は、是非お買い求めください。もし記事内に誤りに気づかれたら、是非遠慮なくコメント蘭にてご指摘いただければと思います。

#バーについて

基本的に機械学習は、特徴量とラベルの行列（テーブル)を仮定します。オルタナティブデータを用いる場合でも、自然言語処理ならばベクトル化を行い、一つの特徴量に落とし込み、行列にします。

金融ではこのテーブルの行をバーと伝統的に呼みます。要は一つのサンプルのことですね。よくあるのは、時間によってサンプリングを行なったバー(標準バー)ですね。本の中では、ティックバーやボリューム(出来高)バーなど、様々なバーが紹介されています。

##なぜバーについて考えるのか？

いくつかバーがあると述べましたが、そもそもなぜいくつか必要なのでしょうか？なぜ標準バーではいけないのでしょうか？それは、サンプリングの基本である**無作為抽出になっていないから**、というのが回答になります。

サンプリングとは、基本的に元の母集団を再現する(標本誤差が小さくなるように)ようにサンプリングされるべきです([Wikipedia[無作為抽出]](https://ja.wikipedia.org/wiki/%E7%84%A1%E4%BD%9C%E7%82%BA%E6%8A%BD%E5%87%BA))。
例として、ある株のリターン分布について考えてみましょう。よく知られている通り、株の取引は時間帯によって[出来高が異なります](https://kabumado.jp/stock_market_timetable/)。ここで、例えば分足でサンプリングすることを考えてみます。分足でサンプリングすると、多くの取引があった際(例えば引けなど)には、それら多くの取引を数本のバーで表すため、過少サンプリングとなります。一方、取引が少ない際には、過大サンプリングとなります。

加えて、標準バーを用いていると、分布の非正規性や分散不均一性など、統計モデリング的にあまり好ましくない系列となります([D. Easley, M. L. De Prado, and M. O'Hara(2012)](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1695596)。このような系列では、誤差項が正規分布であり、標準偏差も一定である単純な線形回帰では上手くいかないというわけですね[^1]。
[^1]: 機械学習や深層学習など、非線形性なども学習できると考えられる場合には、あまりこの箇所は気にしなくても良い気がします。

まとめると、標準バーでサンプリングを行なった場合、

* そもそも推定すべき母集団の分布も異なる
* 系列自体もモデリング的に好ましくない統計的性質を持つ

というのが標準バーを避けるべき理由となります。上記の問題を避ける手段として、ボリュームバーなどいくつかのサンプリングの方法が本の中では紹介されているという訳です[^2]。いわゆる層化抽出に対応すると筆者は考えています。
[^2]: とはいえ、例えば月次データをボリュームバーなどでダウンサンプリングを行うと、サンプル数が激減して、統計的に信用できる結果が得られなくなると思うので、そういう場合は標準バーを素直に使うのが良いと思われます。

# まとめ

本記事では、なぜいくつかのバーが考案されているのかの背景をお話させて頂きました。一言でまとめると、元の母集団を再現するようにサンプリングを行うためということでした。この考え方は、統計モデリング一般にとても大切です。なぜなら、元の母集団を表すように適切にサンプリングされていないと、それらのデータを用いて統計モデルを組んだところで正しい結果を得られないためです。
Dart のテストが全て実行されない

Dart のライブラリ開発時、テストファイルが `pub run test`で全て実行されなかった。

実行されるためには、以下の規則が必要となる ( Flutter も同じ )。

- 実行要件
	- ディレクトリとして、 `/test` 配下に存在すること
	- ファイル名として、`*_test.dart` であること


---
- 環境
  - Dart SDK version: 2.9.2 (stable) (Wed Aug 26 12:44:28 2020 +0200) on "macos_x64"
- 参考資料
	- [flutter \- Running all unit tests in Dart \- Stack Overflow](https://stackoverflow.com/questions/59812714/running-all-unit-tests-in-dart)
pythonでatcoder水色までプログラミングやった感想

#はじめに

先週のコンテストで無事水色になれたので、今までやったことの振り返りを兼ねて記事をまとめます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/734101/f2ef6f01-6485-7a13-2f7f-d28cf0c3dcbd.png)

#自己紹介

東京工業大学地球惑星科学科卒業
卒論でpythonのライブラリ使っただけで大学ではあまりプログラミングしてませんでした。

新卒でIT系の会社に入社し、業務でpythonを学び始めました。そこで、pythonとプログラミングの知見を深めるためにatcoderを始めました。

東工大入れるくらいには高校数学はできたので（大学数学、物理には跳ね返されたけど）、順調に
水色までは伸ばせました。

#####使っているライブラリ・チートシートのうち、完全にコピペでないものを投げるgithub
https://github.com/ansainbdg/my_kyopro_library

#水色までにやったアルゴリズム

###本番で実際使用して、解けてレートに寄与したもの
・bit全探索
・累積和
・配列二分探索(bisectモジュール)
・関数二分探索(めぐる式)
・unionfind
・逆元
・約数関連
・周期性に着目するテク
・セグ木
・遅延セグ木
・簡単めのdp

###精進したけど本番で出なかったorできなかったもの
・BFS,DFS(wizard in mazeが解けなかった)
・ダイクストラ
・尺取り
・優先度付きキュー

###名前だけ知っててやらなかったもの
・ワーシャルフロイド
・ベルマンフォード
・フロー関連
・全域木
・高速フーリエ変換系

#水色までやって感じたpython競プロのメリットデメリット

###多倍長整数
これが一番大きい！解く時間も大事な競プロにおいてオーバーフローという考える要素が1個減るのは大きい！特に一番感じたのはRoad to Millionaire　
https://atcoder.jp/contests/m-solutions2020/tasks/m_solutions2020_d
でした。これは、制約が小さいながら答えが膨大になり得るので、オーバフローしうるという罠がある問題ですが、python勢は何も考えず貪欲するだけでAC出来ます。なまじ問題が実生活に関連しているせいで、非現実的だが金が膨大に増える可能性を見落としやすいんですよね。しかもこのコンテストは残り2問が高すぎる壁になっていて、青まではDまでの早解きで勝負が決まる回でした。SNSではオーバーフローに気づかず30分も時間を溶かした報告もありましたが、これだけで数百もパフォが変わり得る恐ろしい問題です。このような人のパフォを吸ったのか、当時茶色ながら27分で4完して青パフォを出すことに成功しました。

また、多倍長整数特有のテクとして、bool列を1つの整数として持つテクがあります。こうすると記述が楽になったり、非常に大きい定数倍高速化になったりします。
https://atcoder.jp/contests/abc147/submissions/16047068
これはこのテクを使ってpythonで80msで解いた回答ですが、boolを個別に配列として持つと、80msがTLEになります。

###豊富なライブラリ、関数
`pow(a,-1,mod)`で逆元が高速で出るのはずるいです。
itertoolsのproductでbit演算知らなくてもbit全探索できるのも便利です。
numpy,scipy,networkxも非常に便利です。

#jupyter notebook
インタラクティブにプログラムの検証ができるので、特に始めたてのpython文法うろ覚えの頃にはお世話になりました。（C++に同じようなものがあるかは知らないけども）

###遅い
まあこれはしょうがないですが、numpy,numba,pypyなど高速化できる手法や、先人の知恵が一杯ありますので、どうしても間に合わない問題はほとんど無いのでなんとかなります。

##個人的な結論、意見
プログラミング初心者が競プロ始める言語は、C++とpythonの2択なら私はpythonを推します。

#今後に向けて

次の目標は青ですが、さすがにしばらく時間かかりそうですので気長に頑張ります。
[vagrant]VBoxHeadlessのCPU使用率が100% になる(MAC)

#事象
いつも仮想環境を立ち上げた途端、ファンの音がすごくうるさくなるので、アクティビティモニターで原因を探ってみたところ、VBoxHeadlessのCPU使用率が100%になっていることを確認。

#解決方法
色々調べるとオーディオを無効にすると解決する可能性があるとのこと。
Vagrantfileを以下のように変更すると事象が解決しました。
「vb.customize ["modifyvm", :id, "--audio", "none"]」を追加。

```
config.vm.provider "virtualbox" do |vb|
	vb.customize ["modifyvm", :id, "--audio", "none"]
    vb.gui = false
 end
```
災害復旧対策(ディザスタリカバリ)(システムアーキテクチャ)ー午後

応用情報技術者平成28年秋期 午後2

ファイル：2016h28a_ap_pm_qs.pdf

参照：
https://www.ap-siken.com/kakomon/28_aki/pm04.html

メモを簡単に記載します。
詳細の分析は、上記リンクをご参照くだいますようよろしくお願いします。

１、図1中の①と図2中の③のネットワークアドレス，及び図1中の②と図2中の④のネットワークアドレスが同じである理由を35字以内で述べよ。

③④が①②をベースで作成されるから（私の答え）
→
Webサーバのイメージファイルをそのまま使用するから（参考の答え）

被災運用の発動手順に、各システムのWebサーバのイメージファイルから、クラウド上にWebサーバを作成するから、当然は、Webサーバの①と③は同じですね。
では、なぜ②と④のDBサーバほども同じだろう？
これは、WebサーバでDBサーバをアクセスするための設定があるから。なので、DBサーバのIP情報などを変わると、Webサーバで設定も合せて修正が必要になるので、現行と同じくなった。



＜＜被災運用の発動手順　※一部＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/c4def60c-c479-d30a-326b-1d773f6032f8.png)


２、DHCPサーバとDNSサーバは，あらかじめ現在の設定を変更しておかないと，災害が発生した場合に〔被災運用の発動手順〕に従って作業を進めても，営業店のPCから被災運用時用システムにアクセスすることができない。被災運用に対する準備について，(1)，(2)に答えよ。
（１）、DHCPサーバの設定で，あらかじめ変更しておくべき内容を40字以内で述ベよ。
DHCPサーバの設定について、DNSサーバの設定があります。

災害復旧対策　では「DNSサーバは本社と同じ設定でセカンダリDNSサーバとして使えるように稼働しておく。」という説明があるので、DHCPサーバでクラウドDNSサーバがセカンドリサーバとして設定しておかないと、災害運用でDNSサーバへ繋がなく、業務システムへアクセスできないですね。

コマンドは、下記を参照：

　　dns-server <プライマリDNSのIPアドレス> <セカンダリDNSのIPアドレス>


DHCPサーバで配布されるIPとDNSサーバのIPが同じネットワークによう変更（私の答え）
→
セカンダリDNSサーバとして，192.168.20.3を登録する（参考の答え）

私の考えは、本社のDNSサーバは使えなくなった場合は、クラウドDNｓサーバはプライマリDNSとして変更しなきゃいけないと思った。
本当は、それが必要ないですね、プライマリとセカンドリDNSサーバとして設定されると、プライマリが障害するときに、自動的にセカンドリに行くので、手動でセカンドリがプライマリに変更するのは必要ないでしょう。


（２）、表2のDNSサーバの設定で，あらかじめ変更しておくべき内容を解答群の中から選び，記号で答えよ。

ア、RDATAを192.168.20.2に変更
イ、TTLを600に変更
ウ、TTLを172800に変更
エ、TYPEをAAAAに変更

ここは、表４に、DNSの登録内容の変更が１０分という記載があります。
私の理解は、これは、DNSサーバの変更時間と思いましたが、
本当は、これは、PCクライアントのDNS登録内容のキャッシュを最新に更新する時間です！！

具体的に言うと、表２のTTLです。
現状は、86400秒（＝２４時間）ですが、
表４の要望としては、１０分（＝６００秒）になりますね。


その他選択肢：
　・RDATAはリソースの中身を記述するフィールドです。TYPEが'A'（Aレコード)の場合は、NAMEに対応するIPアドレス等を記述します。RDATAを 192.168.20.3 に変更すると、平時からクラウド上のロードバランサにアクセスすることになってしまうので誤りです。
　　この選択肢は、災害が発生していないときの予めの設定ですね。
　　RDATAはセカンドリに指すと、平日は、クラウドのロードバランスにアクセスしますね。　　

　・キャッシュの有効時間を48時間にする設定なので不適切です。
　・AAAAレコードは、ホスト名とIPv6アドレスの対応を記述するレコードなので誤りです。

＜＜表１、表２＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/9a9c3de1-cfa8-3d12-eb1f-eaf489715d51.png)


＜＜表３、表４＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/73e7d4de-30e7-9706-19ee-fce774a9b277.png)


３、〔被災運用の発動手順〕について，(1)，(2)に答えよ。
（１）、10月10日の10時30分に本社ビルのサーバルームが被災して使用できなくなってしまい，11時に被災運用を発動した場合，社内業務システムは，いつから被災運用が開始できるかを答えよ。

流れは下記ですね：
　　10/10 10:30災害発生
    11:00発動
　　ロードバランサ　２０分 ->11:20
　　DBサーバ
　　起動して、DB復旧し　３０分 →11:50　更新ログ１０分／ファイル　合せて９ファイルので、 ９０分→ 13:20）
　　
　　Webサーバ
　　起動して動作確認　（各システムごと　起動１０分　合せて３０分→ 13:50　動作確認６０／システム　３時間　→ 3 16:50）　
　　DNSの登録内容を変更　災害運用を開始　１０分　→ 17:00

17:00時になります。

（２）、表3中の下線⑤で変更する登録内容について，表2の項目と変更後の値を答えよ。
災害運用時は、（クラウドの）DNSの登録内容は、
　本社のロードバランスサーバから、
　クラウドのロードバランスサーバ
へ変更しますね。


項目：RDATA
変更後の値：192.168.20.2
【Heroku】デプロイ後エラー対処 Could not load the 'mysql' Active Record adapter.

# 起きたこと

RailsでWebAPIを作成しHerokuにデプロイしたつもりが、ブラウザの表示はこうなった↓

![スクリーンショット 2020-10-03 16.11.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305969/d1ac7cdf-bc85-aef3-c408-cb496ff07889.png)

とりあえず`$ heroku logs --tail`してねとあるので、

```terminal
　・
　・　（省略）
　・
2020-10-03T07:07:22.331249+00:00 app[web.1]: /usr/local/bundle/bin/puma:23:in `<top (required)>'
2020-10-03T07:07:22.468514+00:00 heroku[web.1]: Process exited with status 1
2020-10-03T07:07:22.527787+00:00 heroku[web.1]: State changed from starting to crashed
2020-10-03T07:07:23.246388+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=coko-api.herokuapp.com request_id=****** fwd=*******" dyno= connect= service= status=503 bytes= protocol=https
```

んー。。レスポンスが503なのはわかるけどもう少し踏み込んで`$ heroku run rails c`すると、

```terminal
　・
　・　（省略）
　・
Could not load the 'mysql' Active Record adapter. Ensure that the adapter is spelled correctly in config/database.yml and that you've added the necessary adapter gem to your Gemfile. (LoadError)
```

お、MySQLの設定周りでエラーが起きてるようです。以下翻訳↓

> 'mysql' ActiveRecordアダプターをロードできませんでした。 アダプターのスペルがconfig / database.ymlで正しく設定されていること、および必要なアダプターgemがGemfileに追加されていることを確認してください。 （LoadError）

このエラーで調べていたところ、大体2パターンあったので、対処をまとめます。

# パターン1. そもそも`Gemfile`に設定してない

ここまで気がつかないのは稀でしょうけれど、一応確認しておきましょう。

```:Gemfile
gem 'mysql2'  # << 追記
```

修正したらデプロイ

# パターン2. Herokuの環境変数にミス

[Railsアプリでherokuを使うときのDBをMySQLに変更する](https://qiita.com/poster-keisuke/items/f27e190e22d80dc254ed)を参考に環境変数を確認。

```terminal
$ heroku config
=== coko-api Config Vars
CLEARDB_DATABASE_URL:  mysql://***:***@***.cleardb.com/heroku_***?reconnect=true
DATABASE_URL:          mysql://***:***@***.cleardb.com/heroku_***?reconnect=true
　・
　・　（省略）
　・
```

一見合っているかと思いきや。。。

`DATABASE_URL`の先頭が`mysql2`じゃなく`mysql`になってる!!

`$ heroku config:set`で修正（`CLEARDB_DATABASE_URL`の方は`mysql`のままでOK）

```terminal
$ heroku config:set DATABASE_URL='mysql2://***:***@***.cleardb.com/heroku_***?reconnect=true'
```

修正したら、デプロイせずにそのまま反映されます。

![スクリーンショット 2020-10-03 17.01.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305969/aab54205-478b-0e41-2a1a-96c3bc8357d1.png)

自作APIからのレスポンスを確認できました〜

僕の場合パターン2に引っかかってました。
LPIC102　合格

今日合格しました！

勉強期間はおそらく2か月くらい。
勉強日誌つける前からやってました。

使った勉強教材はPing-tとその他気になったワード検索
使ったツールはTeraTermを自宅のPCにインストールしてコマンドの表示など実際に体験

コマ門は見た通り大体80％、模擬試験は90％以上いけば合格しますね。
もっと言葉の意味を理解していれば安心した高得点が得られました。


勉強は101より難しかったけど試験自体は102の方が問題の意味が分かりやすい印象。
これでようやくスキルシートに書ける資格が出来ました。

お次はAWSの勉強をざっくりした後にDockerの勉強する予定です。

正直なにかまだ分かってなくYouTubeで色んな方のを見て自分なりに立てた計画です。
Pythonも合わせて勉強していきたいところ。

とにかく今回の土日は好きなことして来週からまた地道に取り組んでいく。
勉強日誌26・27日目

昨日は帰ってくるのが遅く勉強してそのままダウンでした・・。

記録は
模擬試験　90％
正答率　91%(89)
正答率　85%(62)
正答率　79%(64)
正答率  83%(56)

ここが一番苦手だな
徹底的に攻めよう
正答率　63%(67)

/etc/ssh/sshd_config
sshdの設定ファイル

gpg --verify aaa.gpg
Gnupg　署名する

ssh
インターネット上のサーバにログインし、管理、設定するプロトコル

gpg --gen-key
Gnupg キーペア作成

/etc/ssh/ssh_config
SSHクライアントの設定

~/.ssh/known_hosts
SSHクライアント側にある、サーバの公開鍵が登録

OpenSSH
linuxで使われるオープンソースのSSH

gpg -e -r 
暗号化するファイル
Chocolatelyのインストール


1,2年前の記事通りにインストールを進めようとしたのですが、エラーが出て上手く行きませんでした。
素直にChocolately公式ページのガイドに従いました。
https://chocolatey.org/install

### 管理者権限でWindows PowerShellを起動
タスクバーの検索欄で「po」とか打つと候補に「Windows PowerShell」が出てきます。
「右クリック」→「管理者権限で起動(Run as Administrator)」

### コマンド入力
下記コマンドをそのままコピペして入力します。

```
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
```

数分待って特にエラーなく終わればインストール完了

`choco`
`choco /?`

などとコマンドを叩けばインストールできたことを確認できるかと思います。

nodejsをインストールしたい場合は

```
choco install nodejs
```

と打つだけでインストールできます。

インストールできるものもChocolately公式から確認できます。
https://chocolatey.org/packages/

べんり

おわり
Railsアプリの画像ファイルをS3へアップロード

# 1. バケット作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630397/98202c7d-1ae0-9e17-c453-a6ecabb20454.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630397/2acb8763-bee3-8462-e7f9-646b2a893174.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630397/9ca7018c-01ba-eeb7-5ab8-9f60d9984d0b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630397/09fd97c2-31dc-c6aa-e7ef-eca13b9d705f.png)
IAMユーザーのARNをコピー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630397/883348ba-ae83-c741-5126-4af02aea3a68.png)

```terminal:バケットポリシー
{
    "Version": "2012-10-17",
    "Id": "Policy1544152951996",
    "Statement": [
        {
            "Sid": "Stmt1544152948221",
            "Effect": "Allow",
            "Principal": {
                "AWS": "************①****************"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::************②**********"
        }
    ]
}
```
上記の①に先ほどメモしておいた「ユーザーのARN」を、②に作成した「バケット名」を記述

# 2. fogの設定
```ruby:gemfile
gem 'fog-aws'
```
`bundle install`

```ruby:app/uploaders/image_uploader.rb
if Rails.env.development? || Rails.env.test?
  storage :file
else
  storage :fog
end
```

アプリケーションのルートからconfig/initializers直下に、carrierwave.rbというファイルを作成してください。

```config/initializers/carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  if Rails.env.development? || Rails.env.test?
    config.storage = :file
  else
    config.storage = :fog
    config.fog_provider = 'fog/aws'
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
      region: 'ap-northeast-1'
    }
    config.fog_directory  = 'バケット名'
    config.asset_host = 'https://s3-ap-northeast-1.amazonaws.com/バケット名'
  end
end
```

# 3. 環境変数の設定
```terminal:ec2サーバ
# 本番環境
$ ssh -i [pem鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
（ダウンロードした鍵を用いて、ec2-userとしてログイン）
$ sudo vim /etc/environment
# iを押してインサートモードに移行し、下記を追記する。既存の記述は消去しない。
AWS_ACCESS_KEY_ID='ここにCSVファイルのAccess key IDの値をコピー'
AWS_SECRET_ACCESS_KEY='ここにCSVファイルのにSecret access keyの値をコピー'
# 編集が終わったらescapeキーを押してから:wqと入力して保存して終了
```
AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYは、IAMユーザー作成した際に、DownloadしたCSVファイルにそれぞれ記載があります。

```terminal:ec2サーバ
# 本番環境
# 編集した環境変数を適用するために一旦ログアウトします。
$ exit
$ ssh -i [pem鍵の名前].pem ec2-user@[作成したEC2インスタンスと紐付けたElastic IP]
# 環境変数が適用されているか確認しましょう。
$ env | grep AWS_SECRET_ACCESS_KEY
$ env | grep AWS_ACCESS_KEY_ID
```
# 4. 自動デプロイ
① GitHubへのpush
②「bundle exec cap production deploy」の実行
危険CMD 高速削除

多くの場合Batファイルに組んで「決まったフォルダ」を削除するときが多いです。
コマンドライン直は自殺行為です。さっきもルートをから削除しようとしました。
実験はなにもないフォルダをまず作ります
d:\ai
次に、このフォルダに一度に深くフォルダを作ります
cmdのmkdirの得意とするところです

```powershell:CMD
mkdir d:\ai\ueo\kaki\kukeko
```
このkakiくらいのフォルダでやりましょう。

###Notepadに貼り付けて起きます

```shell:cmd
カレントディレクトリのクリップ
echo %cd% | clip
おとなしめ
del /f /s \* && rd /s \
鬼

```

###やり方（まだおとなしめ）
####ターゲット
今回はDドライブのd:\hoge\tgfolder\ <font color= "red">database</font>
が削除したいフォルダ
####手順
<ol>
<li>cmd.exeをできれば管理者権限で開く　cmd ctrl+shift+enter
<li>削除したいフォルダを開く `cd /d d:\hoge\tgfolder\database`
<li>カレントディレクトリを取得　`echo %cd% | clip`
<li>メモ帳に貼り付けている下記の文字列を加工する（おとなしめの方）
<p><ul>
<li>`del /F /S d:\hoge\tgfolder\database\* && rd /s d:\hoge\tgfolder\database\`<br>このようにコピーしたディレクトリの文字列を加工する。</br>
<li>:dog:オプションスィッチはフォルダの前につける
<li>:cat:Delステートメントにはワイルドカードをつける
<li>Clipから貼り付けてパス名にダブルクォーテーションがついているときは中に入れる
<br>:smile:良い例:`"d:\hoge\tgfolder\data base\*"`
:confounded:悪い例:`"d:\hoge\tgfolder\data base\"*`</br>
<li>ワイルドカードは`*.*`としてもよい
<li>***rd***にはワイルドカードは***不要***
<li>全角のスペースが入らないように注意する
<li>&& は2つ打つ
</UL>

<li>Copyして画面に貼り付けてEnter
<li>削除するか効いてくるのでひたすらYを押す。
<li>もし違うときはY以外を押すかCtrl+Cで止まる。
<li>最後に<font color= "red">プロセスはファイルにアクセスできません。別のプロセスが使用中です。</font>
が出たら成功
`d:\hoge\tgfolder\database\`はもぬけの殻になっています。
<li>エクスプローラーを開きます`explorer .`
<li>`CD\`でカレントをルートにします
<li>CMDを閉じます。
<li>エクスプローラーから目視で`d:\hoge\tgfolder\database\`の一つ上にあがって消します。
<ol>

###理由
この方式はあとに残らないので、最後になにを消したのがbatもないのでわかりません。
このためわざとバグを起こして終了の合図にするとともに、どこ最終的に消すのか確認するようになっています。
`&&`は前のプロセスが終わってから次の命令を実行するという意味になります。

##鬼モード
危険すぎてのせられません。
要は両方とも/Qをつけてdelは `&&`の前に `> nul &&` と`> nul `を入れます。

##超鬼モード
一つ上のフォルダに上がってから実行します。
こうなるとなに一つ残りません。
これはもうbatを組みましょう。

##cmd.exeでもワンライナーができる
今までcmd.exeはワンライナーがかけないと思っていましたが、できます。 ` && `が答えです。
batがウィルスに引っかかるときは、コマンドラインにまとめて打ち込むようにすると早いです。

###補足
今回はCMD.exeを開き、削除したいディレクトリに移動して、貼り付けるだけで削除にすることを考えていましたが、なぜかルートに飛ぶので、断念しました。なぜかrdのときにルートに移動するのです。
【rails】mapメソッドの使い方

mapメソッドについて学習したのでアウトプットいたします。

この記事を読むとmapメソッドの使い方がわかります。


#mapメソッドとは？
「配列の中身を1つずつ取り出してブロックという構文を繰り返し実行する。
そして、ブロックの返り値を集め、新たな新しい配列を作る」

これから詳しく解説します。

例えば、100円、200円、300円の商品があり、全ての商品に税金をかけたいとします。

```csharp

items_price = [100, 200, 300] #3つの価格の配列
tax = 1.1
items_add_tax = items_price.map{|item_price| item_price * tax}
#配列中身の値を一つずつ取り出し、✖️1.1をしていく
put items_add_tax 
=> [110, 220, 330]
#税金が加わった新たな配列ができる
```

#まとめ
mapメソッドの使い方

```csharp

配列オブジェクト.map {|ele| ブロックの処理}
  # eleには配列の要素が１つずつ代入される
  # ブロックの処理は配列の要素の数だけ繰り返し実行される
```
スラック でリマインダー機能を使用する時のテンプレート作成プログラム

#その日1日ミーティングのホストになってしまった！
何かしらスラック のグループでその日1日ホストとなり、会議のためのズーム URLを時間ごとに投稿する機会があると思います。
#問題
・その時間にZOOMのURLの投稿を忘れてしまう
・投稿しなければ！と集中力がゼロになってしまう
#解決法
・スラック のリマインダー機能を使用する。
朝にその日に自分が投稿するものを一斉に予約しておけば、設定した通りに投稿されます。
詳しくは以下のページを参考にしてください。
https://lab.sonicmoov.com/tool/slack-reminder/

#スラックのリマインダー機能を使う際の問題
リマインダー機能を使うには、１つの投稿につき１つのリマインダーを設定する必要がある。つまり、コピペして記載する文章やら時間をゴニョゴニョと書き換える必要があります。（そんなことしなくて良い機能があったら教えてください。。）

#解決法
以下のプログラムを作成しました。

```ruby:riminder.rb
#設定
outputs = ["10:00","11:00","13:00","15:00","16:00","17:00","18:00","19:00"]#zoomのurl投稿時間
channel_name = "#〇〇"#通知チャンネル
notification = "@here"#通知する人
notification_time = "3"#何分前に通知するのか
word = ["朝礼","昼礼","ご参集ください"] #投稿したい言葉

class Riminder #リマインダーを生成するクラスです
  def initialize(times,zoom,channel,notification,pre_time,word) #インスタンス変数？を定義
    @times = times
    @zoom = zoom
    @channel = channel
    @notification = notification
    @pre_time = pre_time
    @word = word
  end

  def sentence #実際に出力する文章を作成します
    n = 0
    @times.each do |time| 
        if n == 0 #outputsの配列の番号？によって出力する言葉を変えています
          sentence = @word[n]
        elsif n == 1
          sentence = @word[n]
        else
          sentence = @word[2]
        end
      bot = "/remind #{@channel} ”\n#{sentence}#{time}\n#{@zoom}\n#{@notification}\n” #{@times3[n]}\n " #この文章が出力されます
      puts bot
      n += 1
    end
  end

  def timechanger #3分前に通知したいので、アウトプット時間から３分前の値を出力してます
    @times3=[]
    @times.each do |time|
      a = time.split(":") #"10:00"の:を削除してます
      time1 = Time.local(2020,10,1,a[0],a[1],00) #Timeという時刻に関するrubyに標準装備されているクラスを使用します
      time2 = time1 - (@pre_time.to_i * 60) #３分前(180秒)（通知したい時間）
      @times3 << "#{time2.hour}:#{time2.min}"#10:10みたいな時間表記に変更してtimes3配列に入れていきます
    end
  end
end


puts "アウトプットの時間は、#{outputs}です"
puts "投稿するチャンネルは#{channel_name}です"
puts "通知メンバーは#{notification}です"
puts "通知時間はアウトプットの#{notification_time}分前です"
puts "あなたのzoomのurlを入力してください"
url = gets.chomp
riminder = Riminder.new(outputs,url,channel_name,notification,notification_time,word)
# riminder.bot
riminder.timechanger
riminder.sentence
puts "生成されたリマインダーをスラックに投稿してください"




```
これをターミナルで実行するとzoomのurlが求められ、入力すると、

```
生成されたリマインダーをスラックに投稿してください
amagatanobuhiko@amagatahikosMBP desktop % ruby riminder.rb
アウトプットの時間は、["10:00", "11:00", "13:00", "15:00", "16:00", "17:00", "18:00", "19:00"]です
投稿するチャンネルは#〇〇です
通知メンバーは@hereです
通知時間はアウトプットの3分前です
あなたのzoomのurlを入力してください
zoom.com
/remind #〇〇 ”
朝礼10:00
zoom.com
@here
” 9:57
 
/remind #〇〇 ”
昼礼11:00
zoom.com
@here
” 10:57
 
/remind #〇〇 ”
ご参集ください13:00
zoom.com
@here
” 12:57
 
/remind #〇〇 ”
ご参集ください15:00
zoom.com
@here
” 14:57
 
/remind #〇〇 ”
ご参集ください16:00
zoom.com
@here
” 15:57
 
/remind #〇〇 ”
ご参集ください17:00
zoom.com
@here
” 16:57
 
/remind #〇〇 ”
ご参集ください18:00
zoom.com
@here
” 17:57
 
/remind #〇〇 ”
ご参集ください19:00
zoom.com
@here
” 18:57
```

のような出力が得られます。
これを下のようなブロックごとにスラック に貼り付けて送信するだけです。

```
/remind #〇〇 ”
ご参集ください19:00
zoom.com
@here
” 18:57
```
上の設定の部分で、通知したいチャンネル、何分前に通知するか、などを設定できます。
これを作った後にスラックでボットが作成できるようだと知りましたが、、まだよくわかってません。
また調べてみます。

以上
[自分用メモ] Rails DBのインデックスの考察

インデックスがよくわからなかったので以下の記事を読んで考えた。

[Rails: 闇雲にインデックスを付けてはいけない（翻訳）](https://techracho.bpsinc.jp/hachi8833/2018_05_14/55774)


インデックスとは、ソートしたカラムを別にコピーして作るようだが、
イマイチ理解できなかったので考察する。

未経験で間違っている前提で書いているので参考にはしないでいただきたい。

上記記事で、例で以下のモデルがあった。


```rb
class ShoppingCart < ActiveRecord::Base
  has_many :shopping_cart_products
  has_many :products, through: :shopping_cart_products
end

class ShoppingCartProduct < ActiveRecord::Base
  belongs_to :shopping_cart
  belongs_to :product
end

class Product < ActiveRecord::Base
end
```

ShoppingCart（カート）
ShoppingCartProduct（カートの商品）
Product（商品）

三つのモデルを作成しているが、ここからつまずいた。

ShoppingCartProductをあえて中間する必要性はなんだろうか、と。
ShoppingCartとProductを直接関連付けない理由は何か、と。

ShoppingCartとProductを仮に関連付けた場合、
カートに入っている商品をクエリすることになるということだろう。

直接商品をクエリすると何がダメなのか。
ここではあえてカートの商品を使っていることと、DBはクエリの速度を出来るだけ上げたいことから言って
カートの商品を間に介入させて法が効率性が良い結果になることはほぼ間違い無いだろう。
その仮定からすると商品を直接クエリすると単純に遅くなると言うことである。

なぜ遅くなるのか。
具体的なカラムやデータが全て参照記事でで書かれていないので憶測になるが
カートモデルが商品と直接関連付いたとすると、カートに複数の商品が存在することになる。
そして商品を閲覧するために商品モデルからカートIDと関連する商品を抽出する必要がある。

例えば、インデックスをここで貼るとする。
商品をカートID順にソートするのである。
それを商品モデルで別のカラムを作成し、商品IDと連動できるようにする。
インデックスは別にカラムを余計に作ることになるので書き込みが遅くなるようである。
まず1つ考えたのは、単に商品モデルを呼び出したい時にいちいちインデックスを含めて
検索するのでは無いか？と考えた。
２つ目に、商品を追加するごとにインデックスを貼ることになるので書き込みが遅くなるのでは無いか。
３つ目にカートから関連する商品を検索した時に膨大な商品リストからカートの商品を検索しないといけないこと。
カートというのは、頻繁に中身が変わるものだし、何回も参照する。
いくら商品モデルでカートのIDの関連をしているからと言って、
カートを見て、都度商品モデルにクエリするのは大変では無いか。
おそらく３つ目が正しい遅くなる理由で、カートの商品モデルを入れる理由なのだろうと推測している。

ここで、カートの商品モデルを中間として位置付けることにより、
カートに入れるボタンを押した時にカートと商品の関連を付ける。
カートに入れるボタンを押した時に中間がないとだめなのでは？とも考えたが
カートと商品に直接関連性を持たせてもおそらく大丈夫だろう。

カートのボタンを押した時に、自分のカートIDと商品IDを元にカートの商品モデルを作成し、
仲介するという理解である。



```rb
class CreateShoppingCartProducts < ActiveRecord::Migration
  def change
    create_table :shopping_cart_products do |t|
      t.integer :quantity, limit: 1, null: false
      t.belongs_to :shopping_cart, index: true, foreign_key: true
      t.belongs_to :product, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end
```

インデックスの話であるが、
カートの一覧を見た時に、カートの商品を検索する。
直接商品を検索することもできるが、インデックスをいちいち商品に貼りたく無いのでは無いかと考えている。
そうなるとカートIDのインデックスをカートの商品に貼り、商品IDから商品を検索したいのかなと考察している。

上の記事の例は、インデックスをカートとカートの商品間、とカートの商品と商品間に貼っているのは間違いで、
カートの商品と商品間にインデックスは貼るなと言っている。
理由としては、カートから商品は検索するが、逆は無いからである。
これは、ふに落ちるので、カートの商品と商品間のインデックスは削除することとなる。
記事では以下のようにインデックスを追加削除するように言っている。

```rb:
class RemoveIndexShoppingCartProductsOnProductId < ActiveRecord::Migration
  def up
    remove_index(:shopping_cart_products, :product_id)
  end

  def down
    add_index(:shopping_cart_products, :product_id)
  end
end
```

インデックスの付け方については少し理解できたが、
DBの設計はまだまだ理解が追いついてないなと感じたため、
簡単なDB設計例で考察してみることとする。

一般的なDB構成例をただ無意識に使うのではなく、
一度立ち止まってなぜこのような設計なのか考える時間も必要である。
送信ドメイン認証、SPFとDKIM、DMARCの違い

## 「送信ドメイン認証」とは

`アドレスが正規なものであることを証明する`、いわば なりすましメール対策に有効な手段になります。
送信元のメールサーバのIPアドレスの認証や電子署名の仕組みを利用して
メールがなりすまされているかを判断します。

送信ドメイン認証 には 3種類あります。

- SPF認証
- DKIM認証
- DMARC認証

## SPF認証とは

SPFとは `Sender Policy Framework` の略
IPアドレスを利用して、受信したメールの送信元が正しいか判断します。

仕組みとしては、
メールの送信側のDNSに`SPFレコード`を登録。
受信側のメールサーバは受信時にSPFレコードを確認し、判断を行う。

## DKIM認証とは

DKMIとは `DomainKeys Identified Mail` の略
電子署名を利用してメール送信元が正しいか判断します。

仕組みとしては、
送信者が送信するメールに秘密鍵情報を利用して作られた`電子署名`をつけて送ります。
受信側のメールサーバは公開鍵を送信元に要求・照合し、判断を行う。

## DMARC認証とは

DMARCとは `Domain-based Message Authentication、Reporting and Conformance` の略
SPF認証や、DKMI認証で認証が失敗した際の対応策を決めるものです。

送信側は、受信側が認証に失敗した際どうするのが良いかの推奨をDNSに`DMARCポリシー`として記述しておき、
受信側はポリシーを参照して認証に失敗したメールをどうするか判断します。


## まとめ

- SPF認証	
	- IPアドレスを利用して、送信元のDNSにSPFレコードを聞きに行く
- DKIM認証
	- 電子署名を利用して、送信元のDNSに公開鍵情報を聞きに行く
- DMARC認証
	- SPF・DKMIが失敗したときに受信側はどうするべきかのポリシーが書かれている

## 参考

- [送信ドメイン認証（SPF / DKIM / DMARC）の仕組みと、なりすましメール対策への活用法を徹底解説](https://ent.iij.ad.jp/articles/172/)
- [送信ドメイン認証とは？](http://www.infomania.co.jp/techinfo/domainkeys.html)
- [受信時の送信ドメイン認証方法｜SPFとDKIMの違いとは](https://www.hai2mail.jp/column/2020/0303.php)
荷物追跡APIのサービスがいつの間にか無くなったので自分で作り直した。

以前自分が使っていた
[暇人が荷物追跡APIとWebアプリを作ってみた](https://qiita.com/botamochi5522/items/57c67ae0ad57fed6e4db)を便利に使わていただいたのですがいつの間にか公開停止していたので自分で作ることにしました。

##サービス概要
URL:https://trackingjp.work
伝票番号で、（ヤマト、佐川、日本郵便）配送の状況を調べるサイトです。
番号を入力するだけで三社自動で検索します。
ステイホームでネットで注文することが増え配達される荷物の管理を簡単にしたかったので作りました。

###伝票番号を入力するだけで会社を気にしないで荷物の状態を確認できる
<br>
![スクリーンショット 2020-10-03 15.13.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762833/92eebd74-f837-6904-ff5d-044ddc052be2.png)

一行ずつ伝票番号を入力してください。

##API概要
URL:https://trackingjp.work/api/v1/tracking/伝票番号
伝票番号に付きましては7DRにて正当性をチェックしているので国際郵便などの場合は使えない可能性があります。



###データ構造

```json
{
	"number": 123456789012,
	"itemType": "ゆうパケット",
	"companyName": "japanpost",
	"companyNameJP": "日本郵便",
	"statusList": [{
			"placeName": "神奈川西郵便局（神奈川Ａ）",
			"placeCode": "243-9799",
			"date": "09/04",
			"time": "00:00",
			"status": "引受"
		},
		{
			"placeName": "杉並南郵便局",
			"placeCode": "168-8799",
			"date": "09/05",
			"time": "06:40",
			"status": "到着"
		},
		{
			"placeName": "杉並南郵便局",
			"placeCode": "168-8799",
			"date": "09/05",
			"time": "16:18",
			"status": "配達完了"
		}
	],
	"delivered": true
}
```
誤った伝票番号などの場合は

```json
{
	"errors": [{
		"message": "エラー内容",
		"code": "エラー内容"
	}]
}
```
##使用技術
フロントにはNuxt.jsを使用しました。
バックにはLaravel,Flaskです。



##利用について
自由にお使いください。

仕様変更、サービスの停止、廃止が予告無く行われる可能性があります。

一応仕様変更がありましたらqiitaあたりに書くかもです。

個人が特定できない形で、動作ログや統計値の情報等を採取する可能性があります。

何かあればコメントによろしくおねがいします。
開発環境では、できるのに、本番環境で、エラーが出る場合の対処法

##環境
heroku

##解決したいこと
開発環境では、できている動作が本番環境ではなぜか,できないこと。
私の場合は、ユーザー管理機能を実装後、ホーム画面のログインボタンを
押すと、「We're sorry, but something went wrong.」が表示されたこと。

##本番環境で動作がうまくいかない時の結論
1 heroku logs --tail --app アプリケーション名　でエラーログを探してみる。
2 マイグレートし直してみて、エラー文が表示されないか確認する。
3 本番環境のページをリロードしてみる。


#私の問題解決に至るまでの過程

##エラー解決までにやってみたこと
heroku logs --tail --app アプリケーション名
をターミナルで実行し、エラーログを探してみたが、見つからなかった。

##原因の結論
 heroku run rails db:migrateを実行し直してみた。すると、
```SyntaxError: /app/db/migrate/20200926093243_devise_create_users.rb:9: syntax error, ```
と表示された。

示されたマイグレーションファイルを確認すると、
``t.string :encrypted_password, null: false,``
と書かれており、末尾の　, が余計に記述されていたことが分かった。
そこを修正し、```git push heroku master```
でコミットし、その後、プッシュをして、マイグレートし直すと、
エラーが解消された。
つまり、herokuへの、マイグレートが文法の間違いでできていなかったことが原因でした。

##まとめ
エラーログを探しても、見つからない時は、herokuへのマイグレーションを再度し直すと、
エラー文が見つかるかもしれません。

結果的にはなぜ開発環境ではうまくいっていたのに、本番環境ではうまくいかなかったのかは
分かりませんでした。
しかし、どちらの環境でも、正常な動作を実現できたので、問題なしと判断しました。
以上になります。

###追記
紹介する方法は私がエラーを解決できた方法であり、エラー解決の方法の一つに過ぎません。
PhpStormで多段sshでコードのデプロイをする

###環境
・Windows10 1909
・OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
・PhpStorm 2020.2

##はじめに
ローカルファイルをサーバ環境に適用するのに、PhpStomでは
適用対象のファイルを開いた状態で Ctrl+Alt+Shift+X または
Alt+9でGitのペインへ移動し、適用したいコミットログを選択して、Tools>Deployment>UploadTo で
ファイルを適用できるので、とても便利です。

で、この適用先が多段接続の場合、接続テストの段階で

```Can't connect to remote host: net.schmizz.sshj.transport.TransportException: Server closed connection during identification exchange
```
と怒られて、うまく接続できなかったので、それを解決したよという話。

##結論
Windowsのsshで正しく接続できるのなら、PhpStormでも接続できる。はまったのはGitBashで接続できているのに↑のエラーが出ていたから。

##設定方法
### configの設定
~/.sshのconfigに

```
Host bastion
  Hostname XXX.XXX.XXX.XXX
  User ec2-user
  IdentityFile ~/.ssh/foo.pem

Host destination
  Hostname YYY.YYY.YYY.YYY
  User ec2-user
  IdentityFile ~/.ssh/foo.pem
  ProxyCommand C:\Windows\System32\OpenSSH\ssh.exe -W %h:%p bastion
```

のように設定します。
ここでGitBashで接続できるのにウインドウズではできなかったこと。
・鍵を~/.ssh/ではなくて、フルオープンのフォルダに置く

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'D:/XXXX/foo.pem' are too open.
```
このように言われてしまいます。

・ `C:\Windows\System32\OpenSSH\ssh.exe` の箇所を`ssh`と書く

```
>ssh destination
CreateProcessW failed error:2
posix_spawn: No such file or directory
```
こうなってしまいます。

sshはフルパスで記載し、鍵はアクセス制限のあるフォルダに置きます。
こうして正しくconfigを記載し `>ssh destination` で接続できれば、Phpstomでも以下の設定で接続できるようになります。
###PhpStormの設定
Ctrl+Alt+Sで設定ファイルを開き、Tools>SSHConfigurations
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51562/c9bf3474-342a-2b9a-0292-02bdef105d36.png)
Hostにconfigで指定した名前を設定し
Authentication TypeとしてOpenSSH config and authentication agentを選択します。

次に、Build,Execution,Deplyoment>Deployment に移動し
SSH Configurationに上で指定した設定を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51562/f8e19a75-6d8e-b448-307b-7584d6ca8722.png)

あとは、Root Path等の設定をします。
[こちら](https://qiita.com/SLEAZOIDS/items/47e36f86c3675ee069fb)に良記事があります。

これで、簡単にデプロイできるようになりました。

##その他
configの設定で、OpenSSH7.3から使用できるようになった`ProxyJump`を下記のように使用しようとすると

```
Host destination
  Hostname YYY.YYY.YYY.YYY
  User ec2-user
  IdentityFile ~/.ssh/foo.pem
  ProxyJump bastion
```
OpenSSH_for_Windows_7.7p1 では接続できませんでした。
OpenSSH_for_Windows_8.1p1を入れたところ、このバージョンでは接続できました。

[こちら](https://gravitational.com/blog/ssh-config/)も参考にしました。
【3D OD LiDAR編】PointPillars : VoxelからPillarの時代へ?!

<h1>PointPillars: Fast Encoders for Object Detection from Point Clouds</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/60987e9b-2f42-da21-0780-fb20a3e2def5.png)

以前の[VoxelNet](https://qiita.com/minh33/items/9f13bb51da4aa8b5a727)との違いは空間をVoxelとして捉えるのではなく、Pillarとして捉えた事！
それにより大幅に高速化された。


<h1>アルゴリズム</h1>
<h2>入力(Pointcloud to Stacked Pillar)</h2>
以下の9つの特徴からなる
x,y,z,r =>pointの位置と反射強度
xc,yc,zc=>pillar内のPointの平均値からの距離
xp,yp => pillarの中心位置からのoffset

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/d0d618fb-ec28-bd19-f25e-e8a1d1f42984.png)

これにより、tensor sizeは、size(D,P,N)となる
D x P x N = 単点が保有する次元数（9) x 点の存在するpillarの数 x pillarに存在する点の数

<h2>特徴量学習(Stacked Pillar to Learned Feature)</h2>
PointNetで(D(9つの特徴),P,N)を(C,P,N)の特徴量を学習する
各Pillar内でChannel-wiseに最大の値を取ると、(C,P)が得られる


<h2>shape変換(Learned Feature to Pseudo Image)</h2>
Pillarを元のHeightとwidthに戻すと(C,H,W)のPseudo Imageが得られる。


*3Dの高さの情報はチャネルに畳み込まれてしまいました

<h2>Backbone</h2>
2D DetectionのBackbone(特徴を抽出するModule)と同じ


<h2>Detection Head</h2>
2D DetectionのSSDのHead(得られた特徴から最終的なDetectionを行うModule)を使用


<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/35f0552c-dff1-989b-bb2f-b1ca1ce14b0f.png)
精度はSECONDよりちょい良いくらいだが、Speedは3倍程度速い！

*Speedに関してDetectionのエリアを絞っているので注意

<h1>結論</h1>
・Voxelの代わりにPillarを使う事で高速化を果たした。


<h1>参考文献</h1>
PointPillars: Fast Encoders for Object Detection from Point Clouds
https://arxiv.org/pdf/1812.05784.pdf
【Python】メモ　辞書について

##Pythonの辞書（dict）のforループ処理（keys, values, items）

Pythonの辞書オブジェクトdictの要素をfor文でループ処理するには辞書オブジェクトdictのメソッドkeys(), values(), items()を使う。

```python
test = {'key1': 1, 'key2': 2, 'key3': 3}
```

**keys(): 各要素のキーに対してforループ処理**
※普通にfor文回しても同じのができる

```python
for A in test.keys():
    print(A)

# key1
# key2
# key3
```

**values(): 各要素の値に対してforループ処理**

```python
for B in test.values():
    print(B)

# 1
# 2
# 3
```

**items(): 各要素のキーと値に対してforループ処理**

```python
for C, D in test.items():
    print(C, D)

# key1 1
# key2 2
# key3 3
```
プリエンプティブルノード上のWebアプリの外形監視記録

# これは何？
GKEのプリエンプティブルノードにデプロイしたWebアプリの外形監視でアラートが上がった期間の記録。プリエンプティブルVMは可用性が保証されていないが、実際にどんな挙動になるのか知りたかった。
プリエンプティブルノードプールについては以下参照。
https://cloud.google.com/kubernetes-engine/docs/how-to/preemptible-vms
24時間以内に停止する頻度については以下の記事もありましたが、実際に停止してから復旧するまでの期間なども確認したかったので実験してみました。
https://qiita.com/EastResident/items/442616d6ad1fe8108ea3

# テスト方法
* GKE上のノードは基本的にプリエンプティブルノード1つだけ
  * 別件の開発で2、3時間くらいノード数を1つ増やしたりすることはあった
* GKEには固定の文字列を返すだけのごくシンプルなWebアプリケーションをデプロイ
* datadogのSynthetics機能で1分ごとにアプリが生きてるかどうかをチェック
  * プリエンプティブルノードの停止以外でもアラートが上がる可能性あり

# スペック
* GKEのバージョンは1.16.13-gke.401（2020-10-03時点。途中でアップグレードしたりしてるはず）
* ノードゾーンはasia-northeast1-a
* ノードのマシンタイプはn1-standard-1
* 諸事情でIstio on GKEも有効にしてる

# 結果
いつから始めたのか覚えていないですが、datadogに残っていたデータが8/20〜だったのでその期間をまとめています。
2ヶ月レンジにしたときの結果の概要。灰色の部分はデータが存在していない期間です。
![datadog-service-health.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382264/869e8e6d-c9e2-09b7-58af-c800f94d03f9.png)

Alertになった時刻〜OKになった時刻の一覧
※再掲しますが、プリエンプティブルノードの停止以外でもアラートが上がる可能性あり

| 日付 | Alert開始時刻 | OK再開時刻 | OK再開時刻 - Alert開始時刻 |
|:-----------|------------:|:------------:|:------------:|
|8/20 | 20:54 | 21:03 | 0:09 |
|8/21 | 02:39 | 13:06 | 10:27 |
| | 20:55 | 21:04 | 0:09 |
|8/22 | 20:57 | 21:07 | 0:10 |
|8/23 | 21:00 | 21:09 | 0:09 |
|8/24 | 21:01 | 21:10 | 0:09 |
|8/25 | 08:22 | 08:32 | 0:10 |
|8/26 | 08:24 | 08:31 | 0:07 |
|8/27 | 08:25 | 08:34 | 0:09 |
|8/28 | 08:27 | 08:36 | 0:09 |
| | 16:45 | 16:54 | 0:09 |
|8/29 | 16:47 | 16:56 | 0:09 |
|8/30 | 16:49 | 16:57 | 0:08 |
|8/31 | 16:51 | 17:01 | 0:10 |
|9/1 | 16:52 | 17:00 | 0:08 |
|9/2 | 16:54 | 17:02 | 0:08 |
|9/3 | 16:56 | 17:05 | 0:09 |
|9/4 | 03:00 | 03:05 | 0:05 |
| | 22:04 | 22:14 | 0:10 |
|9/5 | 22:06 | 22:15 | 0:09 |
|9/6 | 22:07 | 22:16 | 0:09 |
|9/7 | 12:43 | 12:51 | 0:08 |
| | 22:02 | 22:12 | 0:10 |
|9/8 | 22:04 | 22:13 | 0:09 |
|9/9 | 07:55 | 08:03 | 0:08 |
| | 09:08 | 09:16 | 0:08 |
|9/10 | 09:09 | 09:18 | 0:09 |
| | 22:16 | 22:26 | 0:10 |
|9/11 | 22:18 | 22:27 | 0:09 |
|9/12 | 22:20 | 22:29 | 0:09 |
|9/13 | 22:22 | 22:30 | 0:08 |
|9/14 | 22:24 | 22:32 | 0:08 |
|9/15 | 09:52 | 10:01 | 0:09 |
|9/16 | 09:59 | 10:02 | 0:03 |
| | 18:30 | 18:39 | 0:09 |
| | 21:15 | 21:23 | 0:08 |
|9/17 | 21:16 | 21:25 | 0:09 |
|9/18 | 21:18 | 21:21 | 0:03 |
|9/19 | 00:00 | 00:02 | 0:02 |
| | 00:11 | 00:19 | 0:08 |
| | 04:10 | 04:14 | 0:04 |
|9/20 | 04:12 | 04:21 | 0:09 |
| | 17:21 | 17:30 | 0:09 |
|9/21 | 17:23 | 17:32 | 0:09 |
|9/22 | 17:25 | 17:35 | 0:10 |
|9/23 | 09:37 | 09:45 | 0:08 |
| | 10:20 | 10:28 | 0:08 |
|9/24 | 10:22 | 10:31 | 0:09 |
|9/25 | 00:25 | 00:27 | 0:02 |
| | 04:09 | 04:18 | 0:09 |
|9/26 | 04:10 | 04:20 | 0:10 |
| | 10:06 | 10:16 | 0:10 |
|9/27 | 04:02 | 04:11 | 0:09 |
|9/28 | 04:04 | 04:14 | 0:10 |
|9/29 | 04:06 | 04:15 | 0:09 |
|9/30 | 04:08 | 04:18 | 0:10 |
|10/1 | 04:17 | 04:19 | 0:02 |
| | 09:50 | 09:59 | 0:09 |
| | 13:01 | 13:10 | 0:09 |
|10/2 | 13:03 | 13:10 | 0:07

# まとめ
今回記録した期間では、1回あたり〜10分くらい停止しており、1日に複数回停止していることもあった。
また、隣接した日にちであればある程度同じ時刻に停止することがあったが、最長持続時間が24時間なのでそれは想定の範囲内。
Gatsby.js　フォント変更メモ　（リンクまとめ）


![スクリーンショット_2020-10-03_15-45-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692347/0f38f789-e140-d735-c487-609ae1433302.png)

「gatsby-starter-blog」に
Googleフォント、購入フォント、typography.jsのテーマを使用テストした際のメモ。
＊デフォルト.cssのfont-familyは削除しておく

```
$ yarn add typography gatsby-plugin-typography
$ yarn add typography-theme-github
```

```bash:gatsby-config.js
plugins: [
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
]
```

>ディレクトリ

/src/utils 以下に各設定ファイルを作成する

```
|--components
|  |--bio.js
|  |--layout.js
|  |--seo.js
|--normalize.css
|--pages
|  |--404.js
|  |--index.js
|  |--using-typescript.tsx
|--style.css
|--templates
|  |--blog-post.js
|--utils        //ここにフォントの設定
|  |--Inferi-Thin.woff
|  |--font.css
|  |--typography.js
```

>font.css

```
@font-face {
  font-family: "inferi-Thin";
  src: url("./Inferi-Thin.woff");
  font-display: swap;
}
```

>typography.js

```
import Typography from "typography"
import theme from "typography-theme-github"
import "./font.css"

theme.headerFontFamily = ["inferi-Thin", "M PLUS 1p", "Roboto", "serif"]
theme.bodyFontFamily = ["M PLUS 1p", "Roboto", "serif"]
theme.googleFonts = [
  {
    name: "M+PLUS+1p",
    styles: ["400"],
  },
]

const typography = new Typography(theme)

export default typography
```


>参考リンク

* [GatsbyJSで作ったブログのフォントをUDフォントに変更（Miguフォント）](https://gan0803.dev/2020-05-27-font-selection/)
* [GatsbyJSでフォントを変更する](https://www.corylog.com/gatsby/gatsby015/)
* [Typography.jsによるフォントスタイルの設定まとめ](https://qiita.com/MikihiroSaito/items/1ab9d5eeea66a163648b)
* [Typography を使ってテーマを使いつつ Google Fonts を設定してみる](https://dotgirl.net/2020/02/12/typography-google-fonts/)
* [Gatsbyでブログを作った](https://blog.freks.jp/start-gatsby-blog/)
* [gatsby.js公式doc](https://www.gatsbyjs.com/plugins/gatsby-plugin-typography/?=typo)

>ライブラリ

[Typography.js](https://github.com/KyleAMathews/typography.js/)


![スクリーンショット_2020-10-03_15-58-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692347/a5638dfd-3098-51c9-079c-c6ad1575a03c.png)
Word-Press備忘録

最近やっと自分のことわかってきたので、備忘録①とか書いてもどうせ②を出すことなどないのでただつらつらと自分のメモとして活用していきたいと思います。


# LightsailでWP立ち上げたときのディレクトリ

基本一緒なんかも知らんけど今回はLightsailでダウンロードしたから
前提としてLightsailでWPを立てて特になんも手をつけてない状態でどこがWPのディレクトリなのか書いておきます。

```
cd /opt/bitnami/apps/wordpress/htdocs/
```

これ打てばとりあえずWPの頭に来れるのでそのあとは他の人の有益な記事を見ればなんとかなる

自分は以下がやりたくて調べたので一応貼っておきます。
https://alphacast.jp/wordpress/wordpress-header-add/
【GCP】DataFlowを利用してDataStoreにデータを登録(パフォーマンス測定)

# はじめに
GCPのデータパイプラインを構築するプロダクトである、Dataflowを利用して
DataStoreにデータを登録した時のパフォーマンスやオートスケールについて共有します。

初めての方は、以下記事を前提にしておりますので、参照をお願いします。
https://qiita.com/sasuke9097/items/c3538933060f18b4c199

# 前提
* Dataflowを利用してDataStoreにデータが登録できること
* オートスケールの概要について理解していること

# できるようになること
* DataFlowのオートスケールの仕組みについて概要をつかめる
* 簡単なパフォーマンスチューニングができるようになる

## 結果
最初に結果からお伝えします。
１０万件を超えたあたりから、JOB実行時間が変わってきます。
2分間はワーカーの起動や停止に費やしているようです。
CPU時間はきれいにデータ量に比例しています。

| 処理件数 | JOB実行時間 | CPU時間(Read) |CPU時間(Regist) |Worker数|
|:-------- |-----------:|:------------:|:------------:|:------------:|
| 1        | 2分11秒    | 1秒         |1秒|1|
| 100      | 2分12秒    | 1秒       |1秒|1|
| 1,000    | 2分12秒    | 1秒         |3秒|1|
| 10,000   | 2分49秒    | 1秒           |33秒|1|
| 100,000  | 6分33秒    | 3秒      |5分28秒|1 -> 2|
| 1,000,000| 12分4秒    | 9秒      |58分16秒|1 -> 11 -> 13|

## オートスケールの仕組み
DataFlowのオートスケールの指標は、スループットです。
まずは、2、3分処理を動かしてみてスループットやCPU使用率等をもとに
Worker数を決めているようです。
以下が、1,000,000件処理時のオートスケールログです。
![screencapture-console-cloud-google-logs-viewer-2020-10-03-15_06_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223257/0a8791b0-b510-a1cf-1568-6ff1cbb419f5.png)

## パフォーマンスチューニング
パフォーマンスチューニングとして、設定可能なオプションは以下となります。

* デフォルトWoker数
* VMのCPU
* ディスク（HDD or SSD）

やはり、一番簡単なのはデフォルトWoker数だと思います。
VMのCPUは課金への影響が大きそうなので避けたいです。
今回は、1,000,000件処理を10分以内に完了できるようにチューニングします。

### コマンドの実行
ポイントは、「--num-workers=6」です。
JOB実行時のWorker数を指定できます。

```cmd
gcloud dataflow jobs run testText2Datastore --gcs-location gs://dataflow-templates-asia-northeast1/latest/GCS_Text_to_Datastore --region asia-northeast1 --staging-location gs://test-20201003/temp/ --parameters textReadPattern=gs://test-20201003/test1m.json,datastoreWriteProjectId=ace-charter-291406,errorWritePath=gs://test-20201003/error/failure.txt --num-workers=6
```

### 実行結果
9分35秒で完了しました。
Worker数は、12までスケールしました。
![screencapture-console-cloud-google-logs-viewer-2020-10-03-15_52_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223257/b604eceb-0c54-9d2e-8ee5-c274637b225a.png)


## 最後に
オートスケールを利用すると、データ量が急増しても、ある程度処理時間を抑えることが
できることが分かりました。
10倍に増えても処理時間が10倍になることはありませんでした。
データ量に応じて、初期のWorker数を変更するのがパフォーマンスチューニングの基本になるのかなと思います。

次は、DataflowのUDF（ユーザー定義関数）を利用して、加工処理を入れたいと思います。
WSL2からVisual Studio Codeを起動する

しばらくWindows10上のWSL2からLinuxが起動できない状況でしたが、
以下のWindowsUpdateでWSLが起動するようになりました（2020年10月1日現在）。

[Announcing Windows 10 Insider Preview Build 20226](https://blogs.windows.com/windows-insider/2020/09/30/announcing-windows-10-insider-preview-build-20226/)

```shell
PS C:\> cmd /c ver
Microsoft Windows [Version 10.0.20226.1000]
```
---

今まではVisual Studio Codeを起動してから、リモートウインドウを開いていましたが、
コマンドライン(PowerShell)から起動する方法が判りましたので、メモしておきます。

## PowerShellからVisual Studio Codeを起動する方は以下の通りです。
ディストリビューションはUbuntu-20.04を使用しています。

```shell
PS C:\> wsl -d {ディストリビューション名}
```
`wsl`コマンドの他にディストリビューション名が付いた実行ファイルがあります。
例えばUbuntu 20.04 LTSの場合ubuntu2004.exeという名前になります。

```shell
PS C:\> ubuntu2004 run code
```

## ショートカットを作成します
ワンクリックで起動できるようにショートカットを作成しておきます。

### ubuntu2004.exeコマンドのフルパスを調べます
当然、`which`コマンドは無いですね。

```shell
PS C:\> which ubuntu2004
which: The term 'which' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
PS C:\> (gcm ubuntu2004).Definition
C:\Users\nandymak\AppData\Local\Microsoft\WindowsApps\ubuntu2004.exe
PS C:\>
```

### ショートカットを登録します
ショートカットのリンク先に以下を登録します。

```shell
C:\Users\nandymak\AppData\Local\Microsoft\WindowsApps\ubuntu2004.exe run code
```

### ショートカットから起動します。
作成したショートカットをダブルクリックで、一瞬コンソールが表示された後に、VSCodeがWindows側で起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223848/053ba9a8-44a0-72e0-1b80-c02e6a7ba83d.png)
Electron(v9以降)でrequire("hoge").remoteを使えない時のためのtips

#Electronで開発を始めようと思ったらつまづいた

Electronではレンダー側でnodeのモジュールを使う際にはセキュリティの問題から初期設定で使用不可となるよう設定しており、以前のバージョンと比べてセキュリティが向上している。

それに従って、以前までのコードでは動かなくなっている部分もあるようなのでtips

```javascript:main.js
function createWindow () {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })
//↑これではレンダー側の処理でnodeモジュールを使用することができない。


  // and load the index.html of the app.
  win.loadFile('index.html')

  // Open the DevTools.
  win.webContents.openDevTools()
}
```

v9（2020年3月1日）以降では次のように設定を行う必要がある。

```javascript:main.js(v9以降)
function createWindow () {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      enableRemoteModule: true,
    }
  })
//nodeIntegrationとenableRemoteModuleをtrueに

  // and load the index.html of the app.
  win.loadFile('index.html')

  // Open the DevTools.
  win.webContents.openDevTools()
}
```

nodeIntegrationを付け加えなければそもそもnodeモジュールの使用が不可。
nodeIntegrationをtrueにした場合でもenableRemoteModuleがfalseではレンダー側での.remoteが使用不可のままとなる。

#thank you stackoverflow
https://stackoverflow.com/questions/63901266/electron-js-cannot-destructure-property-browserwindow-of-require-remot
Vessel環境で動いていたLaravelプロジェクトを、Homestead環境に移して動かすとphp_network_getaddresses: getaddrinfo failed: Temporary failure in name resolutionというエラー

## 経緯
- VesselでLaravelプロジェクトが正常に動くことを確認した
- Vessel環境でのXdebug実行がわからず、Homesteadに環境をチェンジした
- Homestead環境においてトップページURLにアクセスすると、`php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution`というエラーが発生していた。スクショを撮り忘れてしまったけれど、内容をよく確認するとRedisとの接続エラーのようだった。

## 原因

Vesselの初期化 (`bash vessel init`) をしたときにVesselが`.env`を書き換えていたので、Homestead上でRedisとの接続に失敗した

## 解決

`.env.bak.vessel`という、Vesselが初期化時に取得しているバックアップファイルを用いて、`.env`の設定を切り戻した。

## おわりに

単純なミスですが、結構時間食っちゃったのでここに書き残しておきますw
DDNSを定期更新するまわりくどいスクリプト

DDNS更新をするまわりくどいシェルスクリプトです。
需要はほぼないでしょう。

#ポイント
+ cronで１時間毎起動させる
+ わざわざ１時間前とIPが変わっているか判定してDDNS更新依頼をする
+ IPが変わっていない場合でも１日毎に更新依頼をする
+ わざわざURLパラメータでIPアドレスを通知

#環境

+ MyDNS.JP
+ Raspberry Pi

#前提条件

+ 独自ドメインを取得済み
+ MyDNS.JPに登録済み

#手順
`$ sudo vi /etc/cron.hourly/ddns-update`
※ファイル名は拡張子なし（"."を含まない）で！

```shell:ddns-update
#!/bin/bash
# MyDNS.JPのID
mydnsid="mydns999999"
# MyDNS.JPのPW
mydnspw="xxxxxxxxxxx"
# 前回取得したIPアドレスが書かれたファイル
gipfile=/tmp/prev_gip.txt
# 前回IPアドレス初期化（ファイルが無い場合のIPアドレス比較エラー回避用）
prev_gip="0"

# ファイル読み込み
if [ -e ${gipfile} ]; then
    read prev_gip < ${gipfile}
    # タイムスタンプ取得＆フォーマット
    gipfile_date=`date -r ${gipfile} "+%Y/%m/%d %H:%M:%S"`
    #echo "前回更新日時：${gipfile_date}"
    # タイムスタンプ＋１日を算出
    chkdate=`date -d "${gipfile_date} 1 days" "+%Y/%m/%d %H:%M:%S"`
    #echo "次回更新予定：${chkdate}"
fi
#echo "前回IP：${prev_gip}"

# 現在のIPアドレス取得
gip=`curl -s inet-ip.info`
#echo "現在IP：${gip}"

# 現在日時取得＆フォーマット
nowdate=`date "+%Y/%m/%d %H:%M:%S"`
#echo "現在日時    ：${nowdate}"

# 実行判定
if [ ${gip} != ${prev_gip} ] || \
   [ `date -d "${nowdate}" "+%Y%m%d%H%M%S"` -ge `date -d "${chkdate}" "+%Y%m%d%H%M%S"` ]; then
    curl -s https://ipv4.mydns.jp/directip.html?MID=${mydnsid}\&PWD=${mydnspw}\&IPV4ADDR=${gip} \
         -o /dev/null
    # ファイル更新
    echo ${gip} > ${gipfile}
fi
```

`$ sudo chmod 755 /etc/cron.hourly/ddns-update`

#独り言
+ これで無駄な通信をMyDNS.JP様に流さないゾ
+ 思いのほかラズパイのファンがうるさかったので24時間運用は諦めるカモ
+ /etc/cron.hourly/に置くファイルは拡張子があると動かないなんて・・・ハマったわ！
flutter upgradeしたらValidateの時に　App.framework does not support the minimum OS Version specified in the Info.plist 　とかいうエラーがでた。

この記事のこれをやったら解決した。
https://github.com/flutter/flutter/issues/58200

![スクリーンショット 2020-10-03 15.07.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/44fbe739-69c2-7650-4242-543491459364.png)


①ターミナルでflutter clean を実行。
②完了したら、 /ios/Flutter/AppframeworkInfo.plistができるので、その中の
  `<key>MinimumOSVersion</key>`
  `<string>8.0</string>`
の8.0を9.0に変更。
③Xcodeを起動して、ProjectとTargetの両方で、iOS Deployment Targetの値がios 9.0になるように設定する。
![スクリーンショット 2020-10-03 15.17.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/762871/9f011688-58d3-24fb-8d32-ad6f06f90e10.png)