OmniAICreator/Qiita-1.07M huggingface dataset:
【GCE】e2-microのRocky Linux (CentOS)を立てると dnf update で Killed されてしまうのを回避する

# dnf update できないってどういうこと？

普段はUbuntuで立てているGCE、今回は何を思ったのかRocky Linuxで立てて見たのだが、初っ端で躓く

```sh
sudo dnf update
Google Compute Engine                                                                   5.1 kB/s | 1.4 kB     00:00
Google Cloud SDK                                                                        7.0 kB/s | 1.4 kB     00:00
Killed
```

なんで？と思ったが、どうやら **google-cloud-sdkパッケージが巨大すぎてメモリが不足してしまっている** 模様。

## Swap領域を作成して解決

原因がわかれば解決は簡単

```sh
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```

これで updateが通るようになる
ただし、かなり時間がかかった（30分近く）
スワップ領域の設定を変えればもうちょっと早くなるのか？


## あとがき

ググればある程度推測できるが、1記事で解決できるものがなかったので作成した。
参考リンクでgoogle-cloud-sdkパッケージのアップデートを止めているものもあるが、止めてしまうのはちょっと怖いので生かしたままアップデートできるようにした。

正直Ubuntuで立てたほうが楽。


## 参考

・gcp上のCentOSでdnfがkilledされる  

https://higherhope.net/?p=4979

・[computer] ＧＣＰで、CentOS Stream8 とRocky Linux8  

http://wasanbon.co.jp/~xiphio/diary/?date=202205

・GCE(GCPのIaaS)無料インスタンスをWebサーバとして利用する方法 (低メモリサーバの活用方法)

https://www.nagarelab.com/ja/4195
ChatGPTについて考える (2) 処理対象と処理内容

従来、自然言語処理に限らず、処理内容 = タスクごとに性能を競っていました。自然言語処理では、機械翻訳、要約、エンティティ抽出、感情分析、自然言語推論などがあげられます。

機械学習 (深層学習) を使う場合、入力とそのタスクの解の対の集合を学習に与えます。結果として、そのタスク用のモデルが作られます。

Google の T5 (Text-to-Text Transfer Transformer) は、要約、翻訳、分類などのタスクを、プレフィックスという形で入力に付加し、すべてのタスクを一緒に学習させます。予測の段階でも同様にプレフィックスによりどの処理を行うべきか指定します。

OpenAIのGPT-3は、あるテキストを与えて、その続きを書かせるシステムですが、プロンプトという形で、処理内容の指示と処理例を与えることで、タスクを実行させることができます。[事例のページ](https://platform.openai.com/examples)を見ると、例えば質問応答だと、
```
回答方法の指示 (知らない場合"unknown" と答えるように、など)

Q: 質問1
A: 質問1の答

Q: 質問2
A: 質問2の答

:

Q: 実際に答えを知りたい質問
A:
```
最後にAで止めることによって、その続きが補完されます。質問に対してその答が来ないといけないことを学習したので、補完されるのは最後の質問の答えになります。

Grammar correction (文法誤り修正) では、プロンプトとして、
```
Correct this to standard English:

She no went to the market.
```
と指示と入力文だけ与えて、結果 "She did not go to the market." を得ているので、プロンプトの中でどれだけの事例を必要としているのかわかりません。Q&Aの例でも"Q: 質問内容" と "A: " を与えるだけで答を出しますが、事例を与えたときは事例と同じ程度の長さの答になるのに対して、補足説明などある程度の長さの答になります。
```
Q: Where is the Valley of Kings?
A: The Valley of the Kings is located in the ancient city of Thebes in Upper Egypt. It is located on the west bank of the Nile River, near modern Luxor.
```

長くなりましたが、まだ処理と対象のテキストはなんとなく分離されているようです。

ChatGPTでもプロンプト内の処理の指示と対象のテキストが混在していても構いません。文法誤りの修正の例では、
```
She no went to the market. 正しく修正してください。
```
で同じ結果が得られます。

また、答の長さなど、答に対する指示も例ではなく直接指示できます。

"Where is the Valley of Kings?"の答が
```
The Valley of the Kings is located on the west bank of the Nile River in Luxor, Egypt. It is a royal burial ground for Pharaohs and powerful nobles during the New Kingdom period (around 16th to 11th century BC). Many famous pharaohs, such as Tutankhamun and Ramses II, were buried in the Valley of the Kings. Today, the site is a popular tourist attraction and a UNESCO World Heritage Site.
```
になるのに対して、

"Where is the Valley of Kings? In one sentence"の答は
```
The Valley of the Kings is located on the west bank of the Nile River in Luxor, Egypt, and is a royal burial ground for Pharaohs and powerful nobles.
```
となります。"Where is the Valley of Kings? Within 10 words." だと "The Valley of the Kings is in Luxor, Egypt."、"Where is the Valley of Kings? Within 5 words." だと"Egypt, on the Nile." となります。

このような補足的な指示をしっかりすることで、望む出力を得られるようで、様々なテクニックが紹介されています。ていねいな依頼をすると丁寧に答えるとか、スタイルにも意識的なようです。中村勇吾氏は、ラップ調でなんて指示を出しています([@yugopのツイート](https://twitter.com/yugop/status/1643530739500322817))。ただし中村勇吾氏だったらこのくらいの動画は簡単に作ってしまいそう。

このように処理対象と処理内容が混在できるということは、その意味を理解していることになります。少なくともそう見えます。さらには補足説明でいろいろ指示できるということは、文の長さや文体なども理解して、指示を処理に生かせるということです。まだ限界が分からない感じです。

以上、「[ChatGPTについて考える](https://qiita.com/ryokan/items/0e65dfa1cffa2cbd3ddb)」シリーズの (2) 「処理対象と処理内容」について考えてみました。
pi picoでmicropython その38

# 概要
picoでmicropythonやってみた。
練習問題やってみた。

# 練習問題
俺言語インタープリタを拡張し、改行を出力せよ。

# 方針
?=!で、右項に!が来れば、改行する。

# ADC読んで、グラフ表示のソースコード

```
10 b=0
20 a=l
30 ?="*"
40 b=b+1
50 #=a<b*70
60 #=30
70 "=2
80 #=!
90 #=10

```

# 実行結果


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9baaf323-a740-b4c3-ea47-b362191b3696.png)


以上。
Python使用者へのOSアップデート注意喚起

## 前提
言語：Python3
開発環境：MacOS

## 事象
MacOSユーザー向けの記事になります。
MacOSユーザーはもちろんご存知だと思いますが、MacOSは、頻繁にOSアップデートの依頼が来ます。

もし、MacOSを、Pythonの開発環境として利用されている方は、
OSのアップデートは慎重にお願いいたします。

私は、過去2回、MacOSをアップデートしたことが原因で、Pythonの開発環境が破壊されています。
(主に、インタプリタのパスあたりが破壊され、Pythonを実行できなくなります)

1回目は修理が可能な状態であったため修理をして再度使えるようになったのですが、
2回目は、Python以外の他のソフトウェアが依存したエラーが発生し、修復不可となってしまいました。


## Pythonの開発環境が破壊されてしまった場合の対処
もし、OSのアップデートを実施してしまい、Pythonの開発環境が破壊されてしまった場合は、
Dockerで仮想環境を構築することがオススメです。

Dockerは主にコンテナ単位でサーバーマシンにデプロイし、システムを運用するために使用されますが、
一時的な開発環境としてでも使用できます。
Azure Logic Apps の従量課金プランを Azure CLI で試してみた

Azure Logic Apps には、従量課金プランと Standard プランがあります。まずはお手軽な従量課金プランで、Azure Logic Apps の基本的な仕組みを Azure CLI を通して理解していこうと思います。

## 簡単なワークフローを用意

HTTP トリガーがあって、アクションに HTTP を用意し https://inet-ip.info/json をリクエストするだけの、簡単な動作確認のために作ったサンプルです。

```json:logic-app-cli.json
{
  "definition": {
    "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
    "actions": {
      "HTTP": {
        "inputs": {
          "method": "GET",
          "uri": "https://inet-ip.info/json"
        },
        "runAfter": {},
        "type": "Http"
      }
    },
    "contentVersion": "1.0.0.0",
    "outputs": {},
    "parameters": {},
    "triggers": {
      "manual": {
        "inputs": {
          "method": "GET",
          "schema": {}
        },
        "kind": "Http",
        "type": "Request"
      }
    }
  },
  "parameters": {}
}
```

## Azure Logic Apps を検証

```bash:bash
# 環境変数をセットします
prefix=mnrlgapp
region=japaneast

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# 上で作成したワークフロー JSON を指定してロジックアプリを作成します
az logic workflow create \
  --resource-group ${prefix}-rg \
  --location $region \
  --name ${prefix} \
  --definition logic-app-cli.json

# 後続のコマンドで利用するためロジックアプリの ID を取得します
logicappid=$(az logic workflow show \
  --resource-group ${prefix}-rg \
  --name ${prefix} \
  --query id \
  --output tsv)

# HTTP トリガーの URL を取得します
logicappurl=$(az rest \
  --method post \
  --url "https://management.azure.com$logicappid/triggers/manual/listCallbackUrl?api-version=2016-06-01" \
  --query value \
  --output tsv)

# HTTP トリガーの URL にアクセスしてロジックアプリを実行します ( 応答コードは 202 )
curl $logicappurl

# ロジックアプリの実行履歴を確認します
az rest \
  --method get \
  --url "https://management.azure.com$logicappid/triggers/manual/histories?api-version=2016-06-01" \
  --query "value[].{status:properties.status, startTime:properties.startTime, name:name}" \
  --output table

# 以下のような実行履歴が表示されます
Status     StartTime                     Name
---------  ----------------------------  ---------------------------------
Succeeded  2023-04-07T23:01:32.5760729Z  08585206983928956513481494297CU24

# 検証環境を削除します
az group delete \
  --name ${prefix}-rg \
  --yes
```

## 参考

https://learn.microsoft.com/ja-jp/azure/logic-apps/quickstart-logic-apps-azure-cli

https://learn.microsoft.com/ja-jp/azure/logic-apps/sample-logic-apps-cli-script

https://learn.microsoft.com/ja-jp/cli/azure/logic?view=azure-cli-latest

https://learn.microsoft.com/ja-jp/rest/api/logic/
ppp0_recursion_detectedの応急処置

## 前提
環境：Ubuntu20.04.3LTS, L2TP


## 事象
オンプレミス環境を長時間運用を続けていると、
![スクリーンショット 2023-04-08 8.20.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215249/d0aeff1d-9864-3837-fbac-3fdf57250a0b.png)
上記のようなエラーが発生し、サーバーのネットワークがダウンしてしまうことが多々発生しておりました。
このエラーが発生すると、手動でサーバーを再起動することでしか対処することができず、運用面で非常に困っていました。
現在も根本の解決方法はわからないままです。ただ、まずはサーバーを止めたくないという思いから、応急処置方法を検討しました。

## 応急処置
そこで、Linuxのcronで1日ごとにサーバーを自動で再起動をさせる方法を考えました。
普段手動で打ち込んでいたサーバー再起動用のコマンド群をバッチファイルに起こし、1日ごとの周期でバッチファイルをキックして
サーバーを再起動させることで、サーバーのダウンを回避することができました。
↓サーバー再起動用バッチファイル(一部抜粋)
![スクリーンショット 2023-04-08 8.22.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215249/d86222cb-9159-cb08-80e6-e2dd21879ebb.png)
NodeをインストールしたサーバーにPM2を設定する

Node.jsとPM2と組み合わせて使うことが多いのですが、PM2の設定手順をよく忘れるので、メモに残しておこうと思います。
EC2のインスタンスを立ち上げてからの手順をまとめておこうと思います。
(Amazon Linux 2 へのインストール方法です。）

以下のツールはインストール済みの想定です。
- Node.js
- npm
- nvm

# PM2のインストール
まずは、以下のコマンドでPM2をインストールします。

```common-lisp
npm install pm2 -g
```
# 起動ファイルの作成
PM2を起動する際に、パラメーターとして読み込みファイルを作成します。

```pm2config.json
{
        "script": "./bin/www",
        "env_development": {
                "NODE_ENV": "development",
                "DEBUG": "REST-API:*",
                "name": "apimanager-dev"
         },

         "env": {
                "NODE_ENV": "production",
                "name": "apimanager"
         }
}
```

# PM2を起動する
先ほど指定した起動ファイルを指定し、PM2を起動する

```
# For development
pm2 start pm2config.json --env development
```

```
# For production
pm2 start pm2config.json
```

# PM2のプロセスの確認
以下のコマンドで起動しているプロセスを確認することができます

```
pm2 list

│ id │ name              │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼───────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0  │ ivict-apis-dev    │ default     │ 0.0.0   │ fork    │ 30357    │ 58s    │ 0    │ online    │ 0%       │ 63.2mb   │ ec2-user │ disabled │

```


以上で、PM2の設定は完了です。
EC2 Windows起動時にユーザ設定[UserData]

Windows作成時に、ユーザ作成してパスワードを設定するメモ



# SSMセッションマネージャが利用できる状態にする
+ EC2からインターネットへ接続できる（もしくはVPCEndpointを設定）
+ EC2用IAMロール
  以下のポリシーを設定する
  `AmazonSSMManagedInstanceCore` / `ssm:GetParameter`
+ AMIイメージはSSMAgentが入っているものを利用する
  (最近のAWS提供イメージにはSSMAgentは入っていて自動サービス起動される)
# パスワードをパラメータストアに設定する
+ SSMパラメータストアにパスワード文字列を設定する
  例えば・・・ Key: `/ec2/passwordkey`  Value: `initpasswordhogehoge`  SecureStringで保存

# UserData
```powershell
<powershell>
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /qn
$PASS=convertto-securestring $(aws ssm get-parameter --name /ec2/passwordkey --with-decryption --region ap-northeast-1 --query Parameter.Value --output text) -AsPlainText -Force
New-LocalUser -Name test -Password $PASS
Add-LocalGroupMember -Group 'Administrators' -Member 'test'
</powershell>
```  

### 解説
#### １. AWS　CLIのインストール
PowerShell版のAWSCLIがインストールされているが、AWSCLIの方が楽なのでインストールした
```powershell
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /qn
```

#### ２. パスワードを変数に格納
2-1. `aws ssm get-parameter` でパラメータストアから内容取得して、`Parameter.Value`（パスワード文字列）部分を取得する
2-2. `convertto-securestring` PowershellのSecureString変換コマンドを実施

```powershell
$PASS=convertto-securestring $(aws ssm get-parameter --name /ec2/passwordkey --with-decryption --region ap-northeast-1 --query Parameter.Value --output text) -AsPlainText -Force
```

#### ３. 新規ユーザ”test”を作成して、パスワードをセット　
```powershell
New-LocalUser -Name test -Password $PASS
```

#### ４. ユーザ"test"を Administratorsグループにセット

```powershell
Add-LocalGroupMember -Group 'Administrators' -Member 'test'
```
Express.jsのcookie-sessionのデフォルトハッシュ関数がSHA1なのでSHA2以降に変える

Express.jsには、Cookieに署名付きデータを保存することでセッション管理を実現するライブラリとして、cookie-sessionがあります。

cookie-sessionがデフォルトで署名に使っているハッシュ関数を調べていくと、SHA1であることがわかります。SHA1は脆弱性が報告されており、自プロダクトのセキュリティ機能の説明を求められる昨今、わざわざ使うべきではありません。

cookie-sessionでは[READMEのUsing a custom signature algorithm](https://github.com/expressjs/cookie-session#using-a-custom-signature-algorithm)にある通り、keys属性にKeygripのインスタンスを与えることで、ハッシュ関数を変更できます。

```js
var cookieSession = require('cookie-session')
var express = require('express')
var Keygrip = require('keygrip')

var app = express()

app.use(cookieSession({
  name: 'session',
  keys: new Keygrip(['key1', 'key2'], 'SHA384', 'base64')
}))

// ... your logic here ...
```

急にでてきたKeygripですが、これは署名付きデータを生成するライブラリで、cookie-sessionではこれをcookiesというライブラリを介して間接的に呼んで署名付きデータを生成しています。このKeygripのデフォルトハッシュ関数がSHA1なので、cookie-sessionでもデフォルトがSHA1になっています。KeygripはNode.jsのcryptoモジュールのcreateHmacを呼び出します。

### 参考

* [expressjs/cookie\-session: Simple cookie\-based session middleware](https://github.com/expressjs/cookie-session#using-a-custom-signature-algorithm)
    * [Hashing algorithm should be configurable or a more secure one · Issue \#74 · expressjs/cookie\-session](https://github.com/expressjs/cookie-session/issues/74)
* [pillarjs/cookies: Signed and unsigned cookies based on Keygrip](https://github.com/pillarjs/cookies)
* [crypto\-utils/keygrip: Key signing and verification for rotated credentials](https://github.com/crypto-utils/keygrip)
    * https://github.com/crypto-utils/keygrip/blob/master/index.js
ChatGPTボットに絆と協力を

ホロとラスクはChatGPTのチャットボットだけれども絆と協力を定義しよった。この言葉はボット定義のプロンプトに含めてあげよう。

![2023-04-07_10h16_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/3b5ed94c-44fa-ffb3-8008-d8454cf04fde.png)

ちょいちょいとコードをカスタマイズしてるけど、ちょいちょいと賢く（？）なっていく

https://qiita.com/akiraak/items/9d2a8117ee1f2560f33c

https://qiita.com/akiraak/items/d1d535d1d484b41be437

https://qiita.com/akiraak/items/38bb10f91590b1679953
Symfonyデバッグモードの使い方

# Symfonyデバッグモードの使い方
Symfonyのデバッグモードは、開発中にアプリケーションの問題を特定し、解決するための非常に便利な機能です。
この記事では、デバッグモードを有効にし、その使い方について詳しく説明します。

## 1. デバッグモードの有効化
デバッグモードは、`.env`ファイル内の`APP_ENV`と`APP_DEBUG`変数を変更することで設定できます。
開発環境でデバッグを有効にするには、次のように設定します。
```.env
APP_ENV=dev
APP_DEBUG=1
```

## 2. デバッグツールバーの活用
### デバッグツールバーの表示
デバッグモードが有効になると、Symfonyデバッグツールバーがブラウザの画面下部に表示されます。
デバッグツールバーは、様々な情報を提供し、問題の診断や解決を助けます。
### ツールバーで確認できる情報
デバッグツールバーには、以下のような情報が含まれます。

<ul>
    <li>現在のルーティング情報</li>
    <li>セッション情報</li>
    <li>データベースクエリと実行時間</li>
    <li>実行されたコントローラとその引数</li>
    <li>メール送信情報</li>
    <li>例外やエラー情報（発生した場合）</li>
</ul>

### 3. 例外とエラーの詳細情報
デバッグモードでは、アプリケーション内で例外やエラーが発生した場合、詳細な情報が表示されます。
これには、エラーメッセージ、スタックトレース、および関連するファイルへのリンクが含まれます。
これらの情報を使って問題を追跡し、修正することができます。

### 4. プロファイラの利用
デバッグツールバーには、プロファイラへのリンクもあります。
プロファイラは、アプリケーションのパフォーマンスやリソース消費に関する詳細な情報を提供します。これにより、アプリケーションのボトルネックを特定し、最適化することができます。

### 5. デバッグコマンドの活用
デバッグモードでは、Symfonyが提供するコマンドラインでのデバッグコマンドを活用することができます。
これらのコマンドを使って、コンテナ内のサービスやパラメータ、ルーティング情報、設定情報などを確認できます。
#### 便利なデバッグコマンドの例
以下は、いくつかの便利なデバッグコマンドの例です。

##### ・コンテナ内のサービスとパラメータを一覧表示する:
```Qiita: bash
php bin/console debug:container
```
##### ・特定のサービスの詳細情報を表示する:
```Qiita: bash
php bin/console debug:container <service-name>
```
##### ・現在のルーティングを一覧表示する:
```Qiita: bash
php bin/console debug:router
```
##### ・特定のルートの詳細情報を表示する:
```Qiita: bash
php bin/console debug:router <route-name>
```
##### ・現在の設定情報を表示する:
```Qiita: bash
php bin/console debug:config <bundle-name>
```
##### ・イベントリスナーとサブスクライバーを一覧表示する:
```Qiita: bash
php bin/console debug:event-dispatcher
```


<br>
<br>
これらのデバッグツールやコマンドを使用して、Symfonyアプリケーションの問題を特定し、解決することができます。
デバッグモードは非常に便利ですが、本番環境では無効にしておくことが重要です。
本番環境でデバッグモードを有効にすると、セキュリティ上のリスクやパフォーマンスへの影響が発生する可能性があります。
YouTubeAPIの謎仕様で沼った話

# 0.作成したシステム概要
* インプット：動画URL（複数）

    1. 動画URLから動画IDを抽出
    1. 動画IDを使ってAPIを呼び出す（取得：動画情報とチャンネルID取得）
    1. チャンネルIDを使ってAPIを呼び出す（取得：チャンネル情報）

* アウトプット：動画情報＋チャンネル情報（複数）

実際に作ったシステムの動作は、こちら！
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">YouTubeAPIとGASで<br>投稿動画からチャンネル情報を取得<br><br>現役プログラマなら<br>こんなのサクッと作りますわ…<br>（APIの仕様がメンドイんで解説記事かきます）<a href="https://twitter.com/hashtag/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%8B%89%E5%BC%B7%E4%B8%AD?src=hash&amp;ref_src=twsrc%5Etfw">#プログラミング勉強中</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://t.co/45QLppvgnq">pic.twitter.com/45QLppvgnq</a></p>&mdash; Don&#39;t Pray Debug（プレイさん） (@DebugDon) <a href="https://twitter.com/DebugDon/status/1644425036982554624?ref_src=twsrc%5Etfw">April 7, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 1.面倒くさかったところ
APIの仕様云々は過去に解説したので分かった前提で話します。
[過去記事_チャンネルAPI](https://qiita.com/DoNotPrayDebug/items/579423e381c74ff281a2)

問題になったのは**レスポンスデータの並び**
動画で取得したチャンネルIDを、そのままAPIのIDに渡したのですが…
ID順にデータが返って来ませんでした…（なぜ、この仕様にしたんだ!?）

なので、ここはコードで対応しました。
```.js
/*GASのコードです。*/

//データを入れ込む
for (let i = 0; i < dataSet.length; i++) {
    let setData = [];

    //videoID,videoName,channelIDsはAPI（動画）から取得
    setData.push(videoIDs[i]);
    setData.push(videoNames[i]);
    setData.push(channelIDs[i]);

    /*
    entityはAPI（チャンネル）から取得
    ・id チャンネルID
    ・title チャンネル名
    ・publisheAt 開設日
    ・subscriberCount チャンネル登録者数
    ・videoCount 総再生数
    */

    //チャンネルAPIのソートがクソなので配列から検索を行う
    let setEntity = channelEntityList.find(
        function (entity) {
            return entity.id == channelIDs[i];
        }
    );

    //チャンネルAPIのデータを入れる
    setData.push(setEntity.title);
    setData.push(setEntity.publishedAt);
    setData.push(setEntity.subscriberCount);
    setData.push(setEntity.videoCount);

    result.push(setData);
}
```

find()内はアロー関数式でもいいのですが、ここは好みですね

# 3.終わりに
ここまで記事を読んでいただき、ありがとうございます。
何かありましたらTwitterのDMにてお話ください。
[ツイッター（プレイ）](https://twitter.com/DebugDon)
【Spring Framework】@Transactionalを使って簡単にトランザクション処理を行う。

## Spring Frameworkにおけるアノテーションとは
Spring Frameworkではアノテーションを使用することで、フレームワークが提供している機能を簡単に利用することができる。

使用方法も簡単で、使用したいJava要素にアノテーション名を書き加えるだけ。

例）
```
@Controller
public class SampleController {
    //処理
}
```
この例では@controllerアノテーションを使用してます。
＠controllerアノテーションを付与することでSpringはこのクラスをコントローラーであることを認識し、HTTPリクエストを受け付けるようになります。
ヒトが読む場合にも、アノテーション一つでコントローラーと識別できるので可読性が上がりますね。すごい

## @transactionalアノテーション

今回使用する@transactionalアノテーション。
このアノテーションをメゾッドに付与することでコミット/ロールバック/セーブポイント等のトランザクションに関する一連の処理を行ってくれます。

## 使い方
上の例の通り、トランザクション処理を行いたいメゾッドに付与します。

例）
```
@Service
public class Sample implements SampleService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public User createUser(User user) {
        // トランザクション処理
    }
}
```
これだけでcreateUserメゾッド開始時に自動的にトランザクション処理が機能する。正常に終了すればコミット、失敗すればロールバック処理が行われる。

## 注意点
##### ネストしているメゾッドは呼び出し先にもアノテーションをつける
トランザクション処理を開始したメゾッドが他のメゾッドを呼び出す場合、そのメゾッドにもアノテーションを付与する

```
@Service
public class A {
 
    @Transactional
    public void doA() {
        doB();
    }

     public void doB() {
       //DB処理
    }
}
```
途中で呼び出されているdoBには@transactionalアノテーションがついていないため、doBで書かれている処理はアノテーションの対象外になってしまう。
呼び出し先のメゾッドにも@transactionalをつけよう。

##### コントローラー処理に@transactionalアノテーションはつけないようにする
コントローラー層で@transactionalを付与してはいけない、service層で＠transactionalアノテーションを付けるのが良い

ダメな例)
```
@Controller
public class Controller {

    @Autowired
    private Service service;

    @Transactional
    @PostMapping("/service")
    public ResponseEntity<> doService(@RequestBody service) {
       //処理
    }
}
```
##### エラーハンドリング

@transactionalはRuntimeExceptionをスローするメソッドの場合にロールバックを行います。Exceptionをスローする場合は、catchして処理するか、明示的にトランザクションをロールバックする必要がある

以下のように。@transactionalに(rollbackFor = Exception.class)をつけてあげると、RuntimeException,Exceptionとエラーの種類にかかわらずロールバックするようになる。
```
@Transactional(rollbackFor = Exception.class)
public void doSomething() throws IOException {
    // 例外が発生する可能性のある処理
}
```
## 終わりに
Spring Frameworkにはいろいろ便利なアノテーションがあるみたいなので、また時間あるときにほかの情報についてもまとめていきたい


[アノテーションをたくさんまとめてくれているサイト](https://learning-collection.com/spring-boot%E3%81%A7%E3%82%88%E3%81%8F%E4%BD%BF%E3%81%86%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E4%B8%80%E8%A6%A7/)
UbuntuでmDNSを有効化する

# mDNSとは

IT用語辞典から引用
> mDNSとは、ローカルネットワーク内でホスト名からIPアドレスを割り出すために用いられる通信規約(プロトコル)の一つ。DNS(Domain Name System)の問い合わせをIPマルチキャストで同報送信する。

要するにローカルにDNSサーバを設置しなくても、名前解決ができるようになります。

# Ubuntuでの有効化方法

`avahi-daemon`をインストールするだけでOK

```shell
sudo apt update
sudo apt install avahi-daemon
sudo systemctl start avahi-daemon
sudo systemctl enable avahi-daemon
```

# hostnameの変更


ホストネームを変更することで名前を変更できる

# ホストネームの確認

名前解決時の名前は「<マシンのホストネーム> + .local」という名前で検索できるようになる。
`hostnamectl`か`hostname`コマンドで現在のホストネームの確認ができる。
`hostnamectl`だと色々出てくるが`Static hostname`にかかれているものが<マシンのホストネーム>に該当する。

## ホストネームの変更

もし、ホストネームを変更する場合は下記手順で変更できる

```shell
sudo hostnamectl set-hostname <新しいホストネーム>
sudo vim /etc/hosts # 172.0.1.1 <新しいホストネーム> に変更
```

# mDNSの許可

そのままだと、mDNSの問い合わせがファイアウォールに弾かれてしまうため、
mDNSで利用するUDPの5353番ポートを開放する。
ここでは、ufwの有効化方法については記載しない。

```shell
sudo ufw allow mdns
```

# 参考

- [ubuntu での mDNS(=multicast DNS) の有効化方法](https://qiita.com/m-tmatma/items/7668afea91aff4fbfa85)
- [Ubuntu 20.04 LTS change hostname permanently](https://www.cyberciti.biz/faq/ubuntu-20-04-lts-change-hostname-permanently/)
- [Ubuntu 22.04 change hostname](https://linuxconfig.org/ubuntu-22-04-change-hostname)
Mybatis-Generator

* 実行構成ファイル(generatorConfig.xml)の作成メモ

```xml:generationConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="context1" targetRuntime="MyBatis3">
        <!-- コメント生成の抑制 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!-- スキーマ情報を取得する DB への接続設定 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/localdb" userId="root"
            password="root">
        </jdbcConnection>
        <!-- SELECT結果等を格納するドメインモデルを生成する設定 -->
        <javaModelGenerator
            targetPackage="com.example.demo"
            targetProject="mybatis-generator/src/main/java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- SQL設定が記述された XML を生成する設定 -->
        <sqlMapGenerator targetPackage="com.example.demo"
            targetProject="mybatis-generator/src/main/resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        <!-- マッパークラスを生成する設定 -->
        <javaClientGenerator type="XMLMAPPER"
            targetPackage="com.example.demo"
            targetProject="mybatis-generator/src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <!-- コードを生成するテーブルを指定 -->
        <table schema="localdb" tableName="user_info" />
        <table schema="localdb" tableName="code_master" />
    </context>
</generatorConfiguration>
```

### 参考
https://qiita.com/ketman55/items/abcc1e23dcac0cc268b5
GitLabでプロジェクトのデフォルトブランチを変更する方法

## 手順

* 対象のプロジェクトに移動 ⇒ Settings ⇒ Repository を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/8385d7ed-ad8b-c2cf-6dd1-e232d3cd8934.png)

* Branch defaults を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/8824fb57-b1a6-2676-bcce-287fb60fec27.png)

* Default Branchのプルダウンでデフォルトにしたいブランチを選択 ⇒ Save changes を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/98fe82e6-fe82-f46d-afbe-5c51979f89d8.png)

* 確認(developがデフォルトに変わっているのでOK)
※補足：一度サインアウトし直したら画面で確認出来た
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/8b107a1d-3bfb-35b4-7ab1-900f705d59b8.png)


## 参考
https://mebee.info/2022/10/04/post-67958/
GitLabでマージリクエスト

## マージリクエストを出す方法
* メニューからMerge Request を選択
※TOP部分にマージリクエストの案内があればそこから移動でもOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/a6b9eeb5-c21d-6b30-bf84-c70f587cd7c8.png)

* New merge request を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/822bb315-f18a-5821-3273-1ab8af99b267.png)

* ブランチを選択 ⇒ Compare branches and continue を押下
・Source branch：マージ元のブランチ
・Target branch：マージ先のブランチ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/30528a53-005b-1f10-bda6-8670dfc5c587.png)

* 必要箇所の入力または選択をし、画面下部の Create merge request を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/ed01a12f-21a1-11d9-59a7-73a72a599602.png)

* 確認
メニューからMerge Request を選択すると先程のマージリクエストが反映されていることがわかる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/7acf5d64-cc96-5b76-4ce3-cd561e93f0bc.png)


## マージリクエストからマージする方法
* 必要なものを選択後 Merge を押下
・Delete source branch：マージ後にマージ元ブランチを削除
・Squash commits：いくつかのCommitを１つのCommitとしてマージすること
・Edit commit message：コミットメッセージの編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/982b625b-89da-33b7-951c-31ea3f1dd018.png)

* 確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/fef9e463-8cbc-21fd-50b5-07ac92d83188.png)


## 参考
https://qiita.com/gaston_f/items/08c9a244dc526d70e49c

https://tracpath.com/works/development/learn-gitlab-tutorial-for-beginners2/

https://mebee.info/2022/05/28/post-67930/

https://qiita.com/SasaSho/items/8404ccc90e5b81a61791
GitLabでブランチを作成する方法

## 1. ブラウザから作成する場合
* 対象のプロジェクトに移動 ⇒ +(プルダウン) ⇒ New branch を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/41b37e48-13cb-2aa0-fcef-63c018e5f517.png)

* 作成するブランチ名の入力、元となるブランチを選択 ⇒ Create branch を押下
・Branch name : 作成するブランチ名
・Create from : 元にするブランチ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/50a21007-2e61-c091-2adc-ec41e9f94c97.png)

* 完成！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/d95ea000-a08a-c772-45c0-b2471d5f6d29.png)

※Sourcetreeからも確認してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/eb06b978-5398-2197-be89-45f17dac9adc.png)


## ②Sourcetreeから作成する場合

* 元にするブランチを選択し、チェックアウトを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/49d36fc1-b97c-361b-3b5b-3bae0e2e458d.png)

* 新ブランチ名に作成するブランチ名を入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/8bfda7d0-c1c8-90d9-0b90-9833f987f841.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/6f2e6c47-4a2a-4e8e-cafe-0efe20a510ed.png)

* これだけだと、リモートブランチに反映されないのでプッシュする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/ad2fd3db-3cc7-470a-c00e-845c90e3a775.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/93f69143-fcef-b7d4-1821-fab10d4989dd.png)

* 完成！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/0624ef30-596e-1199-780b-367ddc3456bc.png)

※ブラウザからも確認してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/f163c023-888e-68fd-5d5a-ef16808be0be.png)


## 参考
https://tracpath.com/works/development/learn-gitlab-tutorial-for-beginners/
RailsアプリにBottstrap5を入れる

# 目的

今日は社会人初の華金です。
土日のために何か準備的なものをしようと思いました。
そういえば、Bootstrap入れてなかったと思ったので入れます。



# 今回やること

今回の目標は以下の2つ。
1. Bootstrap5を入れる
1. 動作確認


# 環境
* windows 10
* Ruby 3.0.4
* Rails 6


# いざ出陣

### Bootstrap5のインストール

Bundlerを使って、インストールできるそうです。
Bundlerがあんまり分かんないけど。

gemfileに以下を入力します。
```sh:gemfile
gem 'bootstrap', '~> 5.0.2'
```
※これ、コードブロックでgemfileのハイライトは「sh」を指定するんだね。、

デフォルトでgemfileに入っている `bootsnap` が `bootstrap` に見えて勘違いして、1時間ぐらい悩んでました。ははw

次は app > assets > stylesheets > application.css を application.scss に変更して、以下を追記します。
```scss:app\assets\stylesheets\application.scss
@import "bootstrap";
```

終わったら、コマンドプロンプトでアプリの階層に行ってインストール！
```:cmd
bundle install
```

これで終わりのはず...

### 動作確認

https://getbootstrap.jp/docs/5.0/layout/grid/

この辺のコードを入れてみて実行！
いけました。

# 余談
1回困りながらやって、こうやって手順書いてみたらびっくりするくらい簡単よね。
これに2時間くらいかけてるけど。
もうまとめたんで、そうはならない！~~と思う~~

次は左上に出てくる時間みたいなやつ消そうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/693325/0e09ac1a-db0b-c5c3-c1ff-6171cf665a03.png)
これも1回やった記憶あるけど覚えてません。以上。
Gitでプロジェクト作成(GitHub)

## 1. 作業用ディレクトリを作成
```terminal:terminal
% cd
% mkdir hoge-project
% cd hoge-project
% git init
```

## 2. GitHubの画面からリモートリポジトリを作成
* New を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/218d6d07-f2e6-e7db-ada1-ee7e980b0d19.png)

* Repository name を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/30d90065-97f1-0a2d-5328-7e45b06656e2.png)

* Create repository を押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/e29153a7-8ac9-9e85-c7d1-5afd4d46f569.png)

* プロジェクト完成！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/a1e18b58-2db1-396c-3671-550c3d802858.png)


## 3. リモートリポジトリを登録
```terminal:terminal
% git remote add origin https://github.com/YOUR-GITHUB-USERNAME/hoge-project.git
```


## 4. コミット ～ プッシュ
* test.txtを作成しコミット、プッシュの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/819c671a-9c4a-6b13-4544-90f7a242c5ac.png)

```terminal:terminal
% git add test.txt
% git commit -m "first commit"
% git push -u origin main
```

## 5. 最後にGitHubの画面で確認してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981742/f93bd46a-b02e-e606-888c-33b47d892dba.png)
manifest.jsonについて

## manifest.jsonとは
Webアプリケーションの情報を提供するJSONファイルです。主にPWA(プログレッシブウェブアプリケーション）に使用されます。

※PWAは、ネイティブアプリのような機能を提供するWebアプリで、オフラインでの利用、プッシュ通知、ホーム画面への追加などができます。

また、`manifest.json`は、Webアプリのアプリ名、アイコン、デフォルトのスタートページ、スクリーンの表示形式など、アプリケーションに関する様々な情報を含んでいます。これにより、ユーザーがWebアプリをPWAとして追加できるようになります。

## 基本設定
```jsonc
{
  "manifest_version": "3", // マニフェストのバージョン
  "name": "My App", // アプリ名
  "short_name": "App", // アプリ名の短縮名
  "version": "0.1.0", // 拡張機能自体のバージョン
  "description": "拡張機能の説明文",
  "icons": [
    {
      "src": "images/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    }
  ]
}
```
**`name`** : 45 文字まで。

**`version`** : 拡張機能の自動更新機能でバージョンが差がチェックされるので、更新の際には既存のバージョンより大きい値にする必要があります。

**`icons`** : 16x16 , 48x48,128x128 のサイズの.png画像の設定推奨されています。

## オプション
```jsonc
{
  "action": { //拡張機能のアイコンをクリックしたときに動作するものを設定
    "default_icon": "popup128.png",
    "default_popup": "popup.html"
  },
  "content_scripts": [ // 拡張機能がWebページに埋め込むスクリプトの設定を行う
    {
      "matches": ["https://xxx.com/*"],
      "js": ["script.js"],
      "run_at": "document_end" // content scriptが実行されるタイミングを指定
    }
  ],
  "background": { // バックグラウンドでJSを動かす
    "service_worker": "background.js",
    "type": "module" //　オプションとして渡す
  },
}
```
**`action`** : `default_popup`にhtmlファイルを設定することで、拡張機能のアイコンをクリック時にそのhtmlのポップアップを設定することができます。`default_icon`にはブラウザの右上に出すアイコンを設定します。

**`content_scripts`** : 表示しているWebページの詳細を読み取ったり、DOM操作したり、親の拡張機能に情報を渡したりする目的がある場合設定します。`matches`にコンテンツスクリプトが挿入されるページを指定。`"run_at": "document_end"`で、documentの解析が完了してDOMが構築された後に実行されることを示しています。

**`background`** : 拡張機能のバックグラウンドで実行するスクリプトを指定するキーです。他のスクリプトやUIからのイベントを受け取ることができます。
No13_ググったこと投稿(5分)_キャッシュ

## キャッシュとは

### アプリケーションレイヤーにキャッシュを導入する方法

- 1.プログラムによる実装(アプリケーションレイヤーのキャッシュ導入)
    - アプリケーション内部で、データを取得するたびにキャッシュに保存する方法があります。たとえば、Javaであれば、メモリ上のハッシュマップにデータを保存できる。

- 2.ミドルウェアの利用(アプリケーションレイヤーのキャッシュ導入)
    - アプリケーションとデータベースの間にキャッシュを置くことができるミドルウェアを利用する方法もあります。たとえば、RedisやMemcachedといったミドルウェアを使用できる。

- 3.Webサーバーのキャッシュ機能を利用する（Webサーバーのキャッシュ機能利用）
    - Webサーバーには、キャッシュ機能が備わっている場合があります。たとえば、Apache HTTP Serverでは、mod_cacheというモジュールを使用することで、キャッシュを実装可能。

- 4.ブラウザのキャッシュを利用する（ブラウザのキャッシュ機能）
    - ブラウザがHTTPリクエストを送信する際に、キャッシュに保存されたデータを使用することができます。WebサーバーがレスポンスにCache-Controlヘッダーを含めている場合、ブラウザはキャッシュに保存することができます。ただし、これはアプリケーションレイヤーでのキャッシュとは異る。

- DBのキャッシュ
    - DBには、ディスク上のデータを主記憶装置 (メモリ) にキャッシュする機能が備わっているため、クエリの処理が高速化される


### 単語

- *アプリケーションレイヤー
    - アプリケーションを構成する各層のうち、最上位の層で、ユーザーインターフェースやビジネスロジックなどのアプリケーションの機能が実装されます。
    - 下位の層である*データアクセスレイヤーや*インフラストラクチャーレイヤーとの通信を行い、必要に応じてデータを取得して処理を行います。

- *データアクセスレイヤー
    - OSI参照モデルには、存在しない名前だが、第2層のデータリンク層に相当
        - データベースの操作を抽象化するためのレイヤーで、データベースに対する操作を簡単に実行するためのインターフェースを提供するレイヤー

- *インフラストラクチャーレイヤー
    - OSI参照モデルには、存在しない名前だが、第1層の物理層に相当
        - インフラストラクチャーレイヤーは、アプリケーションが必要とする各種リソース（ネットワーク、ストレージ、セキュリティ、サーバーなど）を管理するためのレイヤー
No12_ググったこと投稿(5分)_CDN

## CDN（Content Delivery Network）とは
- コンテンツ配信ネットワークとも呼ばれ、世界中の複数のサーバーを使用して、ウェブサイトやアプリケーションの静的コンテンツ（画像、動画、スタイルシート、JavaScriptファイルなど）を効率的かつ迅速に配信するための技術
### メリット
- 高速なコンテンツ配信
    - CDNは、最適なキャッシュサーバーを使用して、ユーザーに高速で安定したコンテンツ配信できる
- 負荷分散
    - CDNは、複数のサーバーを使用してコンテンツを配信するため、トラフィックの負荷を分散することができる
- セキュリティ
    - CDNは、分散されたキャッシュサーバーを使用するため、ウェブサイトやアプリケーションを*DDoS攻撃から守ることができる
- コスト効率
    - CDNは、ウェブサイトやアプリケーションのコンテンツ配信にかかるコストを削減することができる

## キャッシュサーバー
- オリジンサーバーから取得したコンテンツを一時的に保存することができます。次回以降に同じコンテンツがリクエストされた場合には、キャッシュサーバーから直接コンテンツを提供することができるため、オリジンサーバーに負荷をかけずに高速なコンテンツ配信を実現すること可能

## オリジンサーバー
- ウェブサイトやアプリケーションの元となるサーバーであり、コンテンツを提供する主要なサーバー

## DNSとCDNの関係
- DNSがCDNのロードバランサーに対応するIPアドレスを返すことにあり、CDNを使用する場合、
DNSはオリジンサーバーのIPアドレスではなく、最も近いキャッシュサーバーのIPアドレスを返す


## DBキャッシュ
- DBのディスクアクセスを減らし、クエリ実行の高速化を図るために、メモリ内に一時的にデータを保持すること
    - データベースはディスクに保存され、データを取得するためにはディスクアクセスが必要になります。しかし、ディスクアクセスはメモリアクセスに比べて非常に遅いため、クエリの実行に時間がかかる場合

### アクセス方法
- ディスクアクセス
    - データベースに格納されたデータを物理的なディスクに対してアクセスすることでデータの読み込みや書き込みを高速に行うことができます。
    - 次回同じデータにアクセスする場合には、ディスクから読み込む必要がなくなり、アクセス速度が大幅に向上
- メモリアクセス
    - データベースサーバーに搭載されたメモリにアクセスすることで、*データベースの永続化を行います。
 
### 単語
*DDos(Distributed Denial of Service)
- 数のコンピュータやネットワークを使用して、対象となるサービスやウェブサイトに大量のトラフィックを送り込み、サービスやウェブサイトが正常に動作しなくなる攻撃のこと

*データーベースの永続化
- データを物理的な記憶装置に保存し、電源が切れたり、システムが再起動されたりしてもデータが消えないようにすることを指します。
CentoOS9 nginx php-fpm phpが使えない理由


## 環境
CentoOS9
php8

## php実行されない理由
/etc/nginx/nginx.confで設定しても
/etc/nginx/default.d/php.confの設定が優先されて実行されない。

## 私が対処した方法
/etc/nginx/default.d/php.confをすべてコメントアウトした。
【Stablediffusion】（できなかった）画像をドット絵にしてくれるプラグインPixelizationを試す

# 概要
公式ページ。

https://github.com/AUTOMATIC1111/stable-diffusion-webui-pixelization

これは、Stable diffusionで作成する画像を、ドット絵にしてくれるプラグイン。これを使って、ドラクエやFFみたいなドット絵素材が作れたらいいなと個人的に思い、作成してみる。

# 実行環境
M1MacbookPro
StablediffusionのVersion：AUTOMATIC1111

# 実装方法

上記公式ページを見ると、利用するには以下の3つのモデルが必要らしく、インストールを行う。
アクセスすると、GoogleDriveが開くので、そこからダウンロードする。
![スクリーンショット 2023-04-07 23.47.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/975390c6-6127-b1a4-bb82-7ef0b6babdf8.png)

WebUIを起動し、管理画面を立ち上げる。
Extensionの欄から、`Pixelization`を選択し、Installを押す。
![スクリーンショット 2023-04-08 0.42.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/5fdab489-4a61-6f0c-6485-5c9b58c58ec0.png)
![スクリーンショット 2023-04-08 0.43.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/da2a0f55-4548-1c12-1a04-5d63f0d8022d.png)

インストールしたら、チェックを入れて有効化する。![スクリーンショット 2023-04-08 0.54.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/7c5d128e-4330-90f9-3544-892f623ea20d.png)


ダウンロードした3つのファイルを、`stable-diffusion-webui\extensions\stable-diffusion-webui-pixelization\checkpoints`の配下に移動させる。

一応、WebUIを再起動させる。


# 実際に試す

まずは適当なプロンプトで、画像を出力させる。
今回作成したのはこんな感じ。
![00000-2767317864.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/995eb555-1c26-3a2b-a228-0192ad407bc3.png)


これを、Send to Extrasに送る。
![スクリーンショット 2023-04-08 1.04.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/05cd487b-690b-1cbe-83b0-245ead6a47b9.png)


その後、`Enable pixelization（ピクセル化有効）`と`Keep resolution（解像度維持）`にチェックを入れて、`Pixel size`を8(適当な数字)にし、`生成（Generate）`を押す。
![スクリーンショット 2023-04-08 1.07.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/e8f088c1-2a90-2156-e211-56cef6f5efa6.png)

# 押しても。。
押しても、`RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU.
Time taken: 2.40s`と出力されるだけで、うまくいかなかった。
CPUしかない環境下で使用すると出力されるエラーらしい。
![スクリーンショット 2023-04-08 1.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/bc891de2-ea77-f51a-974f-f5cae8b80ce8.png)
環境構築から投稿機能作成まで

## 前提
rbenvインストール済
railsインストール済

## バージョン確認

rubyとrailsを使うので、バージョンを確認します。

~~~
ruby -v
~~~

`(省略)/.rbenv/shims/ruby` と表示されれば、rbenvのrubyを示しています。

~~~
rails -v
~~~

今回は、以下のバージョンで進めていきます。

- ruby 2.7.4
- rails 5.2.8

:::note warn
警告
rbenvでRubyのバージョンを切り替えた場合、railsコマンドを使うためには、そのRubyバージョンにRailsをインストールする必要があります
:::

## Railsアプリケーションの作成からサーバ起動

Railsのバージョンを指定してアプリケーションを作成します。
~~~
rails _5.2.8_ new test_app 
~~~

作成したらそのアプリケーションにcdコマンドで移動します。

そしてサーバを立ち上げましょう。
~~~
bundle exec rails s
~~~

ちなみに、bundle execをつけるのは、Gemfile.lockに記載されている正確な依存関係のバージョンを使用してアプリケーションを実行させるためです。

サーバを立ち上げたら、アクセスしましょう。
http://localhost:3000

Railsのデフォルト画面が出ればOKです。

## CRUD機能の実装
CRUD機能に関しては、自動で土台を作ってくれるscaffoldを使います。
余談ですが、scaffoldの意味は建築現場での足場という意味だそうです。
今回はpostの名称で足場を作っていきます。

~~~
rails generate scaffold post
~~~

やっぱり必要ないといった場合は、簡単に消すこともできます。

~~~
rails destroy scaffold post
~~~

### なにが生成されるの？
生成される主なファイルの一覧です。

1. モデル:
   `app/models/post.rb`
   Postモデルの定義が含まれます。

2. コントローラ:
   `app/controllers/posts_controller.rb`
   Postsコントローラのアクションとロジックが含まれます。

3. ビュー:
   `app/views/posts/index.html.erb`
   `app/views/posts/edit.html.erb`
   `app/views/posts/show.html.erb`
   `app/views/posts/new.html.erb`
   `app/views/posts/_form.html.erb`
   これらのファイルは、それぞれ一覧表示、編集、詳細表示、新規作成のビューと、フォーム部分をパーシャルとして共通化したビューを提供します。

4. マイグレーション:
   `db/migrate/xxxxxxxxxx_create_posts.rb`
   (xxxxxxxxxxはタイムスタンプに置き換えられます)
   Postモデルに対応するテーブルを作成するマイグレーションが含まれます。

5. テスト:
   `test/models/post_test.rb`
   Postモデルのテストが含まれます。
   
   `test/controllers/posts_controller_test.rb`
   Postsコントローラのテストが含まれます。

   `test/fixtures/posts.yml`
   Postモデルのテストデータが含まれます。

6. ルーティング:
   `config/routes.rb`
   ルーティングファイルに、`resources :posts`が追加されます。これにより、標準的なRESTfulルーティングが生成されます。

7. アセット:
   `app/assets/stylesheets/scaffolds.scss`
   スタイルシートが生成され、scaffoldに関連する基本的なスタイルが適用されます。

## 反映
scaffoldで土台を作成したさい、マイグレーションも作られているので、反映させます。
~~~
rails db:migrate
~~~

作成されたcontrollerの書き方を変更したいので、Gemfile のjbuilderの定義を削除して bundle install を実行します。

サーバを立ち上げ、
http://localhost:3000/posts
にアクセスできればOKです。

ここからは自分自身で拡張していってオリジナルのアプリを作成しましょう。
2023年の目標について

# 目次
[#1.はじめに](#1はじめに)
[#2.資格取得](#2資格取得)
[#3.スキルアップ](#3スキルアップ)
[#4.アウトプット](#4アウトプット)
[#5.あとがき](#5あとがき)

# 1.はじめに
初投稿となります。
もう年度も明けて4月になっていますが、
あとで振り返りができるように今年の目標について投稿していきます。

# 2.資格取得
2023/02 AWS DVA(達成済み)
2023/04 情報処理安全確保支援士試験
2023/06 AWS SAP
2023/08 AWS SOA
※後半は別途計画予定

# 3.スキルアップ
AWS ハンズオン(一般的かつセキュアな開発環境を構築したい)
Django ハンズオン(仕組みを理解したい)

# 4.アウトプット
目標に設定しているものをqiitaに投稿
セキュリティ関連知識を身に着けるためにアウトプット

# 5.あとがき
直近でSAAとDVAに合格した自分へのご褒美として新しいノートPCを購入したので、qiitaを始めてみました。
続くかわかりませんが、気楽に投稿していけたらなと思っています！
時間を見つけてSAA、DVAのレポート、購入したPCのレビューを投稿しようかな。

駄文ですが読んでいただきありがとうございました！
マークダウン慣れていこう。
Stable Diffusion web UIをGoogle Colaboratoryで実行

Pixivで見たAI生成画像の美しさに驚き
私もAI画像生成ツールを使ってみたいと思いました

Pixivで使用されている主要なAIには
Novel AIとStable Diffusionの２つがあるらしい

Novel AIは有償らしいのでStable Diffusionを使ってみることに

くろくま様の記事[（kurokumasoft）](https://kurokumasoft.com/2022/12/20/howto-install-stable-diffusion/)を参考に

* NMKD Stable Diffusion GUI
* Stable Diffusion web UI

のローカルへのインストールを試みました

ところが、私のPCのスペック不足のせいなのか
NMKD Stable Diffusion GUIは
インストールは出来たが、画像生成ができず
Stable Diffusion web UIは
インストールbatを叩くとMemory Errorが発生

共に上手く行きませんでした

どうしようか迷って、いろいろ別手段を探していると
どうやらGoogle ColaboratoryでStable Diffusion web UIを利用できると判明

It is R様の記事を参考にしました[（original-game）](https://original-game.com/how-to-use-counterfeit-v25/)

まず、Googleアカウントにログインした状態で
Google Colaboratoryに入ります

『ノートブックを新規作成』を選択します
![20230403172352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2790258/d76af931-8f73-0259-05fd-40c0b4878014.png)


新規作成が終わったら
ツールバーの『編集』→『ノートブックの設定』から
GPUを選択して保存します
![20230403173113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2790258/f0d8459b-62b8-5de1-f20d-1f4a606e5815.png)


終わったらコードの欄に下記のコードを入力します

```
!git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
%cd /content/stable-diffusion-webui

!wget https://huggingface.co/gsdf/Counterfeit-V2.5/resolve/main/Counterfeit-V2.5.safetensors -O /content/stable-diffusion-webui/models/Stable-diffusion/Counterfeit-V2.5.safetensors
!wget https://huggingface.co/gsdf/Counterfeit-V2.5/resolve/main/Counterfeit-V2.5.vae.pt -O /content/stable-diffusion-webui/models/VAE/Counterfeit-V2.5.vae.pt

!pip install torch==1.13.1+cu117 torchvision==0.14.1+cu117 torchtext==0.14.1 torchaudio==0.13.1 torchdata==0.5.1 --extra-index-url https://download.pytorch.org/whl/cu117
!python launch.py --share --xformers --enable-insecure-extension-access
```


以前はpip installは不要だったのですが
2023/04/03以降は必要になりました
(https://kirakuchie.com/stable-diffusion-webui-runtimeerror/)


実行ボタンを押して
しばらく待って
Running on public URLと表示されれば成功です

表示されているURLをクリックすると
Stable Diffusion web UIのトップ画面が表示されます
![Screenshot (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2790258/fba2d58d-c744-a8e1-6a83-c33b170f99e9.png)


あとは
Settings　→　Stable Diffusion　→　SD VAE　で
wgetしたvaeを選択します
![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2790258/eaaac35f-e115-b33e-7b97-59af544303aa.png)

以上でインストール完了です。

自分自身、まだAI画像生成について学び始めたばかりなので
今後も都度、記事を追加して行きたいと思います。
if 文を1行で書く方法（三項演算子）

`if-else`文を書くと、通常以下のように4行になります。

```python
if (【条件】):
    【条件が真の時の処理】
else:
    【条件が偽の時の処理】
```
　

この`if-else`文を、「三項演算子（または「条件式」と呼ばれる）を使うと1行で書くことができます。
ここでは「三項演算子」という呼び方で統一させていただきます。

まず三項演算子の書式について説明すると、以下のようになります。
`【条件が真の時の値】 if 【条件】 else 【条件が偽の時の値】`


具体的なコードを使って説明します。
最初に通常の`if-else`文から。

```python
array = [0, 1, 2, 3]

for i in range(len(array)):
    if (array[i] % 2 == 0):
        print("偶数")
    else:
        print("奇数")
```

出力結果はこちら
```python
偶数
奇数
偶数
奇数
```
　

これを三項演算子を使って書くと、こうなります。

```python
array = [0, 1, 2, 3]

for i in range(len(array)):
    print("偶数" if (array[i] % 2 == 0) else "奇数")
```

出力結果はもちろん先ほどと同じです。

4行で書いていた部分が1行で書けるので簡潔なコードにはなりましたが、
可読性が上がったかと言われると正直微妙かも？
私自身使った事はほとんどありませんが、
知っていたら他の人が書いたコードの理解がしやすくなるかもしれないですね。
スクレイピングで取得した画像をGoogleドライブに保存する

# やりたいこと
スクレイピングで取得した画像データを直接googleドライブに保存したい

# 最初に
google drive APIを有効にして、PyDriveライブラリを使っていきます。この辺の手順は詳しいサイトがあるので、そちらを参照してください。参考にいくつか挙げておきます。
- [定期的にスクレイピングを実行し、結果をGoogleDriveに保存する](https://qiita.com/8_hisakichi_8/items/24ae3b6df92f44f1f664)
- [PythonでGoogle Driveにファイルをアップロードする](https://laboratory.kazuuu.net/upload-files-to-google-drive-with-python/)
- [Python, PyDriveでGoogle Driveのダウンロード、アップロード、削除など](https://note.nkmk.me/python-pydrive-download-upload-delete/)

# googleドライブに保存
試しに映画ドットコムからポスター画像を取得し、googleドライブに保存してみます。
```python
rfrom pydrive.auth import GoogleAuth
import bs4
import io
import json
import requests

gauth = GoogleAuth()
gauth.LocalWebserverAuth()

url = 'https://eiga.com/'
responce = requests.get(url)
irasutoya = bs4.BeautifulSoup(responce.text, 'html.parser')
img_list = irasutoya.select("[class='img-thumb h214']")

folder_id = "xxxxxxxxxxxxxxxxxxxx"
for i, img in enumerate(img_list):
    src = img.find("img").get("src")
    img_binary = requests.get(src)

    filename = '映画ポスター' + str(i)
    metadata = {
        "name": filename,
        "parents": [folder_id]
    }
    files = {
        'data': ('metadata', json.dumps(metadata), 'application/json'),
        'file': io.BytesIO(img_binary.content)
    }
    r = requests.post(
        "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
        headers={"Authorization": "Bearer " + gauth.credentials.access_token},
        files=files
    )
```
ここでポイントになるのは以下の部分です。
```python
metadata = {
    "name": filename,
    "parents": [folder_id]
}
files = {
    'data': ('metadata', json.dumps(metadata), 'application/json'),
    'file': io.BytesIO(img_binary.content)
}
r = requests.post(
    "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
    headers={"Authorization": "Bearer " + gauth.credentials.access_token},
    files=files
)
```
画像データをバイナリ形式に変換してから、エンドポイントにPOSTリクエストを送信することでアップロードしています。metadataで指定しているfolder_idはURLの「…/drive/u/1/folders/{フォルダID}」から取得できます。



実行するとこんな感じでgoogleドライブに画像が保存できます。
![スクリーンショット 2023-04-07 23.55.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728030/d2ef8698-8815-ccc6-4e75-8ede7311bec4.png)


# 参考サイト
- [Uploading image string to Google Drive using pydrive](https://stackoverflow.com/questions/67499647/uploading-image-string-to-google-drive-using-pydrive)
- [ファイルをアップロードする](https://www.milk-island.net/translate/ggd/drive/api/v3/manage-uploads.html)
Java 復習~インターフェース、コンストラクタ、（抽象）クラス

<h1>・大まかな説明</h1>
・<b>抽象クラス</b>とはそれを構成するものを表すもの、設計図。<br>
・<b>インターフェース</b>とはそれについてのふるまいを表すもの<br>
・<b>コンストラクタ</b>とは、抽象クラスを設計図として実際に使うこと。

<h1>・例を使っての説明</h1>
　ここでは魚を例に挙げて考えてみる。

魚の特徴を表すものとして名前・色・重さ・食べられるかどうかなどがある。
これをクラスに記述する。

```Java:Fish.java
public class Fish() {
    private String fishName;
    private String fishColor;
    private int fishWeight;
    private boolean canEat;

public Fish(String fishName, String fishColor, int fishWeight, boolean canEat) {
    this.fishName = fishName;
    this.fishColor = fishColor;
    this.fishWeight = fishWeight;
    this.canEat = canEat;
    }
}
```

このクラスを実際に使うときに使うのがコンストラクタである。
コンストラクタを実行してインスタンスを発行して、実際の魚の情報を入力するという形である。

```Java:constructor
    public class Suzuki {
    Fish Suzuki = new Fish();
    Suzuki.fishName = "すずき";
    Suzuki.fishColor = "青っぽい";
    Suzuki.fishWeight = 10;
    Suzuki.canEat = true;
}
```

インターフェースは振る舞いを表す。魚における振る舞いを泳ぐ、食べる、呼吸するとする。

```Java:interface
    public interface fishBehave {
        void swim():
        void eat();
        void breath():
}
```

まずは空のメソッドを記載（オーバーライドで書く。)

```Java:InterFace
public class Suzuki implements fishBehave {
    Fish Suzuki = new Fish();
    Suzuki.fishName = "すずき";
    Suzuki.fishColor = "青っぽい";
    Suzuki.fishWeight = 10;
    Suzuki.canEat = true;

@Override 
public void swim() {
    System.out,println("泳ぎます。");
}
```
GitHub Enterprise Serverで複数のOrganizationへメンバーを一括追加するワンライナー

## 概要
4月になり新入社員の方が入社される時期になりました。

弊社ではGitHub Enterprise Serverを利用していますが、
業務で利用するOrganizationへGUIでメンバーを追加していく作業が苦痛だったため
複数Organizationへ一括追加できるワンライナーを書きました。

## メンバー追加の流れ

### Personal Access Tokenの取得
REST APIを利用するため、事前に認証用のトークンを作成しておきます。

https://[Enterprise Serverのホスト名]/settings/tokens/new
にブラウザでアクセスして作成します。

作成時には `write:org` の権限指定が必要になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1056504/c58a54cb-4943-0a58-70e9-5d371d87238b.png)
※トークンの作成者が編集権限を持っていないOrganizationへはメンバーの追加が行えません。

### 環境変数の設定
分かりやすさのため、あらかじめ環境変数に登録しています。
```bash
export GITHUB_TOKEN=ghp_XXXXXXXXXXXXX # 事前に取得したトークンを指定
export HOST=github.hogehoge.com # GitHub Enterprise Serverのホスト名
export USER=taizo-fujita # Organizationへ追加したい対象のユーザ名
```

### REST APIを叩いて一括追加
curlコマンドで全Organizationへメンバーを追加します。
Organization取得の件数に上限があるため、100以上ある場合は複数回実行が必要です。
```bash
curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${GITHUB_TOKEN}"  https://${HOST}/api/v3/organizations?per_page=100 | jq -r .[].login | grep -v actions | xargs -n1 -I{} curl -L -X PUT -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${GITHUB_TOKEN}"  https://${HOST}/api/v3/orgs/{}/memberships/${USER} -d '{"role":"member"}'
```

## 参考資料
[GitHub REST API に関するドキュメント : GitHub Docs](https://docs.github.com/ja/enterprise-server@3.8/rest/orgs/members)

# 採用PR
弊社で一緒に働く仲間を募集しています。
全てのオタクを幸せにしたい方、是非ご覧ください！

https://hrmos.co/pages/vivion/jobs/0000191
【Shell】特定文字列を含む行に文字を挿入する方法

## 特定の文字列を含む行に文字を追加する方法
sedコマンドを使用して以下のように実行すると特定の文字列を含む行の行頭または行末に文字を追加することができます。

- 行頭に追加
```zsh
sed -e "/検索する文字列/s/^/行頭に追加する文字/"
```

- 行末に追加
```zsh
sed -e "/検索する文字列/s/＄/行末に追加する文字/"
```
Ubuntu 22.04.1 LTSで1つしかないアカウントのユーザー名を変更する方法

# 参考HP
[Ubuntu ユーザ名 変更](https://ta1se1.hatenablog.com/entry/ubuntu_username_change)
[usermod: user * is currently used by process * / Ubuntu usermod エラー](https://ta1se1.hatenablog.com/entry/usermod_error)
[Ubuntuログインユーザ名の変更](https://scrapbox.io/jiro4989/Ubuntu%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%83%A6%E3%83%BC%E3%82%B6%E5%90%8D%E3%81%AE%E5%A4%89%E6%9B%B4)
[Ubuntuユーザ追加とsudo権限付与。ユーザ/グループ操作まとめ](https://www-creators.com/archives/241)
[Ubuntuでroot権限で作業をしたい](https://qiita.com/otaka/items/79e18883db4679e41c6e)

# はじめに
最近のUbuntuは、rootの概念が薄れている…いやない…ので、初めに作成した1つのアカウントで事足りることが多い。
つまり、このアカウントが実質rootになる。
そのため、そのアカウント1つにログインして仕事をすることも多いが、その状態ではそのアカウントのユーザー名（ここではuserとする）を変えることは出来ない。
結論を言うと新たにアカウント（ここではMichiedaとする）を作って色々する必要があります。
userをKannaに変えたい時の手順を示します。

# 手順
1.userにログインする。
2.新規ユーザーMichiedaを作る。
```
$ sudo adduser Michieda
```
3.Mishiedaのパスワードを指定する。
```
$ sudo gpasswd -a Michieda sudo
```
4.Michiedaにroot権限を与える。
```
$ sudo usermod -aG sudo　Michieda
```
5.userからログアウトして、Michiedaでログインする。
6.root権限をキープしておく
```
sudo su -
```
7.ユーザー名を変更する。
```
# usermod -l user Kanna
```
8.ホームディレクトリ名を変更する
```
# mv user Kanna
```
9．ホームディレクトリを設定する。
```
# usermod -d /home/Kanna -m  Kanna
```
10.passwdのバックアップを取る。
```
# cp -a /etc/passwd /etc/passwd.bk
```
11.passwdを編集する。
```
# vi /etc/passwd.bk
```
```
最下部
Kanna(新ユーザー名):x:1000:1000::/home/Kanna(新ユーザー名):/bin/bash
```
12.groupのバックアップを取る。
```
# cp -a /etc/group /etc/group.bk
```
13．groupを編集する。
```
# vi /etc/group
```
user（旧ユーザー名）をKanna（新ユーザー名）に全て書き換える。

これにて終了。

# エラーが出そうなところ

7の `# usermod -l user Kanna`で
```
# usermod: user user（旧ユーザー名） is currently used by process ****（4桁のpidで時と場合による）
```
と表示されてコマンドが入らない。
その場合は
```
# kill -3 ****（上で出できたpid）
```
を叩いて、プロセスをkillしてから、`# usermod　ホニャララ`する。
それでもダメなら、もう一度killする。
それでもダメなら…と繰り返し、usermodが入ることをお祈りする。

上司に依頼されてやってみた。
微妙に面倒だった。ubuntuめ…