OmniAICreator/Qiita-1.07M huggingface dataset:
Vite manifest not found at: .../public/build/manifest.json

## npm run build してるのに……

この記事タイトルに対してよくある回答は、「本場環境に Laravel をデプロイしたら npm run build しなさい」だが、そんなド初心者じゃなくてもエラーになるという話。

ビルド時のログをよくみると manifest.json は出力されている。
しかし、.vite サブディレクトリの中だった。

```
public/build/.vite/manifest.json                            6.28 kB │ gzip:   1.00 kB
```

### 犯人は vite version 5

vite は version 5 から manifest.json の出力先が変更なったとのこと。
出力先をもとに戻すオプションは探したが見つからなかった。
では、Laravel が参照する manifest.json のパスを変更する？ ……こちらもよくわからない。


自分としては、新たに作成した Laravel プロジェクトで sail による Docker コンテナで vite を導入しただけである。なのに、vite の仕様変更に Laravel 側が対応してないのでまったく意味がわからない。

毎回、build したあとに手で移動して対応するのは流石に……

### package.json

毎回手で移動するという発想ができるのなら、package.json の scripts で解決できた。

```json
    "scripts": {
        "dev": "vite",
        "build": "vite build && mv public/build/.vite/manifest.json public/build/manifest.json"
    },

```
DuckDB で IAM Identity Center(旧:AWS SSO) を使って認証しつつ S3 にクエリを投げる

`~/.aws/config` はこんな感じ。

```~/.aws/config
[profile my-sso-profile]
sso_start_url  = https://<MY_AWS_ACCOUNT>.awsapps.com/start
sso_region     = <MY_AWS_SSO_REGION>
sso_account_id = <MY_AWS_SSO_ACCOUNT_ID>
sso_role_name  = <MY_AWS_SSO_ROLE_NAME>
region         = ap-northeast-1
output         = json
```

duckdb 実行前に AWS SSO の profile を指定して `aws sso login` を実行しておく。

```shell_session
$ aws sso login --profile=my-sso-profile
$ duckdb
v1.1.3 19864453f7
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
```


```sql
INSTALL aws;
LOAD aws;
INSTALL httpfs;
LOAD httpfs;

CREATE SECRET (
    TYPE S3,
    PROVIDER credential_chain,
    CHAIN 'sso',
    PROFILE 'my-sso-profile'
);

```

これで S3 の任意のバケット上のオブジェクトにクエリが投げられるようになる。
例えば、Cost and Usage Report の月次データを参照して、AWS の費用分析を出来たりする。

```
SELECT * FROM read_csv('s3://<MY_AWS_USAGE_REPORT>/report/daily/20241201-20250101/daily-00001.csv.gz') limit 3;

┌──────────────────────┬──────────────────────┬────────────────┬───┬──────────────────────┬──────────────────────┐
│ identity/LineItemId  │ identity/TimeInter…  │ bill/InvoiceId │ … │ resourceTags/user:…  │ resourceTags/user:…  │
│       varchar        │       varchar        │    varchar     │   │       varchar        │       boolean        │
├──────────────────────┼──────────────────────┼────────────────┼───┼──────────────────────┼──────────────────────┤
│ aaaaaaaaaaaaaaaaaa…  │ 2024-12-17T00:00:0…  │ JPAA11-1111    │ … │                      │                      │
│ bbbbbbbbbbbbbbbbbb…  │ 2024-12-28T00:00:0…  │ JPBB22-2222    │ … │                      │                      │
│ cccccccccccccccccc…  │ 2024-12-09T00:00:0…  │ JPCC33-3333    │ … │                      │                      │
├──────────────────────┴──────────────────────┴────────────────┴───┴──────────────────────┴──────────────────────┤
│ 3 rows                                                                                   274 columns (5 shown) │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```

274カラムもあって気が遠くなりましたがそういうもんです。歯を食いしばりましょう。

## ref
- https://duckdb.org/docs/extensions/httpfs/s3api

- https://github.com/duckdb/duckdb-aws/issues/14
Squidの構築メモ（Windows）

Squidサーバ
10.10.10.10

Squidを利用するサーバ
20.20.20.20

SquidをDL（.msi）
初期値でインストール
タスクバーに"イカ"が追加される。

タスクバーからイカを右クリックしてOpen Squid Configurationを選択
squid.confが開く

確認
http_port 3128　←squidに接続するマシンがFWに穴をあけるポート

設定を記述する
dns_nameservers 100.100.100.100  上位にProxy設定がある場合は記入。nslookupで確認する。
acl マシン名 src マシンIP　SquidProxyに接続を許可するマシンを記入
http_access allow マシン名

cache_peer 上位ProxyサーバのIP parent  利用ポート 0 no-query
icp_port 0
never_direct allow all

設定記入終わったらサービス再起動（services.msc）
上手くいかない時はサーバ再起動

SquidProxyを利用するマシンのプロキシ設定を行う

参考URL
https://gup.monster/entry/2021/01/01/102409
https://4thsight.xyz/37141
Elixirで無限ループってどうやるんだろ？

1. OverView

さて、番外編です。
ゲームのプログラミングだと、
初期化 -> ゲーム本体（無限ループ) -> ゲーム終了処理
なんて処理をするじゃないですか、あれ、どう書くべきかってお話です。

Discordで教わったので、まとめておこうとかと思いまして。

2 解説

## 2.1 まずは、オーソドックスに再帰呼び出し

はいはい、最近気に入っております、再帰呼び出しであります。
LISPとかElixirって、再帰やりやすいしね…と言うわけで行ってみましょう。
```
defmodule InfiniteLoop do
  def loop do
    IO.puts("This loop will run forever")
    loop()　<----ここに注目してください。
  end
end

InfiniteLoop.loop()

```
関数loopから自分を呼び出しております。

## 2.2 Streamを利用する

Elixirの遅延評価ライブラリ、Streamで作ります。
目的は、下記の二つの関数を使うためですね。

Stream.cycle/1: 無限に繰り返されるストリームを作成します。
Stream.unfold/2: 初期状態と次の状態を生成する関数を使用してストリームを作成します。

それぞれ、例を見てみましょう。

### 2.2.1 Stream.cycle

流れを説明しておくと、Stream.cycle(["Looping..."])でストリームを作成、その一つ一つに
このStreamを、それぞれ(Stream.each）を使用し、Stream.run()で実行すれば良いだけです。

```
Stream.cycle(["Looping..."])
|> Stream.each(&IO.puts/1)
|> Stream.run()
```

### 2.2.2 Stream.unfold

Stream.unfold/2は、初期状態と次の状態を生成する関数を受け取り、ストリームを生成するための関数です。

使い方は先ほど同じ、ここでは、無名関数を作成して、そいつを無限にくりかえしております。
ここで、この関数がnilを返せば、そこで終了します。

まずは無限ループ
```
Stream.unfold(0, fn state ->
  IO.puts("This loop will run forever with state: #{state}")
  {state, state + 1}
end)
|> Stream.run()
```

戻り値のstateが10以上になったら、nilを返す様にしてみましょうか。

```
iex(2)> Stream.unfold(0, fn state ->
...(2)>   if state < 10 do
...(2)>     IO.puts("Current state: #{state}")
...(2)>     {state, state + 1}
...(2)>   else
...(2)>     nil
...(2)>   end
...(2)> end)
#Function<64.118167795/2 in Stream.unfold/2>
iex(3)> |> Enum.to_list()
Current state: 0
Current state: 1
Current state: 2
Current state: 3
Current state: 4
Current state: 5
Current state: 6
Current state: 7
Current state: 8
Current state: 9
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```


# 3. まとめ

今の目的はゲームなので、Stream.unfoldが良いのかなと感じております。

処理の流れが「初期化 -> ゲーム本体（無限ループ) -> ゲーム終了処理」ですからね。
それでは、スカッシュゲームを書くとしますか…早く書け＞俺
SAP用語集 - 初心者向け🔰 厳選10単語！

こんにちは！😊

SAPの世界って、 **専門用語だらけ** で **難しく** 感じてしまうかもしれません。😥

そこで今回は、 **SAP初心者🔰** の方が **最初に知っておくべき重要用語** を **厳選10個** 、 **分かりやすく解説** します。

この記事を読めば、 **SAPの用語** が **少し身近** に感じられるはずです！😉


### 対象読者

* SAP初心者🔰の方
* SAPの用語を覚えたい方
* SAPの勉強でつまづいている方


### 記事の目的

* SAPの勉強を始めたばかりで、 **専門用語** が **多すぎて** 困っていませんか？
* そこで、 **私と同じようにSAP初心者🔰** の方が、 **スムーズに学習を始められるように** 、 **重要用語** を **分かりやすく** まとめてみました！


### 1. ERP (Enterprise Resource Planning) 🤔

ERPは、 **企業の資源 (ヒト・モノ・カネ) を計画的に管理するためのシステム** のことです。

会社の様々な業務 (会計、販売、人事など) を、 **1つのシステムでまとめて管理** することができます。

**例えるなら、** 会社全体を **指揮する** 指揮者👨‍ orchestral のような存在です。


### 2. モジュール 🧩

モジュールは、 **SAPシステムを構成する部品** のようなものです。

**会計** や **販売**、 **人事** など、 **業務機能** ごとに **モジュール** が分かれています。

**例えるなら、** レゴブロック🧱のようなものです。 いろいろな種類のブロックを組み合わせて、 **自分だけのシステム** を作ることができます。


### 3. SAP S/4HANA 🚀

SAP S/4HANAは、 **SAP社の最新** の **ERPソフトウェア** です。

**従来のERP** よりも **高速** 🚀で、 **使いやすく** 😊なっています。

**例えるなら、** 最新のスマートフォン📱のようなものです。 **サクサク** 動いて、 **使いやすい** インターフェースになっています。


### 4. SAP Fiori ✨

SAP Fioriは、 **SAP S/4HANA** の **ユーザーインターフェース** (UI) です。

**シンプル** ✨で **直感的** 🤔な操作性で、 **スマホ📱** や **タブレット** 💻でも **快適に** 操作できます。

**例えるなら、** スマホ📱の **ホーム画面** のようなものです。 **アイコン** をタップするだけで、 **簡単に** 必要な機能にアクセスできます。


### 5. HANAデータベース 🗄️

HANAデータベースは、 **SAP S/4HANA** で使われている **データベース** です。

**超高速** 🚀な処理速度と **大量のデータ** を **効率的に管理** できるのが特徴です。

**例えるなら、** 従来のデータベースが **自転車** 🚲だとすると、HANAデータベースは **新幹線** 🚄のように速いんです！


### 6. ABAP 💻

ABAPは、 **SAP独自のプログラミング言語** です。

SAPシステムを **カスタマイズ** したり、 **新しい機能** を追加したりするときに使用します。

**例えるなら、** SAPシステムを **改造** するための **工具** 🔧のようなものです。


### 7. BASIS 💪

BASISは、 **SAPシステム全体を支える基盤** となるものです。

**OS** や **データベース**、 **ネットワーク** などと連携して、SAPシステムが **安定して動作** するように **環境を整えたり**、 **管理** したりする役割を担っています。

**例えるなら、** SAPシステムの **土台** 🏠のようなものです。 **BASIS** がしっかりしていないと、 **SAPシステム** は **安定して動作** しません。


### 8. トランザクション 🔄

トランザクションは、 **SAPシステムで行う一連の処理** のことです。

例えば、 **商品の受注** から **出荷**、 **請求** までの一連の流れを、 **1つのトランザクション** として管理することができます。

**例えるなら、** レストラン🍴で **注文** 📝から **会計** 💰までの一連の流れのようなものです。


### 9. マスタデータ 📊

マスタデータは、 **SAPシステムで利用される基本的なデータ** のことです。

例えば、 **顧客情報** や **商品情報**、 **従業員情報** などが、マスタデータとして登録されます。

**例えるなら、** 会社の **住所録** 📇や **商品カタログ** 📖のようなものです。


### 10. 2027年問題 😥

SAPが昔作っていた **「ERP 6.0」** というソフトウェアの **サポート** が **2027年に終了** してしまう問題のことです。

**サポート** が終了してしまうと、 **セキュリティ** 🔒の **脆弱性** や **バグ** 🐛に **対応してもらえなくなる** ので、 **とても危険** です⚠️

そのため、 **2027年** までに **新しいSAP S/4HANAに移行** しないといけないのですが、 **人材不足** でなかなか進んでいないのが現状です😥。


---

**まとめ**

今回は、 **SAP** で使われる **専門用語** を **10個** 厳選して解説しました。

この記事を通して、 **SAP** の **用語** が **少し身近** に感じられるようになったでしょうか？ 😊

**SAP** の **学習** を **続ける** ことで、 **もっと** **SAP** の **世界** を **理解** できるようになると思います。

**頑張って** ください！💪


**もっと詳しく知りたい人は…**

* SAPの公式ウェブサイトを見てみよう！👀
    * [https://www.sap.com/japan/index.html](https://www.sap.com/japan/index.html)
* SAP関連書籍を読んでみよう！📖
    * 図解即戦力 SAP S/4HANAの導入と運用がこれ1冊でしっかりわかる教科書
    * 世界一わかりやすいSAPの教科書 入門編


おすすめの記事→　[SAP S/4HANAってなに？ 🤔🔰](https://qiita.com/josephmonch/items/fa359c9ef99f1d9fe600)
Vueのトースト（クリック不要のアラート）の実装


# 実装例
![スクリーンショット 2025-01-10 171933.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957418/63a46971-ac4c-fdcd-a3f1-8feade4170d1.png)


# 必要なコマンド
```
npm install @meforma/vue-toaster
npm install vue-toasted --save
npm install vue-toast-notification 
npm install vue-toast-notification@^3
```

# トーストを追加する上での注意点
[印刷プレビューについて](https://qiita.com/studyhiminato1107/items/680fd7fd3032f081be51 "印刷プレビューについて")

トーストは使用すると表示されてから、設定した時間で消失しますが
1度使用するとタグが残り続けます。
なので印刷プレビューに影響が出ることに留意してください。

# src/main.js
```
import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persistedstate';

import App from './App.vue'
import router from './router'
import './index.css'; // index.cssをインポート
import VueToast from 'vue-toast-notification';
import 'vue-toast-notification/dist/theme-sugar.css';

const app = createApp(App)
const pinia = createPinia();
pinia.use(piniaPersist); // persist プラグインを追加

app.use(pinia);
app.use(router);
app.use(VueToast);

app.mount('#app')
```

# src/views/SideBar.vue
```
<template>
  <div>
    <label>サイドバー</label>
    
    <button
      @click="showSuccessToast"
    >ぼたん</button>

  </div>
</template>

<script>
import { ref, reactive, computed, watch, onMounted, toRefs,getCurrentInstance } from 'vue';

export default {
  name: "SideBar",
  setup() {

    const { proxy } = getCurrentInstance();
    const showSuccessToast = () => {
      if (!proxy || !proxy.$toast) {
        console.error("Toast instance is undefined. Ensure VueToast is properly registered.");
        return;
      }
      proxy.$toast.open({
        message: "操作が成功しました！",
        type: "success",
        duration: 5000,
      });
    };

    return {
      //----------------------------------//
      showSuccessToast,
      //---------------------------------//

    };
  },
};
</script>

<style>

</style>

```

# 実装内容 解説
```
    const { proxy } = getCurrentInstance();
    const showSuccessToast = () => {
      if (!proxy || !proxy.$toast) {
        console.error("Toast instance is undefined. Ensure VueToast is properly registered.");
        return;
      }
      proxy.$toast.open({
        message: "操作が成功しました！",  //表示する文字
        type: "success", //トーストのタイプ（）
        duration: 5000,
        position: "bottom-right", // トーストを画面右下に表示
      });
    };
```


# [トーストの表示位置を変更]
トーストの表示位置は position オプションを使用して設定します。

利用可能な値:
"top": 画面の上部中央
"top-right": 画面の右上
"top-left": 画面の左上
"bottom": 画面の下部中央
"bottom-right": 画面の右下
"bottom-left": 画面の左下

# [トーストの色を変更]
vue-toast-notification は
type によってスタイルを変更できます。デフォルトで利用可能な type の値は以下です。

デフォルトのタイプ:
"success": 緑色（成功）
"info": 青色（情報）
"warning": オレンジ色（警告）
"error": 赤色（エラー）
Linux/Macの環境を自動で設定するシェルスクリプトを書いた

# 筆者について

```
name → Koki Teramoto
age → 18
language → ja_JP, en_US
```


# 本編

今回は自動で環境を設定するシェルスクリプトを設定していきたいと思います。ちなみに、人生初のシェルスクリプトです。

## 何を設定したいか

僕が設定したシェルスクリプトは次のものをインストールしてくれます。

- zsh, curl, wget, git, gh
- Oh-My-ZSH, zsh-autosuggestions, rustup, Alacritty, zsh-theme

## パッケージのインストールの設定

下の記事を参考にさせてもらいました。

https://qiita.com/YutoMizutani/items/bb98e27c0c52d5053ff4

ここに、パッケージマネージャーの設定にHomebrewを追加しました。というのは、ここにあるのはほぼMacにもありますので、Linuxほどバカバカ設定することはないと思いますが一応設定しておきます。

## その他必要ツールのインストール

その他必要なものは普段の操作をそのままシェルスクリプトに書いていきました。

## すでにインストールされているものがあるとき

すでに設定しているものがあるとき、あるいは、何かしらのエラーで処理に失敗した時に全てのシェルスクリプトが止まるのを防ぐために、`()`でサブシェルを設定しました。ちなみに、参考記事は下の通りです。

https://qiita.com/some-nyan/items/f8db7fc9ba2cd48c6435

## 最終的に

最終的に以下のようなスクリプトが完成しました。


```bash:config.sh
#!/bin/bash

# Install ZSH
echo "Install ZSH"
(
required=(zsh curl wget git gh)
pm=(brew apt yum port pacman brew)

for r in ${required[@]}; do
  if ! type ${r} >/dev/null 2>&1; then
    for p in ${pm[@]}; do
      if type ${p} >/dev/null 2>&1; then
        echo "Not installed ${r}, will be installed."
        yes | sudo ${p} install ${r}
        break
      fi
    done
  fi
  if ! type ${r} >/dev/null 2>&1; then
    echo "Error: Required ${r}"
    exit 1
  fi
done
)
# Install Oh-My-Zsh
echo "Install Oh-My-ZSH"
(
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
)

# Install zsh-autosuggestion
echo "Install zsh-autosuggestions"
(
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
)

# Install rustup
echo "Setup rustup"
(
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
echo 1
# Setup alacritty
echo "Setup Alacritty"
git clone https://github.com/alacritty/alacritty.git
cd alacritty
sudo tic -xe alacritty,alacritty-direct extra/alacritty.info
mkdir -p ${ZDOTDIR:-~}/.zsh_functions
)

# get zshtheme
cd ~/.oh-my-zsh/themes
wget https://raw.githubusercontent.com/0-terarin-0/prv-myconfig/refs/heads/main/mytheme.zsh-theme

# Set .zshrc
cd ~ ;mv ~/.zshrc ~/.zshrc_old
cat <<EOF >> .zshrc
# Setting of Oh-My-ZSH
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="mytheme"
plugins=(
git
zsh-autosuggestions
)
source $ZSH/oh-my-zsh.sh

# Other Settings
fpath+=${ZDOTDIR:-~}/.zsh_functions
EOF

#Reload
exec $SHELL -l
```

## 実行方法

以下のコマンドを入力するだけです。

```bash
sh -c "$(wget https://raw.githubusercontent.com/0-terarin-0/prv-bash-myconfig/refs/heads/main/config.sh -O -)"
```

# 最後に

今回は以前のアドベントカレンダーで言ってた環境の自動化設定についてやってみました。やっぱりシェルスクリプトは難しいですね。
【AWS】EC2タイプのECSが起動しなかった時の解決方法

## はじめに

最近、AWS ECS (Elastic Container Service) でEC2タイプのコンテナがなかなか起動しない事象発生。最終的に原因はEC2インスタンスのリソース不足だったのですが、そこに至るまで様々な確認を行ったので、今後のためにも、同じような問題に遭遇した方の助けになればと思い、解決までの道のりをまとめました。

## 発生した問題

ECSクラスタにコンテナインスタンスを登録しようとしたところ、いつまで経っても登録されず、タスクをデプロイできませんでした。

## 調査の開始 - まずはログから

EC2インスタンスにSSH接続し、ECSエージェントのログ (`/var/log/ecs/ecs-agent.log`) を確認しました。

```
level=error time=... msg="Error getting ECS instance credentials from default chain: NoCredentialProviders: no valid providers in chain. Deprecated."
```

このエラーから、当初はIAMロールの設定に問題があると考えました。

## 確認したこと

### 1. IAMロールの設定

* **IAMロールのアタッチ:** EC2インスタンスに正しいIAMロール (`AmazonEC2ContainerServiceforEC2Role` など) がアタッチされているか確認。
* **信頼関係の設定:** IAMロールの信頼関係で、EC2インスタンスがロールを引き受けることが許可されているか確認。
* **必要なポリシーのアタッチ:** IAMロールに `AmazonEC2ContainerServiceforEC2Role`、`AmazonSSMManagedInstanceCore` (SSMエージェント利用時) などの必要なポリシーがアタッチされているか確認。

### 2. ネットワーク設定

* **セキュリティグループ:** EC2インスタンスのセキュリティグループのアウトバウンドルールで、HTTPS (443) が許可されているか確認。特に、以下のエンドポイントへのアクセスを許可しているか確認。
    * ECS エンドポイント
    * STS エンドポイント
    * ECR エンドポイント (コンテナイメージをプルする場合)
    * S3 エンドポイント (SSMエージェントなどをダウンロードする場合)
* **NAT Gateway:** プライベートサブネットにEC2インスタンスを配置している場合、NAT Gateway が正しく設定され、ルートテーブルも適切に設定されているか確認。
* **VPCエンドポイント:** ECS関連のVPCエンドポイント (存在する場合) の設定とセキュリティグループを確認。

### 3. ECSエージェントの状態

```bash
sudo systemctl status ecs
```

でECSエージェントの状態を確認。`inactive (dead)` になっている場合は、以下のコマンドで再起動を試みる。

```bash
sudo systemctl restart ecs
```

ログ (`/var/log/ecs/ecs-agent.log`) を確認し、エラーがないか確認。

### 4. ECS設定ファイル

`/etc/ecs/ecs.config` を確認し、`ECS_CLUSTER` の設定が正しいか確認。

### 5. cloud-initのログ

`/var/log/cloud-init-output.log` を確認し、EC2インスタンス起動時の初期化処理でエラーが発生していないか確認。`user_data` スクリプトの実行結果などをチェック。

## 意外な落とし穴 - EC2インスタンスのリソース不足

上記の設定を何度も見直しましたが、問題は見つかりませんでした。ふと、EC2インスタンスのCPU使用率やメモリ使用率を確認したところ、ほぼ100%で張り付いている状態でした。

今回利用していたインスタンスタイプは `t2.small` でしたが、ECSエージェントやその他必要なプロセスを起動するにはリソースが不足していたようです。

## 解決策

EC2インスタンスのインスタンスタイプを、よりリソースの大きいもの (`t3.large` など) に変更したところ、ECSエージェントは正常に起動し、コンテナインスタンスとしてクラスタに登録されました。

## まとめと教訓

ECSコンテナインスタンスが起動しない場合、IAMロールやネットワーク設定に目が行きがちですが、EC2インスタンス自体のリソースも重要な要素であることを痛感しました。

今回の経験から、以下の点を意識することが重要だと学びました。

* **ログは詳細に確認する:** エラーメッセージだけでなく、その前後のログも確認することで、問題の切り分けにつながることがある。
* **基本的な設定の確認は怠らない:** IAMロール、ネットワーク設定、ECSエージェントの状態など、基本的な設定に誤りがないか丁寧に確認する。
* **リソース状況も考慮する:** 特に初期構築時や、インスタンスタイプを変更した際には、EC2インスタンスのリソース状況も確認する。

今回の問題解決には時間がかかってしまいましたが、得られた知識は今後の運用に必ず役立つはずです。同じような問題で困っている方の参考になれば幸いです。
Spring Framework の RestTemplate を使って Cloud Run アプリを OAuth 認証トークン付きでコールする方法

Cloud Run ではコール時に認証をかける設定をすることでセキュアなアクセスを実現できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3724339/f6a76f0b-ddb2-31d7-d705-1092f47f27d3.png)

[Google Cloud のリファレンス](https://cloud.google.com/run/docs/samples/cloudrun-service-to-service-auth?hl=ja)だと Google の http クライアントを使ったトークンの受け渡しになっているためそのままでは Spring Framework の提供している RestTemplate クラスを使ったリクエストができません。

ここでは RestTemplate クラスを使ったトークン渡しでの Run アプリへのアクセス方法を書き残します。

```
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.RequestEntity.BodyBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.IdTokenCredentials;
import com.google.auth.oauth2.IdTokenProvider;
```

```
final String CLOUD_RUN_AUDIENCE = "https://xxx.region.run.app";
final String CLOUD_RUN_URL = "https://xxx.region.run.app/rest/hoge";

// トークンを発行する
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();

if (!(credentials instanceof IdTokenProvider)) {
	throw new IllegalArgumentException("Credentials are not an instance of IdTokenProvider.");
}

IdTokenCredentials tokenCredential =
		IdTokenCredentials.newBuilder()
			.setIdTokenProvider((IdTokenProvider) credentials)
			.setTargetAudience(CLOUD_RUN_AUDIENCE)
			.build();
tokenCredential.refresh();
AccessToken token = tokenCredential.getAccessToken();
String accessToken = token.getTokenValue();

// RestTemplate のインスタンスにトークンを付与して Run のアプリをコールする
RestTemplate template = new RestTemplate();

HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.USER_AGENT,   "agent");
httpHeaders.add(HttpHeaders.CONTENT_TYPE, "text/plain");
httpHeaders.setBearerAuth(accessToken);

BodyBuilder bb = RequestEntity.method( HttpMethod.GET, CLOUD_RUN_URL);
for (Entry<String, List<String>> header : httpHeaders.entrySet()) {
	bb.header(header.getKey(), header.getValue().toArray(new String[0]));
}		

ResponseEntity<byte[]> response = template.exchange(bb.body(new byte[0]), byte[].class);
System.out.println("response : " + response.getBody());

```
PartyRockで基盤モデルAmazon Novaを使用する

PartyRockのPublic Roadmapを眺めていたら昨年のre:Inventでリリースされたばかりの基盤モデルAmazon NovaがPartyRockで利用可能になっていました。
>Access select new state-of-the-art foundation models from Amazon - Nova Micro, Nova Lite, Nova Pro for text generation and Canvas for image generation.

正確なリリース日時は不明ですが、以下4つのモデルが利用可能になっているようです。

- Amazon Nova Micro
- Amazon Nova Lite
- Amazon Nova Pro
- Amazon Nova Canvas

Amazon Novaの確認を兼ねて簡単なアプリを作成してみます。



PartyRockとは
----------
PartyRockはAWSが提供している生成AIの教育ツールです。
ノーコードでアイデアを生成AIアプリケーションとして形して、実験を通して生成AIを学ぶことが出来ます。
AWSアカウントは不要で、Google/Amazon等のアカウントがあればどなたでも無料で利用を開始できます。
コーディングの知識がなくても簡単なプロンプトで生成AIを試すことができますので、生成AI活用のアイデア出しに最適です。

Text Generation
----------
早速、Amazon Novaを動作確認してみます。
アップロードしたドキュメントを要約するアプリを作成します。
公式に対応している言語は英語ですが、日本語のプロンプトも受け付けます。

![スクリーンショット 2025-01-09 18.11.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/9182aac9-b091-81c3-3dfc-ef353f0f80c7.png)


ドキュメントアップロードとText Generationが2つの簡易的なアプリが出来ました。
アップロード可能なドキュメントの文字数は80万文字/500ページ相当まで（以前は12万文字/95ページ相当でした）
![スクリーンショット 2025-01-09 18.12.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/9dfd9064-7008-d5dc-00bf-896415771818.png)


Text Generationの基盤モデルをAmazon Novaに変更してみます。

![スクリーンショット 2025-01-09 18.12.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/2460f5bd-14ec-296a-3158-b004ad47b13e.png)

Amazon Titen Textと入れ替わりでAmazon Nova Micro / Lite / Pro の3モデルを確認できますね。
ここではAmazon Liteを選択します。


![スクリーンショット 2025-01-09 19.34.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/f3653919-7243-e5ef-b7c0-396f37090c6d.png)

問題なく要約もできています。



Image Generation
----------
画像生成も動作確認してみましょう。
プロンプトの指示通りの画像を生成するアプリを作成します。

![スクリーンショット 2025-01-09 19.51.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/840e7c69-71b6-f720-6e8c-a76e62588637.png)


Amazon Titan Imageと入れ替わりでAmazon Nova Canvasが追加されています。

![スクリーンショット 2025-01-09 19.51.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/c83be0b4-c27d-0939-0b7e-d299278220ed.png)


Amazon Novaで生成した画像です。
Seed値を固定して複数のパターンで生成してみました。

![スクリーンショット 2025-01-09 19.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/269554b9-f2d2-f48b-fc49-4c05686d7ec3.png)

![スクリーンショット 2025-01-09 20.07.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/af8cd1c9-8233-eeea-1269-f08ba88ae3e1.png)

![スクリーンショット 2025-01-10 17.00.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193020/f0a98f16-a438-fa50-52d3-df38a064581d.png)


さいごに
----------------
最新の基盤モデルAmazon NovaをParty Rock上で気軽に試すことができるようになりました。
Amazon Novaだけでなく、Bedrockで利用可能な基盤モデルも随時追加されています（直近だとMistral系が追加）
その他にも定期的なアップデートが予定されているようですので、出来ることの幅が広がりそうで楽しみです。
（教育ツールという位置づけなので、本番利用としての想定はされていない点は認識しておきましょう）
【2025年01月版】Ubuntu24.04 で systemd-journal-remote で journallog を転送する

# はじめに

いままで、rsyslogを使ってログの転送をしていたけど、journallogをそのまま転送できるらしいので試してみたメモ

# 受信側の設定

## インストール

```terminal
$ sudo apt install systemd-journal-remote
```

## 設定の編集

httpsではなく、httpで受信する(httpsの証明書とかしんどい)

```terminal
$ sudo cp /lib/systemd/system/systemd-journal-remote.service /lib/systemd/system/systemd-journal-remote.service.back
$ sudo vim /lib/systemd/system/systemd-journal-remote.service
$ diff /lib/systemd/system/systemd-journal-remote.service /lib/systemd/system/systemd-journal-remote.service.back
16c16
< ExecStart=/usr/lib/systemd/systemd-journal-remote --listen-http=-3 --output=/var/log/journal/remote/
---
> ExecStart=/usr/lib/systemd/systemd-journal-remote --listen-https=-3 --output=/var/log/journal/remote/
$ sudo systemctl daemon-reload 
```

## ログディレクトリの作成

```terminal
$ sudo mkdir -p /var/log/journal/remote
$ sudo chown systemd-journal-remote /var/log/journal/remote
```

## FWの穴を開ける

必要であれば

```terminal
$ sudo ufw allow 19532
```

## サービスの起動

```
$ sudo systemctl enable --now systemd-journal-remote.service 
```

# 送信側

## インストール

```terminal
$ sudo apt install systemd-journal-remote
```

## 設定

```terminal
$ sudo vim /etc/systemd/journal-upload.conf
```

ホストのIPを設定する

```
[Upload]
URL=http://<ホストのIP>:19532
```

## サービスの再起動

```terminal
$ sudo systemctl restart systemd-journal-upload.service 
```

# 参照方法

受信側で `journalctl` で参照する
`--directory` 指定以外は普段と変わらない

```
$ sudo journalctl --directory=/var/log/journal/remote _HOSTNAME=<対象のホスト名>
```

:::note warn
複数ホストのログを同一ディレクトリに置いた場合は、`-r` や `-f` が一つのホストのログでしか機能しないので注意
:::

# さいごに

かんたんでしたね
git log を見やすくする

## git log (デフォルト)

![ScreenShot 2025-01-10 16.35.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/2a088499-a74d-f495-04a9-c8d9853c3c5d.png)

コミットの詳細が見たい場合は git show で個別に見るから要らない。一覧性を高めたい。

(例でsvelteのリポジトリのログを出してます)

## git log --oneline (デフォルト)

![ScreenShot 2025-01-10 16.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/bb5d11ce-4c60-f729-7d90-2f5c2b108c5b.png)

情報量が少ない。日付とコミッター名は欲しい。

## git log (改善版)

![ScreenShot 2025-01-10 16.35.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/b630ab9b-94dd-9d00-c993-5a9ed4a79c5b.png)

```
コミット名 日付(相対) コミッター名 リファレンス コミットメッセージ
```

を表示するようにしています。

`~/.gitconfig` に追記します。

```~/.gitconfig
[log]
    date = relative
[format]
    pretty = format:%C(yellow)%h %C(blue)%>(12)%ad %C(green)%<(8)%aN %C(red)%d %C(reset)%s
```

日付を表示したい人は次のフォーマットにすると良いです。

```
[log]
    date = format:%Y-%m-%d %H:%M
```

コミット見たい時に秒まではいらないと思うので分まで表示にしてます。

### オプションの解説

```
[log]
    date = relative
```

通常絶対時刻が表示されますが、 `relative` にすると「2 days ago」「3 hours ago」といった人間が読みやすい相対時刻になります。

```
[format]
    pretty = format:%C(yellow)%h %C(blue)%>(12)%ad %C(green)%<(8)%an %C(red)%d %C(reset)%s
```

`pretty = format:...` はログ表示に使う書式を定義します。
横一列だと見づらいですが、全体の構造は以下のとおりです。

```
%C(yellow)%h # 黄色で短いコミットハッシュ(先頭7桁)を表示
%C(blue)%>(12)%ad # 青色で右寄せで幅12文字分を取って日付を表示([log] dateで指定したフォーマット)
%C(green)%<(8)%an # 緑色で左寄せで幅8文字分取ってコミット作成者の名前を表示
%C(red)%d # 赤色でコミットに付随するリファレンス(ブランチ名、タグ名)を表示
%C(reset)%s # 色をリセットしてデフォルトの白色でコミットメッセージの件名を表示
```

- `%C(red)%d` → `%C(auto)%d` にするとブランチ名やタグ名も色分けされますが、個人的にごちゃごちゃ感がしたので赤一色にしています
- `%Cred%d` 括弧付ける必要はないのですが、見やすいので括弧付けてます
- 相対日付を表示してますが、具体的な日時がわからないデメリットもあるので、別にエイリアス定義しても良いかもと思ってます

### グラフ表示のエイリアス

```~/.gitconfig
[alias]
    tree = log --graph --pretty=format:'%C(yellow)%h %C(blue)%ad %C(green)%cn %C(magenta)%d %C(reset)%s'
```

```
$ git tree
```

## コミットログのフォーマットについて

カスタマイズしたい人はこちらを参照ください。
https://git-scm.com/docs/pretty-formats
私のCLF-C02試験の旅 

私は最近、AWS認定クラウドプラクティショナー（CLF-C02）試験に合格しました。その成功の鍵となったのは、間違いなく使用した準備資料です。その中でも特に優れていたのがTestInsightsのCLF-C02試験問題でした。これらの問題は非常に正確かつ包括的でした。試験で出題された印象的な質問の例を以下に示します：
質問：
AWSクラウドコンピューティングはどのようにして企業のコスト削減を支援しますか？（2つ選択）
A: AWSは各AWSリージョンでサービスの料金を変更します。
B: AWSはオンデマンドで容量を調整できるようにします。
C: AWSは1週間以上アイドル状態のAmazon EC2インスタンスに割引を提供します。
D: AWSはAWSクラウドからインターネットへのデータ転送に料金を請求しません。
E: AWSはオンプレミスのデータセンターを構築・維持する多くのコストを削減します。

私はTestInsightsを使ってこの質問を事前に準備していました。驚くべきことに、試験の約80%が彼らの資料に基づいていました！
CLF-C02を準備している方には、TestInsightsを強くお勧めします。現在、プロモコードSAVE50で50%割引を提供しており、無料デモで内容を確認できます。彼らのサポートで試験に合格するチャンスを逃さないでください！

もしAmazon認定資格を目指しているなら、このリンクを役立ててください。私はプロモーション目的ではなく、皆さんの参考になる情報を共有したいだけです。
https://testinsights.com/exams/amazon/
なぜマルチクラスタが必要？Kubernetes SIG Multiclusterが解決する課題とは

最近、Kubernetesの運用が高度化するにつれ「複数のクラスタをまたいだ運用」に注目が集まっています。これは「マルチクラスタ運用（multi-cluster）」と呼ばれるもので、Kubernetesコミュニティでも SIG Multicluster として正式に取り組みが進められています。

## そもそもKubernetesクラスタを複数持つ必要があるのか？

「単一クラスタだけではダメなの？」と思う方もいるかもしれません。もちろん小規模なシステムや、地理的・組織的に集約して運用できる環境であれば、単一クラスタで問題ないケースもあります。しかし、大規模システムや地理的要件、法的制約などが絡むと、1つのクラスタだけではうまく対応できません。具体的に以下のような課題が存在します。

## 1. 地理的要因（Location）

### レイテンシの低減
エンドユーザに近い場所でアプリケーションを実行したい場合、地理的に離れた複数リージョンへ分散してデプロイする必要があります。たとえば、アメリカ・ヨーロッパ・アジアにそれぞれクラスタを置くことで、ユーザに近い場所からレスポンスを返せるようにするわけです。

### 法的要件（管轄）
国や地域によっては「個人情報を国外に出してはならない」といった規制があることも珍しくありません。データを保存・処理する場所が厳密に制限される場合、それぞれの国・地域に専用クラスタを設置せざるを得ません。

### データグラビティ
特定クラウドプロバイダやデータセンターなど、既に大容量のデータが存在する環境とアプリケーションを分離したくない場合、どちらかに寄せるか、必要に応じて複数クラスタを連携させる必要があります。

## 2. 分離（Isolation）

### 環境の分離
開発・テスト・ステージング・本番など、用途の異なる環境をそれぞれ別クラスタで管理したほうが安全かつ分かりやすい場合があります。

### パフォーマンス
大量のリソースを消費するワークロード（AI/ML、ビッグデータ解析など）を他のワークロードと切り離すことで、安定性が高まります。

### セキュリティ
機密情報を扱うワークロードや、信頼度の低いコードが混在している場合など、クラスタレベルで分離したほうが影響範囲を限定しやすくなります。

### 組織的分離
部署ごと、またはプロジェクトごとに管理責任が異なる場合、それぞれが独自のクラスタを持った方がオペレーションや責任分担が明確になります。

### コスト管理
複数チームが1つのクラスタを利用すると、請求やコスト分配が複雑になることがあります。チームごとにクラスタを分ければ、「どの部署がどれだけ支払うか」が分かりやすくなります。

## 3. 信頼性（Reliability）

### ブラスト半径の縮小
1つのクラスタで障害が起きた場合でも、他のクラスタに波及しないようにすることで、サービス全体の可用性を高めることができます。

### インフラの多様化
特定のクラウドプロバイダやリージョンで障害が起きても、他で稼働中のクラスタに切り替えられるようにしておくと、サービスダウンを回避できます。

### スケール
大規模アプリケーションが単一クラスタに収まらない場合、複数クラスタに負荷を分散し、柔軟にスケールアウトできるようにします。

### アップグレードの範囲
Kubernetesクラスタのバージョンアップやメンテナンス時に、1つの大きなクラスタだと影響範囲が大きくなります。複数クラスタに分散しておけば、段階的かつ計画的にアップグレードを行いやすくなります。

## SIG Multiclusterの役割

こうした複数クラスタを管理する上で発生する課題を解決するために、Kubernetesコミュニティ内で活動しているのが **SIG Multicluster** です。SIG（Special Interest Group）は特定の分野でKubernetesをより良くするために活動するグループであり、SIG Multiclusterでは主に以下のテーマに取り組んでいます。

### 1. 複数クラスタ間での通信やワークロード連携
- サービスディスカバリ
- ネットワークの接続・スクリプト化

### 2. クラスタメタデータの共有
- 各クラスタの状態やリージョン情報などをどう管理・共有するか

### 3. マルチクラスタを意識しない運用
- 単一クラスタと同様のユーザーエクスペリエンスで使える仕組みの検討
- マルチクラスタ環境を安全かつシンプルに運用するためのAPIやツールの整備

## 具体的にはどんなことをやっているの？

### MCS（Multi-Cluster Services） API
Kubernetes Serviceの概念を「複数クラスタ間でどう扱うか」という視点で拡張する試みです。

### Cluster Registry
複数クラスタを一元管理する仕組み。クラスタのメタデータ（例えばどのプロバイダか、どのバージョンか）をまとめる"データベース"的役割を果たします。

### マルチクラスタCI/CDパイプラインの検討やドキュメント整備
クラスタをまたいだアプリケーション配置やロールアウト、ロールバックなどをどう扱うか、といったベストプラクティスをコミュニティで議論。

## まとめ

Kubernetesを運用する環境が大規模化・複雑化するにつれ、複数のクラスタを連携させたいケースは今後ますます増えていくでしょう。そんなときに **SIG Multicluster** が作り出すAPIやツール、ベストプラクティスを活用すれば、単一クラスタで慣れ親しんだKubernetes体験を失わずに、複数クラスタを効率良く運用できるようになります。

主な課題は以下の3つです：
- 地理的要因（レイテンシ・法的要件）
- 分離（セキュリティ・コスト・組織運用）
- 信頼性（ブラスト半径・スケール・アップグレード影響）

これらの課題に悩んでいる方は、ぜひマルチクラスタ運用とSIG Multiclusterの取り組みをチェックしてみてください。Kubernetesの新たな可能性を広げる一助になるはずです。

この記事が、マルチクラスタ運用の必要性やSIG Multiclusterの活動内容への理解を深めるきっかけとなれば幸いです。それでは、また次回の記事でお会いしましょう！
[備忘メモ]プルリクの規模をclocで計る

この記事は
===

* すぐに忘れてしまうので単なる備忘メモです

やりたいこと
===

* 本番リリースをする時にdevelop => masterにプルリクを作ってマージすると思います
* だいぶ未来になってから、分析目的でそのプルリクで入った修正量を測定したいことがよく出てきます

利用ツール
===

* git
* cloc（詳細は割愛）

手順
===

マージコミットの特定
---

* 履歴を表示します

```:bash
git log --pretty=oneline --first-parent master
```

* そうするとずらっと履歴が出てくるので、/1000 等と打ってプルリク番号で検索します
* ```Merge pull request #1000 from abc/develop``` 等が引っかかって出てくるのでそのハッシュと、その直前のハッシュをメモります

clocの実行
---

* さっきのハッシュでclocを実行します

```
cloc --fullpath --exclude-dir=tests --diff マージコミットの1つ前のハッシュ マージコミットのハッシュ
```

終わりに
===

* ちゃんとバージョンタグ打ってれば大丈夫という話もあるけどね
Laravel11 Sailを開発環境でSSLに対応

Valetやパッケージの追加などの方法も紹介されていますが、なんともしっくりこないのでオレオレ証明書を利用してNginxをフロントに配置して対応した。

## 1. 必要なディレクトリとファイルの作成

```sh
mkdir -p ./docker/nginx
touch ./docker/nginx/default.conf
mkdir ./docker/ssl
```

## 2. 証明書の作成
```sh
mkcert -install
mkcert -key-file ./docker/ssl/localhost-key.pem -cert-file ./docker/ssl/localhost.pem localhost 127.0.0.1 ::1
```

漢らしくopensslで作るでもいい。

## 3. docker-compose.ymlの設定
Nginxコンテナ追加
```yml
services:
    laravel.nginx:
        image: nginx:1.25
        ports:
            - "${APP_PORT:-80}:80"
            - "${SSL_PORT:-443}:443"
        depends_on:
            - laravel.test
        volumes:
            - .:/var/www/html:ro
            - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
            - ./docker/localhost.pem:/etc/ssl/localhost.pem:ro
            - ./docker/localhost-key.pem:/etc/ssl/localhost-key.pem:ro
        networks:
            - sail
    laravel.test:
		  # ...
```

## 4. Nginx設定
```nginx
server {
    listen 80;
    server_name localhost;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name localhost;

    ssl_certificate /etc/ssl/localhost.pem;
    ssl_certificate_key /etc/ssl/localhost-key.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    root /var/www/html/public;
    index index.php;

    location / {
        proxy_pass http://laravel.test:80;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

## 5. 起動

```sh
./vendor/sail up -d
```

https://localhost にアクセスして動作を確認。

標準でSSL用意されてるとか、推奨の方法があれば教えてくれ...五飛。
Power Apps で SharePoint ドキュメントライブラリの pdf ファイルを表示する


# はじめに

SharePoint ドキュメントライブラリ内の pdf ファイルを Power Apps 上で表示したいというニーズがありますが、少し癖があるので備忘のため記事化しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/811eb5d4-fddd-3921-574c-3b3f5163f95e.png)

# アプローチ

こんな感じでドキュメントライブラリ内の pdf ファイルを Power Apps の PDF ビューアーで表示させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/61eee837-4c23-6bda-63d9-b955227c5cdc.png)

まず、左側のギャラリーで選択したアイテムのプロパティを　PDF ビューアーの`[Document]`プロパティに入れればいいと思いましたが、残念ながら上手くいきませんでした。[代わりにブラウザーで開く] をクリックするとアクセスできますが。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/e2cd5622-382f-6fca-293d-5f7890e21090.png)

最終的には、Power Automate と連携するこどで実現できました。

Power Apps トリガーのため、こちらから新規作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/c10cad44-912d-6be9-ae6c-a2033f09899b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/015d2cd4-dc3a-545c-c5cb-b55950558dda.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/0e3e1a03-a7a3-156a-9a28-6d5e065a8412.png)

Power Automate の作りはシンプルです。こんな感じでファイルの識別子を Power Apps から受け取り、そちらを基にファイルコンテンツを取得して、変換をして Power Apps に返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/64379325-db3b-6acd-9d7d-f49e8bb04bd0.png)

技術的にコアとなる [作成] アクションの式は以下の通りです。アクション名が既定のままであれば、そのまま貼り付け可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/5fe20cb0-9500-c98d-e282-4e0545bfaeba.png)

```
dataUri(base64ToBinary(body('ファイル_コンテンツの取得')?['$content']))
```

そして、作成アクションの出力を Power Apps に返します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/5d550c51-6e55-e751-6a2d-252ae56b12e2.png)

こちらの Power Automate と Power Apps をつなぎ、例えば、以下のように、ギャラリー内に追加した pdf のアイコンをクリックした際 (`[OnSelect]`プロパティ)、Power Automate のフローを渡して、結果を変数に格納します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a8393acf-5514-1cc0-c770-840590ecfae8.png)

```
Set(
    varDocumentContent,
    GetPDFContents.Run(Gallery1.Selected.識別子).result
)
```

そして、PDF ビューアーの`[Document]`プロパティに変数を入れいます。こちらで、Power Apps の PDF ビューアーで、SharePoint ドキュメントライブラリ内の pdf ファイルを閲覧できるようになりました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ea040107-99db-1128-1f49-ffea14104f5c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/55b50740-0b07-a4ed-3f02-7b54dbf2c525.png)

※Power Apps だけでも実現する方法はありそうですが、少し癖があるため、こちらの方法の方が、再現性が高いと考えています。もちろん、将来的には、例えば「ギャラリー名.Selected.プロパティ名」だけで表示できるようになるなど、もっと簡単に実現できるようになることを期待しています

なお、ギャラリー内の PDF アイコンについて、以下のようにして、ファイルの拡張子が pdf の場合だけ表示するようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a29ae81f-5d63-cef3-29d2-867fa45249f7.png)

```
If(
    EndsWith(
        ThisItem.拡張子付きのファイル名,
        "pdf"
    ),
    true,
    false
)
```
改行が消えたsqlite3を分割する

```
import re

def split_sql_statements_extended(sql):
    """
    改行や空白がないSQL文を解析し、SQLiteコマンドやコメント、SQL文を適切に分割する。
    - セミコロンで区切る。
    - コメント（--, /* */）やSQLiteの内部コマンド、主要なSQLキーワードを考慮。

    :param sql: 改行や空白がないSQL文 (str)
    :return: 分割したSQL文やコメントのリスト (list of str)
    """
    # 正規表現で各要素を分割
    pattern = re.compile(r"""
        (--.*?(?=CREATE|INSERT|SELECT|UPDATE|DELETE|DROP|BEGIN|COMMIT|ROLLBACK|\.|;|$)|  # 行コメント
        /\*.*?\*/|                                                                   # ブロックコメント
        \.[^\s;]+.*?(?=CREATE|INSERT|SELECT|UPDATE|DELETE|DROP|BEGIN|COMMIT|ROLLBACK|\.|;|$)| # SQLiteコマンド
        .*?;)                                                                        # 通常のSQL文（セミコロンで終わる）
    """, re.VERBOSE)

    # マッチした部分をリストに分割
    matches = pattern.findall(sql)

    # 不要な空白を削除し、空要素を除外
    statements = [stmt.strip() for stmt in matches if stmt.strip()]
    return statements


# 使用例
raw_sql = """
--コメント1CREATE TABLE test (id INTEGER PRIMARY KEY,name TEXT);--コメント2INSERT INTO test (id,name) VALUES (1,'Alice');SELECT * FROM test;--コメント3.tableBEGIN TRANSACTION;INSERT INTO test (id,name) VALUES (2,'Bob');COMMIT;ROLLBACK;
"""

result = split_sql_statements_extended(raw_sql)

# 出力
for idx, stmt in enumerate(result, 1):
    print(f"Statement {idx}: {stmt}")
```
OANDAのAPIを利用して４時間足のサポートレジスタンスを判断するコード

表題について書いていきます。
取り敢えず暫定的なものなので、後々更新するかも…

```python
import oandapyV20
import oandapyV20.endpoints.instruments as instruments
import pandas as pd
import datetime

# OANDAのアクセストークンとアカウントID
access_token = 'YOUR_OANDA_ACCESS_TOKEN'
account_id = 'YOUR_OANDA_ACCOUNT_ID'

# APIクライアントの初期化
client = oandapyV20.API(access_token=access_token)

# 通貨ペアと時間足の設定
instrument = "EUR_USD"
granularity = "H4"

# 過去3か月分のデータ取得
end = datetime.datetime.now()
start = end - datetime.timedelta(days=90)
params = {
    "from": start.strftime('%Y-%m-%dT%H:%M:%SZ'),
    "to": end.strftime('%Y-%m-%dT%H:%M:%SZ'),
    "granularity": granularity,
}

# APIリクエストの作成と実行
candles = instruments.InstrumentsCandles(instrument=instrument, params=params)
client.request(candles)
data = candles.response['candles']

# データフレームの作成
df = pd.DataFrame([{
    'time': candle['time'],
    'open': candle['mid']['o'],
    'high': candle['mid']['h'],
    'low': candle['mid']['l'],
    'close': candle['mid']['c'],
    'volume': candle['volume']
} for candle in data])

# 高値と安値で止まったラインを見つけるロジックの実装
df['high_swing'] = df['high'].rolling(window=10).max()
df['low_swing'] = df['low'].rolling(window=10).min()

# 結果の表示
print(df[['time', 'high', 'low', 'high_swing', 'low_swing']])
```

全体としてのコードは以上になります。
時間軸や通貨ペアを変更したいときは

```python
# 通貨ペアと時間足の設定
instrument = "EUR_USD"
granularity = "H4"
```
ここの部分を変更してください。
期間の変更はここのdays = 90の部分を変えると良いです。
90日なので正確に３か月ではないですが…


```python
# 過去3か月分のデータ取得
end = datetime.datetime.now()
start = end - datetime.timedelta(days=90)
params = {
    "from": start.strftime('%Y-%m-%dT%H:%M:%SZ'),
    "to": end.strftime('%Y-%m-%dT%H:%M:%SZ'),
    "granularity": granularity,
}
```

このコードで過去３か月にわたる４時間足でのサポートレジスタンスラインの発見をすることができると思います（後でちょっと動かしてみます）
初めてのAWS学習教材について

（Qiita初投稿です。。。温かい目で見てください！）
# ・はじめに


クラウドってストレージでデータ保存するやつでしょ？？？

って思っていたのですが、やれる事の多さに惹かれて業界未経験の人間が

「クラウド使った仕事したい！資格取ろう！」ってなったところからスタート
# ・勉強方法
AWS CLFの取得を目指す

調べたら沢山出てきた

その中から職場の講師の方にどれがおすすめか伺い2つに決めました。
どういった教材なのかと使って数日の感想も添えたいと思います。



## AWS Cloud Practitioner Essentials(Japanese)
1つ目の教材

AWS公式で出している学習コース
簡単に言うと動画で基礎を教えてくれる教材。

３人?の講師の方が分かりやすい例え話と、
時にはユーモアを交えて解説してくれます。

全部で11章。
全て学び終えたら自分はもうAWSマスターになるんじゃないかと錯覚する

ただ基礎って言ったけど、AWSの基礎は教えてくれるけど
バンバンIT用語使ってるので説明が理解出来ない。

説明を理解するために調べる。また調べる。また調べる…etc

学習の所要時間は8時間と書いてあったけど全然終わらない。
自分は倍の時間かかりました。。

最後に認定テストがあり全30問中24問以上正解で合格
3回受けてギリギリ合格。。。

すぐにマスターにはなれなかった。そんな甘いもんじゃない。

**＊まとめ1**

長所：

**主に動画で解説してくれるので文字とにらめっこするのが得意でない人におすすめ。**
動画だけじゃ難しいよ！って人には、動画の下に
文字や図にも起こして解説してくれているので視聴後に見ると理解度が上がる。
**→全体的に見やすいので見づらいとかのストレスはない。**

**最低限スマホがあれば学習出来るので電車やちょっとしたスキマ時間も使える。**
(本でも出来るけど、重たい本持たなくて良い点は長所)

短所：

AWS以外の専門用語も沢山出てくるので完全未経験だとこの教材だけでは難しい。
(ググっていけば問題ない。ただスムーズには進まない)

以上がインプットするのに使った教材です。


## 【CLF-C02版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（6回分390問）
2つ目の教材

ひたすら試験と同じ形式で問題に答えていく教材。
講師に聞いたところ

**【合格するにはひたすら問題を解くこと！！！】**

って感じで言っていたので6回分390問もあるこの教材は最強です。

まだ全部には着手出来ていないのですが、

試験と同じ形式で時間制限有りで一気に65問行うモードと
1問1答形式ですぐに正誤が分かるモードがあります。

後者のモードを先に取り組み、
すぐに正解が分かり、不正解分の選択肢の解説まであるので倍以上のスピードで理解していける感覚です。

1.2回1問1答形式を行ってから、
試験と同様の形式で行い無事合格ラインに届きました。

また一通り行ってから何周も行いたいと思います。

初めてudemyを使ったけどこれは良いとすごく感じました！！
書籍で同じように行おうとした場合

1問毎に問題ページと答えページをパラパラめくって確認めんどう、、

問1の答えと解説見たいのに問2の答えまで見ちゃった、、

など答え合わせするのにも労力をそれなりに使う経験をしたことがあったので
添削までしてくれることにより**ひたすら問題を解く**という事に全力を集中して注げるのでかなり好感触です！

**＊まとめ2**
長所：
**ポチポチ押して問題を解けるので学習しやすい！**

**正解以外の解説もある為、不正解の選択肢のこれはなんだっけ？が起こりづらい。**
また文字だけではなく図を使った解説もある。
(不正解の選択肢は簡単な解説しかないので100％の理解は難しい)

**スマホがあれば学習出来るのでどこでも出来る。**
(まとめ1にも似たこと書いたな～)

短所：
udemyが開けない時があり、学習したいタイミングで出来ない。
(ずっとぐるぐるして読み込めない。おそらくサーバーエラー)
→3日間使って1度だけなので頻繁には起こらないはず…。

以上がアウトプットで使った教材です。


# ・最後に
今回は使いませんでしたが、
**AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー**

こちらの書籍もおすすめしていただいたのですが、ひたすら問題を解きたかったので
今回は動画視聴のみでインプットを行いました。

評判すごく良いので資格取った後でも知識確認で読んでみたいと思います。

拙い文章でしたが最後まで読んでいただきありがとうございました。
キャッシュバスティングについて

# ブラウザのキャッシュの仕様
ブラウザはCSS、JSファイル、画像ファイルなどの静的コンテンツをキャッシュする。このおかげで、同じサイトのURLをリクエストした際に、静的コンテンツのダウンロードをしなくなるので、描画速度が速くなる。

キャッシュされた静的コンテンツは、サイトのURLと紐づけて保存される。

# キャッシュバスティングとは
Webアプリを更新した場合、最新のWebアプリをブラウザ側で読み込んでくれるようにする方法。
ブラウザのキャッシュ機能によって、更新前のWebアプリが読み込まれることを回避したいときに利用する。


キャッシュバスティングは、静的コンテンツのURLに一意の識別子を追加することで実現され、ウェブブラウザーは、ローカルに保存されているキャッシュバージョンを読み込むのではなく、ウェブサイトを訪れるたびに静的コンテンツの新しいバージョンをダウンロードするようになります。
【2025年01月版】Proxmox8.3 で QEMU Guest Agent を有効にする

# はじめに

Proxmoxのコンソールで、各VMのIPsが`No Guest Agent configured`になっているのが気持ち悪いな。。。

設定しよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/03abd65a-740e-446f-c6f7-162a06c3ae79.png)

# `qemu-guest-agent` のインストール

```terminal
$ sudo apt install qemu-guest-agent
```

# VMの設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/7d1b36c4-95cb-e041-7a8b-88553b9052b8.png)

　↓

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/0637ff91-4b19-9cd9-531e-e694570cc1fc.png)

# VMの停止と起動

- 必ず、再起動ではなく、停止しましょう

```terminal
$ sudo poweroff
```

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/0637ff91-4b19-9cd9-531e-e694570cc1fc.png)

　↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/c20fe31b-19f2-7789-9b16-62c0f4b5cbfd.png)

# IPs が表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/b45fd510-6af6-59d5-0578-f20feaf76992.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/29b1d289-0a47-b548-6c69-a6e388922eb5.png)

# さいごに

かんたんでしたね

# リンク

[PROXMO : Qemu-guest-agent](https://pve.proxmox.com/wiki/Qemu-guest-agent)
PyMuPDF を用いて印刷用の PDF を作成 (2)

2 年ほど前に[この記事](https://qiita.com/dan_yok/items/98e7c5bb8d1c41ec1168)で PyMuPDF を用いて[無線綴じ](https://printmall.jp/blog/archives/20210302/3249/)で印刷する場合のページ割付を行うためのコードを紹介したが、今回は「中綴じ用」のそれである。

## 中綴じ用のページ割付

以下のコードで **saddle_stitching.pdf** が生成される。

```Python
import sys
import fitz

def main(filename):

    src = fitz.open(filename)
    page_count = src.page_count
    page = src.load_page(0)
    width = page.rect.width
    height = page.rect.height

    dst = fitz.open()

    imax = int((page_count + 3) / 4) * 2
    if page_count % 4 == 0:
        j = page_count - 1
    else:
        j = imax * 2 - 1
    k = 0
    for i in range(imax):
        if i % 2 == 0:
            if j >= page_count:
                dst.new_page(-1, width = width, height = height)
            else:
                dst.insert_pdf(src, from_page = j, to_page = j)
            dst.insert_pdf(src, from_page = k, to_page = k)
        else:
            dst.insert_pdf(src, from_page = k, to_page = k)
            if j >= page_count:
                dst.new_page(-1, width = width, height = height)
            else:
                dst.insert_pdf(src, from_page = j, to_page = j)

        j -= 1
        k += 1

    dst.save('saddle_stitching.pdf')

if __name__ == "__main__":
    if len(sys.argv) == 2:
        main(sys.argv[1])
```

### 2in1

PyMuPDF を使って一気に処理することも可能であるが、[PDFMate Free PDF Merger](https://www.pdfmate.com/free-pdf-merger.html) で 2in1 印刷用の PDF に変換している。
UI Actionの条件とAjax

```ruby:qiita.rb
条件
(new x_tomg_XXX.XXXスクリプトインクルード().XXXメソッド())

function onclick(){
	var in_sksho_sysid = g_form.getUniqueValue();
	var gajax = new GlideAjax('x_tomg_XXX.Common');
	gajax.addParam('sysparm_name', 'XXX');
	gajax.addParam('sysparm_sys_id', XXX);	// Input: 請求書のsys_id
	gajax.getXMLAnswer(function(answer) {
		var sysid = answer;	// Output: XXXsys_id
		var jump_url = "/x_tomg_XXX_CES_XXX.do?sysparm_anken_sysid=" + sysid;
		window.open(jump_url, "_blank");
	});
}
```
Ruby でベンチマークした結果を棒グラフで確認する

# やりたいこと

ベンチマーク結果を棒グラフで確認したい。

# 方法

ベンチマークには [benchmark-ips](https://github.com/evanphx/benchmark-ips) を、グラフの描画には [Gruff Graphs](https://github.com/topfunky/gruff) を使用する。

```shell-session
$ gem install benchmark-ips gruff
```

```rb
require 'benchmark/ips'
require 'gruff'

report = Benchmark.ips(quiet: true) do |x|
  x.report('String#+') { '村上' + '春樹' }
  x.report('String#<<') { '村上' << '春樹' }
  x.report('String#concat') { '村上'.concat('春樹') }
  x.compare!
end
# Comparison:
#            String#<<:  7385757.8 i/s
#        String#concat:  6956169.4 i/s - 1.06x  slower
#             String#+:  5297130.7 i/s - 1.39x  slower

bar = Gruff::Bar.new
# いくつかカラーテーマがある。
# https://github.com/topfunky/gruff/blob/39091ff482e5071dfe4f7597687420c01a35d93f/lib/gruff/base.rb#L431-L459
bar.theme_pastel
report.entries.each { bar.data(it.label, it.stats.central_tendency) }
output_path = Pathname(Dir.home).join('Downloads/bar_chart.png')
bar.write(output_path)

# 画像ファイルをプレビュー開く (macOS 限定) 。
system("open #{output_path}") 
```

![bar_chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/b83f50cc-e781-1a70-35d8-499d786b6ced.png)

# バージョン情報

```shell-session
$ ruby -v
ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin24]

$ gem install benchmark-ips gruff
Successfully installed benchmark-ips-2.14.0
Successfully installed gruff-0.25.0
2 gems installed
```
UI Messagesの呼び出す方法

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3971184/9ae339e6-ce5d-4341-d0cf-c404d579210b.png)
```ruby:qiita.rb
function showModal(msg) {
    var gm1 = new GlideModal("glide_warn", true);
    gm1.setTitle("確認");
    gm1.setPreference("title", msg);
    gm1.render();
}
```
スクリプトの実行方法

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3971184/59d59ba3-03e9-648c-0444-00562be00a8b.png)
```ruby:qiita.rb
                    //前提条件判断
                    var exScript =XXXXRecord.getValue("u_zntjknscript");
                    if (exScript) {
                        //スクリプト実施
                        var evaluator = new GlideScopedEvaluator();
                        //パラメータ渡す
                        evaluator.putVariable("sysid", "XXXXX");
                        //実施フラグを取得 実施
                        exeFlg = evaluator.evaluateScript(XXXXRecord, "u_zntjknscript");
```
Protocol Buffersでint16が使えない理由

# Protocol Buffersで`int16`が使えない理由

Protocol Buffers（以下、`proto`）を使っていると、「`int16`型があれば便利なのに」と思うことがあるかもしれません。しかし、`proto`では`int16`を直接サポートしていません。この記事では、その理由を解説し、関連する公式情報や議論のリンクもご紹介します。


# なぜ`int16`は使えないのか？

## 1. **型設計の簡潔性**
Protocol Buffersでは、汎用性を重視して型設計を行っています。そのため、`int16`や`int8`といった細かい型をサポートせず、以下のような基本的な型に統一されています：

- **`int32`**（符号あり32ビット整数）
- **`int64`**（符号あり64ビット整数）

公式ドキュメントにもスカラー型一覧が記載されています：
[Protocol Buffers公式スカラー型リスト](https://protobuf.dev/programming-guides/proto3/#scalar)


## 2. **通信サイズに影響しない**
Protocol Buffersでは、[Varintエンコーディング](https://developers.google.com/protocol-buffers/docs/encoding)が採用されています。この方式では、値の大きさに応じて通信サイズが決まるため、`int16`を使用した場合と`int32`を使用した場合で通信サイズには大きな違いがありません。

例：
- 値が小さい場合（-64 ～ 63）：**1バイト**
- 中程度の値（-8192 ～ 8191）：**2バイト**
- 大きい値（-1,048,576 ～ 1,048,575）：**3バイト**

つまり、`int16`が導入されても通信効率におけるメリットは限定的です。


## 3. **複雑性を排除する設計**
`int16`をサポートすると、他にも`int8`や`uint16`といった型の導入を検討する必要が生じます。このような型の増加は、Protocol Buffersの設計を複雑にし、異なる言語間の互換性を損なう可能性があります。

Protocol Buffersの開発者たちは、このシンプルさを維持するために細かい型を導入しない設計を選びました。この方針については、GitHubの議論でも言及されています：
[Protocol Buffers Issue #3091: Why no support for smaller integers?](https://github.com/protocolbuffers/protobuf/issues/3091)


# 結論
Protocol Buffersで`int16`が使えない理由は以下の通りです：
1. `int32`が`int16`の範囲を完全に包含している。
2. Varintエンコーディングにより、通信サイズへの影響がほぼない。
3. プロトコル設計をシンプルに保つため。

そのため、`int16`の代わりに`int32`を使用することが推奨されます。


## 参考資料
- [Protocol Buffers公式スカラー型リスト](https://protobuf.dev/programming-guides/proto3/#scalar)
- [Protocol Buffers Issue #3091: Why no support for smaller integers?](https://github.com/protocolbuffers/protobuf/issues/3091)

---

この記事が、Protocol Buffersにおける`int16`の扱いに関する疑問の解消に役立てば幸いです。
Docker + Django + Uvicorn 環境で、ホットリロードされない問題の解決策

# Docker + Django + Uvicorn 環境で、ホットリロードされない問題の解決策

表題環境で開発中、Djangoの開発サーバ―ではHTMLの更新もしっかり検知するのだが、

`uvicorn call_system.asgi:application --host 0.0.0.0 --port 8000`

でサーバーを立ち上げたとき、何をやってもHTMLの変更が検知されなかった。

##  --reload　もダメだったが・・・

`uvicorn call_system.asgi:application --host 0.0.0.0 --port 8000 --reload --reload-include *.html`

結論、上記でいけた。

`--reload-include *.html`

が効いた。GPTも頼りにならなかったから解決したときは昇天した。
Macの仮想環境でKali Linuxを立ち上げた時のメモ

### 前おき
tryhackmeでセキュリティの勉強のためにkalilinuxを使ってみようと思った。
tyrhackmeではvmを用意してくれているが、2台vmを開けなければならない時など相当重かったのでなんとかしたかった。

### Mac
以下のMacで試した。
2017 iMac intel Corei7 ventura13.7.2
2022 MacBook Air M2 Sequoia 15.2

### M2に時間がかかった
iMacはvirtualBoxVMにkaliの公式サイトからisoをダウンロードし特に問題なくGUIまでインストールできたが、MacBookが諸々つまづいた。

### Docker
MacBookではまずDokcerを使った。
https://zenn.dev/dev_zacker/articles/c42faf432278dc
このサイト通りにすすめると、問題なくkaliを立ち上げられた。
ただGUIはVNCをつかってtryhackmeのkaliを操作するようでやはり動きの重さが気になった。
CLIでは全く問題なく動作する。
CLIだけれよければ、ymlなどを作らなくても以下のコマンドで簡単にインストールできるようだ。
```:インストール
docker pull kalilinux/kali-rolling
```
```:起動
docker run -it --name kali_container kalilinux/kali-rolling /bin/bash
```
強いて言えばパスワードでつまづいた。
sudoのパスワードは`kali`で設定されていた。

### UTM
次にUTMを試した。
UTMをターミナルからインストールした。
```:インストール
brew install --cask utm
```
kaliは公式サイトからmac silicon用のKali Linux 2024.4を落としてISOを使ったが、この先が進まなかった。
https://www.kali.org/get-kali/#kali-installer-images

```
display output is not　active.
````
調べたところ、この問題にぶつかっている方は多かったようだ。
解決策として:
 * しばらく放置する。
 * 仮想ディスプレイカードを色々変えてみる。

などがあったが、こうなるとダメだというご意見があり、新しいシリアルを作ることをご提案されていた。
https://qiita.com/kurab/items/1e114d1aa1a8238d4ecc

### 結論
少しの進歩はあったが、これでもインストールを完了するには至らなかった。
結局、公式サイトからダウンロードしたkaliはあきらめ、UTMギャラリーからダウンロードして無事インストールできた。ダウンロードには三時間ほどかかったと思う。

### 追記：
しばらく使ってみたがUTMが最も良さそうだ。動きも安定している。
Macは本体ストレージが限られているのでファイルを動かしやすいのがいい。

### VirtualBox
最後にVirtualBoxだが、何度かいくつかの方法でインストールを試したがいずれも起動できないか、EFIが動くところまでで止まってしまう状態だった。
気になっていること：UTMに使用するイメージにx86_64を使えば良かった気もするが、多分ダメだったろう。(追記：シリコンにarmではないものは論外だった。さらに仮想環境のOSを安定させるのに苦労した。特にマップ変更しているキーボードの設定。)

とりあえず以上です。