OmniAICreator/Qiita-1.07M huggingface dataset:
PHP の BC Math 関数のわかりにくい間違え方

# これは何？

https://qiita.com/takogaki/items/5cb37b157b2a612ffa93

を拝見し、へー PHP には `bcadd` `bcmul` とかいう関数があるんだへーと思い。
動作確認したら想像と違っていたのでその記録。

# BC Math の特徴

[bcadd の公式ドキュメントらしきもの](https://www.php.net/manual/ja/function.bcadd.php) を見ると分かる通り、 `bcadd` などの引数は文字列になっている。return value も文字列。
そうでないと困る。

# 気になったこと

## 引数は文字列にする必要がある

公式でない文書にはよく

```php:PHP
<?php
echo bcadd(2.34, 4.56, 3);
```

のように、 `bcadd` に浮動小数点数を渡してる例があるが、これは `bcadd` を作った人の意に反する。
どれぐらい意に反するかというと、

```php:PHP
<?php
echo bcadd(0.1, 0.0001, 6)."\n"; #=> 0.100100 が出る。
echo bcadd(0.1, 0.00001, 6)."\n"; #=> エラー
echo bcadd(1, 10000000000000.0, 0)."\n"; #=> 10000000000001 が出る。
echo bcadd(1, 100000000000000.0, 0)."\n"; #=> エラー
```

これぐらい。
PHPer の人なら分かる通り（なお、私は PHPer ではない）、これは

1. `0.00001` を `bcadd` に渡そうとする
1. `bcadd` は文字列を要求しているので `0.00001` を文字列に変換する
1. `0.00001` は、文字列にすると `"1.0E-5"` になる
1. `bcadd` は「 `E` が入っている文字列は食べられません」ということでエラー。

ということ。浮動小数点数を渡されることは全く考慮されていないことがわかる。

あるいは。

```php:PHP
<?php
$a = 6.99999999999999;
$b = 7.0;
echo "op - : b-a=".($b-$a)."\n"; #=> op - : b-a=9.7699626167014E-15
echo "bcsub: b-a=".bcsub($b, $a, 20)."\n"; #=> bcsub: b-a=0.00000000000000000000
```

このように、 `bcsub` の方が精度が低いように見えてしまうケースもある。
`bcsub` を正しく使う（引数を文字列にする）と

```php:PHP
<?php
$a = "6.99999999999999";
$b = "7.0";
echo "op - : b-a=".($b-$a)."\n"; #=> op - : b-a=9.7699626167014E-15
echo "bcsub: b-a=".bcsub($b, $a, 20)."\n"; #=> bcsub: b-a=0.00000000000001000000
```

のように、誤差のない結果が得られる。

## floor, ceil は、無い

私が見逃しているのかもしれないけど、BC Math シリーズには四則・非数・平方根・比較 ぐらいで切り上げ切り捨てのような関数はない。

素朴に `floor` などに突っ込むと暗黙のうちに浮動小数点数への型変換が発生し、下記のように計算誤差が出ることがある。

```php:PHP
<?php
$a = "101010101010101010";
$b = "30303030303030303";
$c = bcadd($a,$b,0);
echo bcmod($c, 1000000, 0)."\n"; #=> 131313 (正しい)
echo (floor($c) % 1000000)."\n"; #=> 131312 (誤差が出ている)
```

じゃあどうやって切り上げ切り捨てをすればいいんだという話になるわけだけど。

A. 文字列処理で自力実装
B. BC Math 関数を組み合わせて自力実装

の二通りしか無いと思う。

# 感想

難儀だね。

とはいえ。この手の記事を書く以外の目的で PHP を触る可能性はほとんどないのでひとごとだけれども。
Azureの可用性ゾーンのゾーン番号はサブスクリプション毎に異なる


背景
--------

前に書いた記事より。

https://qiita.com/fukasawah/items/486563aa66a1bfe8a278

> どのゾーンを指し示すのかはサブスクリプション毎に違います。AWSのゾーンIDみたいですね。
> ソースは・・・どこかで見た気がするんですが、見つかりませんでした・・・

~~ソースが見つからなかったので試しました。~~

これやらないと、ゾーン1ばかり使われて分散しないみたいな事象になってしまうので、何かしらやっているはず。だけど確証がなかった。


2022/06/06 追記: 書いてありました。[2021年12月頃に追記されていました](https://github.com/MicrosoftDocs/azure-docs/commit/580748c38190f17d2218d7e9691bc107f9625cb5#diff-b83237cb02d7097ceaea051147272ad69be2553e85417fc21c55caedd8a37ee0R33)。

https://docs.microsoft.com/en-us/azure/availability-zones/az-overview#availability-zones

> Each data center is assigned to a physical zone. Physical zones are mapped to logical zones in your Azure subscription. Azure subscriptions are automatically assigned this mapping at the time a subscription is created.


検証
----------

### 検証方法

同じゾーンなら物理距離的にpingの応答が早いはずです。

そこで、2つのサブスクリプションA, Bで1,2,3ゾーンのVM計6台を立て、それぞれ(6x6=36ケース)でpingを50回行い、その最小値を取りました。

東日本で試しました。

### 手順

以下のリポジトリにまとめました。

https://github.com/fukasawah/sandbox-az-zone-vm-survey

### 結果

VMのサイズを変えたので2回分あります。1回目(B1s), 2回目(D2sv4)の結果を見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52527/9d519c21-b2a7-8d9a-c244-29fa775c7f98.png)

赤背景が強いほど遅いものです。赤字は別サブスクリプション中で最も早い値です。

一応、結果のログを置いておきます

https://github.com/fukasawah/sandbox-az-zone-vm-survey/tree/main/logs


### 考察

この結果から、おそらく以下のように対応していると考えられそうです。

- A-zone1 == B-zone1
- A-Zone2 == B-Zone3
- A-zone3 == B-Zone2

また、数値だけ見るとA-zone3、B-Zone2に関しては、自身に対しても1msオーバーするという調子が悪そうな傾向は一致しています。

つまり、**ゾーン番号は必ずしも実体のゾーンと一致しない** というのは言えそうです。

リソースグループが絡む可能性はありますが、リソースグループ間の通信をゾーンを合わせて連携させるというケースは十分あり、リソースグループで分けてしまうと予期しない性能劣化をすることとなってしまいます。なのでリソースグループは絡んでいないと考えています。

試した回数が少ないので正確なことは言えませんが、おそらくはサブスクリプション毎に異なると思います。


蛇足
------------

### ゾーン間のレイテンシ

東日本内の別ゾーン間は3ms弱といえそうです。


### サブスクリプション移動はできなさそう

サブスクリプションで変わるならサブスクリプション移動したら、例えばA-zone2からB-zone3となってわかりやすいのでは？と思い、リソースグループ内のリソース（VM,NIC,OS-Disk,NSG,VNET）を移動しようとしたら、PublicIP等が引っかかって出来ませんでした。

Public IPもゾーン指定しているので、そういったリソースがある場合は無理なのかもしれない。


まとめ
-------

分かりやすい場所に明記してください・・・
numpy形式の２つの画像をマージする方法のメモ


人生生きていると画像をマージしたいタイミングに出逢うこともあるかと思います。

そういった時はこちらでマージできます。

基本的なnumpyの操作ですが備忘録として残しておきます。

```merge_image.py
def merge_image(original: np.ndarray, mask: np.ndarray, thresh: int = 0) -> np.ndarray:
    """画像にマスクをマージする。

    Args:
        original (np.ndarray): cv2.imread()で読み込んだRGB(3channel)画像
        mask (np.ndarray): cv2.imread()で読み込んだグレースケール(1channel)画像
        thresh (int): マスクのしきい値。

    Returns:
        np.ndarray: マージされたRGB(3channel)画像
    """

    ## マスクする部分を初期化
    mask_condition = mask > thresh
    for i in range(3):
        original[mask_condition, i] = 0

    ## マスクを加える（必要に応じて色を変更してください。）
    original[:, :, 0] += mask
    original[:, :, 1] += mask
    # original[:, :, 2] += mask
    return original
```
VBAでスイッチ文を記述する

# VBAでスイッチ文

VBAにはswicthはない。
その代替にSelect Case ～ Case ～ Case Else ～ End Selectを使用する。
VBAのCaseはラベルではなく次のCase文が来るまでのブロックを実行する。
よってCase文が連続した場合には空文が指定されたとみなされ何も実行されない。
なおBasicの特徴としてCase文の後にコロンをつけて実行文を記述することもできる。

        Case "foo"  ⇒なにも実行されない
        Case "bar"  ⇒なにも実行されない
        Case "baz"  ⇒ b = 30 が実行される
            b = 30

~~~Visual Basic
Sub select_case()
    a = "foo"
    b = ""
    Select Case a
        Case "foo"
        Case "bar"
        Case "baz"
            b = 30
        Case Else
            b = 40
    End Select
    Debug.Print b
End Sub
~~~
Github リポジトリにデプロイ用ssh公開鍵情報を登録する

# 概要

- 任意のGithubリモートリポジトリにデプロイ用ssh公開鍵の情報を登録する方法をまとめる。

# 方法

1. Githubの任意のリモートリポジトリを開く。
1. 「Settings」をクリックする。

    ![miriwo0104_laravel8_easy_crud.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/01de153c-4c4a-ccad-fe99-64269e088914.png)

1. 「Deploy keys」をクリックする。

    ![General.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/58490fa4-0962-8c66-0692-553e1b73743e.png)

1. 「Add deploy key」をクリックする。

    ![Deploy_keys.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/7e518d70-bbcc-11cf-7be3-1e889f521071.png)

1. 「Title」に登録するsshキーの名前（任意）を入力する。「Key」にssh公開鍵をコピーして貼り付ける。「Allow write access」はチェックを入れない事をおすすめする。（「Allow write access」はチェックを入れるとデプロイ先からのpushができてしまう。予期せぬ事故を防ぐためにこのチェックは外しておいたほうが無難な気がする。）すべての入力が終わったら「Add key」をクリックすると登録する事ができる。

    ![Add_deploy_key.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/bf2f9d82-6351-c19c-aa05-e8389043b4fe.png)
複数話者文字起こしの練習

# 1. はじめに
Amazon Transcribeでは、(2022年3月現在、最大10人までの)複数話者に対応して文字起こしができる。試しに、使ってみた。

# 2. 使い方
## 2.1. 音声ファイルを用意する。
mp4a等(FLAC, MP3, MP4, Ogg, WebM, AMR, そして WAV)のファイルを用意する。なお、AACの場合、どこかでAWSが受け付けるフォーマットに変換する必要がある。

- [「2022年最新」AACをMP3に無料変換する方法](https://www.videoconverterfactory.com/jp/tips/aac-to-mp3.html)

## 2.2. Amazon Transcribe
mp4a等のファイルをS3に登録する。(アクセス権限は最小で非公開にしておいても、Transcribeは動く。このため、オーナーと同一権限で処理が行われるのではと思われる。)
ここで、話者(Speaker)識別のフラグをオンにして音声認識を実行する必要がある。デフォルトはチャンネル別なので、フラグを変更する必要がある。そして、音声認識結果のjsonファイル(asrOutput.json)を作成する

- (AWS) [音声を文字起こしする](https://aws.amazon.com/jp/getting-started/hands-on/create-audio-transcript-transcribe/)

## 2.3. jsonからテキストに変換する。

上記のファイルだと、json書式で見ずらいのでテキストに変換する。以下のコマンドで変換する。なお、スクリプト本体は参考資料の[github](https://github.com/trhr/aws-transcribe-transcript)を参考のこと。

```
git clone https://github.com/trhr/aws-transcribe-transcript
cd aws-transcribe-transcript
python3 transcript.py asrOutput.json # output goes to asrOutput.json.txt
```
出力は、上の場合(拡張子に.txtが追加され)`asrOutput.json.txt`が出力される。出力例としては以下のような感じである。`[0:17:35]`が開始時刻からの時分秒である。`spk_0`/`spk_2`が話者に相当する。

```
[0:17:35] spk_2: ま 一つ 提案 という か 質問 さ せ て いただけれ ば と

[0:17:39] spk_0: 思い ます ありがとう ござい ます それでは
```

# A. 参考資料
## A.1. 使い方の例(ほかのWeb頁)

- [【Amazon Connect】コンタクトセンターで使える? Amazon Transcribeで会話をテキスト化！](https://www.bit-drive.ne.jp/managed-cloud/column/column_44.html)

## A.2. 公式資料や使ったスクリプト
- [Amazon Transcribe](https://aws.amazon.com/jp/transcribe/)
  - [音声を文字起こしする Amazon Transcribe を使用](https://aws.amazon.com/jp/getting-started/hands-on/create-audio-transcript-transcribe/) # 利用方法の公式説明
  - [Amazon Transcribe の料金](https://aws.amazon.com/jp/transcribe/pricing/)
  - [入力可能データ](https://docs.aws.amazon.com/transcribe/latest/dg/how-input.html) # FLAC, MP3, MP4, Ogg, WebM, AMR, そして WAVに対応する。(mp4aにも対応している)
  - [スピーカーの特定 (スピーカーダイアリゼーション)](https://docs.aws.amazon.com/ja_jp/transcribe/latest/dg/diarization.html)
  - [カスタム語彙](https://docs.aws.amazon.com/ja_jp/transcribe/latest/dg/custom-vocabulary.html) # 認識精度を上げたい場合に100程度の単語を登録できる。
- [trhr/aws-transcribe-transcript](https://github.com/trhr/aws-transcribe-transcript) # 話者名とその発言ごとに、切り分けるPythonスクリプト。もともとは、PHPで書かれていたようだが、それをPythonに書き換えたらしい。
OpenCVでレシート画像のロゴを探す（Template Matching）

# 目的
- ファミマのレシートを探したい
- OpenCVの理解
- なんか画像処理っぽいことしたい

OpenCVにTemplate Matching機能があると聞き、どんなもんだろうと思いお試ししてみました

# 環境
- Windows11 Home
- VSCode
- Python3.9
- pip
opencv-python 4.5.5.62
numpy         1.22.1

# 本編
## 参考文献
ありがとうございます。お世話になりました

https://dev.classmethod.jp/articles/search-images-in-an-image-with-opencv-python/

https://pystyle.info/opencv-template-matching/

https://www.mathpython.com/ja/opencv-image-size/



## プログラム
### 元の画像
いろいろなレシートを混ぜて取りました。
大きさの違うロゴを左上に貼り付けて、これも探せるといいな。

![20220308_171222.jpg1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245578/d8a9679e-72f6-0a17-99af-d24dfc0200ec.jpeg)

### テンプレート画像
これを探したい。

![famima.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245578/7a476021-1097-c338-84ef-6f9c93ed0c67.jpeg)


### TemplateMatching

```python
    ## 1.file load
    img = cv2.imread(DATA_DIR + filename)

    famima_template = cv2.imread('famima.jpg')
    height, width = famima_template.shape[:2]

    # 画像の検索（Template Matching）
    result = cv2.matchTemplate(img, famima_template, cv2.TM_CCORR_NORMED)

```

### scoreによる足切り

```python
    # 閾値による足きり
    threshold = 0.93
    loc = np.where( result >= threshold)
    dst=img.copy() 
    for pt in zip(*loc[::-1]):
        cv2.rectangle(dst, pt, (pt[0] + width, pt[1] + height), (0,0,255), 10)
   
    save_image(filename+"2", dst)

```
まあまあうまくいったのですが、大きさが違うと探せないのかな？

![20220308_171222.jpg2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245578/c8a3c76d-5cdd-d2a7-0f4d-177b530913f0.jpeg)



### 一番scoreが高いもの

```
    # 検索結果の信頼度と位置座標の取得
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    
    # 検索結果の左上頂点の座標を取得
    top_left = max_loc
    # 検索結果の右下頂点の座標を取得
    bottom_right = (top_left[0] + width, top_left[1] + height)

    # 検索対象画像内に、検索結果を長方形で描画
    cv2.rectangle(img, top_left, bottom_right, (255, 255, 0), 10)

```
ここのロゴを切り抜いたので正解です。

![20220308_171222.jpg3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245578/8e16f763-1428-f43d-2f08-f2d4c0f301a5.jpeg)


## まとめ

- まったく同じものを探し出すことはできる
- 大きさが違ったりすると探せない。
AWS EC2 AmazonLinux2でsshキーを発行する

# 概要

- EC2 AmazonLinux2のインスタンス内でsshキーを発行する方法をまとめる。

# 方法

1. 下記コマンドを実行してsshキーペアを作成する。

    ```terminal
    $ ssh-keygen -t rsa
    >Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa): 空欄でEnter
    >Enter passphrase (empty for no passphrase): 空欄でEnter
    >Enter same passphrase again: 空欄でEnter
    ```

1. 下記コマンドを実行して公開鍵を出力する。

    ```terminal
    $ cat /home/ec2-user/.ssh/id_rsa.pub
    ```
FirestoreのカバレッジをGitHubActionsでいい感じに表示する

# はじめに
Firebaseの定番データベースであるFirestore。お値段も手頃だし、リアルタイム同期が簡単にできるのでどんどん使いたいところですが、問題なのがセキュリティ。

サーバーサイドでRDB等に接続して使う場合は、そのハブになるプログラムの部分で権限制御していけばいいのですが、Firestoreを使う多くの場合は、クライアントから直接接続するため、Security ruleを使ったアクセス制限をしていかないとダメですよね。

ただ書くとしても、セキュリティルールも単純な場合はいいですが、少し複雑化するとちゃんとテストを書いておかないと、重大なセキュリティインシデントになりかねないものです。

むしろ、そこさえしっかりしていれば、かなり安全にFirestoreに使っていけるはずです。

そこで、専用のGitHubActionsを作りました！

https://github.com/SonicGarden/firestore-rules-report-action

# 使い方

GitHubActionsでセキュリティルールのテストを実行すでにしていたら簡単。
以下のステップを追加するだけです。

```
      - name: coverage request
        id: coverageRequest
        uses: SonicGarden/firestore-rules-report-action@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          report-url: 'http://localhost:8080/emulator/v1/projects/project-test:ruleCoverage'
```

そうすると、プルリクのtriggerで動かしていた場合、プルリクコメントのところに、以下のような感じで全部テストが通ってることを表示してくれます。

```
Firestore rules coverage report!
🎉 Security rule test is covered!
```

もし、抜けてた場合は、以下のように行数とその行のセキュリティルールが表示されるようになっています。

```
Firestore rules coverage report!
😱 Lack of test rule lines!

6       allow write: if request.auth.token.admin == true;
8         allow write: if request.auth.token.admin == true;
13       allow read, write: if request.auth.token.admin == true;
```

# 注意点

何回か自分で使ってて引っかかったことを説明しておきます。

## プルリクトリガーで動かして！

プルリクコメントに結果を出力します。
なので、commitのトリガーとかで作ってると何も起きてないように見えます。

## emulatorとの接続、切断はテストで１回だけにして！

まず、これは、Firebase emulatorのテストレポートの仕組みを使っています。
https://firebase.google.com/docs/rules/emulator-reports?hl=ja

これが、テストのclearup直後のものしか保持されないようで、テストで毎回Firestoreの接続をクリアするような形になっていると、最後のテストの分しか判断してくれないので正常なカバレッジレポートを出力できません。

## NGケースがあるかは検知できない

もう一つ、あくまでこれはカバレッジを見ているだけです。
なので、セキュリティルール上、NGになるケースは対象外になります。当たり前ですけどね。

ただ、セキュリティルールのテストという観点では、むしろNGになるケースの方が重要なことが多いです。
が、そのテストが書けているかどうかは判断できないということです。

# まとめ

弊社SonicgardenのFirebaseを使ったプロジェクトではなるべく使うようにしていて、セキュリティルールのチェックにかなり役立っております。
プルリクに全部示されるので、いつかはやらなきゃ！が視覚化されるもの良いみたいです。。

間違っていたら、とんでもないことが起きかねないセキュリティルールだからこそ、手間でも少しでも状況を把握して悪いことはないはずです。

ぜひ、このGitHubActionsで、安心安全なFirestoreライフを送ってください！
Rubyのバージョンを変更した際のLoadError解決法

## 実現したいこと

Rubyのバージョンを変更した際に発生する、LoadErrorを解決したい✅
```terminal:エラー文（抜粋）
`require': incompatible library version
```

## 解決法
結論から言うと、
```vender/bundle/ruby/バージョン番号```以下のフォルダを全削除して、```bundle install```すれば解決します！！！

<br>


## エラー発生→解決まで
<font color="LimeGreen">その1</font>　rubyのバージョンを変更
```terminal:terminal
rbenv global バージョン番号
又は、
rbenv local バージョン番号
```
<br>

<font color="LimeGreen">その2</font>　GemfileのRubyバージョンの書き換え＆```bundle install```
```ruby:Gemfile
ruby 'バージョン番号'
```

<br>

<font color="DeepPink">エラー発生</font>：```rails s```すると```LoadError```が発生してしまう🤯

<br>

<font color="LimeGreen">その３</font>　ググって[こちらの記事](https://hotoolong.hatenablog.com/entry/2020/04/12/212255)を発見！
```vender/bundle/ruby/バージョン番号```以下のフォルダを全削除して、```bundle install```

<br>

<font color="DeepPink">解決</font>：```rails s```ができるように🎉

<br>


## 最後に
Rubyバージョン変更時のLoadError解決法の記事がなかったので執筆しました！
この記事が多くの悩める方に届けば幸いです🌱
PowerAutomate: キーワード応答 Trigger を使って簡易チャットボット？

# 背景
[キーワードが言及されているとき](https://docs.microsoft.com/ja-jp/connectors/teams/#%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%81%8C%E8%A8%80%E5%8F%8A%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%A8%E3%81%8D) が追加されていた。

名称からして Webhook Trigger なんだけど、何かに使えそうってことで試してみた

# トリガーの既知の問題と制限
キーワードについての制限も追記されてます。

https://learn.microsoft.com/ja-jp/connectors/teams/#known-issues-and-limitations-with-triggers

# 簡易チャットボットの試作
![KeywordWebhook.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6cfe0f22-786b-315f-7340-fa55bd796b82.gif)

キーワードに反応して、応答させたら、そのメッセージにも反応？
ってことで、本番では以下が必要かも

- bot 投稿にして、bot への Reply は除外必要
- キーワード複数はカンマ区切りだが、何に Hit したのかは不明なので、Trigger 後に確認が必要
    - これ面倒過ぎる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e5451e04-566c-10a5-be95-af0a956921f3.png)

# 実利用例と結果
カンマ区切りでキーワード羅列だが・・

## 特殊文字列が入っているとエラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/009e297f-9f20-0c69-0f05-489e92ba3c58.png)

例）
> &|^%...

%20 みたいにしてもダメ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/4c4b989d-17d0-431e-e340-ec23343d1121.png)


## カンマ間に複数キーワード入れてもエラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/62b796f9-8f73-7a98-2ff4-375cf17f2709.png)

## AND, OR などの予約語もありそう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/4c763269-fa76-656d-18e5-de69ade84543.png)

## quote もダメだと、Escape はなんだろう？
- Single quote
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0233059d-3aca-b805-8435-022db3718e28.png)
- Double Quote
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e4feb1da-42c6-c090-1842-c376c4439682.png)

## そのほか
- ~~日本語も反応しない~~
    - 反応する場合もある・・。んーよくわからず
- tag 関連入れると、HTML 記述に反応する可能性ある・・
    - 例）blockquote
- 新規投稿のみ
    - Teams のトリガー自体、Reply には反応しないままなので、当然かな

# あとがき
ん－、英単語のみでしか使えないとなると、もうしばらくは Update 待ちですね
AWS EC2 AmazonLinux2 Gitをインストールする

# 概要

- EC2 AmazonLinux2インスタンスにGitをインストールして`$ git`コマンドを実行できるようにする方法をまとめる。

# 方法

1. 下記コマンドを実行してyumを最新にする。

    ```terminal
    $ sudo yum update
    ```

1. 下記コマンドを実行してGitをインストールする。

    ```terminal
    $ sudo yum install git
    ```

1. 下記コマンドを実行してnot foundがでなければGitがインストールされている。

    ```terminal
    $ git
    ```
swagger mockより、frontend&backend開発環境構築


# 構成

```
ブラウザ(http://localhost:3030) → nginx(3030)→ |→ frontend(8080)
                                             |
                                             |→ backend(7070) → mysql(3306)
                                             |→ swagger mock(7070)
```

# 設定と起動

### nginx

```

http {
......
     
    server {
        listen       3030;
        server_name  localhost;
 
      proxy_buffering off;  
 
      location / {
                proxy_pass http://localhost:8080/;
        }
 
        location /api/ {
                proxy_pass http://localhost:7070/api/;
        }
......
```

### frontend(Vue.js)

```
yarn serve
```

### backend(Django)

```
pipenv run python manage.py runserver 7070
```


### swagger mock server

```python:swagger_server/__main__.py
app.run(port=7070)

```

```
python3 -m swagger_server
```
gem を作って公開してみた 〜公開編〜

# 0. はじめに

こちらは前回の [gem を作って公開してみた 〜開発編〜](https://qiita.com/Satoooon/items/36b032a1ea9539244640) の続きの記事になります。
前回までにgemがビルドの実行までできました。今回はそちらのgem を公開する方法を解説していきたいと思います。　

今回も以下のgemをベースにお話しします。

https://rubygems.org/gems/ruby_calendar

# 1. CLIで公開する

[gem を作って公開してみた 〜準備編〜](https://qiita.com/Satoooon/items/a04cc778b0e5ac11ae24#2-gem%E3%81%AE%E9%96%8B%E7%99%BA%E5%85%AC%E9%96%8B%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E3%82%82%E3%81%AE) にて用意したRubyGems.orgアカウントがあれば公開できます

## 1-0. credentialsの取得

- CLI上でgemを公開するにはRubyGems.orgのWeb APIを使用する必要があります。そのためアクセスキーを取得します。こちらを行うとリリースするたびにアカウント、パスワードの入力が省くことができます。

```shell
$ curl -u <username> https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials

Enter host password for user <username>: *******
```

## 1-1. gemリリース

```shell
$ rake release
ruby_calendar-0.0.1 built to pkg/ruby_calendar-0.0.1.gem
Tagged v0.0.1.
Pushed git commits and tags.
Pushed ruby_calendar 0.0.1 to rubygems.org
```

こちらで公開されました！！ RubyGemsのページに以下のようなページが作成されたかと思います。

https://rubygems.org/gems/ruby_calendar

gemspec　の内容に応じたページに反映されます(青字の内容がページに反映されます)

![gem_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226348/447f34ab-2909-4a6d-21c3-2e38f0cf4005.png)

## 1-2. バージョンアップ

- gemは同バージョンのリリースを実行することはできません。gemを変更した場合バージョン変更の対応をする必要があります
- 以下のようにソースコードを書き換えて `rake buikd` `rake release` のフローでバージョンアップできます

```ruby:lib/ruby_calendar/version.rb
module RubyCalendar
  VERSION = "0.0.2"
end
```

## 1-3. 各バージョンごとに際にした方が良いこと

- 各バージョンごとで対応した内容については　`CHANGELOG.md`　にまとめることをおすすめします。
バージョンアップごとに追記する形で書きまとめておくと利用者に親切です。

# 2.　最後に

３章に分けてgemの開発から公開までの流れを紹介しました。
これで皆さんもgemの開発のきっか絵になれば幸いです。
rspecのスタブで元のメソッドを呼ぶ

# はじめに
先日つまずいた箇所と解決法をメモしています。もっといい方法などもありそうですが、それを見つけた際はまた書き直したいですね。

# TL;DR
元のメソッドを呼びたいときは`and_call_original`メソッドを使う。
```ruby
allow(hoge_moc).to receive(:say).and_call_original
```

# 経緯

### 引数で特定の値を受け取った際の動作を定義する
テスト対象のファイルはこんな感じ。
```ruby:test.rb
class Test
  def test_method
    hoge = Hoge.new
    hoge.say("hello")
  end
end

class Hoge
  def say(message)
    message
  end
end
```

テストファイルはこんな感じ。
`Hoge#say`で`"hello"`という文字列を受け取った際に`"hogehoge"`という文字列を返すようスタブする。

```ruby:test_spec.rb
describe 'Test' do
  context 'test_method' do
    it 'returns hogehoge' do
      hoge_moc = instance_double(Hoge)

      allow(Hoge).to receive(:new).and_return(hoge_moc)
      allow(hoge_moc).to receive(:say).with("hello").and_return("hogehoge")

      expect(Test.new.test_method).eq "hogehgoe"
    end
  end
end
```
### 定義されていない引数を受け取ったときにエラーが発生する

先ほどのテストなら何の問題もなくテストが通る。
しかし定義されていない引数を受け取った時、このテストだとエラーをはいてしまう。
例えば先ほどのTestクラスが以下のようになったとする。
```ruby:test.rb
class Test
  def test_method
    hoge = Hoge.new
    hoge.say("undefined text")
    hoge.say("hello")
  end
end
```

すると先ほどのテストはこのようなエラーをはく。

```
Failures:

  1) Test test_method returns hogehoge
     Failure/Error: hoge.say("undefined text")
     
       #<InstanceDouble(Hoge) (anonymous)> received :say with unexpected arguments
         expected: ("hello")
              got: ("undefined text")
        Please stub a default value first if message might be received with other args as well. 
     # ./spec/test.rb:4:in `test_method'
     # ./spec/test_spec.rb:11:in `block (3 levels) in <top (required)>'
```
長々と書いてあるが、要するに
「`"hello"`を受け取るはずが`"undefined text"`ってヤツを受け取っちまったよ！他の引数も入るならデフォルト値もスタブしてくれよ！」
といった感じ。

### 定義されていない引数を受け取ったときに元のメソッドを呼ぶ
今回は定義されていない引数を受け取ったとき、元のメソッドと同じ動きをしてもらいたかったので、デフォルトで元の動きをするように定義します。

```ruby:test_spec.rb
describe 'Test' do
  context 'test_method' do
    it 'returns hogehoge' do
      hoge_moc = instance_double(Hoge)

      allow(Hoge).to receive(:new).and_return(hoge_moc)
      allow(hoge_moc).to receive(:say).and_call_original
      allow(hoge_moc).to receive(:say).with("hello").and_return("hogehoge")

      expect(Test.new.test_method).eq "hogehgoe"
    end
  end
end
```

これで`"hello"`以外の引数を受け取ったときに元のメソッドと同じ動きをしてくれます。
Webセキュリティの理解のためのリンク集

## SSL証明書

### [SSL証明書とは？仕組みや種類についてわかりやすく解説](https://www.rworks.jp/system/system-column/sys-entry/21283/)

- 公開鍵と秘密鍵を用いたブラウザ<=>サーバ間の暗号化

>1. パソコンのWebブラウザで、企業サイトにアクセス（通信先サーバーへ接続要求）
>1. 通信先サーバーからSSL証明書と公開鍵が送られてくる
>1. Webブラウザは、あらかじめ登録されている認証局の証明書を使って、SSL証明書を検証
>1. 有効なSSL証明書であった場合は、「共通鍵（セッションキー）」を生成
>1. 共通鍵は、SSL証明書に含まれる「公開鍵」で暗号化し、通信先サーバーに返送する。
>1. 返送された「共通鍵」は、通信先サーバー側で保持している「秘密鍵」で復号され、取り出される

### [HTTPS通信の暗号化方式](https://dev.classmethod.jp/articles/https-encryption/)
累計UU数を時系列グラフで表現

## 仕様ツール
Firebase
BigQuery
データポータル

## 実現したい事
アプリの起動UUをリリースからの積上推移を日次で出したい

| 日時 | ユーザー（uu)|
|:-:|:-:|
|3/1のアプリ起動ユーザー  | Aさん、Bさん|
|3/1のアプリ起動ユーザー | Aさん、Cさん、Dさん|
|3/1のアプリ起動ユーザー   | Aさん、Eさん|

というデータがある場合、

| 日時 | ユーザー（uu)|
|:-:|:-:|
|3/1 | 2uu|
|3/1 | 4uu|
|3/1 | 5uu|

のように、「該当日まで何人が個別カウントされたか」という表現。

:::note info
データポータルでのグラフイメージ
日々の積み上げ推移が分かるように。※データポータルのみの機能では現在実現不可
:::

![スクリーンショット 2022-03-08 215720.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2581398/3d23616d-ab2b-3fd9-42ea-b1c0c4b124f4.jpeg)



元々使用していたクエリだとレコード数がかなり多かった為、書き直し。
前後比較して頂けたらと。



## 修正前クエリ

```sql:qiita.sql
with mst_session_users as (
    select
        date(timestamp_micros(event_timestamp), 'Asia/Tokyo') as session_date
        ,user_pseudo_id
    from `テーブル名`
        where _TABLE_SUFFIX BETWEEN @DS_START_DATE AND @DS_END_DATE
    and event_name = "session_start"
    group by 1,2
)
, mst_base_date as (
    select
        date(timestamp_micros(event_timestamp), 'Asia/Tokyo') as base_date
        ,user_pseudo_id
    from `テーブル名`
    where _TABLE_SUFFIX BETWEEN @DS_START_DATE AND @DS_END_DATE
    and event_name = "session_start"
    group by 1,2
)
, mst_cumulative as (
    select
        a.base_date
        , b.session_date
        , b.user_pseudo_id
    from mst_base_date as a
    inner join mst_session_users as b
    on a.base_date >= b.session_date
)
select
    base_date
    , count(distinct user_pseudo_id) as users
from mst_cumulative
group by 1
order by 1
```

## 修正後クエリ

```sql:qiita.sql
with mst_session_users as (
    SELECT
        user_pseudo_id
        ,MIN(date(timestamp_micros(event_timestamp), 'Asia/Tokyo')) AS start_date -- 期間内の最初の日付
    FROM `テーブル名`
    WHERE 
        _TABLE_SUFFIX BETWEEN @DS_START_DATE AND @DS_END_DATE
        AND 
        event_name="session_start"
    GROUP BY 1

), tmp AS (
    SELECT
        start_date,
        COUNT(user_pseudo_id) AS uu_tmp
    FROM mst_session_users    
    GROUP BY 1
)

SELECT
    *,
    SUM(uu_tmp) OVER (ORDER BY start_date ROWS UNBOUNDED PRECEDING) AS users
FROM tmp
ORDER BY 1
```
## 修正部分
修正前WITH句のmst_cumulativeでの処理に相当な負荷がかかっていた
※このWITH句で行数が一気に増えることでデータポータル反映時に処理落ちしてしまっていた。
初心者がimport torchではまった件

# 機械学習プログラミング初心者がPyTorchのインポートではまった。
    pip install  torch

を実行して

    import torch

のコードを実行すると


    NameError: name '_C' is not defined

というエラーが出た。
調べてみるとCythonのインストールが必要らしい。

    pip install Cython

をターミナルで実行した後もう一度コードを実行してみると。


いけた。


【参照】
https://github.com/pytorch/pytorch/issues/1633
マーカーをバインドしてSQLインジェクション対策

PHPにてSQL INSERT文を実行するにあたりSQLインジェクション対策を行うために。
SQLクエリを作成。VALUES()の中の値はマーカー'?'とする・・・①
Prepared statementに作成したクエリを登録。・・・②
作成したマーカーにパラメータをバインドする。・・・③
```php
<?php
$player = "AJ"
$statement = $mysqli->prepare("INSERT INTO team (player) VALUES (?)");  //①、②
$statement->bind_param("s", $player); //③
?>
【勉強メモ】応用情報H29秋午後ネットワーク


# はじめに
2022年4月の応用情報勉強中です。
応用情報H29秋午後のネットワークの問題を通して学んだことや、ポイントをまとめました。
ネットワーク初心者なので自分用の勉強メモですが、他の方にも参考になればと思います。
＊問題の解き方の解説ではありません。

問題はコチラ
https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2017h29.html#29aki

# 知っておきたい前提知識
**ブロードキャスト**
同じネットワークに属する機器全てを宛先としてデータを送る。
ブロードキャストをする場合、宛先MACアドレスに"FFFF.FFFF.FFFF"を指定する。

**ARP**
既知のIPアドレスに対応するMACアドレスを知るための通信プロトコル
このIPアドレスの機器は応答してくださいという命令をブロードキャスト
するイメージ(対応するIPアドレスの機器のみから応答がある)

**L2SW(レイヤ2スイッチ)**
MACアドレスを用いてデータの中継を行うスイッチ
基本的なL2SWではMACアドレスとポートの対応テーブルに基づき、データを中継する。
一般的なL2SWは、通信の度にMACアドレスとポートの関係を逐一登録していく。
今回のSDNの場合は、L2SWはSDNで定義した制御パターンで通信制御を行う。


# 問題のポイント
この問題はSDN(Software-Design-Network)を題材にした問題です。
今回のネットワークではSDNコントローラで定義されたL2SW通信制御テーブル
で通信を制御しネットワークを構築します。
　L2SW#1のテーブルはコチラです
![テーブル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046176/ba910f3a-99c0-164a-b242-34559b214903.gif)
今回の問題のポイントは、このテーブルの意味を理解することだけです。
テーブルのルールは簡単。
①パケットの送信元、宛先MACに対応するパターンを探す
②該当したパターンのアクションへパケットを中継する
(これだけわかれば、この問題の9割は解けます)

前提知識がいるのは設問3(2)
こちらは、テーブルの項番9-13の宛先anyが全てのMACアドレスを示すと記載されているので、
ブロードキャスト用パケットの中継パターンだと想像できます。
(現実的には宛先MACが"FFFF.FFFF.FFFF"の場合はこのパターンにマッチすると思われる)
そして、知っておきたい前提知識の
ブロードキャストとARPについて理解していればコチラもおのずと答えにたどり着きます。


# 少し深堀
一般的なネットワークの場合、宛先MACがブロードキャストであった場合、
L2SWは全てのポートへデータを中継するフラッディングを行います。
しかし、今回はSDNでL2SWは制御されており、ブロードキャストでも特定のポートへ
中継するように制御されています。(なので、ブロードキャストしても違う顧客のサーバー
にデータが届くことはありません)
残りのL2SWに対しても適切にテーブルを定義すれば、MACアドレス(OSI参照モデル第2層)のみで
ある意味独立したネットワークが構築できます。
なので、顧客Yの仮想サーバに例えば192.168.0.1を付与し、顧客Zの仮想サーバにも
192.168.0.1を付与しても問題なく通信ができます。
これが、問題文の"顧客Yと顧客ZのサーバのIPアドレスが一緒であっても、
それぞれの顧客の通信を区別することができる"の意味です。

# 最後に
これまで、SDNという言葉は基本情報の午前問題などで見かけて、ソフトウェアでなんか
ネットワーク管理してるんだなくらいのイメージしか持てていませんでいたが、
ほんのちょっぴり理解が深まった気がします。
【Mac】選択領域の文字数をカウントする

# 要約
MacやiPhoneに標準搭載されている純正のメモアプリは文字数カウント機能がないため、大変不便を感じていた。そこで、ショートカット機能を用いて選択領域の文字数を即座に出力できるアクションを作成した。


# 純正メモアプリ
Appleは標準アプリとして**メモアプリ**をMacやiPhoneにプリインストールしている。
iCloudを利用したデバイス間でのデータ共有やカメラスキャンによる書類の管理ができる。
そのため、料理のレシピやクレジットカードの情報の保存など、私は大変重宝している。


# 就活でもお世話になってます
執筆時は2023年3月、私は就職活動を始めた。
エントリーをしてはエントリーシートの質問事項をコピーしてメモ帳に貼る、期限までに埋めて提出する。。。これをひたすら繰り返す。

こういったエントリーシートの情報や説明会で聞いたことは、全てApple純正のメモアプリに保存している。

理由として、
1. フォルダでの管理に対応
2. デバイス間での共有が可能
3. 写真やPDFを保存可能

が挙げられる。


# 文字数が数えられない
エントリーシートの各項目には文字数制限が設けられている。そのため、逐次字数を確認しなければならない。
Microsoft OfficeのWordなどには選択領域の文字数をカウントしてくれる機能がある。
しかし不幸なことに、**Apple純正のメモアプリには文字数カウント機能がついていない。** なぜ、、、
そのため、下書き段階では別のテキストエディタアプリで編集・文字数カウントを行わなければならず大変不便を被っている。


# カウントできるよ、ショートカットアプリならね。
そんな悩みも**ショートカットアプリ**なら簡単に解決してくれる。
これまでiPhoneやiPadのみでしか使えなかったが、**MacOS Monterey以降のMacOSでも使用できるようになった。**
そこで、このアプリを使って文字数カウント機能を実装する。


# 文字数カウント機能
できるだけ手間をかけずに処理を行いたいので、
1. カウントしたい範囲を選択
2. キーを叩く
3. 画面上で表示

の実質２ステップで表示させることを目指した。


# 1. ショートカットのアクションの作成
こんな感じで作る。

<img width="500" alt="Screenshot at Oct 27 18-00-47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330454/9403ce41-255d-0ae2-8adb-abe0867e276e.png">

### 1段目
"入力を受け取る"でクイックアクション、テキストの入力を受け取る、と設定する。自分はiPhoneでも使用したかったので、共有シートからも受け取るように設定している。

### 2段目
入力を受けて"計算"で文字数を数える。

### 3段目
テキストに”文字数: [2段目の出力]文字"と書き込む。これが実際にポップアップで表示される文字になる。

### 4段目
アラートでテキストをポップアップで表示させる。


# 2. ショートカットキーの設定
次にショートカットキーの設定を行う。
設定 > キーボード > ショートカット > サービス からショートカットの中にある先ほど作ったショートカットにチェックを入れ、割り当てるキーを入力する。
私は適当にF5を割り当てた。
<img width="500" alt="Screenshot at Oct 27 18-00-47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330454/2d279642-8d03-5dae-84cc-eaeca0b97100.png">

これで準備完了。


# 実際の挙動

こんな感じで動く。

<img width="500" alt="Screenshot at Oct 27 18-00-47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330454/38c95057-8ec4-6f99-c5f8-67ea789121b0.gif">


# ショートカットの配布

以下に共有用のリンクを貼っておきます。
ダウンロードにはiPhoneの設定 > ショートカット > 信頼されていないショートカットを許可をオンにする必要があるので各自設定の変更が必要です。

https://www.icloud.com/shortcuts/3a21a916241b41888f690c72f75555c5
componentでapplication_helperを読み込みたい

### 状況

Rails6.1から導入された、viewcomponentを使用していたところhoge_component.rbで
application_helperを読み込めず困っていました...💦

### 実行環境

ruby 3.0.1p64
Rails 6.1.4.6




### 解決方法
Componentの最初にinclude ApplicationHelperを記述する


```ruby
class HogeComponent < ViewComponent::Base
  include ApplicationHelper
  ...
end

```

### 学び
gemや今回のようなapplicationhelperが使用出来ないときは、Helperが読み込めないことがほとんどでした(これで何十時間溶かしてきたことか...😭)
そういう時は一度include　~~Helperとして見ると解決することが多いです!!
エラーが出ると脳死で延々とググってしまう癖があるので、なぜそのエラーが発生しているのかをできるだけ細分化してワンステップごとに解決できるようにしていきます。
焦らない、焦らない...keep calm.....
AWS PrivateLink

# AWS PrivateLinkとは
- [AWS PrivateLink は、トラフィックをパブリックインターネットに公開することなく、VPC、AWS のサービス、およびオンプレミスネットワーク間のプライベート接続を提供します。](https://aws.amazon.com/jp/privatelink/?privatelink-blogs.sort-by=item.additionalFields.createdDate&privatelink-blogs.sort-order=desc)
    - AWS PrivateLink を使用すると、さまざまなアカウントや VPC 間でサービスを簡単に接続して、ネットワークアーキテクチャを大幅に簡素化できます。
    - AWS PrivateLinkは、概念的な言葉で、AWS Consoleに直接的に見たり操作したりできないです。
- [ドキュメント](https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/endpoint-services-overview.html)
- [AWS PrivateLink の料金](https://aws.amazon.com/jp/privatelink/pricing/)
- [AWS PrivateLink と統合できる AWS のサービス](https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/integrated-services-vpce-list.html)



# Private LinkとVPC Endpoint
### インターフェイス VPC エンドポイント
- [インターフェイス VPC エンドポイント (インターフェイスエンドポイント) では、AWS PrivateLink を使用するサービスに接続できます。](https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/vpce-interface.html)

##### 設定
- Subnet
    - Private Subnetを進める
- Security Group
    - 通信をBoundできる
    - 普段はHTTPSのInBoundを許可する
- エンドポイントポリシー
- 通知

##### 構成図
![構成図](https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/images/vpc-endpoint-privatelink-diagram.png)

### Gateway Load Balancer エンドポイント
- [Gateway Load Balancer エンドポイントは、トラフィックをインターセプトし、セキュリティ検査などのために Gateway Load Balancer を使用して設定したサービスにルーティングすることを可能にします。](https://docs.aws.amazon.com/ja_jp/vpc/latest/privatelink/vpce-gateway-load-balancer.html)

### Gateway エンドポイント
- ゲートウェイエンドポイントは AWS PrivateLink を有効化しません。


# CloudformationでSSM用VPC Endpointを構築してみる

```YAML:ssm_vpce.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: 
  SSM VPC Endpoint

Resources:
  SsmVpcEndpointSG:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: vpc-xxxxxx
      GroupName: "ssm-vpce-sg"
      GroupDescription: "ssm-vpc-endpoint-sg"
  SsmVpcEndpointSGIngress1:
    Type: "AWS::EC2::SecurityGroupIngress"
    Properties:
      GroupId: !Ref SsmVpcEndpointSG
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      CidrIp: 172.16.0.0/16
  SsmVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ssm"
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: vpc-xxxxxx
      SubnetIds:
        - subnet-xxxx
      SecurityGroupIds:
        - !Ref SsmVpcEndpointSG
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal: '*'
            Action:
              - "ssm:GetParameters"
              - "ssm:GetParameter"
            Resource:
              - !Sub "arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/*"

```
40 代おっさんLambdaを使ってS3と連携

## 本記事ついて

本記事は プログラミング初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 構成図

![lambdaS3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/6488bc11-1f6d-5b4e-9a8f-c5a13d71d8d7.png)

## Lambda関数を作る

### LambdaのGUIコンソールを開く

関数の作成をクリック

一からの作成をチェックを入れて

関数名を入れて

ランタイムにpython3.7を入れる（今回はpython使用するため）

アクセス権限は
基本的なLambdaアクセス権限で新しいロールを作成にチェック

できたら関数の作成をクリックしてください。

### コードを確認

'statusCode': 200
が return するようになっていると思います。
上にprint(event)を追加

```python
import json

def lambda_handler(event, context):
    # TODO implement
    print(event)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
```

Deployを押す

Testで動かす
イベント名を入れて
作成をクリック

正常に保存されましたと上に出ていると思います。
テスト結果も問題ないものとなっていると思います。

最期に設定のアクセス権限がCloudWatchLogsのみになっていることを確認してください（あとで違いを見ます）

## s3バケットの作成

### s3のGUIコンソールを開く

バケットを作成をクリック

バケット名を入力
バケット名は被らないものにする必要があるので注意

リージョンはLambdaと同じ場所で

このバケットのブロックパブリックアクセス設定は
パブリックアクセスをすべて ブロックにチェックを入れてください。
（そのほうが安全です）

あとはそのままで
バケットを作成をクリック

出来ましたら、自分の作ったs3を確認してください

## lambdaと連携させる

自分の作ったs3をクリックしてプロパティを見て下さい
色々な情報がありますが
イベント通知でイベント通知を作成

イベント名を入れる（わかるものであれば自由で）

プレフィックス・サフィックスで発動条件を絞ることができる

イベントタイプ
今回はすべてのオブジェクト作成イベントで

送信先（ここが重要）

lambda関数にチェックがあることを確認

lambda4関数から選択するにチェックがあることを確認

lambda関数のところに先ほど作った関数を入れてください

### lambdaを確認

lambdaのGUIコンソールに行き、自分の作ったlambdaを確認すると
S3のトリガーあることが確認できると思います

アクセス権限を確認するとリソースベースのポリシーがあることが確認できると思います
こちらをクリックすると詳細な情報が見れると思います

### s3画面からアップロードをしてlambdaが動いたか確認する

s3画面に戻りアップロードをクリックしてください

そうしたら適当なファイルと追加してアップロードをしてください
成功したと思います

lambdaの実行状態を確認するため
lambdaのコンソール画面に画面遷移してください

モニタリングに行って
CloudWatchのログを表示をクリック

ログが二つあると思いますが古い方はテストイベントになります
も一つのほうを確認すると色々な情報が見れると思います。
これでs3と連携ができたことが確認できました。

## 最後に

またこの記事は AWS 初学者を導く体系的な動画学習サービス「AWS CloudTech」の課題カリキュラムで作成しました。
<https://kws-cloud-tech.com/>
Dynamics 365 Guidesの試用版を利用時に問題が発生しましたとエラーがでる（事象解消済み）

## やりたいこと

PCにDynamics 365 Guidesを入れて、試用版を試したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/cbf78319-3628-786e-4aff-f65906774637.png)


## いきなりエラー、どんな事象？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/ed6d3136-b489-85b3-8de2-3aac644df073.png)

試用版のサインアップ後に、PCにGuidesをインストールし起動すると
「Guidesが正しく設定されていない、またはアクセス許可がない可能性があります。管理者に問い合わせるか、以下のドキュメントリンクをご利用ください。」
とエラー画面がでる。

以下docsによると以下追加で設定が必要
- 試用版のアカウント取得する
- データベース追加
- 最大アップロード ファイル サイズの変更
- ソリューションのインストールと構成


## 原因
Guidesの試用版アカウント取得しても、テナント環境作成、データベース追加、ファイルサイズの変更が必要だった。

## 以下設定で解消

### 1.Guidesの概要より、サインアップし無料試用版のアカウント取得

https://dynamics.microsoft.com/ja-jp/get-started/?appname=guides

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/0b7483d1-2b37-cbd9-59b0-a07ac2067ace.png)

### 2.Power Platform 管理センターより既存のテナントにデータベース追加する。

https://admin.powerplatform.microsoft.com/environments

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/1b155080-9a96-8de2-50fa-3c85b501a5de.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/c3c25975-73b1-ccd3-c574-7ec9dc7396ef.png)


### 3.電子メール設定より最大アップロード ファイル サイズの変更をする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/9de1e2fb-db84-4563-ecf7-797dd561a237.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/c77fa632-8cc5-af22-bf70-b24b90dfc3e0.png)


添付ファイルの最大ファイル サイズ フィールドを 131072 に設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/4b2d9f2e-ad0e-b2c5-5047-16045475b51f.png)

### 4.ソリューションのインストールと構成。テナントにGuidesをインストールする。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/5fd61f3b-fce0-8613-7e42-73fec46c8230.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/f6762d4b-977c-64dc-218c-bc4a0ea8e618.png)

### 参考doc.
Common Data Service 環境を作成し、設定プロセスの一部として Dynamics 365 Guides ソリューションをインストールする 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/39445c84-3705-137c-f745-56863b445486.png)


https://docs.microsoft.com/ja-jp/dynamics365/mixed-reality/guides/setup-step-two#set-up-a-default-environment-for-trial-subscriptions-only

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/b7bb37bd-db59-b30d-5472-dff73d3b0ac4.png)


以上
MySQL8 特定のDBのフルアクセスを許可するユーザーを作成する

# 概要

- MySQLにて特定のDBのフルアクセスを許可するユーザーを作成する方法をまとめる。

# 前提

- 当該のMySQLにrootユーザーでターミナルからログインできること。
- 認証プラグインを変更したい方は下記を参考に予めデフォルト設定を変更しておく。
    - [MySQL8系 新規作成されるMySQLユーザーの認証プラグインをmysql_native_passwordに変更する](https://qiita.com/miriwo/items/a15819ee2e11e3b36d3d)

# 方法

1. 下記コマンドを実行してrootユーザーでMySQLにログインする。

    ```terminal
    $ mysql -u root -p
    ```

1. 下記SQL句を実行してユーザーを作成する。

    ```sql
    create user 追加するユーザー名@localhost identified by '追加するユーザーがログイン時に使用するパスワード';
    ```

1. 下記SQL句を実行してユーザーの権限を設定する。

    ```sql
    grant all privileges on データベース名.* to 先程追加したユーザー名@localhost;
    ```

1. 下記SQL句を実行して今与えたユーザーの権限が正しい事を確認する。

    ```sql
    show grants for 先程追加したユーザー名@localhost;
    ```
AWS EC2 AmazonLinux2インスタンスにIAMの情報を登録する

# 概要

- EC2のAmazonLinux2インスタンスにIAMの情報を登録する方法をまとめる。

# 詳細

- 今回はすでに作成されているEC2 → S3接続用IAM情報のアクセスキーとシークレットアクセスキーをEC2側に登録してみようと思う。

# 前提

- EC2に設定する用のIAMユーザーが作成されアクセスキーとシークレットアクセスキーを知っていること。

# 方法

1. EC2へssh接続する。
1. 下記コマンドを実行する。

    ```terminal
    $ aws configure
    ```

1. 下記の様に対話型でcsvファイルの情報を入力してゆく。

    ```
    AWS Access Key ID [None]: csvのAccess Key ID
    AWS Secret Access Key [None]: csvのSecret access key
    Default region name [None]: 何も入力しない
    Default output format [None]: 何も入力しない
    ```
AWS CloudWatchメトリクスの使い方

CloudWatchメトリクスは情報取得の仕方はすこしわかりにくいので、
使い方をここで紹介したいと思います。

**①CloudWatchメトリクス画面への移動**
サービス→CloudWatch→メトリクス→全てのメトリクス

**②期間の指定**
取得したい期間を選択します。
「Absolute」で指定した期間、「Relative」でいまの時間から遡った期間を指定できます。
![スクリーンショット 2022-03-08 20.25.11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/a05a7ef1-f6bb-c2f7-4b42-90c51fa77c74.jpeg)

**③取得したいメトリクスの設定**
※グラフ化したメトリクスの削除
取得したい項目にまざってしまうので、もしチェックが入っていれば外しておきます。
![スクリーンショット 2022-03-08 20.27.15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/9bd8e172-5c48-a623-1be5-d5e770a2b6bb.jpeg)

参照→取得したいメトリクスにチェックをいれます。
右の検索ボックスからインスタンスid等で検索できます。
![スクリーンショット 2022-03-08 20.28.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/4a31b3ef-7f2f-87c6-da2f-9a027a157c4d.jpeg)

チェックをいれるとグラフが表示されます。
（画面上はグラフが表示されていませんが、値が正しくとれていれば出ます。）
「グラフ化したメトリクス」内にも表示されます。
![スクリーンショット 2022-03-08 20.31.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/1fac21b8-5c0d-b3f5-fc08-aa14cc372479.jpeg)

**※CSV出力したいとき※**
アクション→.csv形式でダウンロード でダウンロードできます。
※画面ではグレーアウトされていますが、値が正しくとれていればダウンロードできます。
![スクリーンショット 2022-03-08 20.36.55.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/ea8bb98b-5114-df45-9f19-f2f3d01490fb.jpeg)

サードパーティ製の監視は設定いれて、実際に値がとれるようになるまで地味に手間だったりします。
なので、デフォルトでここまでやれちゃうAWSはやっぱり優秀だなと思いました！UIもいい感じです！
仕事が暇な時にすることリスト

# 大前提
この記事読まずに仕事して下さい。


## 整理系
- 作業机の整理
- PC/ディスプレイの清掃
- キーボードなどの周辺機器の清掃
- PC内の不要ファイル削除
- ドキュメント整理

## 雑務系
- メール確認
- スキルシート更新
- 日報/月報
- 社内アンケート
- 有給申請
- その他各種申請

## 業務効率化系
- ブラウザのブックマーク整理
- キーボード設定見直し
- マウス設定見直し
- 使用ツールのショートカット調査
- 「ツール名 おすすめ設定」でググってより良い使い心地を目指す
 - ブラウザ
 - エディタ
 - SQLクライアント
 - メール管理
 - 勤怠管理
 - PC起動時
 - ターミナル
 - などなど

## 勉強会系
- [connpass](https://connpass.com/dashboard/)等で勉強会を調べる
 - [IT勉強会を探すために捗るサイトまとめ【9選】](https://qiita.com/kobaboy/items/6c80511a10122aa87d02)
- 勉強会に参加する
- 勉強会の発表ネタを探す
- 勉強会に関する読み物
 - [IT系エンジニアのためのプレゼンテーション入門](https://www.slideshare.net/zembutsu/all-we-need-is-presentation-distribution)
 - [ライトニングトーク(LT)準備の参考資料まとめ](https://qiita.com/moomooya/items/45398e06f189d4a26227)

## 交流系
- 社内のSlack等で雑談に参加する
- 社内イベントを企画する
- 上司や同僚に手伝えるタスクがないか聞いてみる
- 前職のエンジニアに連絡をとってみる
- SNSで近況を報告する


## スキルアップ系
- 暇になる前にやっていたタスクの不明点解消
- それをQiita等でアウトプット
- 過去のコードのリファクタリング
- プルリクのレビューにいつもより時間をかける
- 次の案件の技術の勉強
- 資格の勉強・調査
- 良著の再読
 - [2019夏、先輩が若手に贈る「お世話になった技術書60選」- 入門からガチまで –](https://dev.classmethod.jp/articles/bestbook-2019-summer/)
 - [ITエンジニア本大賞2021](https://www.shoeisha.co.jp/campaign/award/2021/about/)
 - [エンジニアとして影響を受けた技術書ランキング2020年版](https://job-draft.jp/articles/434)

## 在宅勤務の効率アップ系
- ストレッチや腰痛体操する
- 気分転換する
- 机・椅子・イヤホンなど購入品調査


## 参考・引用
- [IT勉強会を探すために捗るサイトまとめ【9選】](https://qiita.com/kobaboy/items/6c80511a10122aa87d02)
- [IT系エンジニアのためのプレゼンテーション入門](https://www.slideshare.net/zembutsu/all-we-need-is-presentation-distribution)
- [ライトニングトーク(LT)準備の参考資料まとめ](https://qiita.com/moomooya/items/45398e06f189d4a26227)
- [2019夏、先輩が若手に贈る「お世話になった技術書60選」- 入門からガチまで –](https://dev.classmethod.jp/articles/bestbook-2019-summer/)
- [ITエンジニア本大賞2021](https://www.shoeisha.co.jp/campaign/award/2021/about/)
- [エンジニアとして影響を受けた技術書ランキング2020年版](https://job-draft.jp/articles/434)
kubectl Unable to connect to the server Error

# OverView
久々にKubernetes(EKS)を弄ったとき、以下のエラーが出ました。
````
Unable to connect to the server: getting credentials: exec plugin is configured to use API version client.authentication.k8s.io/v1alpha1, plugin returned version client.authentication.k8s.io/v1beta1
````
その時の対処法です。

# 追記
eksctlを繰り返すたびにconfigがv1plpha1で設定されるため調べてみました。
[Detection of the authenticator credential API version](https://github.com/weaveworks/eksctl/issues/4031)
[eksctl のインストール](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eksctl.html)

まとめるとeksctlのバージョンが古いときに発生するようです。

```
$ eksctl version
0.84.0
### アップデート後
$ eksctl version
0.86.0
```
0.86にすればOKです。


# Environment
Machine : Mac M1
OS : Big Sur 11.2
 
````shell
$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.5", GitCommit:"5c99e2ac2ff9a3c549d9ca665e7bc05a3e18f07e", GitTreeState:"clean", BuildDate:"2021-12-16T08:38:33Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"darwin/arm64"}

$ aws --version
aws-cli/2.4.5 Python/3.8.8 Darwin/20.3.0 exe/x86_64 prompt/off
````

# Action
エラー文言からkube configを見てみる
```yaml
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://hoge.gr7.ap-northeast-1.eks.amazonaws.com
  name: hoge.ap-northeast-1.eksctl.io
contexts:
- context:
    cluster: hoge.ap-northeast-1.eksctl.io
    user: hoge-eks.ap-northeast-1.eksctl.io
  name: hoge-eks.ap-northeast-1.eksctl.io
current-context: hoge-eks.ap-northeast-1.eksctl.io
kind: Config
preferences: {}
users:
- name: hoge.ap-northeast-1.eksctl.io
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - hoge
      command: aws-iam-authenticator
      env:
      - name: AWS_STS_REGIONAL_ENDPOINTS
        value: regional
      - name: AWS_DEFAULT_REGION
        value: ap-northeast-1
      - name: AWS_PROFILE
        value: hoge
      interactiveMode: IfAvailable
      provideClusterInfo: false
```

この部分です。
```yaml
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
```

変更します。
```
vi ~/.kube/config
・・・
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
・・・
```
確認します。
```
$ kubectl config view
apiVersion: v1
clusters:
- cluster:
・・・
users:
- name: hoge.ap-northeast-1.eksctl.io
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - token
```
getコマンドでやってみます。
```
$ kubectl get pod,svc
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   109m
```
出来ました。

ご参考まで。
pyenv でpythonの共有ライブラリもインストールする

Linuxにおいて、pyenvでpythonをインストールするときに、

```terminal:bash
CONFIGURE_OPTS="--enable-shared" pyenv install 3.x.x
```

みたいなオプションをつけてあげると、pythonの共有ライブラリ（`Python.h`とか`libpython3.x.so`など）もpyenvのパスの下にインストールされる。共有ライブラリはビルドが必要なパッケージを入れるときに必要かも。

## 参考文献
- https://qiita.com/methane/items/bf0b74550bee125cdea4
Androidアプリケーション技術者認定試験ベーシックに合格への道

# はじめに
去年の夏頃、Androidアプリケーション技術者認定試験を受けて合格しました。
勉強方法や参考書など、検索しても古いものが多かったので、最近の合格談として皆様の参考になればと思い記事にしました。

# 試験について
http://it.prometric-jp.com/testlist/android/


受験料:¥16,500(税込)
受験可能日:ほぼ毎日(会場によっては土日祝も○)
試験形式：70問4択 70%以上の正答で合格
出題範囲:[アプリケーション技術者試験](http://ace.it-casa.org/ace/scope/)

出題内容的にはかなり内容が古いです。
出題内容が古いままなので、参考書も新しいものが出ていません。。



# 難易度は？
Android java1年、kotlin1年経験した状態で勉強を始めましたが、知らない内容が結構ありました。(個人差あり)
参考書の理解、問題集のやり込みをしないとまず受からないと思います。
andorid javaの知識があれば、参考書もスラスラ読めるので勉強自体にはそこまで時間がかからないと思います。
出題内容は8〜9割問題集と同じような問題が出ます。
なんじゃこりゃ？という問題もちらほらありましたが、参考書を読んで参考書の問題と問題集を9割以上正答できるようになっていれば受かると思います。


筆者は1回目69点で落ちて2回目74点で合格しました。(69点で落ちた時3日間くらい凹みました笑)

# 勉強方法
* 参考書をざっと読んで、参考書にくっついている問題を何回も解く (緑本)
* 問題集を解く (黒本)
* 間違えた問題の解説を見る、解き直す、問題と答えを覚える(※選択肢のABCDではなく答えで覚えるように！)
* 参考書で覚えておかないといけない部分がなんとなく分かるので、参考書を読んで覚える

9割以上正答できるまで何度も↑を繰り返す




## 使った参考書/問題集
* [携帯OS教科書 Androidアプリケーション技術者ベーシック (緑本)](https://www.amazon.co.jp/%E6%90%BA%E5%B8%AFOS%E6%95%99%E7%A7%91%E6%9B%B8-Android%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%8A%80%E8%A1%93%E8%80%85%E3%83%99%E3%83%BC%E3%82%B7%E3%83%83%E3%82%AF-%E5%B1%B1%E6%9C%AC%E9%81%93%E5%AD%90-ebook/dp/B00G9QITA2)
 →Kindle版を購入しましたが、中古で買えば安く済みます。
* [徹底攻略 Androidアプリケーション技術者認定試験ベーシック問題集 (黒本)](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-Android%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%8A%80%E8%A1%93%E8%80%85%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93%E3%83%99%E3%83%BC%E3%82%B7%E3%83%83%E3%82%AF%E5%95%8F%E9%A1%8C%E9%9B%86-IT%E3%83%97%E3%83%AD-IT%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-ACE%E8%A9%A6%E9%A8%93%E5%AF%BE%E7%AD%96%E5%A7%94%E5%93%A1%E4%BC%9A/dp/4844330322)
 →Kindle版が無かったので、メルカリで購入しました。(初版は誤記が多いので、できれば4版を買いましょう )
　試験番号:OA0-001→新しい 試験番号:KS0-A01→古い

# おわりに
試験の内容は古めですが、Androidの基礎を学ぶという観点では勉強になりました。
Android開発をしている方、これからもAndroidをやっていく方は受験を検討してみてはいかがでしょうか。
AWS EC2 AmazonLinux2 Laravel用のPHPをインストールする

# 概要

- EC2のAmazonLinux2インスタンスにLaravel用のPHPパッケージを入れる方法をまとめる。

# 方法

1. EC2インスタンスにssh接続をして下記コマンドを実行しyumを最新の状態にする。

    ```terminal
    $ sudo yum update
    ```

1. まずは下記コマンドを実行して当該のインスタンスでamazon-linux-extrasが入っているか確認する。

    ```terminal
    $ which amazon-linux-extras
    ```

1. 下記コマンドを実行してamazon-linux-extrasでインストールすることのできるPHPのパッケージを検索する。

    ```terminal
    $ amazon-linux-extras | grep "php"
    > 42  php7.4                   available    [ =stable ]
    > 51  php8.0                   available    [ =stable ]
    ```

1. 今回はPHP8.0がほしいので下記コマンドを実行してPHP8.0のインストールに必要なコマンドを出力する。

    ```terminal
    $ sudo amazon-linux-extras enable "php8.0"
    ```

1. 下記がインストールに必要なコマンドである。

    ```terminal
    Now you can install:
     # yum clean metadata
     # yum install php-cli php-pdo php-fpm php-mysqlnd
    ```

1. 筆者は下記を実行する。

    ```terminal
    $ sudo yum clean metadata
    $ sudo yum install php-cli php-pdo php-fpm php-mysqlnd
    ```

1. 足りないパッケージを別のリポジトリを追加してインストールする。
1. 下記コマンドを実行してPHPインストール用のリポジトリを追加する。(AmazonLinux2はRHEL7/CentOS7系なのでリポジトリもそれに対応したものを入れる。)

    ```terminal
    $ sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
    $ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
    ```

1. 下記コマンドを実行して追加したリポジトリから必要パッケージをインストールする。

    ```terminal
    $ sudo yum install --enablerepo=remi,remi-php80 php php-devel php-mbstring php-gd php-xml php-mcrypt
    ```

1. 下記コマンドを実行してインストールされたPHPのバージョンを確認する。

    ```terminal
    $ php -v
    ```

1. 下記コマンドを実行してyumを用いてインストールされたPHPのパッケージを確認する事ができる。（下記は本記事の方法に従ってインストールされた筆者の環境のものである）

    ```terminal
    $ yum list installed | grep php
    php.x86_64                     8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-cli.x86_64                 8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-common.x86_64              8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-devel.x86_64               8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-fpm.x86_64                 8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-gd.x86_64                  8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-mbstring.x86_64            8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-mysqlnd.x86_64             8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-pdo.x86_64                 8.0.13-1.amzn2                 @amzn2extra-php8.0
    php-pecl-mcrypt.x86_64         1.0.4-1.el7.remi.8.0           @remi-php80       
    php-xml.x86_64                 8.0.13-1.amzn2                 @amzn2extra-php8.0
    ```