OmniAICreator/Qiita-1.07M huggingface dataset:
C#で非推奨のクラス、メソッドに警告を表示する

# 1. はじめに
* Javaで使用していた@DeprecatedアノテーションのようにC#でも同じように非推奨クラス、メソッドに警告を表示したい

# 2. ObsoleteAttribute クラス
* クラス、メソッドに```[Obsolete]```属性を指定することで対応できる　(Microsoftサイト参照)

https://learn.microsoft.com/ja-jp/dotnet/api/system.obsoleteattribute?view=net-7.0

## 2.1.警告にする場合
* 属性に```[Obsolete("任意のメッセージ")]```をつける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/632d0ad7-27ea-0406-bae6-724889911c38.png)

## 2.2. コンパイルエラーにする場合
* 属性に```[Obsolete("任意のメッセージ",false)]```をつける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/7c6ac569-18f6-d05e-38eb-6a1156688746.png)

## 2.3. コンストラクタ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/01aac231-4efc-a134-cd76-658ade98a17e.png)

# 3. 動作確認
## 3.1. サンプルコード
```csharp
        private void Form_Load(object sender, EventArgs e)
        {
            ExecuteWarning();
            ExcecuteError();
        }

        [Obsolete("Warning")]
        public static void ExecuteWarning()
        {
            Debug.Print("Warning!");
        }

        [Obsolete("Error",true)]
        public static void ExcecuteError()
        {
            Debug.Print("Error!");
        }
```

## 3.2. VisualStduio
* コードエディタに警告、エラーの波線が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/b0aff27a-b73c-1092-b479-41757221843b.png)
* 想定通り警告。エラーが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/56a4cc3d-ceb1-4922-b706-9fd6a9afd4bf.png)

# 4. 参考文献

https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/381obsolete/obsolete.html
Java Silver SE 11に合格しました！

# はじめに

タイトル通り2023/2/25にJava Silver SE 11の試験を受けてきました。
受験した経緯としては相変わらず社内評価のためというのは勿論ですが、Web系の作業も振ってもらえるように一定の知識を持っていることを証明したかったので受けました。
※今やっている案件は全然Web系ではないので、今後Webやクラウドにシフトしたいと考えてます

# 勉強方法・勉強期間

参考書の購入や勉強はちょこちょこ行ってましたが、ベンダー系は自分で試験日を決めれるためずるずると受験がずれ込んでました。。自分で追い込まないといけないと思い、2月に入ってから試験日予約(2/25)して本格的に勉強を始めました。

試験対策としては [徹底攻略Java SE 11 Silver問題集[1Z0-815]対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5Java-SE-11-Silver%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-815/dp/4295007625/ref=sr_1_2_sspa?crid=1F667J01W1RN0&keywords=java+silver&qid=1677576684&sprefix=java+%2Caps%2C217&sr=8-2-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUExSDNHN1RBUDlEUUxHJmVuY3J5cHRlZElkPUEwNzM3NDYwMzlaVDI2TllNUjExQyZlbmNyeXB0ZWRBZElkPUEyMTkwRzlFMVpaVk1CJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ==) (通称:黒本)を使って勉強してました。
黒本は13章構成(1-11章が各分野毎の問題、12-13章が模擬試験2回分)となっており、1-11章を3周、12-13章を2周しました。

ちなみに、土台作りのために以前使用した教材はこちらです。
[スッキリわかるJava入門 第3版 (スッキリわかる入門シリーズ)](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BJava%E5%85%A5%E9%96%80-%E7%AC%AC3%E7%89%88-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295007803/ref=sr_1_1?keywords=%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AAjava&qid=1677577161&sprefix=%E3%81%99%E3%81%A3%E3%81%8D%E3%82%8Ajava%2Caps%2C253&sr=8-1) 

継承やポリモーフィズムについて中々頭に入ってこなかったのですが、こちらのYouTubeチャンネルが非常にわかりやすかったのでおすすめです。
[せかチャン - 世界一わかりやすい情報科チャンネル](https://www.youtube.com/@SekaChan)

また、黒本著者のチャンネルもありますのでこちらもおすすめです。
[黒本著者が教える やさしくない!? Java](https://www.youtube.com/@java9521)

勉強時間としては、Java言語の勉強(土台作り)38時間と試験勉強51時間で合計89時間ほどになります。

# 試験当日
はじめてのベンダー試験だったので無難にテストセンターで受験しました。
沖縄のテストセンターは那覇の1か所のみで、時間帯によっては道が混むため早めに家をでました。自家用車で向かったのですが目星つけてたコインパーキングが満車で他を探すことになったので早めに出てよかったです。。
試験は最大3時間と長丁場のため、チョコ食べてトイレ済ませてから会場入りしました。

■試験問題について
受験者の声だと黒本で見たことがあるやつ、似たようなやつが沢山出題されるとありますが、個人的には半分くらいの印象で、はじめましてな問題が多く感じて面食らってました。。受験料が3.7万もするので試験時間最大限使いました。
試験中トイレに行けないのですが、空調がめちゃめちゃ効いてて寒かったので最後の1時間は別の戦いもありました。。

# 試験結果
正解率78％で無事合格できました！
![JavaSilver.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1579802/0e0125f4-e3f7-8c86-0c21-888e522c94b0.png)



# さいごに
Java言語での開発経験がある方は黒本だけで合格できるレベルだと思いますが、Java未経験や他業種の方はしっかり準備が必要な試験だと感じました。
そのため無事合格できたのは自信に繋がったので受験して良かったと思いました。
ベンダー試験は初でしたが受験料高いのと、テストセンターのメモ用ペンの異常な渇きやすさだけは何とかしてほしいところです…
次は23年春季SC受験に向けて頑張ります！
Springでポートフォリオを作成する　3.基本設計

# 前回まで
前回までは機能の洗い出しを行いました。

https://qiita.com/Jackoguro/items/89be9512f984fa8d2d3c

# 参考資料
https://www.udemy.com/course/digisaku_requirements_definition_and_system_design/

# この記事の目的
今回から基本設計のフェーズに入ります。
基本設計は大きく分けて、画面設計、機能設計、データ設計の3つに分かれます。

この記事では基本設計の概念を整理していきます。

# 基本設計の目的
どうやってビジネス要件をシステム実装するのか
- [ ] 画面設計：オブジェクト指向UI、タスク指向UI
- [ ] 機能設計：ドメイン駆動設計
- [ ] データ設計：ドメイン駆動設計

# 基本設計の流れ
1. 画面設計
1. 機能設計
1. データ設計
1. 1～3を繰り返してブラッシュアップする

画面設計を最初に行う理由として、実際にクライアントに見てもらうことで要件定義の検討漏れが早期に見つかるためです。
その背景として、クライアント側にこの要件定義で本当に良いの確認してもらう(機能が足りてないことがあるから)必要があるです。

## 画面設計
### UI/UXの考え方
UX(User Experience)：ユーザーにどんな体験をして欲しいか
UI(User Interface)：ユーザーが実際に操作する画面をどう作るか

### UIとUXの違い
UX：画面設計の目的
UI：UXを実現する手段

おしゃれ、使いやすい、直感的などの体験(UX)を実現するために、ボタンの配置やページ遷移の方法(UI)を考える

### タスク指向UI/オブジェクト指向UIの違い
UIにはタスク指向UI/オブジェクト指向UIの2つの考え方があります。
この考え方の違いは、タスク(アクション、行動)を起点に設計しているか、オブジェクト(目的のもの、対象物)を起点に設計しているかの違いです。

#### タスク指向UI：行動・アクション(タスク)を起点に設計
タスク指向UIの例として、銀行ATMや賃貸の検索サイトがあります。
賃貸の検索サイトの場合、①検索方法を選択→条件を絞り込む→③物件表示

#### オブジェクト指向UI：ユーザーが欲しいもの、知りたいこと(情報にフォーカス)
オブジェクト指向UIの例として、フードデリバリーサイトがあります。
フードデリバリーサイトの場合、①一覧から食べたいものを選択→②店舗とメニューを選択→カートに入れる

### オブジェクト指向UIが注目されている？
オブジェクト指向UIが注目されている1番の理由として、**操作が直感的にできる**ことが挙げられます。
日常生活でも私たちは何らかの目的があった上で行動することが多いと思います。
このように、**対象物から行動**に移行する方が自然な考え方です。
オブジェクト指向UIは日常生活と似ているため、直感的で目的にたどり着きやすいUIであるとされています。

参考サイト

https://fastcoding.jp/blog/all/direction/ooui/

## 機能設計
画面設計が終わったら、システムに実装する機能を設計します。
機能設計は**裏側で実行する処理、必要なデータを定める**フェーズです。

### 機能設計で考えること
1. ユーザーの操作の裏側で行われる処理(機能名と処理内容)
1. 処理に必要なデータ、データの取得元(画面から入力、DBから取得等)
1. 処理したデータの受け渡し先(画面表示、DBへ保存)

## データ設計
最後はデータ設計です。

###データ設計で考えること
1. データの具体的な中身
1. DB設計
1. データの流れ(データフロー)

ここで意識すべきことは、データは大きく分けて4種類ある点です。

プログラムに**入力**するデータ
1. 画面からユーザーが入力するデータ
2. データベースから読み取るデータ

プログラムから**出力**するデータ
1. 画面に表示するデータ
1. DBに保存するデータ

# 最後に
これで基本設計の概念整理を終了します。
次回から画面設計に入って行きます。
Windows環境のPowerShellでインターネットからダウンロードしたスクリプトの扱いについて

以前、[Windowsでインターネットからダウンロードしたファイルのブロックについて](https://qiita.com/SAITO_Keita/items/4ce171bce91b6daa5cbf)について記事を書きました。

WindowsのEdgeなどでインターネットからダウンロードしたファイルには、代替データストリームが追加され外部から取得したファイルとして判別されます

PowerShellでは、ps1スクリプトファイルにこの代替データストリームがついている場合。
実行ポリシーによってスクリプト実行時の動作が変わるため説明します。

[実行ポリシーについて](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.3#manage-signed-and-unsigned-scripts)

## 代替データストリームがついているps1ファイルを用意する

どこか外部にps1ファイルを配置して、ブラウザでダウンロードして用意する方法もありますが。
ローカル端末のみで下記コマンドを実行すると、代替データストリームが付与されているファイルを生成できます。

```PowerShell
New-Item -Value "Write-Host HelloWorld" -Path Helloworld.ps1 | Set-Content -Stream "Zone.Identifier" -Value @("[ZoneTransfer]","ZoneId=3")
```

上記コマンドを実行すると下記ファイルが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/ba943c0d-4e41-0829-fea8-5bf651dfdc01.png)

今回はこのファイルをWindows環境のPowerSHellに用意されている、実行ポリシーで実行して動作を確認します。

## 実行環境

- Windows 10 21H2
- PowerShell 7.4.0-preview.1
- Windows PowerShell 5.1.19041.2364

### 実行環境のスコープについて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/a98a82af-b01e-b4b2-be5f-29b728321068.png)

今回、実行している端末の実行ポリシー設定については下記となります。

| Scope         | ExecutionPolicy |
| ------------- | --------------- |
| MachinePolicy | Undefined       |
| UserPolicy    | Undefined       |
| Process       | UndefinedD      |
| CurrentUser   | RemoteSigned    |
| LocalMachine  | RemoteSigned    |


## PowerShellの実行ポリシーについて

Windows環境ではPowerShellの実行ポリシーは下記の種類があります。

- AllSigned
- Bypass
- Default
- RemoteSigned
- Restricted
- Undefined
- Unrestricted

今回は下記のように、プロセススコープを対象にして実行ポリシーを設定してスクリプトを実行します。

```PowerShell
Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope Process
./Helloworld.ps1

Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
./Helloworld.ps1

Set-ExecutionPolicy -ExecutionPolicy Default -Scope Process 
./Helloworld.ps1

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
./Helloworld.ps1

Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope Process
./Helloworld.ps1

Set-ExecutionPolicy -ExecutionPolicy Undefined -Scope Process
./Helloworld.ps1

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process
./Helloworld.ps1
```

実行結果（PowerShell 7)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/97c78bd2-fd09-cb5a-c655-bfeaeff305bd.png)

実行結果画像を確認すると、`Bypass`と`Unrestricted`除いて他の実行ポリシーでは代替データストリームが付与されたスクリプトファイル（外部から取得したスクリプト）は実行失敗していることがわかります。

`Bypass`については無条件でスクリプトが実行されていますが、`Unrestricted`については警告が表示され、実行前に確認が入ります。

またWindows PowreShellでも同様の結果となります。

## 気をつけたいこと

PowerShellスクリプトをWindows端末やサーバーに配置する際。

実行ポリシーとスクリプトファイルの状態によっては、実行が失敗してしまうことがあります。

意図しないエラーを防ぐためにも、環境を準備する際には確認したいポイントです。

## 総評

PowerShellの実行ポリシーについては、過去苦しめられた人も多く。
PowerShellが嫌われる要因の一つな気もします。

実行ポリシーはWindows以外の環境の場合は、`Unrestricted`しかありませんが。Windows環境の場合は色々と選択肢があるので適切に設定して利用したい所です。
CnosDB クライアントのデフォルトの同時実行数は?

CnosDB クラスターへの接続を開始していますが、クライアントの同時実行性を高めたいと考えています：

-t --target-partitions Optional; the number of slices to execute the query, increasing which can increase concurrency. Not specified by default.

指定されていない場合、デフォルトの同時実行レベルは：
クライアントがターゲット パーティションなしで起動すると、コンピューターの CPU コアの数を確認し、この値に設定します。後でドキュメントを更新します。
【Rocky Linux 9】14.Brotli設定（Apache）

## Brotli設定
インターネット通信を新しい圧縮アルゴリズム「Brotli」にて圧縮する

### プラグイン読み込み
```shell-session:/etc/httpd/conf.modules.d/00-brotli.conf
LoadModule brotli_module modules/mod_brotli.so
```

### バーチャルホスト設定
```shell-session:/etc/httpd/conf.d/virtualhost.example.com.conf
<VirtualHost *:80>
    ServerName      example.com
    DocumentRoot    /var/www/example.com
    ErrorLog        logs/example.com/error_log
    CustomLog       logs/example.com/access_log combined env=!nolog
</VirtualHost>

<VirtualHost *:443>
    ServerName      example.com
    DocumentRoot    /var/www/example.com
    ErrorLog        logs/example.com/ssl_error_log
    CustomLog       logs/example.com/ssl_access_log combined env=!nolog
    Protocols       h2 http/1.1

    # Brotli settings
    SetOutputFilter BROTLI_COMPRESS
    SetEnvIfNoCase  Requst_URI \.(bmp|gif|htc|ico|jpe?g|mpe?g|png|swf|woff|ttf)$" no-brotli
    BrotliCompressionQuality 5
    BrotliCompressionWindow 18
    BrotliFilterNote Input instream
    BrotliFilterNote Output outstream
    BrotliFilterNote Ratio ratio
    LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' brotli
    CustomLog "logs/example.com/brotli_log" brotli

    SSLEngine       on
    SSLCertificateFile      /etc/letsencrypt/live/example.com/cert.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
    Header always set Strict-Transport-Security "max-age=31536000"
</VirtualHost>
```

### Apache再起動
```shell-session
systemctl restart httpd
```
C#でAESを使用して文字列を暗号化、複合化する

# 1. はじめに
* C#で文字列をハッシュ化する関数を作りたい
* Microsoft社のAESクラスを使用して暗号化、複合化したい

# 2. AESとは
* 「Advanced Encryption Standard (AES)」の略でアメリカが2001年に標準暗号として定めた共通鍵暗号アルゴリズムである
* AESはSPN構造のブロック暗号で、ブロック長は128ビット、鍵長は128ビット・192ビット・256ビットの3つが利用できる

https://ja.wikipedia.org/wiki/Advanced_Encryption_Standard

# 3. サンプルコード
```csharp:Utility.cs
using System.Security.Cryptography;
using System.Text;

namespace Utility
{
    /// <summary>
    /// 暗号化に関するユーティリティクラス
    /// </summary>
    public static class CryptographyUtil
    {

        // AES暗号化 key生成するための文字列 (256bitキー(32文字))
        private const string _aesKey = "12345678901234567890123456789012";
        // AES暗号化 初期化ベクトルを生成するための文字列 (128bit(16文字))
        private const string _aesIv = "1234567890123456";


        /// <summary>
        /// AESで暗号化する関数
        /// </summary>
        /// <param name="plain_text">暗号化する文字</param>
        /// <returns></returns>
        public static string AesEncrypt(string plain_text)
        {
            // 暗号化した文字列格納用
            string encrypted_str;

            // Aesオブジェクトを作成
            using (Aes aes = Aes.Create())
            {
                // Encryptorを作成
                using ICryptoTransform encryptor =
                    aes.CreateEncryptor(Encoding.UTF8.GetBytes(_aesKey), Encoding.UTF8.GetBytes(_aesIv));
                // 出力ストリームを作成
                using MemoryStream out_stream = new();
                // 暗号化して書き出す
                using (CryptoStream cs = new(out_stream, encryptor, CryptoStreamMode.Write))
                {
                    using StreamWriter sw = new(cs);
                    // 出力ストリームに書き出し
                    sw.Write(plain_text);
                }
                // Base64文字列にする
                byte[] result = out_stream.ToArray();
                encrypted_str = Convert.ToBase64String(result);
            }

            return encrypted_str;
        }


        /// <summary>
        /// AESで復号する関数
        /// </summary>
        /// <param name="base64_text">複合化する文字</param>
        /// <returns></returns>
        public static string AesDecrypt(string base64_text)
        {
            string plain_text;

            // Base64文字列をバイト型配列に変換
            byte[] cipher = Convert.FromBase64String(base64_text);

            // AESオブジェクトを作成
            using (Aes aes = Aes.Create())
            {
                // 復号器を作成
                using ICryptoTransform decryptor =
                    aes.CreateDecryptor(Encoding.UTF8.GetBytes(_aesKey), Encoding.UTF8.GetBytes(_aesIv));
                // 復号用ストリームを作成
                using MemoryStream in_stream = new(cipher);
                // 一気に復号
                using CryptoStream cs = new(in_stream, decryptor, CryptoStreamMode.Read);
                using StreamReader sr = new(cs);
                plain_text = sr.ReadToEnd();
            }
            return plain_text;
        }

    }
}
```

# 4. 参考文献
https://learn.microsoft.com/ja-jp/dotnet/api/system.security.cryptography.aes?view=net-6.0

https://ito-room.com/aes-string-csharp/
【Rocky Linux 9】12.SSL取得（Let's Encrypt）

## SSL証明書取得
ApacheのSSL化、メールサーバーのSSL化のためにSSLを取得する
Let's Encryptでは無料でサーバー証明書を発行してくれるため、これを利用する

### Certbotインストール
CertbotはEPELパッケージに含まれるため、EPELを使用することを明示し、インストールする
```shell-session
dnf --enablerepo=epel install certbot
```

### サーバー証明書取得
| パラメーター | 内容                  |
|:------------|----------------------|
| -w          | ドキュメントルート     |
| -m          | メールアドレス        |
| -d          | ドメイン名            |
| -n          | ユーザー入力を求めない |
| --agree-tos | ACME利用規約に同意する |

```shell-session
certbot certonly --webroot -w /var/www/example.com -m server@example.com -d example.com -n --agree-tos
```

### 取得した証明書の確認
4ファイルが作成されていることを確認する
```shell-session:ls /etc/letsencrypt/live/example.com/
cert.pem
chain.pem
fullchain.pem
privkey.pem
```


### 証明書更新自動化サービスの設定
証明書が自動的に更新された際にApacheを再起動するようにする
```shell-session:/etc/sysconfig/certbot
POST_HOOK="--post-hook 'systemctl restart httpd'"
```

### 証明書更新の自動化
```shell-session
systemctl enable --now certbot-renew.timer
```
【Rocky Linux 9】11.APCu設定（PHP）

## APCu設定
ユーザーデータを共有メモリにキャッシュすることで高速化する。

### APCuインストール
```shell-session
dnf --enablerepo=epel install php-pecl-apcu
```

### APCu設定
基本的にはデフォルトのままで問題無い。
```shell-session:/etc/php.d/40-apcu.ini
; Enable APCu extension module
extension = apcu.so

;       This can be set to 0 to disable APCu
apc.enabled=1

;       Setting this enables APCu for the CLI version of PHP
;       (Mostly for testing and debugging).
;apc.enable_cli=0

;       Sets the path to text files containing caches to load from disk upon
;       initialization of APCu. preload_path should be a directory where each
;       file follows $key.data where $key should be used as the entry name
;       and the contents of the file contains serialized data to use as the value
;       of the entry.
;apc.preload_path=

;       The size of each shared memory segment, with M/G suffixe
;apc.shm_size=32M

;       The number of seconds a cache entry is allowed to idle in a slot in case
;       this cache entry slot is needed by another entry.
;apc.ttl=0

;       The number of seconds that a cache entry may remain on the
;       garbage-collection list.
;apc.gc_ttl=3600

;       If you begin to get low on resources, an expunge of the cache
;       is performed if it is less than half full. This is not always
;       a suitable way of determining if an expunge of the cache
;       should be per apc.smart allows you to set a runtime configuration
;       value which     is used to determine if an expunge should be run
;       if (available_size < apc.smart * requested_size)
;apc.smart=0

;       A "hint" about the number variables expected in the cache.
;       Set to zero or omit if you are not sure;
;apc.entries_hint=4096

;       The mktemp-style file_mask to pass to the mmap module 
apc.mmap_file_mask=/tmp/apc.XXXXXX

;       On very busy servers whenever you start the server or
;       modify files you can create a race of many processes
;       all trying to cache the same data at the same time.
;       By default, APCu attempts to prevent "slamming" of a key.
;       A key is considered "slammed" if it was the last key set,
;       and a context other than the current one set it ( ie. it
;       was set by another process or thread )
;apc.slam_defense=0

;       Defines which serializer should be used
;       Default is the standard PHP serializer.
;apc.serializer='php'

;       use the SAPI request start time for TTL
;apc.use_request_time=0

;       Enables APCu handling of signals, such as SIGSEGV, that write core files
;       when signaled. APCu will attempt to unmap the shared memory segment in
;       order to exclude it from the core file
;apc.coredump_unmap=0
```

### PHP-FPM再起動
```shell-session
systemctl restart php-fpm
```

### APCu動作状況確認
apc.phpを利用する
（krakjoe / apcu：https://github.com/krakjoe/apcu）
sipsコマンドでの--setPropertyの使い方

--setPropertyは、sipsコマンドで画像のプロパティを変更するためのオプションです。このオプションを使用することで、画像ファイルのEXIFデータなどのメタデータを変更することができます。

--setPropertyオプションは、次のように使用します。

```shell
sips -s property <property_name> <property_value> <image_file>
```

ここで、<property_name>はプロパティの名前を、<property_value>は設定する値を、<image_file>は変換する画像ファイルのパスを指定します。

例えば、以下のコマンドを使用することで、画像のキャプションを設定することができます。

```shell
sips -s property caption "This is a caption" image.jpg
```



また、--setPropertyオプションは、-dオプションと併用することで、元の画像ファイルからコピーすることもできます。-dオプションを指定することで、元のファイルのプロパティをコピーし、--setPropertyオプションを使用して、プロパティの値を変更します。

例えば、以下のコマンドを使用することで、元の画像ファイルのプロパティをコピーし、タイトルを「My Title」と設定することができます。

```shell
sips -d copy --setProperty title "My Title" image.jpg
```

このように、--setPropertyオプションを使用することで、画像ファイルのメタデータを変更することができます。
【Rocky Linux 9】09.PHP設定

## PHP設定
WordPressなどのPHPで動作するシステムを動かすためにPHPをインストール・設定する

### PHPインストール
```shell-session
dnf install php php-{bcmath,cli,common,devel,fpm,gd,intl,ldap,mbstring,mysqlnd,opcache,pdo,xml}
```

### Apache設定
* Apacheはpreforkではなくeventで動作するため、PHPはPHP-FPMにproxyにてUNIXソケット、もしくはfcgiに流すことになる
* ```proxy_module```と```proxy_fcgi_module```を読み込ませる
```shell-session:/etc/httpd/conf.modules.d/00-proxy.conf
# This file configures all the proxy modules:
LoadModule proxy_module modules/mod_proxy.so
#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
#LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
#LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
#LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
#LoadModule proxy_connect_module modules/mod_proxy_connect.so
#LoadModule proxy_express_module modules/mod_proxy_express.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so
#LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
#LoadModule proxy_http_module modules/mod_proxy_http.so
#LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so
#LoadModule proxy_scgi_module modules/mod_proxy_scgi.so
#LoadModule proxy_uwsgi_module modules/mod_proxy_uwsgi.so
#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
```

### PHP設定
```shell-session:/etc/php.ini
[PHP]
zend.multibyte = On
zend.script_encoding = UTF-8
expose_php = Off
log_errors_max_len = 4096
html_errors = On
post_max_size = 32M
upload_max_filesize = 16M
auto_detect_line_endings = On

[Date]
date.timezone = "Asia/Tokyo"

[iconv]
iconv.internal_encoding = UTF-8

[Session]
session.use_only_cookies = 0
session.use_trans_sid = 1

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = "ASCII,ISO-2022-JP-MS,UTF-8,CP51932,SJIS-win"
mbstring.http_output = pass
mbstring.encoding_translation = On
mbstring.detect_order = "ASCII,ISO-2022-JP-MS,UTF-8,CP51932,SJIS-win"
mbstring.substitute_character = none
```

### PHP-FPM起動・自動起動
```shell-session
systemctl enable --now php-fpm
```
【Rocky Linux 9】08.バーチャルホスト設定（Apache）

## バーチャルホスト設定
IPアドレスのドキュメントルートは「/var/www/html」、バーチャルホストのドキュメントルートは「/var/www/バーチャルホスト名」とする
ログファイルもバーチャルホスト用のディレクトリを作成して保存するようにし、ログローテートスクリプトも編集する

### ローカルホスト用バーチャルホスト設定
```shell-session:/etc/httpd/conf.d/virtualhost.localhost.conf
<VirtualHost *:80>
    ServerName      localhost
    DocumentRoot    /var/www/html
    ErrorLog        logs/error_log
    CustomLog       logs/access_log combined env=!nolog
</VirtualHost>
```

### メインホスト用バーチャルホスト設定
```shell-session:/etc/httpd/conf.d/virtualhost.example.com.conf
<VirtualHost *:80>
    ServerName      example.com
    DocumentRoot    /var/www/example.com
    ErrorLog        logs/example.com/error_log
    CustomLog       logs/example.com/access_log combined env=!nolog
</VirtualHost>
```

### メインホスト用ディレクトリ設定
```shell-session
mkdir /var/www/example.com
chmod 777 /var/www/example.com
mkdir /var/log/httpd/example.com
```

### Apache再起動
```shell-session
systemctl restart httpd
```

### logrotateスクリプト修正
```diff_shell:/etc/logrotate.d/httpd
# Note that logs are not compressed unless "compress" is configured,
# which can be done either here or globally in /etc/logrotate.conf.
- /var/log/httpd/*log {
+ /var/log/httpd/*log /var/log/httpd/*/*log {
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
    endscript
}
```
負荷に関する知見

# これはなんですか
負荷試験と呼ばれるものと、継続的な改善に関するアプローチの仕方について簡単に述べたもの。

# 負荷とは
負荷とは２つの観点を持つ。

1. アクセスに関するもの
   時間あたりのアクセス数量。
   俗にいうAPIアクセス(TPS)やアクティヴユーザ数、同時接続数、View数のこと。
   ストアやストレージの読み取り速度がサービスの質に直結する場合はReadやWrite速度も勘案。
   イメージは人通り。狭い道ではたくさんの人は通れない。
1. ストアされているデータ量
   契約ユーザ数○○、紐づくデータ数
   ストレージであれば○○MiBやオブジェクトの数, DBでいえば各種テーブルの行数など、蓄積されていくもの。
   イメージは溶けない雪、しんしんと降り積もる。でも適切に受け入れればちゃんと生活できる。

# 負荷試験について
サービスの成長曲線から予測するのが一番フィットした感じかなと思いますが、だいたい想定の十倍くらいを上限とするのがよいかなと思います。

上記２つの観点から想定をだします。
実施にあたって必要なのは下記
1. 自動化された1.テストの作成
1. ストアされるデータの構築。

ユーザ数はたとえば１０万人を見込んでいるなら１００万人で負荷試験を回す。
１００万ユーザと、それに付属するデータの整備である。
何日かAPIをループで回して作ってもいいし、DBに直接叩き込んでも良い。

その１００万人がどのようなアクセスをするのか、バックヤードの業務は回るのか。

この時、テストケースがきちんと動作するようなチューニングをアプリケーション、インフラストラクチャ、データストアに対して行う。

# 運用
クラウドの利点を最大限に活用すること。
最初から１００万人を想定したspecの設定はお金の浪費なのでやらない。
負荷に対するロードマップや見直しポイントをたてて負荷にあわせ適切な施策や、ボリュームを確保する。

# 継続的な改善
最初から徹底的にやろうとしない。
ローンチするときに負荷試験をやったあとは、その後やらないことがほとんどなので漏れ出る改善点は出てくる。
たとえば追加されたfeatureに対する徹底した負荷試験はあまりやっているところを見ないので、どこかで人間やシステムが我慢できなくなるポイントに行き当たる。
そういうところは最初にやった負荷試験の知見をもとに、少しの全体最適と全力の部分最適化の探究で乗り切るといいんじゃないでしょうか。

たまに負荷試験用の環境やデータを維持するリッチな開発現場もあるけれど、負荷試験環境の構築を自動化できてるほうが望ましいと思う。
【Rocky Linux 9】06.chrony設定

## chrony構築
* サーバー上の時間を日本標準時間に自動的に合わせる

### chronyインストール
```shell-session
dnf install chrony
```

### chrony設定
* 日本のサーバーでStratum1のNTPサーバーと同期したい場合は```ntp.nict.jp```を設定する
* 日本のサーバーでIXに近いNTPサーバーと々期したい場合は```ntp.jst.mfeed.ad.jp```を設定する（Stratum2）
* 海外のサーバーの場合は、```pool.ntp.org```や```time.google.com```、```time.cloudflare.com```などを設定する
```shell-session:/etc/chrony.conf
# 時刻同期先サーバー変更
pool ntp.nict.jp iburst
```

### chrony起動
手動で時刻を合わせてから起動させ、自動起動にする
```shell-session
chronyc makestep
systemctl restart chronyd
systemctl enable chronyd
```

### chrony確認
```shell-session
chronyc sources
```
NTPサーバー名の前に「*」または「+」が表示されていれば時刻同期中である


# 参考サイト
https://centossrv.com/almalinux/chrony.shtml
【Rocky Linux 9】05.Vim設定

## Vim設定
* デフォルトでインストールされているのはvim-minimalではるが、高機能版であるvim-enhancedをインストールする
* 独自設定は```/etc/vimrc```ではなく```/etc/vimrc```が読み込んでいる```/etc/vimrc.local```に記述する

## vim-enhancedインストール
```shell-session
dnf install vim-enhanced
```
## Vim設定
```shell-session:/etc/vimrc.local
" 文字コードの自動認識
if &encoding !=# 'utf-8'
  set encoding=japan
  set fileencoding=japan
endif
if has('iconv')
  let s:enc_euc = 'euc-jp'
  let s:enc_jis = 'iso-2022-jp'
  " iconvがeucJP-msに対応しているかをチェック
  if iconv("\x87\x64\x87\x6a", 'cp932', 'eucjp-ms') ==# "\xad\xc5\xad\xcb"
    let s:enc_euc = 'eucjp-ms'
    let s:enc_jis = 'iso-2022-jp-3'
  " iconvがJISX0213に対応しているかをチェック
  elseif iconv("\x87\x64\x87\x6a", 'cp932', 'euc-jisx0213') ==# "\xad\xc5\xad\xcb"
    let s:enc_euc = 'euc-jisx0213'
    let s:enc_jis = 'iso-2022-jp-3'
  endif
  " fileencodingsを構築
  if &encoding ==# 'utf-8'
    let s:fileencodings_default = &fileencodings
    let &fileencodings = s:enc_jis .','. s:enc_euc .',cp932'
    let &fileencodings = &fileencodings .','. s:fileencodings_default
    unlet s:fileencodings_default
  else
    let &fileencodings = &fileencodings .','. s:enc_jis
    set fileencodings+=utf-8,ucs-2le,ucs-2
    if &encoding =~# '^\(euc-jp\|euc-jisx0213\|eucjp-ms\)$'
      set fileencodings+=cp932
      set fileencodings-=euc-jp
      set fileencodings-=euc-jisx0213
      set fileencodings-=eucjp-ms
      let &encoding = s:enc_euc
      let &fileencoding = s:enc_euc
    else
      let &fileencodings = &fileencodings .','. s:enc_euc
    endif
  endif
  " 定数を処分
  unlet s:enc_euc
  unlet s:enc_jis
endif
" 日本語を含まない場合は fileencoding に encoding を使うようにする
if has('autocmd')
  function! AU_ReCheck_FENC()
"    if &fileencoding =~# 'iso-2022-jp' && search("[^\x01-\x7e]", 'n') == 0
      let &fileencoding=&encoding
"    endif
  endfunction
  autocmd BufReadPost * call AU_ReCheck_FENC()
endif
" 改行コードの自動認識
set fileformats=unix,dos,mac
" □とか○の文字があってもカーソル位置がずれないようにする
if exists('&ambiwidth')
  set ambiwidth=double
endif

"--------------------
" 検索設定
"--------------------
" 検索時に大文字小文字を無視する
set ignorecase
" インクリメンタルサーチを有効にする
set incsearch
" 検索時にハイライトを無効にする
set nohlsearch
" 検索の循環
set wrapscan

"--------------------
" 表示設定
"--------------------
" シンタックスハイライト
syntax on
" 行番号を表示する
set number
" 対になる括弧を表示する
set showmatch
" モードを表示する
set showmode
" ルーラーを表示する
set ruler
" 高度な自動インデントを行う
set smartindent
" 編集中のファイル名を表示する
set title
" Shift+矢印キーで選択できるようにする
set keymodel=startsel

"--------------------
" 編集設定
"--------------------
" auto indentを有効にする
set autoindent
" タブの代わりに空白文字を挿入する
set expandtab
" タブをスペース4つ分にする
set tabstop=4
" 上の行の末尾の文字を1文字消去する
set backspace=2
" シフト移動幅を4にする
set shiftwidth=4
" 見た目のtabstopを変える
set softtabstop=4
```
【Rocky Linux 9】04.Bash設定

## Bash設定
* /etc/bashrcをいじらず、/etc/bashrcが読み込んでいる/etc/profile.d/*.shに配置する
* ログイン後の画面をカスタム
* コマンドエイリアスを追加

```shell-session:/etc/profile.d/user_settings.sh
# 一番下に追記する
case ${UID} in
    0)
        PS1='\[\e[1;35m\]\H\[\e[0m\] \[\e[4;31m\]\[\e[1;31m\]${PWD}\[\e[0m\]\[\e[1;31m\]\$\[\e[0m\] '
        PS2='\[\e[1;31m\]>\[\e[0m\] '
        ;;
    *)
        PS1='\[\e[0;35m\]\H\[\e[0m\] \[\e[4;34m\]${PWD}\[\e[0m\]\[\e[0;34m\]\$\[\e[0m\] '
        PS2='\[\e[0;34m\]>\[\e[0m\] '
        ;;
esac

HISTTIMEFORMAT='%Y-%m-%d %T '
export HISTTIMEFORMAT

PATH="$PATH:/usr/local/sbin:/usr/local/bin"
export PATH

alias ls='ls --color=tty -F'
alias ll='ls --color=tty -Flh'
alias la='ls --color=tty -FlhA'
alias mv='mv -i'
alias cp='cp -i'
alias rm='rm -i'
alias vi='/usr/bin/vim'
```

当該変更は、次回のログイン時以降、適用されるようになる。
即時適用するには、```source /etc/profile```を実行する。
【Rocky Linux 9】02.SSH設定

## SSHの設定
* 「root」でログインさせない
* 空のパスワードでログインさせない
* パスワードではなく鍵認証とする
```shell-session:/etc/ssh/sshd_config
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthenticatio no
PermitEmptyPasswords no
```

### SSH再起動
再起動させると同時に、自動起動としておく。
```shell-session
systemctl stop sshd.service
systemctl enable --now sshd.service
```

## 鍵認証設定
一般ユーザーで行う

### 鍵認証用の鍵ペア作成
色々と問われるが、全て「空Enter」とする
```shell-session
ssh-keygen -t ed25519 -a 256
```
・パスフレーズを設定する場合
```shell-session
ssh-keygen -t ed25519 -a 256 -N "パスフレーズ"
```
・GitHubで使用する書きを作成する場合
```shell-session
ssh-keygen -t ed25519 -a 256 -C user@example.com
```

### 公開鍵設定
```shell-session
cd
cat .ssh/id_ed25519.pub > authorized_keys
chmod 600 .ssh/authorized_keys
rm -f .ssh/id_ed25519.pub
```

### 秘密鍵設定
秘密鍵は、一般ユーザーのホームディレクトリに移動した後の```.ssh/id_ed25519```となる。
重要なファイルであるため、SCP等で移動させ、ローカルに保存しておく。
この秘密鍵を利用し、サーバーへと公開鍵接続を行う
Windowsの場合、
https://kmiya-culti.github.io/RLogin/
https://www.ranvis.com/putty
https://poderosa.sourceforge.net/index-ja.html
このあたりのSSHクライアントがオススメです。
【Rocky Linux 9】01.初期設定

## パッケージ管理システム（dnf）設定

### EPELインストール
```shell-session
dnf install epel-release
dnf clean all
```

### EPEL設定
EPELを使用すると明示しないとEPELパッケージを取得しないようにする
```diff_shell:/etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux $releasever - $basearch
# It is much more secure to use the metalink, but if you wish to use a local mirror
# place its address here.
#baseurl=https://download.example/pub/epel/$releasever/Everything/$basearch/
metalink=https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch&infra=$infra&content=$contentdir
- enabled=1
+ enabled=0
gpgcheck=1
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$releasever
```

### インストール済パッケージの一括アップデート
```shell-session
dnf -y update
```

### ベース・開発ツールパッケージ群インストール
```shell-session
dnf -y groupinstall base "Development tools"
```

### dnf-automaticインストール
``` shell-session
dnf -y install dnf-automatic
```

### dnf-automatic設定ファイル編集
```diff_shell:/etc/dnf/automatic.conf
# Whether updates should be applied when they are available, by
# dnf-automatic.timer. notifyonly.timer, download.timer and
# install.timer override this setting.
- apply_updates = no
+ apply_updates = yes
```

### dnf-automatic起動・自動起動
```shell-session
systemctl enable --now dnf-automatic-install.timer
```

## SELinuxの無効化
```shell-session:/etc/sysconfig/selinux
SELINUX=disabled
```
SELINUXが「enforcing」になっており、これを「disabled」に変更した場合は、システムの再起動が必要となる。

## 不要パッケージの削除

### Cockpit削除
```shell-session
dnf remove cockpit
```

---

## 参考サイト
https://centossrv.com/almalinux/almalinux8-init.shtml
【Rocky Linux 9】00.前提条件・目次

## 作成するサーバー
初期設定（SSH + firewalld）
Webサーバー（Apache + PHP + VirtualHost + SSL）
データベースサーバー（MariaDB）
サーバー監視（Zabbix）
メールサーバー（Postfix + Dovecot + SSL）

## サーバーネットワーク
IPアドレス：10.10.10.10
ドメイン名：example.com

## 目次
[【Rocky Linux 9】01.初期設定](https://qiita.com/T_Tsan/items/2c48a87e1c21fa01fc5d)
[【Rocky Linux 9】02.SSH設定](https://qiita.com/T_Tsan/items/5943685891078bbdc217)
[【Rocky Linux 9】03.firewalld](https://qiita.com/T_Tsan/items/bb10197fa37af9e0d545)
[【Rocky Linux 9】04.Bash設定](https://qiita.com/T_Tsan/items/6b4ccff142311adb2ac0)
[【Rocky Linux 9】05.Vim設定](https://qiita.com/T_Tsan/items/0c273e8dac035eb79748)
[【Rocky Linux 9】06.chrony設定](https://qiita.com/T_Tsan/items/adcc4e822aa79eab9cef)
[【Rocky Linux 9】07.Apache設定](https://qiita.com/T_Tsan/items/9c456c4ce503b5339b11)
[【Rocky Linux 9】08.バーチャルホスト設定（Apache）](https://qiita.com/T_Tsan/items/daf8a199dcc01b77b528)
[【Rocky Linux 9】09.PHP設定](https://qiita.com/T_Tsan/items/43619d71235ae415a96b)
[【Rocky Linux 9】10.OPcache設定（PHP）](https://qiita.com/T_Tsan/items/fad43d33a44bf1bd214e)
[【Rocky Linux 9】11.APCu設定（PHP）](https://qiita.com/T_Tsan/items/644bd8561ef128f717ab)
[【Rocky Linux 9】12.SSL取得（Let's Encrypt）](https://qiita.com/T_Tsan/items/df2646aa1eddaa359fa9)
[【Rocky Linux 9】13.SSL設定（Apache）](https://qiita.com/T_Tsan/items/aaf3e9a7c4eac52c6457)
[【Rocky Linux 9】14.Brotli設定（Apache）](https://qiita.com/T_Tsan/items/922e154311d6640a0670)
[【Rocky Linux 9】15.MariaDB設定](https://qiita.com/T_Tsan/items/ad97d50110537adb83c0)
[【Rocky Linux 9】16.Zabbix設定](https://qiita.com/T_Tsan/items/4b4d9c302bc1531c3312)
[【Rocky Linux 9】17.ZabbixWeb設定](https://qiita.com/T_Tsan/items/beb8f360222a510bfd36)
プライベートなリポジトリのGithub Actionsを他リポジトリでも共有し利用する

## はじめに

Github Actionsをいくつか作ってチームでも運用していくなかで、他チームや別リポジトリにも展開がしたくなりましたが、publicなリポジトリを作らないとだめかなと思っていたところ、割りと最近に同じユーザーや組織内のprivateなリポジトリのActionを共有できるようになったそうなので試してみました。

https://github.blog/changelog/2022-12-14-github-actions-sharing-actions-and-reusable-workflows-from-private-repositories-is-now-ga/

## 必要な準備

[公式ドキュメント](https://docs.github.com/en/enterprise-cloud@latest/actions/creating-actions/sharing-actions-and-workflows-with-your-enterprise)にも書いてありますが、設定の許可が必要になります。

>他の内部リポジトリまたはプライベート リポジトリのワークフローへのアクセスを許可するようにリポジトリを構成します。詳細については、「リポジトリの GitHub Actions 設定の管理」および「リポジトリの GitHub Actions 設定の管理」を参照してください。

具体的には、リポジトリのSettings→ActionのGeneralから以下画像の選択肢にチェックを入れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/080ad7a7-059c-f452-c419-a854f5965aa6.png)

あとは、共有したいアクションをリポジトリに準備しておけば完了です。

## 使ってみる

以下、アクセスしてみただけの機能も何もない実行結果ですが、しっかり認識されていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/243820b6-5fbf-f4e6-a7b0-738e746bdbd7.png)


## 最後に

個人で利用することはそんなにないかもですが、社内での共通的な仕組みづくりなんかで役に立ちそうですね。

## 2023/3/9 補足

確認中に自分も知らなくてハマってしまったので備忘録として記載しておきます。

actisonの共有はただusesで使うだけで問題ないのですがworkflowsの共有は以下の注意点があります。

- 共有元となるワークフローのon条件には、`workflow_call`で必要であれば引数などを指定すること
- 呼び出し側では、ワークフローはStepのタスクとしてではなくてjobsの直下で呼び出さないといけない

具体的には以下のように書かないとアクションがエラーとなってしまうため注意が必要。

```yml
name: test action

on:
  workflow_dispatch:
  
jobs:
  private_action:
    uses: yus-sasaki/SampleDocs/.github/workflows/IssuesAssignAuthor.yml@main
```
sipsコマンドで、元の画像の撮影日時を維持す方法

sipsコマンドで画像を変換する場合に、元の画像の撮影日時を維持するには、-dオプションを使用します。-dオプションを使用することで、元の画像の撮影日時を新しい画像にコピーすることができます。

以下は、sipsコマンドでJPEG形式に変換する際に、元の画像の撮影日時を維持するための例です。

```shell
sips -s format jpeg -d copy --setProperty formatOptions 85 input.jpg --out output.jpg
```
アプリコードをUbuntu内に入れたらnode run ができなくなった

### Dockerってホントにむずい
画面共有してたら「え、ローカル環境遅くない？？」って言われて
WSL上にあるはずだけどな？？と思ってはいたけど、
なんせこれが初めての案件なもんで
遅いも早いも比べる対象がない。（笑）

### アプリコードをUbuntuの領域に入れないと
https://qiita.com/minato-naka/items/84508472c04f628e576e
こちらの記事を参考に
Ubuntu領域にコピーしました。

### 動かしてみた
前までのローカル環境では考えられないぐらいのスピード
そりゃ遅いとあおられるわけですね。

### コンパイルしてみる
これまで通り
```
node run dev
 ```
でコンパイルしてみると

```
run dev
Creating node_run ... done

> dev
> npm run development


> development
> mix

sh: 1: mix: Permission denied
ERROR: 126
```
こんなエラーが吐き出された

なんか権限回りのことみたい


こちらの記事を参考にしました。
https://inno-tech-life.com/dev/js/ts-error-permission-denied/
本当にありがとうございます。

一度C直下でnodeをinstallしたから
WSLの領域内に入るとユーザーが変わるんですね…

忘れないようにします。
npmのパッケージやgoのモジュールのライセンスファイルを一つにまとめるシェルを作った

最近、vue+Goでwebアプリを作成している駆け出しエンジニアです。
今回は、`npm`と`go`のパッケージやモジュールについて、LICENSEファイルを一つのjsonにまとめるシェルを作成しました。

# 経緯

バックでもフロントの両方でオープンソースのパッケージやモジュールを使用しているのですが、一ライセンス周りでつまづきました。
LICENSEファイルを転記するには数が多すぎる。

世の中にはnpmの[license-checker](https://www.npmjs.com/package/license-checker)やgoの[go-licenses](https://github.com/google/go-licenses)など、驚くほどに便利なツールがあるのですが、LICENSEファイルをまとめてくれる機能は無いようです。

そこで、今回は上記の`license-checker`と`go-licenses`を拡張したPowerShellを書いてみました。
GitHubにアップロードしたので、よければご利用ください。
使い方の詳細は`README.md`をご参照ください。

https://github.com/HoppingGanon/get-licences

# 結果
テストで作ってみたvueのアプリに使ってみると・・・

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884998/29b7c170-841b-9f49-1f46-ce2acbbf26d7.png)

しっかり出力されています。

![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884998/743b542b-b2a2-1c41-d83c-0c3dcf2bd515.png)

Goも同様に出力してみますが、こちらはモジュールの2階層の部分だけをインポートしてるため、1階層目にあるライセンスファイルを取得できなかったようです。こういったケースはままあると思うのですが、ちょっと複雑な動きになりそうなので手作業で追加することにしました。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884998/65cb8e39-5c8c-323a-bc0b-af3fc94a706e.png)

エラーはありましたが、数十件分の作業は自動化できたので、役立たずではなさそうです。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884998/9bec272d-fb8b-a871-0046-dc5ef0a23b00.png)


以上です。
ライセンス表記は先人の技術や知恵に対して最低限の敬意思うので、気を付けたいです・・・
この記事について間違い等ありましたらコメントでご指摘いただけると助かります。
【Astar】EVM上の資産をNativeの資産に変換する方法

![](https://storage.googleapis.com/zenn-user-upload/c3e26f233110-20230225.jpeg)

皆さん、こんにちは！

現在、akindoさん、Astar Network、slash主催のハッカソンに参加しているのですが、Native上の資産を入手するで躓いたのでメモとしてブログ記事にまとめます！

https://app.akindo.io/hackathons/K8mdAL3qEhnBaakA

今回、AstarNetworkのハッカソンではprive獲得の対象となるためにメインネットにWASMコントラクトをデプロイする必要がありましたが、EVM⇨Nativeの資産に変換したことが一度もなかったのでこれを機にやってみました！

ちょうどUNCHAINの build to earnでAstarを入手していたのでチャレンジできます！
Astarが必要になりますので、まだ持っていない方はJPYCを購入し、DEXでAstarに変換するなどして用意しておいてください！

ちなみに下記コースをクリアすると今なら 1000Astarもらえます！

https://app.unchain.tech/learn/ASTAR-SocialFi


全体の流れは以下の通りです！

1. **すでにAstarをEVMで保有している場合**

:::note info
① ArthSwapで AStar を WSDNにSwap
② AstarPortalに移動してbridgeのページに遷移
③ AstarNetwork上のWSDNをShiden Network上のSDNへbridge
④ EVMのアドレスからNativeのアドレスにtransfer
⑤ AstarPortalに移動してETH Withdraw
:::

2. **Astarを持っていない場合**

:::note info
① JPYCを購入 (**Astar Network上で発行してもらうこと！**)
② ArthSwapでJPYCとAstarを変換
③ ArthSwapで AStar を WSDNにSwap
④ AstarPortalに移動してbridgeのページに遷移
⑤ AstarNetwork上のWSDNをShiden Network上のSDNへbridge
⑥ EVMのアドレスからNativeのアドレスにtransfer
⑦ AstarPortalに移動してETH Withdraw
:::

JPYCでのAstar購入は割愛させていただきます。

## ① ArthSwapで AStar を WSDNにSwap

まずは、ArthSwapで AStar を WSDNにSwapしましょう！ 

![](https://storage.googleapis.com/zenn-user-upload/cf22abe6488c-20230225.png)

うまくSwapできれば下記のようなポップアップが表示されます！

![](https://storage.googleapis.com/zenn-user-upload/a460849adfee-20230225.png)

Metamaskで増えていることが確認できました！

![](https://storage.googleapis.com/zenn-user-upload/6a713a971cd9-20230225.png)

## ② AstarPortalに移動してbridgeのページに遷移

次にAstar上にあるWSDNをShidenNetwork上に移動させます！

Bridgeリンクを押しましょう！

![](https://storage.googleapis.com/zenn-user-upload/46f954c15e41-20230225.png)

## ③ AstarNetwork上のWSDNをShiden Network上のSDNへbridge

Swapしたい金額を指定してブリッジしましょう!

:::message
最低必要金額を保有していない場合、エラーになる可能性があるのである程度のWSDNは保有しておいた方が良いです！
:::

![](https://storage.googleapis.com/zenn-user-upload/6d203b7be1fc-20230225.png)

うまくいけば下記の用になります！

![](https://storage.googleapis.com/zenn-user-upload/d84bead15e26-20230225.png)

## ④ EVMのアドレスからNativeのアドレスにtransfer

さぁ！　いよいよNativeに資産を変換します！

送金先のアドレスを Nativeのアドレスで指定して Transferしましょう！

![](https://storage.googleapis.com/zenn-user-upload/1778e1ffb1e5-20230225.png)

私の場合はこうなりました！
![](https://storage.googleapis.com/zenn-user-upload/b053f0972acd-20230225.png)


Metamaskのポップアップはこんな感じで出力されます！

![](https://storage.googleapis.com/zenn-user-upload/053582b8230d-20230225.png)


## ⑤ AstarPortalに移動してETH Withdraw

ここまできたらあと一歩です！

Astar-PortalにアクセスしてShidenNetworkの資金を確認すると EVM Withdrawのところの数値が増えているはずなのでこれをクリックしましょう！

https://portal.astar.network/#/shiden/assets

署名が求められるのでパスワードを入力して資産を引き出すことができるのでこれで完了です！

![](https://storage.googleapis.com/zenn-user-upload/dc5f34f58067-20230225.png)

しばらくすると処理が完了して、ちゃんと資産として残高が増えているはずです！！

![](https://storage.googleapis.com/zenn-user-upload/9ade8032efd6-20230225.png)

**増えてました！**

メインネットにWASMコントラクトをデプロイできるようになりました！！！

ちょっとステップが多いですが、今後WASMコントラクトを開発していく上では重要なテクニックになりそうです！
ハッカソンに出て腕を磨いていきます！！
Deviseを導入した場合のSeedの作成方法まとめ

## ■環境

- Rails 7.0.4
- Devise 4.8.1

## ■記事を書いた経緯

- rails:db:resetするたびにサンプルユーザーを登録（メール認証）するのがめんどくさかったため、DeviseのUserモデルにサンプルユーザーを作ったところ詰まりました。こんなつまらないことに時間を使うのは勿体無いので、他の初学者の方の参考になれば嬉しいです。

## ■前提

- Deviseでユーザー登録・ログイン／ログアウト・メール認証（有効化・パスワード再設定）・リメンバー機能を実装しております。
- モデル名はuser.rbです。

## ■作成方法

Confirmation（メール認証機能）を利用していない場合

```seed.rb
User.create!( email: "example@gmail.com",
              password:              "foobar")
```

Confirmation（メール認証機能）を利用している場合

```seed.rb
User.create!( email: "example@gmail.com",
              password:              "foobar", 
              confirmed_at: Time.now)
```

ちなみにメールアドレスにはバリデーションがかかっているのでなるべく存在するメールアドレスを記載することをお勧めします（Guthub等でコード管理している場合は環境変数等に設定することをお勧めします）。
for文で同期処理を行いたいときの注意点

Vueでループ処理を書く機会があり、非同期ではなく同期処理をしたい時に躓いたのでメモしておきます。

処理をループして行いたい時に`forEach`を利用すると１回目の処理の結果に関わらず非同期に処理が行われるため
オブジェクト内の処理が並列実行されてしまう
⇨この場合、前の処理の結果を参照して次の処理を行うことができない。

また、以下のようにforEach内にawait処理を行なっても失敗してしまう。
```
const func = async ()=>{
       const list = [1,2,3];
       list.forEach( index =>{ await sample(index); } );
};
```
同期処理、直列処理を行いたい場合はfor文,`for-await-of`を利用する
以下のようにすることで一周目の処理の結果を待った後、次の処理は走らせることができます。
```
const func = async ()=>{
    const list = [1,2,3];
    for await ( const index of list ){
        function sample( index );
    }
};
```
Nuxt3 / Vue3 – v-for の中で v-model を使う

# 配列の例

```js
<template>
  <div>
    <form>
      <dl v-for="person in people">
        <dt>{{ person.name }}</dt>
        <dd>
          <input v-model="person.value">
          {{ person.value }}
        </dd>
      </dl>
      <input type="submit" @click="submit">
    </form>
  </div>
</template>

<script setup lang="ts">

function submit(event){
  event.preventDefault()

  console.log(people.value)
}

const people = ref(
  [
    { name: "Alice", value: '' },
    { name: "Bob", value: '' },
    { name: "Carorl", value: '' },
  ]

)
</script>
```

![image](https://user-images.githubusercontent.com/13635059/221751950-70860bdc-fbee-4426-a125-f118f75a0e5c.png)

# 連想配列の例

```js
<template>
  <div>
    <form>
      <dl v-for="(person, key) in people">
        <dt>{{ key }}</dt>
        <dd>
          <input v-model="person.value">
          {{ person.value }}
        </dd>
      </dl>
      <input type="submit" @click="submit">
    </form>
  </div>
</template>

<script setup lang="ts">

function submit(event){
  event.preventDefault()

  console.log(people.value)
}

const people = ref(
  {
    alice: { value: '' },
    bob: { value: '' },
    carol: { value: '' },
  }

)
</script>
```

![image](https://user-images.githubusercontent.com/13635059/221754565-a745a84d-dd2f-421c-bd93-4b173d26ccbd.png)


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
開発サーバーにあるリモートリポジトリを、SSHでローカル環境にクローンする

Gitのリモートリポジトリは、Github等のサービスを利用してホスティングするケースが多いかと思いますが、自前の開発サーバー等でホスティングしている場合に、ローカル環境にクローンする方法をご紹介します。

## 前提

ローカル環境から該当のサーバーへのSSH接続できるよう```~/.ssh/config```は以下のように設定済み、公開鍵もサーバーに配置済みとします。

```:~/.ssh/config
host develop
    user xxxxx
    hostname 192.0.2.0
    port xxxxx
    identityfile ~/.ssh/id_rsa
```

また、今回クローンしたいサーバー上のリモートリポジトリのパスは```/var/local/repo/hoge.git```、ローカル環境でGitリポジトリを管理しているディレクトリが```~/repo```であったとします。

## ローカル環境にクローン

ローカル環境にて以下を実行します。
```bash
cd ~/repo
git clone develop:/var/local/repo/hoge.git
```

これで、クローンしたリポジトリが```~/repo/hoge```に作成されました。

## おわりに

sshの接続設定を済ませていればシンプルなコマンドでクローン出来ました。
前職ではずっとGithubしか使っていなかったので、リポジトリのページで提示されるURLを```git clone```コマンドに渡せば良かったですが、自前サーバーでホスティングしている場合のクローン方法で迷ってしまったので、今回記事にしてみました。
[複数同時圧縮対応]コマンドを使って、Macで画像を圧縮する方法

Macで画像を圧縮するためには、以下のコマンドを使うことができます。

sipsコマンドを使用する方法：
```shell
sips -s format jpeg -s formatOptions 90 input_file -o output_file
```


このコマンドでは、input_fileで指定されたファイルをJPEG形式に変換し、品質を90％に設定してoutput_fileに保存します。

convertコマンドを使用する方法：
```shell

convert -quality 90 input_file output_file
```


このコマンドでは、input_fileで指定されたファイルをJPEG形式に変換し、品質を90％に設定してoutput_fileに保存します。

どちらのコマンドも、圧縮したい画像ファイルのパスをinput_fileに指定し、保存先のファイル名をoutput_fileに指定します。また、必要に応じて品質設定を調整することができます。


以下は、Automatorのクイックアクションでsipsコマンドを使って画像を圧縮するためのスクリプトです。このスクリプトは、複数のファイルを選択した場合にも動作するようになっています。

```shell
for f in "$@"
do
  if [ -f "$f" ]
  then
    # 圧縮率を設定する（85%）
    QUALITY=85

    # ファイル名と拡張子を分離する
    filename=$(basename "$f")
    extension="${filename##*.}"
    filename="${filename%.*}"

    # 新しいファイル名を作成する
    new_filename="${filename}_compressed.${extension}"

    # 画像を圧縮する
    sips -s format jpeg -s formatOptions $QUALITY "$f" --out "${f%/*}/$new_filename"
  fi
done
```

このスクリプトでは、まず選択されたファイルを1つずつ処理します。ファイル名と拡張子を分離し、新しいファイル名を作成します。次に、sipsコマンドを使用して、指定された圧縮率で画像をJPEG形式に変換し、新しいファイルに保存します。

複数のファイルを選択した場合、このスクリプトはそれぞれのファイルに対して順番に処理を行います。圧縮された画像は、元の画像と同じ場所に保存され、ファイル名に_compressedが追加されます。




### コマンドの二つの-sの意味とは

sipsコマンドの-sオプションは、指定されたプロパティを設定するために使用されます。-sオプションに続く文字列は、設定するプロパティ名とその値を指定します。

sips -s format jpeg -s formatOptions 85 input.jpg --out output.jpgの場合、-s format jpegは、出力ファイルの形式をJPEG形式に設定するために使用されています。-s formatOptions 85は、JPEG形式で出力する際の圧縮率を85%に設定しています。

つまり、このコマンドでは、-sオプションを2回使用していますが、それぞれが異なるプロパティの設定に使用されています。第1の-sオプションは、出力形式を設定するために使用されており、第2の-sオプションは、出力形式がJPEGである場合の圧縮率を設定するために使用されています。
組込プログラミング：排他制御

<h3>■排他制御とは</h3>
前回、ファームウエアの中には「タスク」という一連の処理を繰り返し行うプログラムがたくさんあって、それらは並行して動く、ということを書きました。このようなタスクの並行処理環境で次に必要になってくるのが「排他制御」です。「他」を「排する」というくらいなので、現実世界で言うとカラオケルームで誰かが使っていたら他の人は排される（待たされる）みたいなものでしょうか。タスクを使ってプログラミングを進めていると、タスクAがある資源（メモリ上の情報）を読み書きする一連の処理の間は、タスクBにはその資源の読み書きをしないでほしい、というケースが出てくると思います。

もう少し具体的に例を挙げましょう。
```
タスクA：
void task_a()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		printf(%d\r\n", i);
	}
}
```
```
タスクB：
void task_b()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		printf("%c\r\n", 'a'+i);
	}
}
```

これらが並列に動くとどうなるでしょうか。
（※注）
実際にこれらをタスクとして実行すると、ただループを実行してタスクが終了してしまいます。簡略化のため話題の他の要素は省略していますのでご注意ください。

なんとなく、
```
0
a
1
b
2
c
...
```
のように互い違いに出力されるかもね、くらいのイメージは持てるかと思います。実際はもっとひどくて、

```
0a

1
b
c

...
```
のように、文字とCRの間やCRとLFの間でタスクが切り替わる可能性もあります。ですから、例えば少なくとも「文字\r\n」までは一気に表示したいのであれば、

```
タスクA：
void task_a()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		排他開始
		printf(%d\r\n", i);
		排他終了
	}
}
```
```
タスクB：
void task_b()
{
	int i;
	
	for (i = 0; i < 10; i ++) {
		排他開始
		printf("%c\r\n", 'a'+i);
		排他終了
	}
}
```
のように排他制御APIを呼び出すことになります。
（応用問題として、0～9、a～jまでそれぞれを一気に表示したいのであれば、どこで排他開始、終了APIを呼び出すと良いかわかりますか？）


<h3>■名前：セマフォとミューテックス</h3>
排他制御するものの名前として以下の2つがあります。<br>
<b>〇セマフォ</b><br>
冒頭に書いたカラオケルームがたとえば10部屋持っていたとしたら、最初の10組はすぐに入れますがそれ以降は空き待ちになります。どこかが空いたら待ち行列の先頭の組が入れます。このように、資源が複数あるものの制御を行うものをセマフォと言います。もともとは進行か停止を指示する鉄道などの手旗信号が語源のようです。<br>
<br>
<b>〇ミューテックス</b><br>
こっちはカラオケルームが1部屋ある場合です。つまり「空きかどうか」だけを表現するもので、資源数が1のセマフォはミューテックスと同じ、と言えます（厳密には機能的な違いもあるのですが、ここでは省略します）。<br>
語源はmutual exclusion：相互排他から来ているようです。<br>
<br>
iTRON OSでは普通排他制御に資源数1のセマフォを使います（そのため、これ以降ここでは排他制御するもののことをセマフォと呼びます）。排他開始APIはwai_sem()、排他終了APIはsig_sem()です。動的生成に対応しているiTRON OSの場合、目的に応じてcre_sem()にて任意の数だけセマフォを生成して使用します。動的生成に対応していないiTRON OSの場合は添付のコンフィグレータなどのツールで静的生成します。<br>
<br>
正直、最低限iTRON OSにはタスクとセマフォだけ用意されていれば、あとのタスク間メッセージ通信やメモリ確保などの仕組みは最悪自分で書けます。セマフォはそれぐらいタスクと並んでOSの根幹となる仕組みなのです。特定の資源のみを排他制御できる便利な機能ですが、実はその使用には細心の注意が必要です。今回はセマフォの概要説明で終わってしまったので、その話は次回に回します。
<br>

<h3>■今日の閑話</h3>
セマフォは名前の使い方が独特な感じがします。語源が手旗信号というところから、排他開始はwait semaphoreだからwai_sem()、排他終了はsignal semaphoreだからsig_sem()まではなんとなくイメージできます。でも私がこの会社に入ったとき、先達が作ったOSではsemP()、semV()という名前がついていました。何のP、Vか諸説あるようですが、結局は手旗信号関連のオランダ語のようです。完全にP/Vに慣れた後でwai/sigの世界に入ったとき、またどっちが開始でどっちが終了か覚えるのにややしばらくかかりました...
<br>
<br>

Cente：
https://www.cente.jp/

お問合せはこちら：
https://www.cente.jp/otoiawase/
Flutter🐬コマンド一発で、android と iOS 両方にアップロードしたいしデプロイしたいんだ！

# 前書き
Flutter でアプリをデプロイするのに、いちいちandroid と ios のコマンド打つのも面倒だし、ビルドナンバーをインクリメントするのも面倒くさい！

コマンド一発で、全部済ませたいんだ！！


# env ファイルの作成
```.env
ANDROID_UPLOAD_LINK: https://~~~
```

# deploy.sh を作成
```deploy.sh
#!/bin/bash

iosDeploy() {
  echo "🍎 iOS build started 🚀🚀🚀"
  flutter build ipa --release --export-options-plist=ExportOptions.plist
  echo "🍎 iOS build finished 🎉🎉🎉"
}

androidDeploy() {
  echo "🍏 Android build started 🚀🚀🚀"
  flutter build appbundle
  open -R ./build/app/outputs/bundle/release/app-release.aab
  open $ANDROID_UPLOAD_LINK
  echo "🍏 Android build finished 🎉🎉🎉"
}


# Increment version
perl -i -pe 's/^(version:\s+\d+\.\d+\.\d+\+)(\d+)$/$1.($2+1)/e' pubspec.yaml

source .env
# Deploy
iosDeploy &
androidDeploy &

wait
echo "Both builds finished 🎉🎉🎉"
```

# deploy.sh に実行権限を付与
```
chmod +x deploy.sh
```


# 実行🦄
```
./deploy.sh
```

SAYONARA
Almalinux8.7にLIGGGHTS-PUBLICをインストールした時にハマったこと（随時更新）

Almalinux8.7にLIGGGHTSをインストールしようとして、安易に「Fedoraと一緒でええんでしょ？」とか考えてたら、ドはまりしたポイントを紹介します。
```bash:LIGGGHTSマニュアルより拝借
Ubuntu 16.04LTS:
  sudo apt-get install openmpi-bin libopenmpi-dev libvtk6.2 libvtk6-dev
-----
Ubuntu 17.10:
  sudo apt-get install openmpi-bin libopenmpi-dev libvtk6.3 libvtk6-dev
-----
Fedora 25:
  su -
  dnf install openmpi openmpi-devel paraview-openmpi paraview-openmpi-devel gcc-c++
  exit
  echo "export PATH=$PATH:/usr/lib64/openmpi/bin" >> ~/.bashrc
  echo "export LIBRARY_PATH=$LIBRARY_PATH:/usr/lib64/openmpi/lib:/usr/lib64/openmpi/lib/paraview" >> ~/.bashrc
  echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib64/openmpi/lib:/usr/lib64/openmpi/lib/paraview" >> ~/.bashrc
  echo "export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/lib64/openmpi/include/paraview" >> ~/.bashrc
  echo "export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/lib64/openmpi/include/paraview" >> ~/.bashrc
```
「AlmalinuxだからFedoraと一緒でいいよね？」と思ったそこの貴方。**僕はダメでした**。ディレクトリがちゃんとあるか確認しましょう。私のAlmalinux8.7ではこうなりました。
```bash:Almalinux8.7用
Almalinux 8.7:
  su -
  dnf install openmpi openmpi-devel paraview-openmpi paraview-openmpi-devel gcc-c++
  exit
  echo "export PATH=$PATH:/usr/lib64/openmpi/bin" >> ~/.bashrc
  echo "export LIBRARY_PATH=$LIBRARY_PATH:/usr/lib64/openmpi/lib:/usr/lib64/openmpi/lib/paraview" >> ~/.bashrc
  echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib64/openmpi/lib:/usr/lib64/openmpi/lib/paraview" >> ~/.bashrc
  echo "export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/include/openmpi-x86_64/paraview/paraview" >> ~/.bashrc
  echo "export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/include/openmpi-x86_64/paraview/paraview" >> ~/.bashrc
```
誰かの役に立ちますように。