OmniAICreator/Qiita-1.07M huggingface dataset:
A5M2からRDSのAuroraに接続してDB操作する方法

# 全体の流れ
1. サブネットグループの作成
2. DBの作成
3. A5M2からの接続
4. 注意事項

# 1. サブネットグループの作成
## 1-1 DBサブネットグループを作成
AWSマネジメントコンソール > RDS > サブネットグループ > 「DBサブネットグループを作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/8dd3d429-8714-c202-4900-f91731cf6454.png)

## 1-2 サブネットグループの設定
以下の通りサブネットグループを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/8f606d28-e3f6-1f49-7d30-ea2be34e6b14.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/3da88468-78a3-b538-000e-6ef174cd3135.png)

## 1-3 パブリックかどうかの確認
今回は外部から直接アクセス可能にする想定のため、作成したサブネットが**パブリック**かどうかを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/d308cd64-89de-2580-29c8-fe515afb069d.png)

ターゲット**igw-00c6208f99bd50b8f**に対し、送信先が**0.0.0.0/0**となっているためOK

# 2. DBの作成
## 2-1 データベースの作成
AWSマネジメントコンソール > RDS > 「データベースの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/ab3e15e2-9bfa-5f32-0d15-d71ccc6f87cc.png)

## 2-2 データベースの設定
以下の通りデータベースを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/8fa9a65c-b6a2-a6ab-113c-4e60c58549c8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/514a1d6e-eb6e-0b3b-a759-c0598b7c6bc0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/99f331ad-b33b-f0d7-6061-baa0d65aebed.png)
**※自動生成したパスワードは控えておく**
**※本番環境を想定してマルチAZ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/14335c14-9b18-5711-258c-9736f0428f35.png)
**※サブネットグループと同じVPC**
**※A5M2からアクセスできるようパブリックアクセスをありにする**

## 2-3 接続情報を取得する
作成完了後、接続情報詳細を表示し、接続情報を控えておく（**パスワードを確認できるのはこの時のみ**）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/f710727b-b7b3-b515-1eef-51a7caab413f.png)

## 2-4 インバウンドルールの編集
「VPCセキュリティグループ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/ae6f5504-847a-6472-0ab6-eb75e49ba4e5.png)

「インバウンドルール」タブの「インバウンドのルールを編集」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/6cf348e3-6768-1b79-c2dc-92882edb4b45.png)

「ルールを追加」から**PostgreSQL**、**マイIP**を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/7973c9e6-fde3-9226-7208-84aa0145ce4b.png)

# 3. A5M2からの接続
## 3-1 データベースの追加
A5M2を開き、「データベース」 >「データベースの追加と削除」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/dc5d16b7-8e02-a5b1-625c-66c9dcf88da2.png)

「追加」から**PostgreSQL**を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/7eb09498-14a9-0a11-957b-ac886992d7e7.png)

サーバー名、データベース名、ユーザID、パスワードを入力し、「OK」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681113/8d1d4243-e353-a916-7ccf-60ed4a5f1f3f.png)
個人開発で作った技術スタックDBサービスの掲載企業数がもうすぐ70社に到達する！

8月に個人開発で「[what we use](https://whatweuse.dev)」という企業の技術スタックをまとめたデータベースサイトをリリースしました。

企業の技術スタックを横断的に検索できるWebサービスです。例えば、「Rust」を使っている企業を探したい場合、従来であれば、その企業の採用サイトに行って、ソフトウェアエンジニアの募集要項を見ないといけなかったのが、what we useでRustで検索すれば、その企業一覧をみることができます。

https://www.whatweuse.dev/

β版リリース時の内容はこちらにまとめており、開発経緯など興味ある方いればこちらも一読お願いします！

https://qiita.com/mycndev/items/757cf6932b8687a06e36

あれから2ヶ月程度が経過し、諸々進展あったので、この記事でまとめようと思います！

## 掲載企業数がもうすぐ70社！
めちゃめちゃありがたいことに、多くの企業に掲載リクエストをいただいており、βリリース当時は8社だった掲載企業数をいまや70社近くにまで増やすことができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731282/0faccf35-ae3a-c983-dd49-87a96cbd54a5.png)
ただ、まだ管理画面などは開発しておらず、スプレッドシートでちまちま作業しています。意外とこれが便利で、データ入力規則とかをいい感じに活用すると、一企業あたり5~10分くらいでデータ投入が完了するので、あとは、Vercelのデプロイを走らせてサイトに反映するだけです。

## 企業・技術スタック検索機能を実装 done
企業数が多くなってきて、一覧から探すのがしんどくなってきたので、企業検索機能を実装しました。
企業検索といってもそんな大袈裟なものではなく、特定のキーワードで企業をフィルタリングできる機能です。70件の企業をすべて取得した上でフロントエンドでフィルタリングしているだけなので、バックエンドとの通信はなく爆速です。将来的には、業界でフィルタリングとかできると面白いかなーと思っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731282/a0ae91e2-14ac-1954-c6e4-835e65c0b681.png)

技術スタック（ツール）の方も、企業と同じやり方で検索できるページを用意しました。このページがリリース当時から実現したかったことでしたが、実際に検索してみると、まだまだ掲載企業数を増やしていきたいと思うようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2731282/2ab0a030-3628-df27-dcb5-120b1304eb3f.png)

## SEOがうまくいかない！
what we useは企業詳細ページが既述の通り70ページほど、ツールごとの採用企業ページ（例えば、["NestJS" を採用している企業](https://whatweuse.dev/tool/nestjs)）が520ページほどで合計600ページ程度が存在しているのですが、そのほとんどがまだGoogleにインデックスされておらず、ほとんどの流入がTwitterやQiitaになっています。

中長期的には「（企業名） 技術スタック」「（企業名） エンジニア」というキーワードでの流入を獲得していきたいので、SEOは優先的な問題です。

最近気づいたのは、https://whatweuse.dev と https://www.whatweuse.dev が混在していて、sitemapにはwwwなしのURLを登録していたのに、実際にインデックスされていたのはwwwありの方でした。このあたり、混在しているのはあまりよろしくなさそうなので、最近wwwありURLからwwwなしURLにリダイレクトする設定をVercel上でしてみました。

これで数ヶ月後にどんどんインデックスされて各企業やツールのキーワードで流入があることを祈ります。
（SEO専門ではないので、詳しい方いたら是非、コメントやTwitterなどで教えてください・・・）


## おわりに
まだまだ企業数を増やしていきたいと思っているので、引き続きリクエストお待ちしています。掲載リクエストはこちらのGoogleFormで受け付けており、リクエストいただいてから、平均で1-2日くらいで掲載完了のご連絡ができると思います。もちろん無料です。

https://forms.gle/tg8EBCRuyNExgaUr5
Dockerのmysqlのコンテナを日本語対応にする

# 背景
DockerでMySQLのコンテナを立てて、いろいろしてみようと思っていたところ、日本語対応していないことに気がついた。

記事を探してみると、解決方法がいっぱいでてきた。読んでみると、Debian版のmysqlイメージを使用して、aptを駆使して日本語対応しようという方法だった。
でも、armアーキテクチャでは、Debian版は対応していないっぽい。
M1搭載Macだと、Oracle Linux版mysqlイメージで日本語対応させるしかなさそう。

>failed to solve: rpc error: code = Unknown desc = failed to solve with frontend dockerfile.v0: failed to create LLB definition: no match for platform in manifest sha256:159ec

# MySQLを日本語対応する方法

なんでもいいから、とりあえずMySQLコンテナを日本語化したい人は飛ばしてくださいな。

mysqlのイメージのもととなるイメージは「Oracle Linux slim」が使用されているので、もろもろのインストールは`microdnf`コマンドを使う。

Oracle Linux slimで、次の操作をすると、日本語の環境になる。
```bash:bash
$ sudo microdnf update -y
$ sudo microdnf install -y glibc-locale-source
$ sudo localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
$ export LANG=ja_JP.UTF-8        
$ export LC_ALL=ja_JP.UTF-8
$ locale  #きちんと変更されているかの確認
LANG=ja_JP.UTF-8
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=ja_JP.UTF-8
```

# MySQLコンテナの日本語化の方法

先ほどの方法をdocker-composeで設計すると以下のようになる。

```
% tree
.
├── docker-compose.yml
└── Dockerfile
```

```yml:docker-compose.yml
version: "3"

services:
  mysql:
    container_name: "mysql"
    hostname: "mysql"
    build:
      context: "."
      dockerfile: "Dockerfile"
    # ボリューム
    volumes:
      - ./mysql/conf.d/:/etc/mysql/conf.d/
      - ./mysql/.db/:/var/lib/mysql        # データベースのデータを残すため
    ports:
      - "3306:3306"
```

```Dockerfile:Dockerfile
FROM mysql:8

ENV MYSQL_ROOT_PASSWORD password
ENV MYSQL_DATABASE admin-device
ENV TZ "Asia/Tokyo"

RUN microdnf update -y \
    && microdnf install -y glibc-locale-source \
    && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8

ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
```

# 追記
「もしかしたら、この設定も必須かもしれない」と思い、追記しました。

MySQLの設定は、`/etc/mysql/conf.d/my.cnf`に記載すればいいみたい。
なので、こんな感じの`my.cnf`に。
```:my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[client]
default-character-set=utf8mb4
```

以下のようなディレクトリにして、Dockerfileも編集しておく。(composeファイルはそのままで大丈夫)
また、データベースの初期化を行いたい場合は、init.dというディレクトリを作成して、sqlファイルをぶち込んでおく。
```
% tree
.
├── docker-compose.yml
├── Dockerfile
├── conf.d
│   └── my.cnf
└── init.d
    └── init.sql
```
```Dockerfile:Dockerfile
FROM mysql:8-oracle

ENV MYSQL_ROOT_PASSWORD password
ENV TZ "Asia/Tokyo"

RUN microdnf update -y \
    && microdnf install -y glibc-locale-source \
    && localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8

ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8

COPY conf.d /etc/mysql/conf.d
COPY init.d /docker-entrypoint-initdb.d
```
Dockerfileの最後の2行に、ローカルのディレクトリをコンテナ内にコピーする命令を追加した。

これで、M1 MacのDockerでMySQLコンテナの日本語化&初期化が可能。
インフラ(AWS)エンジニアでもある程度はコーディングスキルは必要な理由 

# この記事の概要
プログラミングが苦手だから全くやらずにインフラ(AWS)エンジニアという方が多いみたいですが、
ある程度は必要みたいです。

こちらのブログを書かれたエンジニアの方のTwitterで呟かれていたことを参照していきます。

https://note.com/poly_soft/

# 大前提
僕はインフラエンジニアではないです。笑
なんでこんな記事を書いているんだーと突っ込みたくなると思いますが、
この記事を書いた当時は、インフラエンジニアになる可能性があったので
AWSの学習をしていた時期に書いた記事です。


# どういう場面で使うのか
以下の場面で使うみたいです。

⚫︎```AWS Lambda```
⚫︎```GCPのCloud Functions```
⚫︎```シェルスクリプト```
⚫︎```ビックデータ処理用のコード```
⚫︎```ジョブ制御用のコード```


このあたりである程度のコーディングスキル必須になるみたいです。

実際に現役のAWSエンジニアの方に聞いたのですが、
***インフラエンジニアとプログラマーのジョブチェンジは可能***みたいです。
***最近のインフラエンジニアはクラウドを使える必要***があるので、
プログラミング知識も必要みたいです。インフラからプログラマーへ移動するにしても、
インフラがわかる人として社内でも一目置かれるみたいです。


# インフラのコードの自動化
インフラ環境をコードで書いたら実際にインフラをAWS上に作って、
それがコードと一致してるかをテストし
サーバーからアプリ配信するところを自動化します。このようなコードの自動化で
コーディング知識は使えるみたいです。
プログラマーほどのコーディング知識は不要ですが、基本的な文法は知る必要はあります。

https://qiita.com/Hashimoto-Noriaki/items/a222bd3ec4285272ca93

# どの言語とフレームワークがいいか
現役のAWSエンジニアの方がお話をされていたのですが、
***TypeScript***と***React***がおすすめみたいです。
あとはPythonですが、まずは上の２つはある程度学習していくといいみたいです。


# コードの自動化を教えてくれるスクール
こちらのスクールではinfrastructure as a codeを教えてくれるみたいです。
自分もこのスクールの代表の方からアドバイスをいただきました。
自分はやっていないのですが、評判はかなりいいです。
カリキュラムの内容も現場で通用するものになっています。
現役のプログラマーの方やインフラエンジニアの方でコードの自動化を
学びたい方はすごく優秀なスクールです。興味あれば問い合わせしてみてください。
このスクールからお金はもらっていません!

https://www.ryukke.com/?p=9782

# Udemy教材
Udemyだとこの２つが評判いいみたいです。

https://www.udemy.com/course/iac-by-packer-aws/

https://www.udemy.com/course/iac-with-terraform/?aEightID=s00000016735001&AID=190908007224&a8=UnOGgnV4RajJIJ-T90jy45W1FaNTjOW5y0qSVaXYsSe4RaOnMyOdjym-FyscmcWqiS2yYbOdinOGZs00000016735001
コレクションの全列をテキスト型に変換する

# 経緯
2つのコレクションをUtility - Collection Manipulation::Transpose Collectionで行列変換し、
Utility - Strings::Get Collection as CSVでテキスト化した後、Excelにペタッと貼りつけて比較したいときに、
コレクションの列のうち例えばコレクション型の列が含まれていると、図のようなデータコンバートエラーが発生し、Transposeできない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/66acdbc3-1256-740a-6411-0cf1574a4002.png)

全列がテキスト型（String）であればうまくTransposeできそう。。。
というわけで、コレクションの全列をテキスト型に変換するアクションをささっと作ってみたいと思います。

# やりたいこと
コレクションの各列のデータ型をテキスト型に変換したい。

# 作ったアクション
**Utility - Collection Manipulation::タイプをtextに変換**
Filter Collectionをベースに作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/0103df5c-5f52-2c59-3324-003dfb4c94e1.png)

#### Input
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/d326893e-41fc-4637-57a5-868185a3d2cf.png)

#### Output
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/b998e199-34d3-56ed-7f71-e026762480f4.png)

#### Code
```vb
Dim NewRow As DataRow
Collection_Out = New DataTable()

For Each Column As DataColumn In Collection_In.Columns
	Collection_Out.Columns.Add(Column.ColumnName, GetType(String))
Next

For Each parentRow As DataRow In Collection_In.Rows
	NewRow = Collection_Out.NewRow

	For Each c As DataColumn In parentRow.Table.Columns
		Dim Value = parentRow(c.ColumnName)
		If c.DataType.Equals(GetType(DataTable)) Then
			NewRow(c.ColumnName) = ""
		Else
			NewRow(c.ColumnName) = parentRow(c.ColumnName)
		End If
	Next

	Collection_Out.Rows.Add(NewRow)
Next

NewRow = Nothing
Collection_In = Nothing
```

変換元のコレクションの列にコレクション型が含まれていた場合、テキスト変換するとなぜかフィールド名が値として出力されてしまい違和感があったため、ブランクとして出力するようにしました。

# 検証

### 事前準備
Inputのコレクションを下の図のように定義しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/328cbb27-b81c-b033-3395-53ddd7446f17.png)

画像とバイナリデータについては適当な画像データをインポートしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/529c8585-1800-510f-14f4-e40013eae4cd.png)

### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/b26f50fa-42d2-9224-fe7d-fd05be8ce2e3.png)

コレクション型の列の値はブランクになっています。
パスワード型の列の値はマスクが外れていますので、実運用でこのアクションを使う場合は注意してください。
画像の列の値はSystem.Drawing.Bitmap
バイナリの列の値はSystem.Byte[]
となっています。

# 使い道
Utility - Collection Manipulation::Transpose Collectionで、複数のデータ型を持つコレクションの行列変換を行うときくらいかなと思います^^;
リモートデスクトップで社内PCにアクセスしようとしたら、接続できなかった話 

自身のPCから社内PCへアクセスしようといつも通りVPNを接続し、リモートデスクトップを起動し、滑るようにIPアドレスを入力。
さぁ仕事を始めようかと思った瞬間、下記の警告文が・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727339/0b90d6c7-6b51-dc12-1a2e-2ff6ede76761.png)

 
ググったやり方でも解決できなかったが、おまぬけ設定が原因でそれを解除したら解決した方法を記録する。

# 環境
- OS : windows11 pro

# リモートデスクトップ接続ができない場合の対処方法（通常はこれ）
まずは、普通はこれで解決する方法です。
## リモート デスクトップ用のファイア ウォールが 「 外部ネットワークからの接続を拒否 」 に設定されている場合
以下の順で進めていくと良い
**システムとセキュリティ > Windows Defender ファイアウォール**
１．コントロールパネル
２．システムとセキュリティ
３．Windowsファイアウォールによるアプリケーションの許可
４．許可されたアプリ画面で、設定の変更をクリック
５．許可されたアプリおよび機能の一覧にある**リモートデスクトップ**を選択
６．**プライベート**と**パブリック**にチェックを入れ、OKをクリック

**Windowsツール > セキュリティが強化されたWindows Defenderファイアウォール**
１．受信の規則
２．**リモート デスクトップ - ユーザー モード (TCP 受信)**を選択
３．プロパティを開く
４．プロパティ画面の**詳細設定**を選択
５．プロファイル内の**ドメイン・プライベート・パブリック**のすべてを選択

大体は、ファイアウォールが原因ではじかれてリモートデスクトップに接続できないよう。

ファイアウォールが原因で詳しく知りたい方は以下の参考サイトを
[Microsoft](https://learn.microsoft.com/ja-jp/troubleshoot/windows-server/remote/cannot-connect-to-vdi-remote-computer)


しかし、私の場合は、上記はしっかり設定されていた状態なのである。

# リモートデスクトップ接続ができない場合の対処方法（もしかしたらこれかも）
これは、本当におまぬけ！
結論から言うと、Hyper-Vを有効にしていたことで、インターネットのアクセスポイントがバーチャルイーサネットに設定されていたことだった（下記の画像）
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727339/2f3d419a-747d-cb62-f870-426cd99e7593.png)

では、これを解決する方法は、以下である。
**Hyper-Vマネージャーを起動**
１．仮想マシンを選択
２．**仮想スイッチマネージャー**を選択 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727339/4a8da9e8-d784-81fa-c17b-1ffc90a57a32.png)
３．外部ネットワーク（E）の選択を**プライベートネットワーク（P）に切り替える**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727339/7fe815a1-9af6-7b62-be49-d9f6a127a4ab.png)
４．OKをクリックする

以上で、Hyper-Vを無効にできる。
すると、下記の画像のようにイーサネット接続もしくは、Wi-Fi接続になり、無事にリモートデスクトップで社内PCに接続できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727339/f2952f2f-cf96-68f8-5213-01f3f0a2fb0c.png)
 
# まとめ
仮想環境で開発環境をそのままで、リモートデスクトップに接続したのが原因だった。
仮想環境を使わない場合は、接続を無効にしましょう。
includeとextendの違いについて

## 環境
Ruby 2.6

## はじめに
includeとextendの使い方については、Rubyの文法書を読めばたいてい書いてありますが、簡単に言えば次のようになります。

モジュールに記述したメソッドをクラスに取り込む際に、

- クラスメソッドとして取り込む場合（つまり、取り込むクラスがクラスメソッドとして定義している場合）は、extendを使って取り込みます。

- インスタンスメソッドとして取り込みたい場合（つまり、取り込むクラスがインスタンスメソッドとして定義している場合）は、includeを使って取り込みます。

文法書を読めば、「なるほど、それだけの話か」だけで終わってしまいますが、一応、手を動かして動作を確認してみないと、本当に理解したことにはなっていないものです。プログラミングは頭だけで理解するのでなく、手を動かして体で理解することが何よりも大事だと思っています。ということで、includeとextendの違いを実際に動かして確認してみましょう。

## 動作確認（その１）

つぎのようなモジュールを作成します。
```test.rb
module Test_module
    def mod_test
        puts "OK"
    end
end
```

モジュールをクラスメソッドとして取り込みます。ここで、extend Test_moduleの代わりに、include Test_moduleと記述すればエラーになります。メソッドを呼び出さずに、includeだけする分にはエラーにはなりません。因みに、extend Test_moduleは、class << selfの上に記述します。class << selfの下に記述すればエラーになります。
```test.rb
class Test_class
    
    extend Test_module

    class << self
        def cls_cls_test1
            mod_test
        end
    end
end
```

ここように、モジュールに記述したメソッドが、クラスメソッドとして呼び出すことができるようになります。
```
$Test_class.cls_cls_test1
=> OK

$Test_class.mod_test
=> OK
```

## 動作確認（その２）

次は、モジュールをインスタンスメソッドとして取り込みます。そのためには、include Test_moduleと記述して取り込みます。extend Test_moduleと記述すればエラーになります。
```test.rb
class Test_class
    
    include Test_module

    def cls_cls_test1
        mod_test
    end
end
```

このように、インスタンスメソッドとして呼び出すことができるようになります。
```
$Test_class.new.cls_cls_test1
=> OK

$Test_class.new.mod_test
=> OK
```
Azure IoTを触ってみた

# はじめに
今回Azure IoTについて勉強してみたいので備忘録として記事にしています。

# IoT、Azure IoTとは
IoTとは「Internet of Things（モノのインターネット）」の略で、従来インターネットに接続されていなかった様々なモノ（センサー機器、駆動装置（アクチュエーター）、住宅・建物、車、家電製品、電子機器など）が、ネットワークを通じてサーバーやクラウドサービスに接続され、相互に情報交換をする仕組。
Azure IoTは、IoTを高い可用性およびセキュリティで実現するためのサービス群のことを言うようです。

# Azure IoTはいろいろなサービスからなっている
Microsoftの公式サイトには以下のようなイメージが載っています。
![Qiita](https://learn.microsoft.com/ja-jp/azure/architecture/reference-architectures/iot/images/iot-refarch.svg#lightbox#lightbox)

https://learn.microsoft.com/ja-jp/azure/architecture/reference-architectures/iot

たくさんのサービス（サービス以外もありますが）が書かれておりうんざりしてしまいますが、すべてを知っている必要はありません（後ろの方はIoT用のサービスというわけでもないですし）。ここでは代表的なサービスについて記載します。
中核となるのはAzure IoT Hubで、すべてのデバイスの情報がここに集められて後続サービスに回されます。

|分類|サービス名|説明|
|:---|:---|:---|
|Devices|-|デバイス側に組み込むSDKやOSがここに含まれる。これらを利用し簡単にAzue IoTに通信できたり、高いセキュリティを担保したIoT機器を作ることができる。|
|-|Azure IoT Edge|デバイスからの情報を直接Azureに送信せず一旦受け取るHubの役割をするもの。プロトコル変換やできるだけNW帯域を消費しないようデータの整形や集約を行う。|
|Ingestion & provisioning|Azure IoT Hub|デバイスとクラウドの接続点となるサービス。機器から流れてくるデータ蓄積や機器の状態監視などを行う。|
|Ingestion & provisioning|Device Provisioning Service(DPS)|IoTの運用コストを抑えるためのサービス。デバイスをIoT Hubに自動で接続でき機器を追加するたびに接続先情報を書き込む必要が無い、障害時などにIoT Hubの接続先を切り替えたい場合などに機器を触る必要が無いなどの利点がある。|
|Hot path|-|リアルタイムな情報を取り扱うところ。故障検知や予兆警告などに利用する。Azure Stream Analyticsは、IoT Hubからデータを読み込み、および加工を行い後続サービスへのデータの受け渡しを行う感じ。|
|Warm path|-|リアルタイムというほどではなく数時間単位ぐらいのデータを取り扱うところらしいが、いまいち使い道が分からない。。。|
|Cold path|-|日、月単位などの過去データを取り扱うところ。統計分析や機械学習などを行いHot pathの閾値に利用したり、Hot pathでは検知できない故障予知などを行う。|
|Management & business integration|-|データの可視化を行うサービス群。|

# Azureに接続できるデバイス
いざAzureへ繋げようと思っても既存の機器でそれができるのか？、新規に導入するとして何を使えばいいのか？という疑問に対しては「Azure Certified Device プログラム」というものがあります。

https://learn.microsoft.com/ja-jp/azure/certification/overview

Azure Certified Device プログラムで認定されている機器は、Azureで適切に動作することが保証保証されています。以下のサイトに各機器がカタログ化されています。

https://devicecatalog.azure.com/devices?certificationBadgeTypes=IoTDevice

# 実践
[Azure IoT実践（Azure IoT Edge for Linux on Windows）](https://qiita.com/takess/items/27663cdfdeef751e10da)
UINavigationViewControllerの戻る(pop)をisMovingFromParentで判定するのは危険

ナビゲーションを使っている場合に「戻るボタン」で戻ったことを判定するのに`viewWillDisappear`内で`isMovingFromParent == true`を使う方法がググると結構出てきます。
※Qiita内だと https://qiita.com/yimajo/items/d9409d83fecf9875061d とか。

が、うまく動作しないパターンをいくつか見つけたので記録しておきます。


# 検証用Xcodeプロジェクト
検証用に作ったXcodeプロジェクト: https://github.com/pomu0325/isMovingFromParent

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9490/fcac838c-6a16-f3f1-4912-bfcc3a6664ad.png)

- NavigationControllerに以下のViewControllerを埋め込む
  - ViewController（背景黒いやつ）
    - PushボタンでViewController2を表示
  - ViewController2(背景白いやつ）
    - `animated: true`のボタンで`setViewControllers([viewController], animated: true)`する
    - `animated: false`のボタンで`setViewControllers([viewController], animated: false)`する
    - `viewWillDisappear`内で`print("isMovingFromParent: \(isMovingFromParent)")`して状態を調べる

# 正しく判定できないケース

以下の操作や処理をすると、`viewWillDisappear`の`isMovingFromParent`では戻ったかどうかが正しく判定できません。

## スワイプで戻ろうとして途中でやめたとき

最近のiOSだと画面左端からのスワイプでナビゲーションの「戻る」ができますが、途中で指を離したり戻したりすると「やっぱやめた」ができます。

![swipeback.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9490/c42a333c-8ed5-24ea-5b85-2f58caad33ea.gif)

が、スワイプを始めたタイミングで`viewWillDisappear`が呼ばれ、このタイミングでも`isMovingFromParent`は`true`になっているので「やっぱやめた」場合に「戻る」判定を早まってしまいます。

※ https://qiita.com/yimajo/items/d9409d83fecf9875061d#comment-a08822f1e2081fe33bb0 のコメントでも言及されていました


## `animated: false`で`setViewControllers`した時

直接ビューのスタックを書き換えたい時に使える`setViewControllers`をした際に「戻る」操作はしていないので除外したいことがあり`isMovingFromParent`で判定をしていました。

意外にも`animated`の指定次第で`isMovingFromParent`が変わってしまいます。

- `animated: true`の場合: `isMovingFromParent == false`になる
- `animated: false`の場合: `isMovingFromParent == true`になる

ので、誤判定されてしまいます。
【Flutter】戻ると画面がリビルドされてしまう

Flutterで次のような操作をした時に、戻るボタンタップの後にページAがリビルドされてしまうという問題にハマりました。

```
ページA→ページB→ページC→戻るタップ→ページB
```

原因としては`ページA→ページB`の時に`maintainState: false`を指定していたことでした。

```
Navigator.of(context).push(MaterialPageRoute(
    builder: (_) => MyHomePage(id: widget.id + 1),
    maintainState: false)); // falseだと戻るでリビルドされる
```

[ドキュメント](https://api.flutter.dev/flutter/material/MaterialPageRoute-class.html)によるとmaintainStateの説明は次のようになっていました。
```
Whether the route should remain in memory when it is inactive.
ルートがアクティブでなくなってもメモリに維持するかどうか
```
true:維持する場合は、メモリにあるのでリビルドされない。false維持しない場合はメモリにないのでリビルドされる。
    ということだと理解しました。

おそらくページB以降でページAに関わるステータスが変更された時に、表示を更新したくてこのように回避していたのかもしれません。

```dart:再現コード
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(id: 1),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.id}) : super(key: key);

  final int id;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    print("Page ${widget.id} built!");
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.id.toString()),
      ),
      body: Center(
          child: ElevatedButton(
              child: Text("Open next page"),
              onPressed: () {
                Navigator.of(context).push(MaterialPageRoute(
                    builder: (_) => MyHomePage(id: widget.id + 1),
                    maintainState: false)); // falseだと戻るでリビルドされる
              })),
    );
  }
}
```
Bean バリデーションが効かなかった話(1 errors<EOL>Field error in object validation)

JavaのフレームワークSpring bootでBean バリデーションを実行した際にバリデーションが効かなかったのでいろいろと調べました。

## やりたいこと

フロントで入力した値をList型のformでバインドして指定したフォーマット（@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm :ss")）の通りに値が入らなかったらエラーを出すという処理です。

## コード

```java:workUser.java
@Data
public class WorkUser {
	private int id;
	private String userName;
	
	@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
	private LocalDateTime   startTime;
	
	@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
	private LocalDateTime   finishTime;
	private int  workFlag;
	
	@NotNull
	private String message;
	private String  duration;
	private LocalDate  startDate;
	private LocalTime  StartTiming;
	private LocalTime  FinishTiming;	
}
```

```java:workUserForm.java
@Data
public class WorkUserForm {
	
	  @Valid
	  private List<WorkUser> userworkList;

}

```

```java:UserPageController.java

	@PostMapping("/mypage/changeRecord")
	public String changeRecord(@Validated WorkUserForm form, Model model,BindingResult bindingResult,HttpServletRequest httpServletRequest) {
		
		// 入力 チェック
		if (bindingResult.hasErrors()) {
			return getUserList(model, httpServletRequest, form);
		}
			
        //行いたい処理		
	}


```


上記の構成でフロントから来たList型の値のバリデーションをしようとしましたが以下のエラーが出てきました。
```
1 errors<EOL>Field error in object validation　...............
```

## 結論
BindingResult bindingResultはバリデーションを行いたいformの後につける必要がありました。


```java:UserPageController.java

	@PostMapping("/mypage/changeRecord")
	public String changeRecord(@Validated WorkUserForm form, BindingResult bindingResult, Model model,HttpServletRequest httpServletRequest) {

    //行いたい処理
		
	}
```

## 感想
かなり盲点をついたエラーだと感じました。javaはさまざまなルールがありまだまだマスターするには時間が必要だと認識できました。

参考サイト

https://stackoverflow.com/questions/61992386/org-springframework-validation-beanpropertybindingresult-5-errors
Google Apps Scriptでファイルを分けて開発する環境について

## Google Apps Scriptでファイルを分割して管理したい
自動化の一環としてGmailのメールコンテンツをAPI連携したい時があるかと思います
こういった場合は、Google Apps Scriptのお世話になる訳ですが、私がGASで開発する際には、ローカルでコードを書いて、claspでuploadしています
そうすれば、コードのgit管理も出来ますので

このGoogle Apps Scriptって[.clasp.json](https://github.com/google/clasp#project-settings-file-claspjson)に[ファイルのupload順](https://github.com/google/clasp#filepushorder-optional)は設定できるのですが、実行時に別のファイルの読み込みエラーになることが多くて、歯痒い思いをしてきました


だからといって1ファイルに全てを書き込むのは関心事の分離から避けたい状況な訳でして...

## どう対応したか

複数ファイルに分けて書いて、npmでbundleしています
bundleと同時にJavaScriptへのトランスパイルも行なっています
トランスパイルはclaspでも出来ますが、実行時に生じたエラーの対応を考えると、同じファイルがローカルにある方が良いと考え今の方式を採用しました

ディレクトリ構成や設定内容は下をご確認ください
(実装内容はsourceディレクトリにファイルを分けて置いています。この記事では割愛しています)
* .clasp.jsonで"rootDir":"./dist"を指定してbundleとトランパイルしたファイルを出力しています。またappsscript.jsonもこちらに置いています
* esbuildも試しましたが、古めのTypeScriptには対応していないこと、TypeScriptのバージョンを上げると、GASの実行エンジンが入口となる関数を見つけてくれなかったことから諦めました
* source内には14ファイル、1000物理行ほどのファイルですので、webpackでも問題ありませんでした。今は色んなツールがあるのとすんなり動いたのでswcを使っています。clasp pushが一番時間がかかるので、どのツールでも大差はないと思います


ディレクトリ構成
```tree.sh
dist/
source/
.clasp.json
package-lock.json
package.json
tsconfig.json
webpack.config.js
```

``` webpack.config.js
const path = require("path");
const GasPlugin = require("gas-webpack-plugin");

module.exports = {
  mode: "development",
  devtool: false,
  context: __dirname,
  entry: "./source/index.ts",
  output: {
    path: path.join(__dirname, "dist"),
    filename: "bundle.ts",
  },
  resolve: {
    extensions: [".ts", ".js"],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: "ts-loader",
      },
    ],
  },
  plugins: [new GasPlugin()],
}
const loaders= {swc: 'swc-loader'};
const loaderOptions= {
    swc: {
      sync: true,
      jsc: {
        parser: {
          syntax: "typescript",
          tsx : true
        }
      }
    }
  };
```

```tsconfig.json
{
    "compilerOptions": {
      "target": "ES5",
      "module": "ESNext",
      "allowJs": false,
      "outDir": "./dist",
      "skipLibCheck": true
    }
}
```

```package.json
  "scripts": {
    "build": "webpack --progress --env loader=swc",
    "push": "npm run build && clasp push",
    "build:esbuild": "esbuild source/index.ts --bundle --outfile=dist/bundle.ts",
    "build:webpack": "webpack"
  }
```

なお、当方backend側の人間でして、npmに詳しいわけではありません
何か変な設定をしていたら、やさしく教えて頂けると嬉しく思います

## 終わりに
同じ思いをしていている方の何らかの参考になると嬉しく思います
zFS Encryption

<H1>Encrypted zFS Requirement</H1>
zFS Encryption does not need both of 

- EXTENDED format
- SMS-Managed
<h2> Reference</h2>

https://www.ibm.com/docs/en/zos/2.5.0?topic=process-encrypting-existing-file-system-data

```
Existing zFS file systems can be encrypted.
The zFS aggregate that contains these file systems does not need to be SMS-managed extended format.
```
https://www.ibm.com/docs/en/zos/2.5.0?topic=cnfstiaed-defining-vsam-linear-data-set-that-has-key-label
```
The encryption support provided by DFSMS is normally only allowed for SMS-managed extended format data sets.
zFS aggregates are exempt from this restriction.
Use of the ZFS keyword instead of LINEAR will allow key labels to be assigned to any VSAM linear data set that is supported by zFS.
```
https://www.ibm.com/docs/en/zos/2.5.0?topic=v2r4-using-zos-data-set-encryption-enhancements
```
Specifying a key label for a non-extended format data set
Encrypted data sets must be SMS-managed. Encrypted extended format data sets can also be compressed format.

Considerations when planning for data set encryption
Encrypted data sets must be extended format. Refer to Extended-Format VSAM Data Sets and Processing Extended-Format Sequential Data Sets for information on allocating extended format data sets, including guidelines and restrictions.
```
【React】郵便番号のフォーム入力中に'-'を自動で追加する

```html:sample.html
<div className="postcode">
    郵便番号 <br />
    <input
        value={text}
        onChange={handleChange}
        onKeyUp={handleKeyUp}
        onBlur={handleBlur}
        onCompositionStart={startComposition}
        onCompositionEnd={endComposition}
        type="text"
        placeholder="000-0000"
        maxLength={8}
    />
</div>
```

```typescript:sample.tsx
//Enterキー押下時、日本語変換のものかどうか判定する
const [composing, setComposition] = useState(false);
const startComposition = () => setComposition(true);
const endComposition = () => setComposition(false);

const [text, setText] = useState("");
const handleChange = (e: { target: { value: string } }) => {
  setText(() => e.target.value);
};

//郵便番号にハイフンを自動挿入するメソッド
const insertStr = (text: string) => {
  //４桁目が'-(ハイフン)’でない場合で８桁以上入力されている場合は末尾を削除する
  if (text.length >= 8) {
    return text.slice(0, 3) + "-" + text.slice(3, text.length - 1);
  }
  return text.slice(0, 3) + "-" + text.slice(3, text.length);
};

//入力時に郵便番号に自動でハイフンを付けるイベント
const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
  //日本語変換中は処理を行わない
  if (composing) {
    return;
  }
  //削除キーではハイフン追加処理が働かないように制御（8がBackspace、46がDelete)
  const key = e.key;
  if (key == "Backspace" || key == "Delete") {
    return false;
  }

  //３桁目に値が入ったら発動
  if (text.length === 3) {
    setText(insertStr(text));
  }
  //４桁目が'-(ハイフン)’かどうかをチェックし、異なる場合は挿入
  if (text.length >= 3 && text.substring(3, 4) !== "-") {
    setText(insertStr(text));
  }
};

//フォーカスが外れた際に4桁目に'-'がついているかチェック、なければ挿入
const handleBlur = () => {
  //４桁目が'-(ハイフン)’かどうかをチェックし、異なる場合は挿入
  if (text.length >= 3 && text.substring(3, 4) !== "-") {
    setText(insertStr(text));
  }
};
Windows版のpgAdmin4におけるconfig.pyの場所

# この記事を読むべき人
- WindowsユーザーでWindows上で開発作業している
- pgAdmin4（執筆時点の最新版はv6.14っぽい）をWindowsにインストールしている
- config.pyファイルを直接編集したいと考えている

# config.pyが置いてある場所
　インストール先を変更していない場合なら、「%LocalAppData%\Programs\pgAdmin 4\v6\web」ってエクスプローラーのアドレス欄に入力してみよう。
　config.py と config_distro.py が見るかるはず。
　詳しい書き方については、[The config\.py File — pgAdmin 4 6\.14 documentation](https://www.pgadmin.org/docs/pgadmin4/development/config_py.html)を参照してください。微妙にWindows向けの記載が間違っていたので、この記事を起こしました。

# 参考情報
　pgAdmin4 v6 最新版のダウンロードは、[Download](https://www.pgadmin.org/download/pgadmin-4-windows/)ページから行えます。
　v6以前のバージョンがインストールされていても、v6インストール時に勝手に削除したりしないので、割とややこしいです。
　私は v6.14 （pgadmin4-6.14-x64.exe）で試しました。
WSL2でQMK Firmwareのファームウェアの作成と書き込みをする


## 動作環境

- Windows 10 Pro 21H2
	- Windows Subsystem for Linux (WSL2)
		- Ubuntu 22.04.1 LTS
	- Docker Desktop v4.12.0
	- [avrdude v7.0](https://github.com/avrdudes/avrdude)
	- Visual Studio Code v1.72.0
		- Remote Development v0.21.0

:::note warn
警告
追記[2023/12/30]: Windows11の場合`avrdude.sh`実行エラーとなるため、Windows側でqmk_toolboxで書き込む必要がある。
:::

## ファームウェア作成

【WSL側】`qmk_firmware`をクローンし、カスタムする(ここではLet's Splitキーボード)のキーマップのディレクトリを作成する。

```sh
$ git clone --recurse-submodules https://github.com/qmk/qmk_firmware.git
$ cd qmk_firmware 
$ git switch -c custom-lets_split
$ mkdir -p keyboards/lets_split/keymaps/hgshdt
```

このディレクトリにカスタムした`config.h`, `keymap.c`, `rules.mk`などを格納し、dockerビルド用のスクリプトでビルドする。`lets_split_rev2_hgshdt.hex`が作成されることを確認する。

```sh
$ util/docker_build.sh lets_split:hgshdt
```

## 書き込み

【Windows側】`avrdude`のリリースのサイトから、`avrdude-v7.0-windows-x64.zip`をダウンロードし、Windows側の任意のディレクトリにダウンロード・ファイルを解凍する。
- `avrdude.exe`：Windowsの任意のディレクトリに格納する(ここでは`C:\workspace\qmk\avr`とする)
- `avrdude.conf`：WSL側の`qmk_firmware`内にコピーする

【WSL側】書き込み用のスクリプト(`avrdude.sh`)を作成する。

```sh
$ cd qmk_firmware
$ vi avrdude.sh
```

`avrdude.sh`の中身は以下。[WSLでavrdudeを簡単に使う為の奴 (github.com)](https://gist.github.com/orumin/26e4840fd8aa23cbaac9fdf11e3df01f)を流用させていただいた。変数`AVRDIR`に、Windows側に保存した`avrdude.exe`のディレクトリを指定する。

```sh
AVRDIR="/mnt/c/workspace/qmk/avr"

MODECMD='/mnt/c/Windows/System32/mode.com'
GET_COMPORT='/mnt/c/Windows/System32/reg.exe query HKLM\HARDWARE\DEVICEMAP\SERIALCOMM'

CONNECTED_COMPORT=$(${MODECMD}|grep -oE 'COM[0-9]+'| tr '\n' '|' | sed -e 's/|$//g')
echo "connected port: $CONNECTED_COMPORT"
TARGET_COMPORT=""
while [ "$TARGET_COMPORT" = "" ];do
 sleep 0.5
 printf "."
 if [ -z "$CONNECTED_COMPORT" ]; then
  TARGET_COMPORT=$(${GET_COMPORT}|grep -oE 'COM[0-9]+')
 else
  TARGET_COMPORT=$(${GET_COMPORT}|grep -vE $CONNECTED_COMPORT|grep -oE 'COM[0-9]+')
 fi
done
echo ""
echo $TARGET_COMPORT

${AVRDIR}/avrdude.exe -C ./avrdude.conf -c avr109 -p m32u4 -P ${TARGET_COMPORT} -U flash:w:$1
```

作成したファームウェアをこのシェルスクリプトの引数に指定して実行する。スクリプト実行後待機状態中にリセットスイッチを押す(Let's Splitの場合、最初に左キーボードをUSB接続して実行。次に右キーボードをUSB接続して実行。最後に再度？左キーボードをUSB接続して実行)。

```sh
$ sh avrdude.sh lets_split_rev2_hgshdt.hex
```
情報セキュリティと脅威

# 不正のトライアングル
### 1. 動機
不正を行いたいと考える原因

### 2. 機会
行動を起こせるチャンス

### 3. 正当化
これは不正ではないと思う理由

# 脅威の分類
情報資産は、```機密性(情報が守られていること)```、```完全性(常に正確なデータであること)```、```可用性(いつでも使える)```が確保されていることで価値を生み出す。これらを維持することが情報セキュリティの目的である。
盗聴、なりすまし、改ざんがある。

### 関連記事（盗聴、なりすまし、改ざん）
https://qiita.com/masatom86650860/items/8f9fecf76e27c3ed3759#%E7%9B%97%E8%81%B4%E6%94%B9%E3%81%96%E3%82%93%E3%81%AA%E3%82%8A%E3%81%99%E3%81%BE%E3%81%97%E3%81%AE%E5%8D%B1%E9%99%BA

# 人的脅威やリスクを生み出す行為
### サラミ法
被害者にわからないように、ほんの少額ずつ詐取する手法。少額ずつ銀行口座に振り込ませたり、```複数の顧客の口座から少額ずつ引き落としを行う```などの例がある。

### BYOD(Bring Your Own Device)
```私物のパソコンやスマートホンなどを、業務に使用したり社内ネットワークに接続すること。```
この行為によって持ち込まれた```ウイルスに社内システムが感染したり、許可されていないソフトウェアの使用などのリスク```があり、禁止する企業が多い。

### スニファの悪用
スニファとは、```ネットワーク上に流れるパケットをモニタして、ネットワークトラブルの検出に使うツール```。これを悪用することで盗聴ツールになる。

### 関連記事
https://qiita.com/masatom86650860/items/65c936b1be27ab8561af

# 出典 
https://gihyo.jp/book/2022/978-4-297-12375-8
Convert Es5 to ES6 javascript.


# Arrow Functions

[Convert Es5 to ES6 javascript.](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000K1ZtYSAV)

```
let slideIndex = 1; 
showSlides(slideIndex);

let plusSlides = (n) => showSlides(slideIndex += n);

let currentSlide = (n) =>  showSlides(slideIndex = n);

function showSlides(n) {
   let i;
   let slides = document.getElementsByClassName("mySlides");
   let dots = document.getElementsByClassName("dot");
   if (n > slides.length) {slideIndex = 1}
       if (n < 1) {slideIndex = slides.length}
   for (i = 0; i < slides.length; i++) {
     slides[i].style.display = "none";
     }
   for (i = 0; i < dots.length; i++) {
     dots[i].className = dots[i].className.replace(" active", "");
   }
   slides[slideIndex-1].style.display = "block";
     dots[slideIndex-1].className += " active";
}
```
さくらのレンタルサーバの移行ツールでGoogle WorkspaceのGmailが届かなくなった話

初投稿です。よろしくお願い致します。
さくらのレンタルサーバで新サーバに移行するために、移行ツールを使ったところ、ドメインのゾーン設定をする必要があったので、メモです。
# さくらのレンタルサーバが新サーバに！
https://rs.sakura.ad.jp/speedup/

に記載の通り、さくらのレンタルサーバが増強されました。Pythonのバージョンも3になるということで、ライトプランユーザの私も早速移行することにしました。（容量が100GBってありがたいです）
移行自体は、[移行ツール](https://help.sakura.ad.jp/rs/2756/?_gl=1%2Ajnzy80%2A_ga%2AOTIwNzA1NTIwLjE2NjU0NzcwNzg.%2A_ga_M3MLBH78ML%2AMTY2NTk3MjgwMi4xNi4xLjE2NjU5NzM5MjQuMjUuMC4w%2A_ga_RY0M78YRM0%2AMTY2NTk3MjgwMi4xMC4xLjE2NjU5NzM1MzIuNDIuMC4w&_ga=2.110094405.1986018258.1665833226-920705520.1665477078)を使い、トラブルなく完了！したはずだったのですが。。。
# あれ？Gmailでメールが受信されていない
携帯でメールを確認したところ、移行した時刻以降、メールが届いていない。。。[メール設定は移行される](https://help.sakura.ad.jp/rs/2759/?article_anchor=js-nav-3)はずだよなと思ったのですが、私は独自ドメインでGoogle Workspace（G Suiteから無料で移行）を使っているので、嫌な予感がして、Workspaceのコンソールからドメインの管理の項目を見ると、Gmailが無効になっていました。どうやらドメインのMXレコードが書き換わってしまったようです。
# @のMXレコードを編集しましょう
次の順番でGmailを復旧させました。
1. Google Workspaceのコンソールへ移動し、ドメインの管理へ移動。Gmailを有効をクリック。
1. コンソール上でドメインの情報を取得すると、SAKURA　INTERNETを認識するので、次は[さくらインターネットの会員認証](https://secure.sakura.ad.jp/auth/login?url=https%3A%2F%2Fsecure.sakura.ad.jp%2Fmenu%2Ftop%2Findex.php)でログイン。
1. 契約中のドメイン一覧をクリックし、ページ上部にあるドメインコントロールパネルへのリンクをクリック。
1. レコード設定で編集をクリック。
1. 編集するのは@のMXレコードだけです。まず、既存のMXレコードに「1 ASPMX.L.GOOGLE.COM.」を上書き。次に、下のレコード追加ボックスでエントリ名を@、タイプをMXとして、次の4つを一つずつ追加します。
　5 ALT1.ASPMX.L.GOOGLE.COM.
　5 ALT2.ASPMX.L.GOOGLE.COM.
　10 ALT3.ASPMX.L.GOOGLE.COM.
　10 ALT4.ASPMX.L.GOOGLE.COM.
1. 最後に保存して、さくらインターネット側の変更は終了。Google　Workspaceに戻り、手順を進めると、MXレコードの検証が行われ終了です。

# サーバの移行に油断は禁物
ですね！
AWS クラウドプラクティショナー合格体験記

# はじめに
AWS クラウドプラクティショナーを受験して、無事合格することができました。
未経験の状態から1か月で資格取得することができましたので、経験ある方ならもう少し早くとれるのかなと思います。
自分なりに学習方法等まとめてみましたので、今後受験する方の参考になれば幸いです。

# 受験した当時の経歴
未経験でインフラエンジニアとして転職してすぐ
AWSってなに?クラウド?はて...。というような状態で学習開始。
「IPアドレスとはなにか」など会社内の研修と合わせてほんとーーに初歩的な所から学習していきました。

# 試験概要
出題問題数 : 65問
合格点 : 700/1000点
出題形式 : 択一選択式 ・複数選択式
試験時間 : 90分
受験料金 : ¥11,000 +tax

# 試験範囲
・クラウドの概念　26%
・セキュリティとコンプライアンス　25%
・テクノロジー　33%
・請求と料金設定　16%

# 学習方法

<1週間目>　

・参考書を一通り読む
覚えられなくてもとりあえず一通り読む。
(問題集を解いたときにこんなこと書いてあったなー程度)
ただ、この参考書に載っていないサービスも多々あったのでこの参考書だけで合格は難しいかなと思います、、

↓使用した参考書↓
[AWS認定資格試験テキスト AWS認定クラウドプラクティショナー](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B/dp/4797397403/ref=asc_df_4797397403/?tag=jpgo-22&linkCode=df0&hvadid=295691444786&hvpos=&hvnetw=g&hvrand=13862707295877300606&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009241&hvtargid=pla-718362586207&psc=1&th=1&psc=1)

<2週間目>

・AWS無料のデジタルトレーニングを受講する
動画で学習でき、ただ本を読むよりも覚えやすいなと感じました。

[Skill Builder AWS Cloud Practitioner Essentials (Japanese) (日本語実写版)](https://explore.skillbuilder.aws/pages/16/learner-dashboard?ctl99=t-_elearning~p-0~l-_ja~field16-_12)

<3.4週間目>

・とにかく問題集を解きまくる
問題を解きながら自分で単語集を作って、「このサービスなんだったっけ」と思ったときに見返したり、暗記シートのように使って覚えたりしました！
全部で4.5周解き、(応用レベルを90%以上とれるまで)
問題の不正解の選択肢も、どんなサービスなのか考えながら解くように心がけました。

↓使用した問題集↓
[Udemy【2022年版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問）](https://www.udemy.com/course/aws-4260/)　


AWS公式の模擬試験も受けましたが、実際の試験よりもかなり簡単。
この結果が良くてもあまりあてにならないかなと思いました。
CLFはとにかく単語を覚えれば受かる試験だと思うので、最短で合格したい！という方は上記で紹介したudemyの問題集や、Tech Stockなど問題を解きながら覚えていくのがおすすめです✨

[TechStock AWS WEB問題集](https://techstock.jp/exam/)

# 試験を受けてみて
問題を解きながらまず思ったのが、思ったより難しい！
公式の模擬試験なんか簡単すぎる...
udemyの応用レベルより全体的には少し簡単なくらいのレベル感でしたが、応用レベルと同じくらいの問題も多々ありました
udemyの応用レベルを理解して解けるようになっていれば、ほぼ確実に合格できると思います！
Python, Djangoの環境構築 (windows)

【Pythonのインストール】
1.最新のPythonのインストーラーをダウンロード
2.ダウンロードしたパッケージを実行(その際「Add Python 3.x to PATH」をチェック)
3.コマンドプロンプトで「py --version」を実行し、「Python 3.XX.XX」と表示されることを確認


【仮想環境の設定】
・virtualenvのインストール(初回のみ)
1.コマンドプロンプトで「pip install virtualenv」を実行
2.「pip freeze」を実行し、インストールされたことを確認

・仮想環境の作成
1.コマンドプロンプトで仮想環境を構築したいディレクトリに移動
2.「virtualenv env」を実行
3.指定したディレクトリに「env」フォルダが作成されたことを確認

・仮想環境の実行/終了
1.コマンドプロンプトで仮想環境を構築したディレクトリに移動
2.実行する場合、「env\Scripts\activate」を実行
3.終了する場合、「deactivate」を実行
PHPのセキュリティを上げる（エスケープ処理）

PHPのコードが完成したときに出てくる問題の一つにセキュリティがあると思われます。
その時に圧倒的に役に立つhtmlspecialcharsというエスケープ処理があるのですが、初見で試そうとしてミスした記憶があるのでメモします。
エスケープ処理についての説明はググると出てくるため割愛させていただきます。

# 環境
* PHP8.0
* ロリポップ スタンダード

# コード
```sample.php
//エスケープ処理
function h($s) {
    return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
}
```
これを上部に組み込むと動作します。
使う際は、
```sample.php
//h()の中に変数を入れる
h($_POST['id'])
```
これだけでセキュリティを上げることができますので是非お試しください。
Moduleの使い方について

## 環境
Ruby 2.6

## はじめに
モジュールの使い方は、大きく２種類に分けることができます。

1. モジュールを単体で呼び出して使う
2. クラスにinclude（もしくはextend）してクラスの拡張メソッドとして使う

そして、上記1の方法しか使わない場合、上記2の方法しか使わない場合、上記1,2の両方を併用して使う場合とで、メソッドの定義の仕方が変わってきます。

そんな３種類の定義の仕方をまとめてみました。

## 動作確認（その１）

動作確認用に、３種類のモジュールを作成しました。
```test_module.rb
# 1のパターン
module Test_module1
    def self.mod_test1
        puts "#{__method__}"
    end
end

# 2のパターン
module Test_module2
    def mod_test2
        puts "#{__method__}"
    end
end

# 3のパターン
module Test_module3
    def mod_test3
        puts "#{__method__}"
    end
    module_function :mod_test3
end
```

モジュールを単体で呼び出して使う場合、パターン１、パターン３は問題なく動作します。
```
$Test_module1.mod_test1
=> mod_test1

$Test_module3.mod_test3
=> mod_test3
```

パターン２の場合はエラーになります。このような書き方はできません。
```
$Test_module2.mod_test2
=> undefined method `mod_test2' for Test_module2:Module (NoMethodError)
```

## 動作確認（その２）

上記のモジュールをクラスに取り込みました。
```test_class.rb
class Test_class
    
    extend Test_module1
    extend Test_module2
    extend Test_module3

    class << self        
        def cls_cls_test1
            mod_test1
        end

        def cls_cls_test2
            mod_test2
        end

        def cls_cls_test3
            mod_test3
        end
    end
end
```

パターン１の場合は、クラスから呼び出して使うことはできません。呼び出そうとするとエラーになります。
```
$Test_class.cls_cls_test1
=> undefined local variable or method `mod_test1' for Test_class:Class (NameError)

$Test_class.mod_test1
=> undefined method `mod_test1' for Test_class:Class (NoMethodError)
```

パターン２の場合は問題なく動作します。
```
$Test_class.cls_cls_test2
=> mod_test2

$Test_class.mod_test2
=> mod_test2
```

パターン３の場合は、クラスの中のメソッドから、外部のモジュールを呼び出す分には問題ないが、外部のモジュールのメソッドを直接呼び出すことはできないという制限が入ります。
```
$Test_class.cls_cls_test3
=> mod_test3

$Test_class.mode_test3
=> private method `mod_test3' called for Test_class:Class (NoMethodError)
```

## 結論

下記のような使い分けをしましょうということになります。

- モジュールを単体で呼び出して使うようなときでしか使わない場合は、メソッドにselfをつける。

- クラスにinclude（もしくはextend）して、クラスの拡張メソッドとしてしか使わない場合は、selfも、module_functionもつけない。

- モジュールを単体で呼び出して使う場とき、クラスにinclude（もしくはextend）してクラスの拡張メソッドとして使うときと、両方の使い方をする場合は、module_functionを使う。（ただし、クラス内のメソッドからしか読み込まれないという制限付き）
Local（Local by Flywheel）の環境にIPアドレスでアクセスした

Wordpressのテスト環境をパソコン上で作ってみようと「LOCAL」で環境を構築しました。
なかなか便利です。

管理画面はこのようになっています
![スクリーンショット 2022-10-17 13.15.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45016/d320efee-b3b3-69c6-38ba-1ea62f13d003.png)


ブラウザにアドレス「test.local」を入力するとトップページが表示されました。

なぜこのアドレスの名前解決ができているのか疑問に思ったので（どこが変更されているのかを把握しておきたいと思った）
もしかして、と　/etc/hostsを参照すると、追加されていました。

```
## Local by Flywheel - Start ##
::1 test.local #Local Site
127.0.0.1 test.local #Local Site
::1 www.test.local #Local Site
127.0.0.1 www.test.local #Local Site
## Local by Flywheel - End ##
```
このhostsの記述であれば、「http:://test.local/」とアドレスバーに入力すれば
下記のディレクトリにアクセスしているのだと理解しました。
pingも応答します。

```
~$ ping -c 2 test.local 
PING test.local (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.047 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.168 ms
~/Local Sites/test/app/public$ pwd
/Users/hoge/Local Sites/test/app/public
~/Local Sites/test/app/public$ ls
index.php		wp-comments-post.php	wp-load.php
license.txt		wp-config-sample.php	wp-login.php
readme.html		wp-config.php		wp-mail.php
test.html		wp-content		wp-settings.php
wp-activate.php		wp-cron.php		wp-signup.php
wp-admin		wp-includes		wp-trackback.php
wp-blog-header.php	wp-links-opml.php	xmlrpc.php
```

これで謎がとけてスッキリとして使えると思ったのですが、
なぜか　「<span>http</span>://127.0.0.1/」では「404 Site Not Found」
となります。
![スクリーンショット 2022-10-14 16.35.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45016/fcd784b7-4c8c-f5f7-5a72-d62d91fc8d97.png)


Wordpressのテストをローカルマシンで行うにはこれで十分の環境はできましたが、なぜhostsに書いてあるtest.localではアクセスできて、127.0.0.1ではアクセスできないなくて、悩みました。

ifconfigで調べたローカルIPでも、同じようにSite Not Foundの表示になりました。

結論はこれです。
・メニューバーからPreferenceを開き、画面左のメニューからADVANCEを選び、「Router Mode」とあるのでそこを Site Domains から localhost へ変更し画面右下の「APRLY」をクリックする
・左上の×ボタンをクリックして、Localのメイン画面に戻ると上部に「Warning! This…」と表示されているので、「FIX IT」をクリックする

![スクリーンショット 2022-10-17 14.12.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45016/c22851fa-08b8-985a-ad18-6cd6c8dd768e.png)

・Site Hostの表示が「localhost:ポート番号」に変更されているのでそのアドレスでアクセスできる　　
<span>http</span>://localhost:10003でも　<span>http</span>://127.0.0.1:10003でも、ローカルIPアドレスがわかっていれば、たたとえば<span>http</span>://192.168.1.10:10003でもアクセスが可能
![スクリーンショット 2022-10-17 14.16.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45016/b48ef910-e1fd-3d11-a027-79fc2a63b5ef.png)
vim で fatal: unsafe repository" が出てアップデートできない

備忘録なのでちょっと雑です・・・。

nvimでplug-vimでプラグインのアップデートを試みていたところ以下のようなエラーが発生しアップデートできなかった。

`fatal: unsafe repository`
# エラーが発生した環境
nvim(NVIM v0.9.0-dev-71-gd9a80b8e2)
Windows 10

私の環境ではたまたま上記の組み合わせだったのですが、
上記の組み合わせ以外（Linux、本家vim）でも発生すると思います。

# 原因
 Git for Windows ver2.35.2 で仕様変更された影響らしい。

gitの実行ユーザーとリポジトリのフォルダの所有者が別々だとエラーが出るようになったらしい。

gitのバージョンを確認するにはCLI（コマンドプロンプト等）で`git --version`で確認できます。
```:CLI
git --version
git version 2.36.1.windows.1
```
ちょっと表記が怪しいですが2.35.2よりも上のバージョンっぽいです。


# 解決策
主に二つ解決策があります。

以下のように __gitの方でこれを許容する設定を追加する方法。__
```
git config --global --add safe.directory [許可したいリポジトリへのパス]
```

もう一つは __Windowsの方でフォルダの所有者をgitの実行ユーザー（今PCを使っているユーザー）に変更する__ 方法。

どうするのが定石なのでしょうね？これ以外方法は無いのでしょうか...。

git config --globalで一つずつ変更するのは大変なのとあんまり良くない気がしたので、とりあえずフォルダの方の所有者を変えることにしました。

あんまり時間はかけてられないので・・・。

私の場合はnvimのプラグインのフォルダの所有者がAdministratorsになっていたので、実行ユーザーに変更しました。
（vimの方のプラグインフォルダはAdministratorsになってなかったけど...この辺りよくわからないですがたまたまなんでしょうか？）

## 所有者の確認の方法と
GUIがわかりやすいと思います
フォルダ右クリック→プロパティ→セキュリティタブ→詳細設定→所有者
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270838/63219530-1739-4ec9-a823-c7a5a8c195d0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270838/76920d04-d3b2-9fb9-88a6-7a3f0df76993.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270838/86a79226-0313-22b5-0e82-4a58c4bf01d8.png)

ここから所有者を変更してもいいのですが、プラグインを何個も導入している場合は大変なのでコマンドを使うと良いと思います。

Windowsにもchmodみたいなコマンドはtakeownとicalosがあります。
あんまり難しくないのであとは調べて頑張ってください...。
（ごめんなさい）

私は以下のコマンドで一括で変更しました。
```powershell:nvimのプラグインフォルダ内
dir | % { takeown /d Y /r /f $_.BaseName }
# dirコマンドでリポジトリ（プラグインフォルダ）を取得してtakeownで所有者変更してます
```


# 参考
https://www.neko3cs.net/entry/error-git-fatal-unsafe-repository

https://qiita.com/elfincafe/items/dd0f8793113f0437f078
【はじめまして】はじめました

はじめまして辛太郎です。

今回Qiitaを始めた理由としましては、
業務中自分で何となく解決したやり方を書くSalesForceのメモ代わりになります（要は初心者向け）。
メモ代わりなので公開向けの綺麗なレイアウト修正や正確性は対応しておりません。
対応しておりませんが、どうしても見づらかったら修正なりなんなりします。

正直、専門的な知識を要するSalesForceにおいて、
更に専門的なAPEXに対する日本語ナレッジが少なすぎたので。
もっともっと言うなら機械翻訳が辛すぎる、読解が難しい。
<font color="#ff0000">**皆が皆ちゃんとコーディングとか設計が出来ると思うなよ。**</font>

自分は技術的な部分はかなり弱いので、

<font color="#ff0000">**「もっと効率的な書き方がある！！！」**</font>
<font color="#ff0000">**「こんなんじゃセキュリティがうんぬんかんぬん！！！」**</font>

とかめちゃくちゃ丁寧にご指摘を食らっても

**「？？？？？？？？？？？？？？？？？？？？？？？？」**

となる可能性が信じられないくらい高いです。
あくまでメモ用なのでご了承いただければ幸いです。
よろしくお願いいたします。

＾～＾
Windowsで『暗号化オラクルの修復…』の認証エラーでリモートデスクトップできない時

# 現象

Windows10からWindows Serverへリモートデスクトップを試すがエラー。

エラー文言は下記。
> 認証エラーが発生しました。
> 要求された関数はサポートされていません。
> リモートコンピューター:※※※
> 原因はCredSSP 暗号化オラクルの修復の可能性があります。
> 詳細については、https\://go.micorosoft.com/fwlink/?linkid=866660 を参照してください

# 原因

サーバー（リモートデスクトップされる側）のWindowsUpdateが古い為。

# 暫定的な対応

:::note warn
セキュリティレベルを下げて、 **とりあえずリモートデスクトップできるようにする** やり方です。
根本の解決ではないです。
:::

**リモートデスクトップする側** で行う設定です。

ファイル名を指定して実行で ```gpedit.msc``` 。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6f5cac54-83bf-6162-4f53-46ad7a49d584.png)

コンピューターの構成 ⇒ 管理用テンプレート ⇒ システム 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9a94c07d-cdee-98cd-a3f3-490d95649265.png)

資格情報の委任 ⇒ 暗号化オラクルの修復 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/fce3529a-7a39-6098-927b-571a33162d05.png)

有効 ⇒ 脆弱 ⇒ OK 。
（PCの再起動は不要）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/69e7c9dd-f746-1527-7674-ba7e99dcb743.png)

# 参考サイトさん

https://qiita.com/fmfm29/items/be213ff906b17809bf92

# バージョン

Windows 10 Pro 21H2 OSビルド 19044.2130
PCM1795も鳴らしてみた

秋月電子で特売品でPCM1795が半額の300円で出ていたので購入してみました。ちょうど変換基板も特売になっていました。

どうもTIがパーツの小売を禁止して、在庫を早く処分しなければならなかったのかもしれません。

いつものようにC基板で組み立てます。

820Ωの金属皮膜抵抗が無かったので、秋葉原のお店で探したところ820Ωは1/2Wしかなく1/2Wは秋葉原の在庫が無く通販か取り寄せになるということでした。

仕方ないので千石電商で1/4Wを10本150円で購入しました。

他は手持ち部品で作りました。

Opアンプの正負電源は±5Vを使っていて、PCM1795のアナログ側の電源(+5V)もこれからとります。

![写真（2022-10-17 13.41）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/aa3edb11-3750-7a2a-99f0-1fde5cc63156.jpeg)

Vcomの47uFx2はオーディオ用のコンデンサーにしたいのですが、手持ちにいいものがなかったので、とりあえずつけていて、いずれ変えます。

左右独立にこだわったわけではなく、LT1364が2個しか手持ちがなく、以前買って使っていなかったLT1363があったのでそれを使いました。

プラス側の電流を計ってみたら49.5mAありました。

シングルからデュアルへの変換基板は、おそらくかなり前に買った千石電商の500円ジャンク袋に大量に入って物です。

PCM1795はI2CかSPIで設定できるのですがデフォルトI2Sなので、そのままでpic32mx_usb_i2sやPCM2706で鳴りました。

LUXMANのD-03X(25万円くらい)はデュアルでPCM1795を使っているようです。

秋月電子のPCM1795の特売はあっという間に終ってしまい定価500円になっていました。そしてほどなく販売終了になりました。

円安なので500円でもDigikeyなどに比べると格安なのですが。

PCM1795は2009年くらいの発表されたもので、10年以上たったいまだに高級CDプレーヤーなどに使われているのは、もはやDACの進歩は止まったのかもしれません。

当初OPアンプを上の写真のようにLTのものを使っていたのですが、安いJRCのものの方がいい感じに鳴っています。
EC2インスタンスのバックアップ(イメージを作成)して、いつでも前の状態に戻れるようにする方法

# 前提
EC2インスタンスの環境を色々いじっている時に、前の状態に戻したいと思うことありますよね。
また、「これってやって大丈夫かな？」と実施を不安に感じることも多いと思います。
そんな時に、今の状態をどこかにそっくりバックアップとれたらいいのにな、と思ったあなた。
その機能、ちゃんとありますよ。ということで紹介です。


# EC2 インスタンス一覧を開く
EC2を開いたら、左サイドメニューの「インスタンス」から、インスタンス一覧を開いてバックアップを取りたいインスタンスのチェックボックスをオンにする。
![スクリーンショット 2022-10-16 13.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/7bd67953-8cac-e65e-50ed-5fcbc0bf0ce1.png)


# インスタンスを停止する
「インスタンスの状態」ボタンから、インスタンスを停止させておく。
![スクリーンショット 2022-10-16 13.33.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/829b9e24-721e-ed4d-494d-8d977951a9ea.png)


# イメージ(バックアップのこと)を作成する
アクションボタンから、イメージを作成を選択する。
![スクリーンショット 2022-10-16 13.45.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/3774f166-d0cb-bf72-0aea-d129d1b56f4e.png)

新しい画面が開くので、そこにイメージ名を入力して「イメージを作成」ボタンを押す。
イメージの説明を備忘録として状況のメモを入れておくと後でわかりやすい。
![スクリーンショット 2022-10-16 13.48.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/be827b3f-1b9b-e91e-491c-f6973e02d7cb.png)

# 作成したイメージはAMIに作成されている
![スクリーンショット 2022-10-17 13.40.23 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/3a89bd5e-ad53-a161-a8a7-b956f57ec6ea.png)

# イメージからインスタンスを復元する
使いたいイメージのチェックボックスをONにして、「AMIからインスタンスを起動」ボタンを押す。
![スクリーンショット 2022-10-17 13.44.02 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/c6f23bbc-cf73-b91e-1cac-00c33ea8323a.png)