OmniAICreator/Qiita-1.07M huggingface dataset:
Express.js 早見メモ

## Install

```
npm intall express
```

## Minimum Code

```js:index.js
const express = require('express');
const app = express();
const PORT = 3000;

app.get('/', (request, response) => {
    response.send("Hello.");
});

app.listen(PORT, () => {
    console.log(`http://localhost:${PORT}`);
});
```

## Run

```
node index.js
```

## Codes

```js:index.js
// Receive Post Parameter
app.use(express.urlencoded({ extended: true }));
// Receive JSON 
app.use(express.json());

// GET Reqest
app.get('/users', (request, response) => {
    // Get query parameter
    const country = request.query.county;
    const users = getUsers(country);
    response.send(users);
));

// Using path parameter
app.get('/users/:user_id', (request, response) => {
    const userID = request.params.user_id;
    const users = getUsers(userID);
    response.send(users);
));

// POST Request
app.post('/users', (request, response) => {
    // Get request data
    const userID = request.body.userID;
    const name = request.body.name;
    createUser(userID, name);

    // Response JSON
    response.json({"status":"ok"});
});

// PUT Request
app.put('/users/:user_id', (request, response) => {
    ...
});

// DELETE Request
app.delete('/users/:user_id', (request, response) => {
    ...
});
```

## For more information

https://expressjs.com/

https://www.tohoho-web.com/ex/express.html
【ハッキング入門】SUIDビットが設定されたファイルの検索方法

# はじめに

特権昇格の第一歩としてSUIDがセットされたプログラムを探すことがあります。
HackTheBoxやTryHackMeでもよく使用します。
その際のコマンドを紹介します。

# 結論

`find / -user root -perm -4000 2>&1 | grep -v -e "Permission denied" -e "No such file or directory"`を実行する。

:::note info
2024/05/08追記
`find / -perm -u=s -type f 2>/dev/null`
上記コマンドもスッキリしていて良いかもしれない
出力結果はほぼ同じ
:::


# SUIDとは

SUIDはLinuxで使用されるパーミッションの一つです。
SUIDが設定されたプログラムは、プログラムを所有するユーザーの権限で実行されます。

例えば、パスワードを変更する`passwd`コマンドは、通常はrootユーザーのみが実行できますが、SUIDが設定されている場合、通常のユーザーでも`root`ユーザー権限でパスワードを変更できます。

```
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 63960  2月  7  2020 /usr/bin/passwd
```

この権限設定の不備を攻撃者は悪用し特権昇格へと繋げます。

# SUIDの検索

SUIDを検索する際のコマンドを紹介します。

`$ find / -user root -perm -4000 2>&1 | grep -v -e "Permission denied" -e "No such file or directory"`


- find /
    - ルートディレクトリ配下の全てを検索
- -user root
    - root が所有するファイルを表示する
- -perm -4000
    - SUIDビットがセットされたファイルだけを表示する
- 2>&1
    - 解説は[この記事](https://sry.hatenablog.jp/entry/2020/03/29/142630)がわかりやすいと思います
- grep -v -e "Permission denied" -e "No such file or directory"
    - 出力から`Permission denied`と`No such file or directory`のワードを除去します

結果、SUIDビットがセットされたプログラムファイルのみ表示されます。

```
$ find / -user root -perm -4000 2>&1 | grep -v -e "Permission denied" -e "No such file or directory"
/usr/bin/fusermount3
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/mount
/usr/bin/su
/usr/bin/umount
/usr/bin/pkexec
/usr/bin/fusermount
/usr/bin/crontab
/usr/bin/sudo
/usr/bin/passwd
(省略)
```

:::note info
`find / -user root -perm -4000 -exec ls -l {} \;>/tmp/result`のように実行すると、プログラムファイルを`ls -l`形式で出力し、結果を`/tmp/result`ファイルに保存します。
:::


# 参考サイト

https://docs.oracle.com/cd/E19683-01/816-3967/secfiles-23001/index.html

https://kazmax.zpp.jp/linux_beginner/setuserid.html

https://sry.hatenablog.jp/entry/2020/03/29/142630
[GAS] Gmailで受信した楽天ペイの利用明細をGoogleスプレッドシートに転記

### 対象
* 楽天ペイの利用明細をGmailで受け取っている方
* 本スクリプトを理解して自分用にカスタマイズ可能な方

### 利用方法
Googleドライブ -> 新規 -> Googleスプレッドシート -> 拡張機能 -> App Script
myFunctionを差し替えて[実行]

### スクリプト
``` javascript
function myFunction() {
  
  const setting = {
    query:"from:楽天ペイ after:2024/1/1 before:2025/1/1 ご利用明細",
    max:10,
    keywords:["ご利用日時","伝票番号","ご利用店舗","電話番号","決済総額","獲得予定ポイント","お取引内容","お支払方法"],
  }
 
  const threads = GmailApp.search(setting.query, 0, setting.max);
  const messagesForThreads = GmailApp.getMessagesForThreads(threads);
 
  const rows = [setting.keywords];
  for(const messages of messagesForThreads){
    for(const message of messages){
      const plainBody = message.getPlainBody();
      const columns = [];
      for(const keyword of setting.keywords) {
        const matches = plainBody.match(keyword + ".*");
        let cellText = "---";
        if (matches) {
          cellText = matches[0].replace(keyword, "").trim();
        }
        columns.push(cellText);
      }
      rows.push(columns);
    }
  }
 
  const sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet();
  sheet.getRange(1, 1, rows.length, rows[0].length).setValues(rows);
}
```

### 注意事項
* 検索条件は2024年分としています。setting.queryを調整して下さい
* 1日の検索数に制限があるため上限を10スレッドとしています。試して問題が無ければsetting.maxを調整して下さい
* 特殊なケースは一切考慮していません。自己責任でご利用、改変お願いします

### 実行結果
一部マスクしています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3230652/2c1ea17d-5463-3581-d299-b5705f37b65f.png)
【備忘録】Dockerの入れ方 on AWS EC2

# 環境
Amazon Linux2

# Dockerのインストール
```bash
sudo yum install docker
sudo systemctl start docker
```
確認
```
sudo docker --version
```

# 「sudo」なしで実行できるようにする
```
# dockerグループが存在していない場合、追加
sudo groupadd docker
# 自分（$USER）をdockerグループに追加
sudo gpasswd -a $USER docker
```
`exit`して再度入ると「sudo」なしで使えるようになる。
エクセルで『クリップボードに大きな情報があります…』のダイアログを出さないようにしたかった

# 概要

これを出さないようにしたかったです。

>クリップボードに大きな情報があります。
>この情報をほかのプログラムに貼り付けられるようにしますか？
>後で張り付けるためにクリップボードに保存する場合は、はいをクリックします。
>クリップボードにある情報を削除する場合は、いいえをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/52de004b-2b2f-6774-34c4-76f3ffd88be7.png)

このダイアログは比較的たくさんのセルをコピーしたあと、エクセルファイルを閉じる前に出てきます。

個人的にファイルを閉じるということは、テキストエディターなどに貼り付けが済んでいて、 **『はい』を選択することはほぼ無い** です。

# エクセルの設定ではどうやら無理そう

2024年04月27日時点で調べた限り **根本的にこのダイアログを出さない設定** は無さそうでした。

VBAで出さない **処理** はできそうですが、エクセルファイル一つ一つにVBAを仕込むのは求めてるものではなかったです…。

# 妥協案

**『選択エリアの枠が点線になっている』** というのが **ダイアログが出る条件** です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/39109f42-07ff-f902-2c4e-0e766aae83c1.png)

逆に、こうなっていると出ないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/48c03a74-3d0c-4498-4b8c-3c6c61e29167.png)

つまり、 **エクセルファイル閉じる前にESCキー押す** をやればよいです。
いちいちその操作するのは面倒ですが、『ダイアログのいいえを選択』よりは手数が少なくて済むかなぁ…てかんじです。

# 参考サイトさん

https://support.microsoft.com/ja-jp/topic/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A7%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AE%E8%AD%A6%E5%91%8A%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95-f3cae9a0-f95c-d9b5-707b-f4059b72bff3

https://vba-labo.rs-techdev.com/archives/50

# バージョン

Microsoft Windows [Version 10.0.22631.3527]
Microsoft Excel for Microsoft 365 MSO (バージョン 2403 ビルド 16.0.17425.20176) 32 ビット
[Rails] Delayed_Jobのテーブル構成についてまとめた

### 概要
`DelayedJob`のテーブル構成（列構成）についてまとめました。

### DelayedJobとは...？
RailsでJOBを非同期処理するための`gem` です。

`DelayedJob`はデータベースをキューとして利用します。

つまり、実行するジョブの情報をデータベースに保存し、その情報を基に非同期でJOBを処理する方式ということです。

### DBのカラム構成
上記を踏まえてテーブル構成を見ていきましょう

| カラム名     | 役割                                                                                                                 | 
| ------------ | -------------------------------------------------------------------------------------------------------------------- | 
| `id`         | レコードの一意の識別子。<br>自動的にインクリメントされる。                                                               | 
| `priority`   | ジョブの優先度を示す。<br>数値が低いほど優先度が高い。                                                                   | 
| `queue`      | ジョブが割り当てられたキューの名前。<br>キューに対応するワーカーがジョブを処理する | 
| `attempts`   | ジョブが実行された回数。<br>失敗する度にインクリメントされる。                                                       | 
| `handler`    | ジョブのオブジェクトをYAML形式でシリアライズしたもの。<br>ジョブに渡されたオブジェクト情報などが含まれる             | 
| `last_error` | ジョブが失敗した際のエラーメッセージが格納される。<br>デバッグに活用する。                                           | 
| `run_at`     | ジョブが実行される予定の日時。<br>この時間が現在時刻を超えると、ジョブは実行される。                                 | 
| `locked_at`  | ジョブがロックされた日時。<br>ジョブが処理中であることを示す。                                                       | 
| `locked_by`  | ジョブをロックしているワーカー。<br>どのワーカーがジョブを実行したか確認できる。                                     | 
| `failed_at`  | ジョブが最終的に失敗した日時。<br>再試行の限界に達した場合、値が格納される。                                         | 

以上です。
Rails学習者の役に立てば幸いです...！
RustのゲームサーバーをDDos攻撃から守るためにTailScaleの後ろに置いた話

## この投稿について
初めまして。
マルチゲームサーバー 「Nekoniwa-Network」を運営している者です。
今回、サークルの先輩や同期、非常勤の先生など...etc
たくさんの人のお世話になりながら、自鯖を攻撃から守るフロントインフラを構築しました。
#### これが本当に大変だった。

初めての投稿では、フロントインフラに何を構築したのかを紹介していこうと思う。

## なぜTailScaleの後ろに置き始めたのか
まずはこちらを見ていただこう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779484/7f25e5ee-a690-b9d2-59bc-c478377f93a7.png)

時は2023年5月、午後10時頃の出来事である。
サーバー利用者からこんな連絡が来た。

#### 「サーバーからキックされて繋がらないです...」

その頃はよくサーバー機器に不具合が起きていたので、またサーバーの不具合だろうと思ってブラウザを立ち上げた瞬間、これがサーバーの不具合ではないことが分かった。
ネットにつながらないのである。
断続的に接続が復旧したり切れたり...これはただ事ではないなと思いルーターのFireWallを確認した時の写真がこれだ。
この写真からだとわかりにくいが、複数のIPアドレスからすさまじい数のパケットが飛んできていた。
これが私の初めてのDDos攻撃経験だ。
どうしようもなく、ほとぼりが冷めるのを待つしかなかった。

後日の出来事である。
突然一通の電話が来た。

**某P社「プロバイダ会社です。先日すさまじい数のパケットがお宅に集中して、地区の1/3程度のリソースを占めてたんだけど心当たりありますか？」**
**私「あぁ...攻撃されてた時の話ですかね...」**
**某P社「たぶんそれです。さて、単刀直入にもうサーバーを起動しないでいただきたい。次同じことが起きたらお宅の回線を停止しますからね。」**
**私「ﾜｧ...」**

と、もう少しちゃんとしたやり取りはあったが、プロバイダーからお叱りを受けてしまった。
何かしら対策をしてもう一度サーバーを起動したい！！と考えていたが、1年はおとなしくサーバーを停止して過ごすことにした。

2024年4月、講義や独学で学んだ内容を使えば、自宅グローバルIPを公開せずパケットもフロントサーバでさばけるのでは...?と思いたったはすぐ行動。
このqiitaの内容につながってくる。

## 内容
前置きが長くなったが、今回やったことを説明しよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779484/241f2f83-bd04-0087-ec7a-e1f9d9915d27.png)
以上が現在のネットワーク構成図である。
(あまり書いたことないので汚くて申し訳ないです...)

簡単に流れを説明する。
```
1. 接続してくるプレイヤーはさくらのVPSに接続する
2. 特定のPort宛に接続してきたプレイヤーのIPをDNATでさくらのTaleScale IPに流す
3. SNATを使ってカプセル化したグローバルIPをRustサーバのTailScale IP宛に流す
4. RustサーバはTailScaleから来たパケットをPortごとに処理して返答する
```

これが一連の流れになる。
当初はリバースプロキシを組んですべてをさくらのTailscale IPで処理しようとしていた。
けれど、Rust(EAC)は同じパケットからの接続について解決できるのは1つ迄という制約があるらしい。
ので、SNATで個々のグローバルIPを流してやることで解決した。(この仕様に半日苦しめられた)

こうしたことにより、攻撃を受けた際の受け皿がさくらのVPSとなる。
また、受け渡しはTailScaleを介すので自宅グローバルIPが外に出ていくことはない。

あぁ、なんと素敵なのだろう。

行った設定も簡単で、TailScaleに接続してIPフォワードのルールを組んでUFWルールを設定して...完成！という簡単なものなので、
**「DDosが怖い・グローバルIPをSteam(FP)に教えたくない」**
という方々はぜひ試してほしい。

また、この構成は自宅がIPoE回線の皆様もサーバーを建てることが出来るやり方なので、Port開放が出来なくて困ってる人も一度試してみてほしい。

さくらのVPSも月額900円程度なので、VTuberにサブスクするよりお手軽にサーバーを作ることが可能だろう。

詳しいやり方や手順については、作ってほしいという声があれば備忘録的に残そうと思う。
<br>
*スペシャルサンクス: 某仮想化の鉄人先生, konkichiさん, nikkiさん*


参考: 

https://zenn.dev/heuristics/articles/49b538de8b1701

https://qiita.com/tinoue@github/items/ebcdf5423d87df0ad7cc

https://qiita.com/onodes/items/6c62bd3f1a4d2350f8e8

https://taroline.hateblo.jp/entry/2015/09/01/024702

https://qiita.com/forestsource/items/5f34080658251d74ab2c
【Golang】無名関数を関数の引数もしくはリターンで使用する

自分に対する備忘録として残すもの

## 無名関数を関数の引数で使用する
サンプルコード

```Go
package main

import "fmt"

// 関数applyFunctionは、無名関数を引数に取り、その関数を実行します。
func applyFunction(f func(int) int, x int) int {
    // 引数として渡された無名関数を実行し、結果を返す
    return f(x)
}

func main() {
    // 無名関数を作成し、その場で引数として渡す
    result := applyFunction(func(n int) int {
        return n * 2
    }, 5)

    // 結果を出力
    fmt.Println("Result:", result)
}
```

引数に渡す無名関数は以下の通りでも良い。（個人的にはこちらの方が読みやすいから好き）
```Go
package main

import "fmt"

// 関数applyFunctionは、無名関数を引数に取り、その関数を実行します。
func applyFunction(f func(int) int, x int) int {
    // 引数として渡された無名関数を実行し、結果を返す
    return f(x)
}

func main() {
    // 無名関数を作成し、その場で引数として渡す
    f1 := func(n int) int {
        return n * 2
    }
    
    result := applyFunction(f1, 5)

    // 結果を出力
    fmt.Println("Result:", result)
}
```

## 無名関数をリターンする関数
```Go
package main

import "fmt"

// createMultiplierは、倍率を引数に取り、その倍率で数値を乗算する無名関数を返します。
func createMultiplier(factor int) func(int) int {
    // 引数として与えられた倍率で数値を乗算する無名関数を作成し、それを返す
    return func(x int) int {
        return x * factor
    }
}

func main() {
    // 倍率2の無名関数を作成
    // multiplierはリターンされた無名関数
    multiplier := createMultiplier(2)

    // 無名関数の引数に値を渡して、無名関数を実行する。
    result := multiplier(5)

    // 結果を出力
    fmt.Println("Result:", result)
}
```

サンプル等についてはChatGPTで生成しております。
ステージし忘れたファイルを追加する

# コマンド
```
git reset --soft HEAD^
git push origin main -f
```

# エラー
エラー文をコピーし忘れたが```git reset --soft HEAD^```をしてSourceTreeでステージしなおしてプッシュしようとしたらエラーが起きた。

# 気づき
多分ローカルとリモートのレポジトリの内容が違った（多分表現が違う）からだと思う。

# 参考書をみた
参考書にもローカルからリモートに矢印が書かれていたのでfetchの逆と思われる
# 出典
https://www.kano-info.net/124311236312427git.html

# 調べるのに役に立った
https://qiita.com/ChaaaBooo/items/459d5417ff4cf815abce

# 感想
嬉しい。ありがとうございました。
複数のプロジェクトで使用するUEの自作プラグインの、更新時の同期をとる

# 概要
UEでアプリケーションを作っていると、ほかのプロジェクトでも使用したい処理はプラグインとしてまとめる方が多いと思います。
プラグインの作成中、プロジェクト内で作成したプラグインがプラグイン内で完結しているか確認するため、単体テストを行うと思いますが、その際、gitなどのバージョン管理で同期をとっていると煩わしくなってきます。
複数のプロジェクトで使用する際にプラグインへ変更を加えた場合に、ジャンクションを使用して同期をとることで変更時の各プロジェクトへの適用を簡略化します。

# 対象
UEで複数プロジェクトで使用する処理を、自作プラグインを作成しているが、いずれかのプロジェクトで変更を加えた場合に同期をとって影響を頻繁に確認したいと考えている方が対象です。

# 使用環境
- [GitHub](https://github.com/)
  - [凡例リポジトリ](https://github.com/koiusa/RidingSystemPlugin)
  ※説明の参考のためのパスとして使用しますが、各環境に併せて読み替えてください。
　

# プラグインを常時同期したい場合
### プロジェクト外にチェックアウトする
UEプロジェクト外に、管理したいプラグインをクローンします。

```shell:プラグインのパス
D:\Work\koiusa\RidingSystemPlugin
```

### 管理したいプラグインのジャンクションを作成する

```shell:UEプロジェクトのパス
D:\Work\koiusa\Sandbox_UE5_2
```

UEプロジェクトのPluginsディレクトリにジャンクションを作成します。

```shell:JunctionRidingSystem.bat
mklink /j D:\Work\koiusa\Sandbox_UE5_2\Plugins\RidingSystem D:\Work\koiusa\RidingSystemPlugin\Plugins\RidingSystem
```

以降、プラグインのパス、UEプロジェクトのパス内のプラグインのどちらを変更しても両方に変更が反映されます。

# プラグインを任意のタイミングで同期したい場合

### UEプロジェクト内にサブモジュールを追加する

任意のタイミングで同期をとりたい場合は、gitのsubmodule機能を併用します。
UEプロジェクト内に、管理したいプラグインをサブモジュールとして追加します。
プロジェクト内にsubmoduleを格納するための、ディレクトリを作成します。

```shell:例
│  └─Sandbox_UE5_2
│      ├─forSubmodule
│      ・・・
│      ├─Contents
│      ・・・
│      ├─Plugins
│      ・・・
```

forSubmoduleに移動し、コマンドを実行するためのバッチファイルを作成します。
都度コマンドで実行しても問題ないですが、頻繁に実行す工程はバッチファイルにすることで効率化できます。


```shell:AddSubmodule.bat
git submodule add --force https://github.com/koiusa/RidingSystemPlugin.git RidingSystemPlugin
git submodule update --remote ./RidingSystemPlugin
```

### ジャンクションを作成する

subumoduleで取得したファイルから、対象のディレクトリのジャンクションをUEプロジェクトのPlugins内に作成します。
※基本運用はプロジェクト内に限定されるため、相対パスで指定します。

```shell:JunctionRidingSystem.bat
mklink /j ..\Plugins\RidingSystem .\RidingSystemPlugin\Plugins\RidingSystem
```

以上　ジャンクションを使用したプロジェクト間の同期方法でした。
コマンド3行～AnsibleとCloudFormationを使用してAWS上で5分でプリザンターを試す～

# 内容
何回か検証用のプリザンターを作成する必要がありそうなのですぐ試せるようにコード化。
プリザンターはOSSのノーコード・ローコード開発ツールです。

https://pleasanter.org/

# 作成される環境
AWS上にVPC、パブリックサブネット、EC2つ作成してEC2上にプリザンターをインストール。インターネットからプリザンターにアクセスする。

![pst-aws.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/9c11cf6b-be13-5203-9142-aaa20c261e07.png)

# CFnテンプレートのダウンロード
下記をローカルに保存する。

https://github.com/Toru-Kubota/pst-install/blob/main/cfn/cfn.yml

# CFnからEC2やVPCを作成

* AWSコンソールよりCFnのコンソールに移動
* CFnスタックを新規で作成
* テンプレートファイルのアップロード
※先ほどローカルに保存したファイルを指定

![pst1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/8157d34b-1d8e-d61e-f66b-5ac51355aed5.png)

* スタック名を入力
* SvAllowdCidrの箇所にサーバにアクセス可能なグローバルIPを指定
※（0.0.0.0/0だとフルオープン）
* その他はデフォルト設定でスタックを作成

![pst2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/10d7e004-fa00-a31b-1140-67dd68e173ba.png)

* VPCやEC2などのリソースが作成される

# EC2接続用キーペアのダウンロード

* System Managerのパラメータストアに移動
* キーペアが作成されていることを確認

![pst3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/77112a1d-3268-6295-2d2b-7f4966670d02.png)

* 復元化された値を表示
* テキストファイルにコピペして保存しておく

![pst4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/5bf37cb6-2659-4364-7172-ad22efb68a01.png)

# EC2にアクセス

* EC2のコンソールからパブリックIPアドレスを確認
* SSHで接続

![pst5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/21667a69-aad1-9301-6f1a-c24c7f9ba0b3.png)

# プリザンターのインストール

* 下記3つのコマンドを実行

```shell
git clone https://github.com/Toru-Kubota/pst-install.git
cd pst-install
sudo ansible-playbook -i inventory.ini pst.yml  --connection=local
```

# プリザンターにアクセス
* http\://EC2のパブリックIPアドレスにアクセス
* プリザンターの画面が表示されることを確認

![pst6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/8d1bf104-d04c-6cce-0769-448126ce98bd.png)
【ChatGPT＋DALL-E3】でスタジオ撮影。PromptShare


　どうも、カーブミラーです。

　今回は、スタジオ撮影風景です。PromptShareしますね。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　まずは、個人的？なことをひとつ。

　ChatGPTアクセス用のブラウザを
　　Chromeから
　　　Kiwiに変更しました。

　実は
　　画像のダウンロードが
　　　一度やると、
　　　　二枚目が落とせなくなる、
　　　　　という現象がありまして
　　　　　　不便さを感じていました。

　ブラウザ変えればいけんじゃね？
　　と思い付いたのが、ゆうべ。
　　　そのまま実行。
　　　　今のところ、安定しています。
***
　さて、
　　本題です。

　スタジオ撮影の風景を
　　出すプロンプトを
　　　PromptShareします。

　使い方は
　　以下の五つを
　　　指定してください。

　[BACKGROUND: 背景]
　[APPEARANCE: 人物]
　[ATTIRE: 服装]
　[ACCESSORY: 装飾]
　[POSE: ポーズ]

　BACKGROUNDを変えたければ、
　　“風景”の部分を変えます。

　[BACKGROUND: 街なか]とか。

　では、Promptです。

```Text:スタジオ撮影の風景Prompt
[BACKGROUND: 背景]
[APPEARANCE: 人物]
[ATTIRE: 服装]
[ACCESSORY: 装飾]
[POSE: ポーズ]

A studio set shoot, with the background being [BACKGROUND], featuring a single model, a [APPEARANCE]. She is dressed in [ATTIRE], adorned with [ACCESSORY]. Her pose is [POSE]. The lighting is from professional studio lights, aiming for a high-resolution photograph. Aspect ratio is 1:1.
```

　DeepL翻訳
>背景は[BACKGROUND]で、[APPEARANCE]の一人のモデルをフィーチャーしたスタジオセット撮影。 彼女は[ATTIRE]に身を包み、[ACCESSORY]で飾られている。 ポーズは[POSE]。 ライティングはプロ仕様のスタジオライトで、高解像度の写真を目指している。 アスペクト比は1:1。

　“She（彼女）”という単語を
　　使っていますが、
　　　男性でも大丈夫でした。

　変数の値と作画例は
　　こちらです。
***
***user***
[BACKGROUND: 街なか]
[APPEARANCE: 笑顔の若い黒人女性]
[ATTIRE: オレンジ色のキャミソールドレス]
[ACCESSORY: 真珠のネックレス]
[POSE: イスに座る]

***ChatGPT***
![1714189288086.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/3a33f646-2eab-45b8-5c34-042129c390cd.jpeg)

***user***
[BACKGROUND: 街なか]
[APPEARANCE: 渋い顔をした老齢の黒人男性]
[ATTIRE: オレンジ色の上下のスーツ[ACCESSORY: 白いパナマ帽]
[POSE: イスに座る]

***ChatGPT***
![1714189304767.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/60f5c964-2283-264f-80ba-74d2f33f868b.jpeg)
***

　このPromptは、
　　立ち姿は難しいようです。

　何度かやってみましたが
　　バストアップしか
　　　生成してもらえませんでした。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
ダブルドットを含む冗長なパスを正規化する

<!--# ダブルドットを含む冗長なパスを正規化する-->

親ディレクトリを表すダブルドットやカレントディレクトリを表すドットを含む冗長なパスをシンプルなパスに変換したいときはどうしますか？

調べたところ `realpath -ms` を用いることができるようです。

```bash
$ realpath -ms -- /foo/bar/../lib
/foo/lib
```

ただし、相対パスは、カレントディレクトリからのパスの絶対パスに変換されてしまいますので、注意です。

```bash
$ realpath -ms -- foo/bar/../lib
/home/uuu/foo/lib
```

## その他の方法

bash の配列を用いた bash 関数を自作された方がいました。

[冗長なパス foo/bar/../lib を foo/lib に変換する | 晴耕雨読
https://tex2e.github.io/blog/shell/remove-verbose-from-path](https://tex2e.github.io/blog/shell/remove-verbose-from-path)

以上です。
サーバーに新規ユーザを登録する方法

# はじめに
大学院でコンピュータビジョンに関して深層学習を用いた研究を行っており、研究室のサーバー担当を行っています

研究室にはつよつよGPUが乗った共有サーバーが何台かあり、それを利用するための新規ユーザーの登録を定期的に行っています

そこで、サーバーに新規ユーザを登録する流れをまとめておきたいと思います

# 前提条件
以下の記事はUbuntu22.04上で実行しています
<>内は変更してください

# 概要
1. [ユーザを追加する](#ユーザを追加する)
1. [ユーザーデータを保存先を変更](#ユーザーデータを保存先を変更)
1. [権限と所有者を変更する](#権限と所有者を変更する)

## ユーザを追加する
1. ユーザを追加する
    - /home/newuserが作成される
    - パスワード設定を促されるのでpassword2024に設定
    - それ以外の設定は無視でOK
    ```bash: add.sh
    sudo adduser <newuser>
    ```
1. 新たなユーザーの初回ログイン時にパスワードの変更を要求する
    - `0` はパスワード変更までの猶予期間
    - changeではないので注意
    ```bash: chage.sh
    sudo chage -d 0 <newuser>
    ```

## ユーザーデータを保存先を変更
1. 外付けSSDを確認する
    - 容量の大きいディレクトリを見つける
    - ここでは data とする
    ```bash: df.sh
    df -h
    ```
2. data以下に<newuser>のworkspaceを作る

    ```bash: workspace.sh
    sudo mkdir /<data>/<newuser>
    sudo mkdir /<data>/<newuser>/workspace
    ```
3. /home/newuser以下に/data/newuser/workspaceのシンボリックを作成する
    - ホームディレクトリは容量が少ないのでSSDにデータを保存する
    ```bash:link.sh
    sudo ln -s /<data>/<newuser>/workspace /home/<newuser>
    ```

## 権限と所有者を変更する
1. 所有者を変更する
    - シンボリックリンクした先のディレクトリの所有者とグループをnewuserにする
    ```bash:chown.sh
    sudo chown -R <newuser>:<newuser> /<data>/<newuser>
    ```
2. 権限を変更する
    - /home/newuser, /data/newuser の２つを変える
    ```bash:chmod.sh
    sudo chmod -R 750 /home/<newuser>
    sudo chmod -R 750 /<data>/<newuser>
    ```

# おわりに
これで、新規ユーザが登録され、研究データが外部SSDに保存され、研究データが他のユーザに操作される事もなくなりました！
AppSheetで掲示板アプリを作ってみる（初見）

前々から気になっていたGoogleのノーコードアプリ開発プラットフォーム「AppSheet」を使って簡単なアプリケーション制作をして、基本的な使い方を学習しました。

本記事ではその内容について解説をします。
なお、今回は初見のうえ、画面を見ながら試行錯誤してみるので必ずしも効率の良い方法ではないかもしれませんのでご注意ください。

# ざくっとシステム設計

- 投稿者は、文章と画像を投稿することができ、投稿後に編集と削除を行うこともできる
- 閲覧者は、投稿を閲覧することができる

# まずは新規作成

![スクリーンショット 2024-04-27 9.45.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/02d6e456-9984-1b31-0cf8-123883543dab.png)

Createボタンをクリックして新規作成する

![スクリーンショット 2024-04-27 10.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/c1ed771f-c35b-191f-1c69-698c1a4208f8.png)

今回はBlank appを選択します

![スクリーンショット 2024-04-27 10.02.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/19c220fd-cbcf-d069-8d95-fc6f0e6d9f9f.png)

アプリ名の入力を求められたので今回は「Reports」としました

![スクリーンショット 2024-04-27 10.10.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/e131cad3-c35d-5fc2-55a4-4cdd9c230b23.png)

これでアプリの雛形が作成されました
右側に画面も出ているので、すでに動かせそうな雰囲気があります

# データの保存先を設定する

![スクリーンショット 2024-04-27 10.11.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/064e3ce2-4712-415d-e66e-8de1dafe0019.png)

Dataを選択してみると、既にテーブルが１つ作成されていましたが、列の追加・編集ができないようなので、View data sourceをクリックしてテーブル定義を見てみます

![スクリーンショット 2024-04-27 10.14.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/10165c5f-172d-87f5-2020-afb052a4c245.png)

こっちでテーブルの編集ができそうなので、投稿内容を保存するテーブルを作成します

![スクリーンショット 2024-04-27 10.49.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/4b78f1ac-fb77-bcb1-1a27-64c1286afb29.png)

おお・・・データ型も豊富だし、わかりやすい

![スクリーンショット 2024-04-27 10.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/57cca0f6-0287-b1f9-074b-40d4f1fb7aee.png)

とりあえず簡単に投稿本文、投稿者、投稿日時を保存するだけのテーブルを作りました

![スクリーンショット 2024-04-27 11.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/a988db24-a11d-57f6-f48a-3466cc4493f5.png)

次は投稿画面を作りました
For this dataでさきほど作ったテーブルを選択して、画面の種類を選んでいくだけ

![スクリーンショット 2024-04-27 11.33.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/dca83e9a-5787-672f-2ec9-e899e31dc2ff.png)

ナビゲーションに表示するアイコンはペンにしました

![スクリーンショット 2024-04-27 11.34.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/515803eb-0a66-59e4-fd0c-362cc671658c.png)

項目も初期値と表示名を変更しました

![スクリーンショット 2024-04-27 11.40.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/f39c986b-5a7b-1182-6940-f63a3e035960.png)

テスト投稿をしてみます

![スクリーンショット 2024-04-27 11.40.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/5aa9c97a-42c1-051e-01ce-6d6366be4676.png)

ちゃんと保存されてますね！

![スクリーンショット 2024-04-27 11.57.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/652b9f47-d19b-e14f-db82-e9b2eb0ea3e3.png)

閲覧画面も同様にデータを選択して、画面の種類を選んでいくだけです

![スクリーンショット 2024-04-27 11.58.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/e0083993-9a61-f08a-f8c1-996e47b55580.png)

自動的に削除や編集機能もついてますね

# まとめ

初見で一切調べずにやってみましたが、簡単にアプリを作ることができました
業務アプリなどに活用できそうです！
【Windows】個人的におすすめなショートカットキー

※PCはWindows（Windows10以降）を想定しています。

おすすめのショートカットを下表にまとめました。ぜひ、実際に操作しながら確認してみてください。

| 操作内容 | ショートカットキー |
|:-:|:-:|
| 「Windowsのシャットダウン」のウィンドウを開く | （デスクトップ画面がアクティブな状態で）Alt + F4 |
| アプリケーションを終了する | （終了したいアプリケーションがアクティブな状態で）Alt + F4 |
| タスクバーにあるアプリを開く | Win + 対応する数字 |
| エクスプローラーを開く | Win + E |

※ Winは、Windowsロゴキーのことです。
※ 「Windowsのシャットダウン」のウィンドウは下図参照。プルダウンのデフォルトがシャットダウンになっています。なので、シャットダウンをしたい場合はそのままEnterキーを押すだけです。他には再起動なども選択できます。

![windows_shutdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754094/74a287d3-3ac8-987d-4444-5065f97fb73f.png)

※ タスクバーにあるアプリの対応する数字は下図参照
![taskbar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754094/1ff19acd-48fb-4a34-71af-a09265dd18df.png)
AWSとDatadogのインテグレーションで、DatadogAPICall作成がうまくいかなかった話

# はじめに
[こちらのページ](https://docs.datadoghq.com/ja/getting_started/integrations/aws/)に従って、Datadog連携用のCloudFormationを作成、実行したところ、DatadogIntegration-DatadogAPICallのスタック作成に失敗してしまったので、原因と修正方法をまとめます。

# 発生までの経緯
公式ドキュメントに従って、Datadog の AWS インテグレーション構成ページに移動し、Add AWS Account をクリックします。
遷移先で下記のように、Region、APIキー、Forwarder、CSMの設定を行い、CloudFormationテンプレートを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/ba9fa079-14e9-06d6-e48b-3ecdc57e14f6.png)

すると、下記のようにパラメータが入力された画面に遷移するので、そのままスタックの作成を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/2f636fbb-b2f0-3057-c6c7-b11cabed4dd6.png)

すると、DatadogIntegration-DatadogAPICall- から始まるスタックのDatadogAPICallのCREATE_FAILEDになり、スタック作成が失敗します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/b6f9628a-c6ec-8530-3647-9ba742f2c188.png)


CloudWatch logsを確認すると、`ResponseURL: https://cloudformation-custom-resource-response-apnortheast1.s3-ap-northeast-1.amazonaws.com` に対するリクエストに403エラーが返されていました。

APIキーの設定を疑いましたが、自動入力なので間違えるはずもなく...


# 原因

**Datadogアカウントのサイトパラメータと、CloudFormationスタックのDatadogSiteパラメータが一致していないこと**が原因でした。

Datadogにはサイトという概念があり、データ保存場所がサイトによって変わるようです。

https://docs.datadoghq.com/ja/getting_started/site/

サイトごとにURLとサイトパラメータと呼ばれる値が異なっており、私はDatadogアカウント作成時にAP1をサイトとして設定していたので、`ap1.datadoghq.com`がサイトパラメータとなっていました。

しかし、スタック作成時のCloudFormationのパラメータにはサイトUS1を示す`datadoghq.com`が自動入力されていたので、権限を持っていないサイトに関するリクエストを送信したことで403エラーが返されたのだと思います。

CloudFormationスタックのDatadogSiteパラメータを`ap1.datadoghq.com`に修正し、スタックを再度作成すると、作成に成功しインテグレーションを行うことができました。
xargsで標準入力がなければ後続を実行しないオプション。

# xargsで標準入力がなければ後続を実行しないオプション。

対象ファイルを探して、ファイル(コピー、移動、削除)運用するシェルはよくありますよね。

今まで私は、(細かい処理は省いてます)運用シェルで以下のようにしていました。

```
find <検索directory> -type f -mtime +14 > tmp.list

while read LINE
do
if [ -n "${LINE}" ]; then
    rm ${LINE} 
    if [ $? -ne 0 ]; then
         echo "Failed to delete ${LINE}." > ${LOGFILE}
    fi
fi
done < tmp.list
```
わざわざ、tmp.listにファイル一覧を出力してから次の処理にしていたのは、どのファイルで失敗しかた分からなくなってしまうからだ。(findの結果を直接リダイレクトでもいいですが)

どのファイルで失敗しかた分からなくてもいいのなら

```
find <検索directory> -type f -mtime +14 | xargs /bin/rm
```

でいいのだが、findで何も見つからなかったら・・・

```
rm: missing operand
Try `rm --help' for more information.
```

と出て非常に格好悪い・・・

そこでxargsには、標準入力が空だったら何もしない`--no-run-if-empty`オプションがあるではないかw

```
find <検索directory> -type f -mtime +14 | xargs --no-run-if-empty /bin/rm
```

とすればfindで何も見つからなくても格好悪いメッセージを出力することなくスルーしてくれます。
うーーーん、気持ちいいwww
VSCodeのSnowflake拡張のススメ

# VSCodeのSnowflake拡張 おすすめです
みなさん、VSCodeのSnowflake拡張 [Snowflake Extension for Visual Studio Code](https://docs.snowflake.com/ja/user-guide/vscode-ext) を利用していますか？

Snowsight（Snowflakeのウェブインターフェース）の使い勝手が良いので、あえてVSCodeでSnowflakeする必要性を感じていなかったのですが、今更ながら利用したところ結構便利だったのでおすすめさせていただきます！

※ VSCodeへのインストール方法については別記事などをご参照ください。

https://qiita.com/kitappi/items/82ab46aa10b86c6ba4a0#%E3%83%86%E3%82%B9%E3%83%88%E7%92%B0%E5%A2%83%E4%BD%9C%E6%88%90

# おすすめポイント
## インターフェイスが見やすい
まず、Snowflakeの公式のインターフェイス説明はこちらです。

https://docs.snowflake.com/ja/user-guide/vscode-ext#navigating-the-sf-vscext-interface

Snowsightのワークシート画面と比較して、VSCode拡張のインターフェイスの方が使いやすいなと感じています。

Snowflakeのタブをファイル管理タブと別側に分割することで、SQLファイルの行き来とテーブル一覧の確認がタブ切り替え無しにできるところが良いです。
SnowsightのワークシートではDBとワークシートのタブ切り替えが必要で若干手間でした。

また、Snowsightとの違いとして、テーブルの情報が確認しやすいところも気に入っています。
Snowsightのワークシート画面では左側のタブ内に詰まっているので少し確認しづらかったところ、VSCode拡張ではクエリ結果と同様の位置に表形式で表示してくれてかなり見やすい。

![インターフェイス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/8b0cda03-a5b8-af47-ff0a-54d2ca9582d7.png)

## GitHub Copilotの支援を受けることができる
GitHub Copilotの支援を受けてクエリが書けるのはやはり強いです。
※Snowflake Copilotが利用できるようになればちょっと話が変わってくるかもしれません！

https://www.snowflake.com/blog/copilot-ai-powered-sql-assistant/?lang=ja

例えば下記クエリのように、国コード（アルファベット3文字）が登録されているテーブルがあり、3地域に分類したテーブルを別途作成するという時に、コメントでの指示に従って、アルファベット3文字バージョンのクエリを自動で提案してくれます。
これを人力入力は結構面倒なのでかなり良い。

同様に、「難しくはないが書くのが手間」みたないクエリを書く際にはかなり強力な助けになります。
（集約関数を利用していると、GROUP BYに勝手にカラム名を追記してくれるもの助かる。）

```sql
/*
以下の3地域に分類した地域別テーブルをする。
東アジア：韓国、台湾、香港、中国、マカオ
東南・南アジア：タイ、シンガポール、マレーシア、インドネシア、フィリピン、ベトナム、インド
欧米豪：米国、豪州、英国、カナダ、フランス、ドイツ、イタリア、ニュージーランド、スペイン、メキシコ、オランダ、ロシア、スイス、ハンガリー、フィンランド、ポルトガル、チェコ
*/

create or replace table region_country_code as
select
    case
        when alpha3 in ('KOR', 'TWN', 'HKG', 'CHN', 'MAC') then '東アジア'
        when alpha3 in ('THA', 'SGP', 'MYS', 'IDN', 'PHL', 'VNM', 'IND') then '東南・南アジア'
        when alpha3 in ('USA', 'AUS', 'GBR', 'CAN', 'FRA', 'DEU', 'ITA', 'NZL', 'ESP', 'MEX', 'NLD', 'RUS', 'CHE', 'HUN', 'FIN', 'PRT', 'CZE') then '欧米豪'
        else 'その他'
    end as region,
    ja_name,
    alpha3
from country_code
;
```

## ステージを操作しやすい
ステージを操作できる機能、地味に便利です。

https://docs.snowflake.com/ja/user-guide/vscode-ext#working-with-stages

GIS関連の解析では、GISソフトで作成したデータ（ポリゴンなど）をインポートして使いたいことが多々あります。
それらのデータをインポートするにはINSERT文でクエリしていくことも可能ですが、データが一定数ある場合にはそこそこ大変なので、GeoJSON等にしてステージに上げてそれをCOPYしてくる流れを取っています。
この中で「ステージに上げる」部分が少し手間でした。。。

しかし、VSCodeの拡張では、ポチポチするだけですぐにステージにファイルをアップロード可能です！
下記スクショのアップロードボタンをポチッとするだけで、ローカルファイルをステージにアップロードできます。

![ステージ作成テスト_sql_—_Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/a037f5dd-9a6d-4635-fbc3-ed474dbe8464.png)


## クエリの共有がしやすい
Snowsightのワークシートも共有可能ですが、VSCodeでは単純にSQLファイルを扱っているだけなので、ファイルの共有が簡単です。
GitHubでも、Googleドライブでも好きな方法で。
汎用クエリ等はGit管理ができる点もいいですね。


## （試していないのですが）Snowpark Pythonとの連携
[英語版のドキュメント](https://docs.snowflake.com/en/user-guide/vscode-ext#working-with-snowpark-python-code)では紹介されていますが、Snowpark Pythonコードをデバックしたり、SQLをシンタックスハイライト・オートコンプリートしてくれるようです。
また、Jinjaテンプレートの構文ハイライトと括弧のオートコンプリートをしてくれるらしい。（Jinjaを使ったことはないけれど、なんだか便利そうな雰囲気）

https://qiita.com/simonritchie/items/cc2021ac6860e92de25d
「世界一流エンジニアの思考法」を読んで大事だと思ったこと

「[世界一流のエンジニアの思考法](https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E6%B5%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AE%E6%80%9D%E8%80%83%E6%B3%95-%E7%89%9B%E5%B0%BE-%E5%89%9B/dp/4163917683)」を読んで大事だと思ったことを備忘録として整理した記事です。  
私の解釈で記載していますので、ご注意ください。

## 「世界一流のエンジニアの思考法」とは

著者の牛尾剛さんがマイクロソフトで働いた経験から得た、一流エンジニアの思考法や、アメリカと日本の働き方の違いを学ぶことができます。

[IT エンジニア本大賞 2024](https://www.shoeisha.co.jp/campaign/award/result) のビジネス書部門にノミネートされています。

## 個人的に大事だと思ったこと

書籍の中で個人的に大事だと思ったことと、それに対する自分の考えを記載します。

### 理解とは人に説明できて、応用して使えることである

人に説明するには、なぜ説明対象が必要なのかという背景まで理解しておく必要があると思いました。

### 理解は時間がかかるものと認める

私は書籍などで新しいことを勉強する時に、理解が曖昧な状態でもページを進めることを優先してしまいます。その結果、使える知識として身についていないことがよくあるので、ひとつずつ着実に理解していきたいと思いました。

### コードを書く前に小さなドキュメントを書く

コーディング以外のタスクでも、始める前にドキュメントとして書き出すことで頭が整理されると思いました。

### 自分のルールを他人に強要してしまう「鏡の法則」

私は少し無理をしがちなのですが、他のメンバも私と同じくらい働くのが当然と考えてしまいます。チーム全体の健康を保つためにも、もっとルーズになるべきなのでしょう。

### 調べずに即実行できることを増やす

技術を徹底的に理解してすぐ取り出せるものを増やすことが生産性向上につながるというものです。
わかりやすいアウトプットを優先してしまいがちですが、日々の積み重ねも大切にしたいです。

### タスクを中断する時はすぐ戻れるように記録をつけておく

前日に実施していたタスクの続きを実施する場合でも、何をしていたか思い出すのに時間がかかります。
記録をつけておくことは、思い出す時間の短縮と頭の整理に役立つと思いました。

### 今実施しているタスクに集中するためにタスクの残骸は消す

終わったタスクに関連するブラウザのタブを閉じることが、例に挙げられています。
私はブラウザのタブだけでなくエクセルなどのファイルも全て閉じるようにしています。

### 常に他人に共有する前提でメモを取る

何か聞かれた時にメモを共有するだけでいいので、工数を削減できます。
また、自分で見返した時や頭の整理に役立ちます。

### リモートワークではクイックコール（予定していない通話）を活用する

チャットより通話の方が、情報量が多くリアルタイムでフィードバックを得ることができます。
私は自分で抱え込んでしまうタイプなのですが、躊躇せずにチームメンバの力を借りることがチーム全体の作業効率向上につながるのでしょう。

### 意見が対立しても相手の意見を尊重する

自分の意見を述べる前に「私の意見では」と一言添えることを癖にしたいです。

### 仕事は楽しむもの

マイクロソフトでの 1on1 では、上司から仕事を楽しめているかを確認されるそうです。
日本とは根本的に考え方が違うのでしょう。

### 新人をできる大人として扱う

新人だとしても他のメンバと同じ同僚として扱うことで、周囲の助けを借りつつ仕事をこなせるとのことでした。
私は過保護なタイプなのですが、それが逆に成長を妨げている可能性があるのではと反省しました。

### 安全圏の外に出てチャレンジする

自分の能力を上回る領域（安全圏の外）に出て何度も失敗することで大きく成長できます。
今の自分にできる範囲で行動しがちな私には耳が痛い話でした。

### 休息は何もしないのではなく違うことをやる

違うことをやることでリフレッシュになり、別に視点を持つきっかけにもなります。

### 毎日 30 分の運動を最優先事項とする

著者の牛尾さんは毎日 30 分の運動を続けることで、気力のなさが解消されたそうです。
ウォーキングなど低負荷でもよいので、毎日継続することが大事だと思いました。

### 自分の人生は自分で決める

我慢していることがあれば、上司や会社のせいにするのではなく環境を変えるなど自分で行動するべきです。
自分の人生は自分の行動次第です。

## 余談

2024 年 4 月に実施された「Qiita Conference 2024」で牛尾剛さんの基調講演があり、YouTube でアーカイブを見ることができます。
この本にはない内容も聞けるのでおすすめです。

[Qiita Conference 2024 Day1](https://youtu.be/xv8ChImHIEk?si=MoGR64XtaGj2D54K)
データ同化を学ぶ

# 和文教科書

https://www.kyoto-up.or.jp/book.php?id=1622

* 海寄り

https://www.kyoritsu-pub.co.jp/book/b10003293.html

* 統計寄り

https://www.metsoc.jp/2008/02/29/11571

* 気象寄り

https://www.kyoritsu-pub.co.jp/book/b10086310.html

* 簡潔

# 英文教科書

Mark Asch, Marc Bocquet, and Maëlle Nodet
Data Assimilation: Methods, Algorithms, and Applications
https://doi.org/10.1137/1.9781611974546

* タイプミス多め。

Steven J. Fletcher
Data Assimilation for the Geosciences 2nd edition
https://www.sciencedirect.com/book/9780323917209/data-assimilation-for-the-geosciences

* 基本知識を全て網羅するが、高くて分厚い。

Evensen, Geir, Vossepoel, Femke C., van Leeuwen, Peter Jan
https://doi.org/10.1007/978-3-030-96709-3

* 無料で読める。
* 記号が独特。

Eugenia Kalnay
Atmospheric Modeling, Data Assimilation and Predictability
https://doi.org/10.1017/CBO9780511802270 

* モデルとデータ同化とアンサンブル予報がまとめられている。
* LETKFは書いていない。

# セミナー資料・レポート

Olivier Talagrand
Adjoint models
https://www.ecmwf.int/sites/default/files/elibrary/1991/12548-adjoint-models.pdf

* 数値モデルをやっているが、同化は知らない人向けのセミナー。

Huang, X.-Y. and X. Yang, 1996: Variational data assimilation with the Lorenz model. Technical Report 26, HIRAM, April 1996, 44 pp.

* Lorenz-63モデルの随伴の書き方が詳しく記述されている。

ECMWF NWP lecture notes
https://www.ecmwf.int/en/learning/education-material/lecture-notes

# 特集号

気象集誌第75巻1B号
Atmospheric Observations and Experiments to Assess Their Usefulness in Data Assimilation (Special IssueltData Assimilation in Meteology and Oceanography: Theory and Practice)
https://www.jstage.jst.go.jp/browse/jmsj/75/1B/_contents/-char/en

# 動画

伊藤耕介さんによる分かりやすい講義

https://youtu.be/Aqc9ZSHd54s?si=Zyg6w4SLxWb_e15P
コンビニスイーツをランダムに表示するLINE BOTをつくる

# はじめに

以前CloudflareWorkers + Hono + LINE Messaging APIでセブンイレブンのアイスクリームをランダムに提案するLINE BOTを作りました。

https://zenn.dev/sui_water/articles/fac4334293a1c0

同じ要領で「コンビニスイーツをランダムに提案する」LINE BOTも作れるんじゃね？と思ったので作成していきます。

# 要件

- Flex Messageでスイーツの画像、名称、価格を表示して画像をタップすると商品ページへアクセスできる
- リッチメニューでセブンイレブンのスイーツ、ローソンのスイーツ、ファミリーマートのスイーツを押すと、対象のスイーツを取得できる
- 毎週火曜日にCron Triggersを使用して最新のスイーツ情報へ更新する
    - セブンイレブンの新商品が更新されているタイミング

# 実際に作成したもの

## QR

https://lin.ee/ANONJtN

## デモ

![20240427_105259.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3351724/bfdd0fd7-d647-1ddd-b22c-30ae67f991b2.gif)


## リポジトリ

https://github.com/Suntory-Y-Water/convenience-store-sweets-bot

# 感想

アイスクリームを返すLINE BOTを作ったときと同じ要領で作成したのでスピード感ある開発ができた

参照したいコンビニが増えたとしても、ページ構造を追加LINEのリッチメニューさえ変えれば動くような仕組みになっている

課題としては商品ページをHTMLRewriterで抜き出しているため、ページ構造が変わった瞬間に動かなくなってしまうところだけど良い案が思い浮かばなかった…

LINE BOT開発自体はおもろいので何かあればまたつくってみる
paiza.ioでnode.js その2

# 概要
paiza.ioでnode.js、やってみた。
練習問題やってみた。

# 練習問題
note.comのAPIを叩け。


# サンプルコード

```
process.stdin.resume();
process.stdin.setEncoding('utf8');

let http = require('https');

const URL = 'https://note.com/api/v2/creators/ohisama_llc';

http.get(URL, (res) => {
  let body = '';
  res.setEncoding('utf8');
  res.on('data', (chunk) => {
      body += chunk;
  });
  res.on('end', (res) => {
      res = JSON.parse(body);
      console.log(res);
  });
}).on('error', (e) => {
  console.log(e.message);
});


```

# 実行結果

```
{
  data: {
    id: 9300283,
    key: '987004565a00a3a690ca251ce4a1629a',
    nickname: 'ohisama',
    urlname: 'ohisama_llc',
    profile: '',
    noteCount: 1,
    magazineCount: 0,
    followingCount: 1,
    followerCount: 0,
    isFollowing: false,
    isFollowed: false,
    isMyself: false,
    originalHeaderImageUrl: null,
    headerImageUrl: null,
    headerImageKey: null,
    profileImageUrl: 'https://d2l930y2yx77uc.cloudfront.net/assets/default/default_profile_4-e3b57528da29acad20d5a2db33268c87f1d39015448757ddf346d60fb5861e49.png',
    profileImageKey: null,
    isBlocked: false,
    blocksYou: false,
    isAdmin: false,
    socials: {},
    isOfficial: false,
    showFollowCount: true,
    externalLinks: {},
    disableSupport: false,
    hasStore: false,
    hasCircle: false,
    customDomain: null,
    followAppealText: null,
    followAppealImage: null,
    isCreatorLikesTabEnabled: true,
    isCreatorMagazinesTabEnabled: true,
    isCreatorCirclesTabEnabled: true,
    isCreatorArchivesTabEnabled: true,
    isCreatorProfileTabEnabled: false,
    isCreatorJobOfferTabEnabled: false,
    isCreatorFollowNumberDisplayed: true,
    style: 'streem',
    isPro: false,
    proUserId: null,
    tlMagazines: [],
    isMedia: false,
    storeUrl: '',
    jobSourceUrl: null,
    isHavingSubscribableMagazines: false
  }
}
```

# 成果物

https://paiza.io/projects/HkRWpNwmTpn65DhEEa6g0Q


以上。
paiza.ioでnode.js

# 概要
paiza.ioでnode.js、やってみた。
練習問題やってみた。

# 練習問題
バージョンを取得せよ。

# サンプルコード

```
process.stdin.resume();
process.stdin.setEncoding('utf8');
// Your code here!

console.log("XXXXXXXX")
const { spawn } = require('child_process');
const ls = spawn('node', ['-v']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});





```

# 実行結果

```
XXXXXXXX
stdout: v16.17.0
```

# 成果物

https://paiza.io/projects/xJH2PwUVbFMNOKn4XkSahg


以上。
golang/goのコードリーディングでVSCodeのコードジャンプが効かない

# 結論

developブランチを参照するのではなく、インストールされているバージョンのブランチを参照する


```
git checkout go1.22.2
```

# memo

goplsで以下のようなエラーが出ていた。
原因はdevelopブランチが開発中のgo1.23のコードになっていたためである。

```
go env env,json,GOMOD,GOWORK: Command failed: /opt/homebrew/bin/go env -json GOMOD GOWORK go: downloading go
```
PDO (PHP Data Objects)・2回目

## はじめに

PDOについてまとめる・2回目

### SQLを発行しデータを登録する

insert.phpで入力された内容を、insert_process.phpで登録処理する。

```php:insert_form.php
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>データの登録</title>
</head>

<body>
    <form action="insert.php" method="POST">
        <div>
            <label for="isbn">ISBNコード：</label>
            <input id="isbn" name="isbn" type="text" siza="25" maxlength="20">
        </div>
        <div>
            <label for="title">書名：</label>
            <input id="title" name="title" type="text" siza="35" maxlength="150">
        </div>
        <div>
            <label for="price">価格：</label>
            <input id="price" name="price" type="text" siza="5" maxlength="5">円
        </div>
        <div>
            <label for="publish">出版社：</label>
            <input id="publish" name="publish" type="text" siza="15" maxlength="30">
        </div>
        <div>
            <label for="published">刊行日：</label>
            <input id="published" name="published" type="text" siza="15" maxlength="10">
        </div>
        <div>
            <input type="submit" value="登録">
        </div>
    </form>
</body>

</html>

```

DBに発行する一連の命令を管理するのは、PDOStatementオブジェクトの役割。
`prepare`メソッドでSQL命令を準備し`execute`メソッドで命令が送信/実行される。

```php:insert_process.php
<?php
require_once __DIR__ . '../DbManager.php';

try {
    $db = getDb();
    $stt = $db->prepare('INSERT INTO book(isbn, title, price, publish, published) 
    VALUES(:isbn, :title, :price, :publish, :published)');
    $stt->bindValue(':isbn', '$_POST[isbn]');
    $stt->bindValue(':title', '$_POST[title]');
    $stt->bindValue(':price', '$_POST[price]');
    $stt->bindValue(':publish', '$_POST[publish]');
    $stt->bindValue(':published', '$_POST[published]');
    $stt->execute();
    header('Location: http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/insert_form.php');
} catch (PDOException $e) {
    die("エラーメッセージ:{$e->getMessage()}");
}
```

接続スクリプトの外部化

```DbManager.php
<?php
function getDb(): PDO
{
    $dsn = 'mysql:dbname=selfphp; host=127.0.0.1; charset=utf8';
    $usr = 'selusr';
    $passwd = 'selfpass';

    $db = new PDO($dsn, $usr, $passwd);
    return $db;
}
```

### PDOStatementオブジェクト

PDOStatementオブジェクトは、PDOオブジェクト`$db`から`prepare`メソッドを呼び出すことで取得できる。
insert_process.phpにおける　`prepare`メソッドに含まれる「:名前」という記述はプレイスホルダーを表す。
プレイスホルダーとはパラメータの置き場所のこと。
PDOオブジェクトではプレイスホルダーに対して実行時に任意のパラメータを引き渡すことができる。
(`bindValue`メソッドで実際にプレイスホルダーに値を設定している。)


```php:prepareメソッド
PDO::prepare(string $statement[, array $driver_options]): PDOStatement

$statement : 発行するSQL命令
$driver_options : 動作オプション
```
新卒2年目が転職ドラフトで初転職した話

## はじめに

こちらの記事は転職ドラフト体験談投稿キャンペーンに参加しています。
https://job-draft.jp/articles/251

この度、転職ドラフトを利用して初めての転職を行ったので、その体験談になります。

## 筆者について

- 2000年生まれ（記事投稿時24歳）
- 2022年4月に新卒でBtoBのSaaSを開発している企業に入社
- 主にJavaを用いたバックエンドの開発に従事
- 2023年12月に転職活動を開始、2024年3月に内定承諾

経験してきた技術については、ざっくり以下のようになっています。

- Java、SpringBoot
- PostgreSQL
- JavaScript、Vue.js（ちょっと）
- Docker、Kubernetes（ちょっと）

## 指名から選考の流れ

### 指名

私は2回のドラフトに参加し、以下のような指名件数でした。

- 1回目：指名11件
- 2回目：指名6件

### 選考

指名をいただいた後は、
カジュアル面談 → 面接（複数回）　→ 内定
という流れです。

私は「とりあえずいろんな会社の話を聞いてみたい」と思っていたので、指名をいただいた企業のほとんどとカジュアル面談をしました。
そこから絞って選考を受けて、辞退やお断りされたりなどありつつも、最終的に3社から内定をいただくことができました。
事業内容、やれること、待遇面などを考慮して1社を選び、内定承諾した形になります。

## 転職ドラフト使って感じたこと

### レジュメのフィードバックがありがたい

転職ドラフトではレジュメと呼ばれる職務経歴書のようなものをフォーマットに沿って入力し、それを企業側に見ていただいて指名をもらうようになっています。

レジュメはドラフト参加前に転職ドラフト審査チームの方に確認していただき、OKをもらわないとドラフトに参加することができません。
その際に審査チームの方から細かくフィードバックをもらえるので、より伝わりやすい職務経歴書を作成するヒントにもなると考えています。

### 指名の内容が具体的

企業側から指名をいただくと、その企業が

- どんな課題を抱えているか
- 自分にどんな役割を期待して指名したのか

などについてかなり細かくメッセージを貰えます。
それによって

- 自分のどこが評価されるのか
- 過剰な期待を抱かれていないか
- 入社後どんな仕事をすることになるか

などが把握できて、それを元にカジュアル面談や面接で質問できるのがよかったです。

### 年収が大幅に上がった

ここは個人差があると思いますが、私の場合は結果的に前職と比較して200万円以上年収が上がりました。
これは転職ドラフトが現年収を提示する必要が無いことも関与していると感じます。

周りの知り合いで他のエージェントを使って転職した方の話を聞くと、現年収を聞かれてそれに沿って次の年収が決まるパターンが多い印象です。
しかし、転職ドラフトではレジュメやその他アウトプットを見て指名金額を判断されるので、現年収にアンカリングされないのが魅力だと思っています。

## まとめ

私にとって初めての転職でしたが、無事に興味のある企業に年収を上げて転職することができました。
転職ドラフトを使ってよかったと強く思っていますし、周囲にもおすすめしています。

本記事を見てくださっている方の転職の参考になれば幸いです。
最後までお読みいただきありがとうございました。
Proxmox Automated Installation の proxmox-auto-install-assistant がない！



:::note info
作成日：2024/4/27
バージョン情報：
PVE 8.2.2
PBS 3.2.2

修正：2024/4/27 16:30
フィードバックが取り込まれ、マニュアルが修正されたことを追記
:::







## TL;DR

- Proxmox Automated Installation を利用するための `proxmox-auto-install-assistant` がPVE・PBS 上で見つからない！
- デフォルトではインストールされていないため、`apt install proxmox-auto-install-assistant` でインストールが必要
- マニュアルにも記載がないので、コミュニティフォーラムにフィードバックした。


## 概要

このイベントのLT3で話した内容とその宿題です。

https://jpmoxs.connpass.com/event/316118/


PVE 8.2、PBS 3.2.2 で追加された新機能として、Proxmox Automated Installation が追加されました。

https://pve.proxmox.com/wiki/Automated_Installation

PBSのマニュアルのほうは、PVEへのリンクとなります。

https://pbs.proxmox.com/docs/installation.html


## `proxmox-auto-install-assistant` が見つからない。

以下の環境で`proxmox-auto-install-assistant` コマンドがありませんでした。

- PVE
  - 8.1 からアップデートしたノード
  - ISOから8.2をインストールしたノード
- PBS
  - 3.1からアップデートしたノード

```
root@pve:~# proxmox-
proxmox-backup-client          proxmox-boot-tool              proxmox-file-restore           proxmox-mail-forward           proxmox-offline-mirror-helper  proxmox-websocket-tunnel
```

## コマンドのインストールが必要

`apt install proxmox-auto-install-assistant` で別途コマンドのインストールが必要でした！
※イベント登壇時に情報提供いただいた方、ありがとうございます！

```
root@pve:~# apt install proxmox-
Display all 128 possibilities? (y or n)
（中略）
proxmox-auto-install-assistant               proxmox-headers-6.2.16-9-pve                 proxmox-kernel-6.2.16-14-pve                 proxmox-kernel-6.5.11-8-pve                  proxmox-kernel-6.8.4-2-pve-signed
root@pve:~#
root@pve:~# apt install proxmox-auto-install-assistant
```



## コミュニティフォーラムへのフィードバック

登壇のために新機能やってみたRTAした身としては、バージョンアップに含めてほしい・せめてマニュアルには記載してほしいという気持ちありますし、同様の事象で困る人もいると思うので、コミュニティフォーラムにフィードバックを送ってみます。

内容としては以下です。

- コマンドが含まれていないのは想定通りか？
- 今後含まれるようになるか？
- 含まれないのであれば、コマンドのインストールについてマニュアルに記載してほしい

https://forum.proxmox.com/threads/proxmox-ve-8-2-released.145723/post-658226


~~反映されるといいなぁと思います。~~ 

### 2024/4/27 16:30追記　早速反映されました。

オンラインマニュアルに `apt install proxmox-auto-install-assistant` をまず初めに実行する旨、追記してくれました！
Neobin さん、ありがとうございます！

https://forum.proxmox.com/threads/proxmox-ve-8-2-released.145723/post-658230

## 参考


https://pve.proxmox.com/wiki/Automated_Installation

https://jpmoxs.connpass.com/event/316118/

https://togetter.com/li/2356114?page=2#h46_0
#Salesforceで日時から年と月を抽出する方法

# Salesforceで日時から年と月を抽出する方法

こんにちは！今日はSalesforceでちょっとした数式トラブルを解決した話をシェアしたいと思います。Salesforceで日時データから年や月を抽出する際、私は最初に簡単なエラーに直面しましたが、それを乗り越えた方法をみなさんと共有します。この記事が、同じ問題に直面している方々の役に立てば嬉しいです。

## 問題発生！

`DateTime` データから年と月を取得しようとしたとき、私は以下の数式を試みました：

```plaintext
TEXT(YEAR({!$Flow.CurrentDateTime})) & "年" & TEXT(MONTH({!$Flow.CurrentDateTime})) & "月"
```

ところが、Salesforceからはこんなエラーメッセージが返ってきました：

```
数式は無効です: 関数 'YEAR()' のパラメーター種別が間違っています。期待日付、受信DateTime
```

## 解決策はこちら！

エラーメッセージによると、`YEAR()` と `MONTH()` 関数が期待しているのは「日付型」のデータで、私が使っていた `{!$Flow.CurrentDateTime}` は「DateTime型」でした。そこで、この型の不一致を解消するために `DATEVALUE()` 関数を使うことにしました。

```plaintext
TEXT(YEAR(DATEVALUE({!$Flow.CurrentDateTime}))) & "年" & TEXT(MONTH(DATEVALUE({!$Flow.CurrentDateTime}))) & "月"
```

`DATEVALUE()` 関数は `DateTime` を `Date` に変換し、それを `YEAR()` と `MONTH()` で処理可能にします。

## 成功！

この修正を加えたところ、無事に年と月をテキスト形式で取得できるようになりました。これで、レポートやダッシュボードに日付情報を簡単に表示できるようになり、作業の効率が大幅に向上しました。

## まとめ

Salesforceで日時データを扱う際は、データ型に注意して正しい関数を使うことが重要です。この小さなトリックが皆さんのSalesforceライフを少しでも楽にすることを願っています。何か問題に直面したら、エラーメッセージをよく読み、適切な関数が使えているか再確認してみてくださいね！

皆さんのSalesforceの旅もスムーズでありますように！
【Docker環境構築】Ubuntu 20.04 + Python 3.10

## 背景
Ubuntu20.04では、通常のPythonインストールだと3.8が入ってしまい3.10のインストールは少し工夫する必要がある。

本記事では、Dockerを用いてUbuntu20.04+Python3.10のローカル開発環境を構築する。

## 環境
Docekr Desctop
Ubuntu 20.04
Python 3.10

## ディレクトリ構成
```
.
├── docker
│   ├── docker-compose.yml
│   ├── Dockerfile
│   └── requirements.txt
└── src
    └── main.py
```

### dockerフォルダ
Docker起動用のファイルが格納されている。

### srcフォルダ
プロジェクトの実行ファイルを格納する。
Dockerコンテナ起動時にはsrcフォルダ内が参照される。

## docker-compose.yml

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

services:
  python:
    image: python3.10
    build: .
    container_name: python3.10
    working_dir: /workspace/src
    volumes:
      - ../src:/workspace/src
    tty: true
```


## Dockerfile
```Dockerfile
FROM ubuntu:20.04
USER root

WORKDIR /workspace
COPY requirements.txt ${pwd}

ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt-get update -y
RUN apt-get upgrade -y
RUN apt-get dist-upgrade -y
RUN apt-get autoremove -y
RUN apt-get autoclean -y

# Python 3.10用のPPAを追加してインストール
RUN apt-get install -y gnupg2 curl
RUN apt-get install software-properties-common -y
RUN add-apt-repository ppa:deadsnakes/ppa -y
RUN apt-get install python3.10 -y
RUN apt-get update -y
RUN apt-get install -y libgl1-mesa-dev
RUN apt-get remove python-pip
RUN apt-get install python3.10-distutils -y
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
RUN pip install -r requirements.txt

# pythonコマンドの参照先をPython3.10に変更
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1

CMD ["/bin/bash"]
```

## requirements.txt

```
numpy
pandas等
使用するライブラリを記載する
```

## コンテナ起動

dockerディレクトリに移動する
```
cd docker
```

コンテナ起動
```
docker compose up -d
```

## 最後に
同じような開発環境を使用する方の参考になれば幸いです。
Ubuntu22.04環境下のOmniverseにいきなりログインできなくなった時に取った対応

# 1. はじめに
[Ubunutu22.04の環境下においてIsaac Sim+ROS2を試そうとしてハマったところ](https://qiita.com/bebebefu/items/a89694659e650665e5db)の記事にも書きましたが、Omniverseの環境をUbuntu22.04の環境下に構築して使おうとしています。そんな中、以前はOmniverseにログインできていたのに、突然ログインできなくなったという問題が発生しました。その際にどのように解決したかを記載したのが、本記事の内容になります。
非常に短い記事になりますが、トラブル解決の一助になれば幸いです。

# 2. 実行環境
- CPU: CORE i7 7th Gen
- メモリ: 32GB
- GPU: GeForce RTX 2070
- OS: Ubuntu22.04(WSL2ではなくPCに直接インストール)
- ROS2: Humble
- Isaac Sim: 2023.1.1
- Nvidia Driver: 525.147.05 (525.85.05が推奨されていますが、私の環境ではインストールできませんでした)

# 3.起こった事象
https://forums.developer.nvidia.com/t/omniverse-launcher-stuck-at-login-in-ubuntu/261635

起こった事象としては、👆でリンクを張った事象と同じようにUbuntu22.04の環境下において、firefox経由でomniverseにアクセスできなくなりました（ずっとローディングしている状態になります）。

# 4. 解決方法
Google Chromeをインストールし、それをデフォルトのブラウザに設定してから、Google Chromeを介してOmniverseにアクセスすると、この問題は解決されました。これは👆のリンクのディスカッションでも言及されている解決策ですが、全ての人に適用されるわけではないようです。ただし、私の場合は有効でした。
GCE に VSCode で接続する

多分、この手順が一番簡単。

参考
https://medium.com/@liu.peng.uppsala/safe-way-to-connect-your-vscode-to-compute-engine-from-google-cloud-platform-using-ssh-4e64c70fbb45

1. GCE インスタンス作成
2. VSCode Remote Development 拡張機能追加
3. ローカルPCからコマンド入力
    > $ gcloud compute ssh {インスタンス名} --zone={ゾーン名} --tunnel-through-iap --dry-run
4. 出力結果をVSCodeに貼り付け

以上です。