OmniAICreator/Qiita-1.07M huggingface dataset:
Blender奮闘記⑤

# 初めに
星空キャンディを作ろうの学習、復習が終わりました。次にこれで得た知識を使用して応用したいと思います。
今回はスーパーボールを作ります。

# 完成イメージ
完成のイメージは前回の記事にありますが、再度挙げます。
![mono74062266-180209-02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/5f9ea91d-50c9-bff7-c081-744d23da8409.jpeg)
スーパーボールの形自体はUV球を使えばほぼそのまま使えるので、問題はテクスチャになります。
ここらへんでシェーダーエディターについて勉強しておきたいところ……

# スーパーボール作成
![ボール部分.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/6aabbf6d-a96c-4199-4635-a2268506d58c.png)
ボール部分は一瞬でした。(UV球を出して成型時に出るバリを作り、スムーズシェードをかけただけです。)

問題はシェーダーエディターですね。

そもそもシェーダーエディターって何だろうかと思ったので調べました。
[【Blender2.8】シェーダーエディター入門](https://styly.cc/ja/tips/blender_shader_beginner/#:~:text=%E3%82%B0%E3%83%A9%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%BF%E3%81%86-,%E3%82%B7%E3%82%A7%E3%83%BC%E3%83%80%E3%83%BC%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%83%BC%E3%81%A8%E3%81%AF,%E3%82%92%E9%81%B8%E3%81%B6%E3%81%A8%E4%BE%BF%E5%88%A9%E3%81%A7%E3%81%99%E3%80%82)
こちらによると、シェーダーエディターとはマテリアルをノードベースで変数するためのエディタとのことです。レンダリングエンジンの違いによって使えるノードが異なるようですが、今回はCyclesを使用することを前提とします。

初めに動画の中で最初に使用したノイズテクスチャについてです。
![ノイズテクスチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/ee0f1e47-3c82-f561-cc30-5359a48a522c.png)
シェーダーエディターで見たときはこのようになります。
![ノイズテクスチャのみ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/3694bd02-e332-c161-fbb5-11f16affa2ae.png)
ノイズテクスチャのみを接続するとこのような模様が出てきます。色の値にノイズが載って出力されるということのようです。

カラーランプは入力に対して2種類の色を出力するノードのようです。
[Color Ramp (カラーランプ)ノード](https://docs.blender.org/manual/ja/3.0/modeling/geometry_nodes/color/color_ramp.html)

今回は入力をノイズテクスチャとしているので、間にカラーランプを挿入すると設定した2色をランダムで配置することになるようですね。

次にマスグレイブテクスチャです。下のサイトにわかりやすく書いてありました。
[マスグレイブテクスチャを分かりやすく説明してみる／使い方編](https://hainarashi.hatenablog.com/entry/20220212/1644635403)

雑に言うと、複雑かつ不規則なパターンを作るテクスチャだそうです。

ノイズテクスチャとの違いはノイズの規模が(設定できるが)ノイズテクスチャよりも荒いということのようです。

これらを適用してスーパーボールを作るとこのようになりました。
![スーパーボール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782192/397f87bd-ad7d-2966-77b7-fe7bbb7d491a.png)

思ったよりもバリ部分もよくできていますし、スーパーボールにありそうなものが出来上がったような気がします。

# 終わりに
今回は応用としてシェーダーエディターの勉強をしました。テスクチャを作る際に今後も使用していきたいと思います。
特にマスグレイブテクスチャは自然な粗を作るうえで重要となるシェーダーのようですので、もっと多用したいですね。
コマンドラインベースでのVitisインストール

## はじめに
先日、**Xilinx社のFPGA開発ツールであるVitisをKVM上のUbuntu20.04LTSにインストール**することを試みました。しかし、webインストーラを起動すると、下記のような黄色い画面（インストーラが正常起動しない状態）が表示されてしまいました。
このように、Vitisインストーラが正常に起動しない場合があります。
その場合は、**コマンドラインベースでのVitisインストール**が代替策となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2756450/48872016-bd84-8b88-a714-03f7dfd020d6.png)

## 参考文献
以下のサイトを参考にしました。ありがとうございます。
https://msyksphinz.hatenablog.com/entry/2016/09/09/020000

## 対象読者
・FPGAを用いた開発に関心のある方
・FPGAを用いた開発の経験がある方

## 本記事の目的
読者の方にコマンドラインベースでのVitisインストール方法を知っていただくこと

## フルインストーラのダウンロード
[Xilinx社のページ](https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vitis.html)からフルインストーラをダウンロードします。
尚、ダウンロードする際には、Xilinxのアカウントが必要となります。
**バージョン2021.2の容量は72GB程度**あるため、ダウンロードに時間がかかります。
夜中にダウンロードを開始して朝を待ちます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2756450/cbc68d3b-ef62-4bf2-55f8-8fbb1c57f87a.png)

## コマンドラインベースでのVitisインストール
ダウンロードした圧縮ファイルを解凍し、フォルダ内にある**xsetup**を用いてコマンドラインベースでのインストールを開始します。
下記のコマンドでconfig用のファイルを生成します。
```
sudo ./xsetup -b ConfigGen
Running in batch mode...
Copyright (c) 1986-2020 Xilinx, Inc.  All rights reserved.

INFO : Log file location - /root/.Xilinx/xinstall/xinstall_1591318833338.log
Select a Product from the list:
1. Vitis
2. Vivado
3. On-Premises Install for Cloud Deployments
4. BootGen
5. Lab Edition
6. Hardware Server
7. Documentation Navigator (Standalone)

Please choose: 1 ← Vitisを選択

INFO : Config file available at /root/.Xilinx/install_config.txt. Please use -c <filename> to point to this install configuration.
```
Config file available...とあるため、/root/.Xilinx/install_config.txtを編集します。
今回は、install directoryを/opt/Xilinxに変更し、それ以外はそのままとしました。
その後、以下のコマンドでインストーラを起動し、インストールを実行します。
```
sudo ./xsetup --agree XilinxEULA,3rdPartyEULA --batch Install --config /root/.Xilinx/install_config.txt
```

## まとめ
コマンドラインベースでのVitisインストール方法を紹介しました。
ソリューションアーキテクト対策_RDS篇

## はじめに
試験勉強した際のメモを自分用に記事化。
内容は公式やBlack Beltの写経ですので目新しいことはありません:pray:


## RDS
### RDSのセキュリティ保護について
データベースの暗号化は、データベースの作成時に行うことができる。

・暗号化の対象
DBインスタンス、自動バックアップ、リードレプリカ、スナップショット

・暗号化方式
AES-256、AWS KMSによる鍵管理
インスタンス作成時にのみ暗号化が可能
スナップショットのコピーの暗号化/リストアが可能

ちなみにDBのリストアとはバックアップしていたスナップショットを突っ込んだり、複製したりの意味。


### RDSのリードレプリカについて
RDSは最大5個のリードレプリカを作成して、読み取り処理の負荷を分散させることができる。
それにより、RDSインスタンスのスケールアップを実施することなくコスト最適な対応が可能。

・ちなみにRDSのレプリケーションとは
複製(レプリカ)を作ること。
マスターのデータベースと同じ内容のデータベースを作成するため、負荷分散やホットスタンバイとしての利用が可能。

・ちなみにRDSの主系はマスター、副系をスレーブという。

リードレプリカについては公式がわかりやすい。
https://aws.amazon.com/jp/rds/features/read-replicas/

マスター、スレーブ、リードレプリカを図にすると以下になる。

<img width="600" alt="スクリーンショット 2022-09-20 11.44.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278897/2a217d5c-3de8-1e69-e02d-344fb7a74b60.png">


### RDSをマルチAZで構成していたら
プライマリに障害が発生した場合、自動でフェールオーバーが発生し切り替わる。
CNAMEレコードをスタンバイから切り替えてプライマリに昇格する。


### RDSのパフォーマンス改善
リードレプリカを増加(最大5台)することでパフォーマンスを向上させることが可能。
アプリケーションの大容量読み込みトラフィックを提供することができるらしい。

ちなみにリードレプリカは非同期的にレプリケートされる個別のDBインスタンスであるため、
レプリケーションデータが遅れることが多く、最新のトランザクションのいくつかを表示できない可能性がある。


### RDSプロキシとは
RDSの機能。例えばLambdaとRDSを連携させたい場合はRDSプロキシを間に挟んで連携する、コネクション管理機能のこと。
(以前はこの機能が実装されていなかったらしい)


### RDSのスケーリングについて
RDSオートスケーリングという機能が存在する。
データ容量が不足した際に、容量を自動でスケーリングする機能。

容量をアップするのであって、パフォーマンスを向上させる訳ではないので注意すること★

### RDSとファイルシステム
RDSはファイルシステムへのアクセスがサポートされていないため、ファイルシステムへのアクセスに基づく設定や自社管理を実現するためにはEC2インスタンスにデータベースをインストールしてデータベースサーバーをカスタムで構築する必要がある。

## RDSとPostgreSQL
・RDSはPostgreSQL13のサポートを開始している

・RDSではPostGISをサポートしている。
※PostGISはPostgreSQLオブジェクトRDB用の地理空間データベース拡張。地理オブジェクトがサポートされているので、SQLで場所のクエリを実行できるようになる

・RDSはEC2インスタンスとの連携やオンプレミスサーバーとの連携が可能

## RDSへの負荷分散(効果が無い対応)
RDSへのアクセス集中を軽減するためにSQSによるキューイング処理を行う。。のは一見効果がありそうだが、負荷分散にはならない。
RDSへのリクエスト処理を並列化しても処理するRDS側のDBインスタンス数は変わらないのが理由。

## RDSとOracle RAC
RDSではRAC構成は実現できないので、EC2インスタンスにOracleをインストールして構成する。

ちなみにRACはOracleのクラスタリング機能で、複数のサーバーで1つのデータベースを構成。
「負荷分散」「拡張性向上」「耐久性向上」を実施することができる。

## RDSの読み取りパフォーマンス向上
RDSの読み取りパフォーマンスを向上させるためには以下のような対応を行う。

・RDSのリードレプリカを追加して、読み取り処理を分散させる
・Elasticacheによるキャッシュレイヤーを追加して、アクセスが集中する一部クエリをキャッシュ処理することで高速処理を実現し、RDSへの負荷を減少させる。
・ストレージタイプをIOPSの大きなサイズに変更することで、RDS本体のI/Oパフォーマンスを向上させる。
※IOPSはHDDやSSDの性能指標のひとつ

この中で用意に実行できてプロセスの改善効果が高いのはリードレプリカ。
RDSリードレプリカは、DBインスタンスのパフォーマンスと耐久性を強化する。
この機能により、読み取りが多いデータベースワークロードの場合、単一のDBインスタンスの容量の制約を超えて柔軟にスケールアウトできる。
既存のDBインスタンスに対してマネジメントコンソール画面から容易に追加することが可能。

### 混同しやすい点
#### RDSインスタンスのサイズをアップグレードする
IOPS性能によってパフォーマンスは向上するが、読み取り処理のスケーリングにはリードレプリカの方が効果的。

#### RDSのオートスケーリングを有効化する
スケーリングによりデータ容量の増強が可能になるが、パフォーマンスの向上にはならない

#### インスタンスタイプの変更
ストレージ最適化インスタンスなど、インスタンスの利用目的に合ったインスタンスタイプに変更することで、その特質に応じた性能が向上する可能性はある。
ただし、インスタンスタイプをマグネティックに変更することで、逆に性能が悪くなる可能性が高い。


## おわりに
引き続き追記します！

以上です。
DataSpiderのSDKのダウンロード方法

## DataSpiderとSDK
データ連携するアプリケーションとして、セゾン情報システムズから提供されているDataSpider Servistaというソフトウェアがあります。
製品の詳細はこちら：https://www.hulft.com/software/dataspider

DataSpiderの定義情報でもあるスクリプトを作成することによりデータ連携することができるようになります。
つまり、スクリプトを作成する際にDataSpiderが提供しているアダプタというものを使用し、これらのアダプタをつなぎ合わせることにより目的のデータ連携ができるようになります。
一方で、目的のデータ連携を実現するためのアダプタが提供されていない場合はどうすればよいでしょうか。
ここで登場するのが、DataSpider SDKです。
このSDKを使用して開発することにより、オリジナルのアダプタを作成することができます。

今回は、このDataSpider SDKの入手方法を紹介したいと思います。

## DataSpider Servista（体験版） の入手
DataSpider SDKを使用するにあたり、DataSpider Servista本体が必要となります。
DataSpiderを少し使用する場合は、体験版が提供されています。
MyHULFTというWebサイトからアカウントを作成し、1か月間有効なライセンスを取得することができ、フル機能を利用することができます。お試しでDataSpiderを使用してみたいというかたには心強いサービスです。なお、この体験版をダウンロードするページからDataSpider SDKもダウンロードするこができます。

* MyHULFTはこちら：
https://his.hulft.com/mypage/login/login/

* DataSpiderインストールの手順はこちら（非常に丁寧に説明してくださっています）：
https://base.terrasky.co.jp/articles/MWULp

## DataSpider Servista Component SDKの入手
1. MyHULFTにログインする。（上記にてDataSpider本体をダウンロードしたサイトと同様）
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849535/2fcf6b3c-03ed-9377-c9f1-a8536a398401.jpeg)

2. 左側のメニューから、「製品情報」をクリックします。
![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849535/b26f6c14-51c6-5e94-1591-b8e3bc5d8dda.jpeg)

3. メニューが展開されますので、そのリストの2番目「ツール/サンプル/ベータ版」をクリックします。
その他のダウンロード一覧が表示されます。
グレーのカテゴリー欄から「ツール」を選択し検索ボタンをクリックします。
![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849535/e56873f1-e42f-3c29-7ef6-d36cf9f8c542.jpeg)

4. 画面をスクロールします。
「DataSpider Servista コンポーネントSDK 4.2」をクリックし、「確認」ボタンをクリックします。
![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849535/ee874ea9-1a0c-1fde-fa41-985b036e4049.jpeg)

5. 画面をスクロールします。
画面下側の「ダウンロード」ボタンをクリックします。
![5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849535/bc7a9e3e-65ed-f927-52dd-c7c3534a8ec9.jpeg)

6. DSS_SDK_42.zip ファイルのダウンロードが開始されます。
以上で、DataSpider本体とSDKが入手できました。

## 次回は
eclipseを使用したSDKの開発環境を構築したいと思います。

https://qiita.com/dataspider-fan/items/64440c41ab458e01497c
ESP32 用の MicroPython をカスタムサイズの FLASH 用にビルドする

ESP32 の MicroPython では、指定したFLASHのサイズのイメージが出来上がる。
公式でダウンロードできるものは、その1つのサイズのビルドになっている。
ESP32-S3-WROOM-1 の Flash のサイズ 4MB を利用しようと思うと、公式でダウンロードできるのは 8MB になっている。

ここで異なったサイズのイメージを書き込むと、マイコン起動時に以下のエラーが表示される。

```
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd0108,len:0xf24
load:0x403b6000,len:0xc2c
load:0x403ba000,len:0x2d60
entry 0x403b61f4
E (251) spi_flash: Detected size(4096k) smaller than the size in the binary image header(8192k). Probe failed.
Traceback (most recent call last):
  File "_boot.py", line 11, in <module>
  File "inisetup.py", line 34, in setup
  File "inisetup.py", line 7, in check_bootsec
OSError: (-24579, 'ESP_ERR_FLASH_NOT_INITIALISED')
MicroPython v1.19.1 on 2022-06-18; ESP32S3 module with ESP32S3
Type "help()" for more information.
>>> 
```

FLASHのサイズは、sdkconfig.base か、各ボードの sdkconfig ファイルにかかれている。

https://github.com/micropython/micropython/blob/9b486340da22931cde82872f79e1c34db959548b/ports/esp32/boards/sdkconfig.base#L54

```
# For cmake build
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
```

ESP32-S3 の場合

https://github.com/micropython/micropython/blob/9b486340da22931cde82872f79e1c34db959548b/ports/esp32/boards/GENERIC_S3/sdkconfig.board#L8-L12

```
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv"
```

`CONFIG_ESPTOOLPY_FLASHSIZE_16MB`は適切なサイズの変数にyをつける。
`CONFIG_PARTITION_TABLE_CUSTOM_FILENAME`は、適切なサイズのファイル名にする。
4MBの場合は、サイズがファイル名につかず、`partitions.csv` になるので気をつける。

特定のボードでのみビルドするには以下を実行する。

```
make BOARD=GENERIC_S3
```

ここを変更する前に、`make` してしまい、変更後再ビルドしようとすると、以下のエラーが出ることがあった。

```
Partitions tables occupies 8.0MB of flash (8388608 bytes) which does not fit in configured flash size 4MB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu
```

この場合、`make clean` すれば解決するはずであるが、解決しないことが合った。ディレクトリ `build-GENERIC_S3` を直接削除して、再度 make すると大丈夫であった。
イヤホンから音が出なかった時の備忘録

# 出来事
いつも通りPCにイヤホンさしてyoutubeみようとしたら、スピーカーから音が出た。出力の設定が切り替わってないのかと思って確認したら、イヤホンになってる。。
![sound_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783848/eb5c023c-aada-570e-2e8d-504fabc32481.png)
PC再起動してみたり、違うイヤホン挿してみたりしても音が出ないので、ドライバのバージョンが古いのかと思ってwindows update確認してみても最新になってる。（ここまでで１時間経ってる）

# 結局
Realtes(R) Audioのversionを以前のversionに戻してみたら直った。
* 音が出なかったRealtek(R) Audioのversion
  * 6.0.9357.1
* 音が出たRealtek(R) Audioのversion
  * 6.0.9313.1

# 手順
1. windowsのアイコンを右クリックして、「デバイスマネージャー」を開く
2. 「サウンド、ビデオ、およびゲームコントローラー」を展開する
3. Realtek(R) Audioを右クリックしてプロパティを開く
4. 「ドライバー」タブに移動して、「ドライバーを元に戻す」を押す
![realtek_property.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783848/1aab16f0-e01a-ca77-434a-6a88fdb889f7.png)

# 環境
* HP ENVY x360 13-ay
* OS: Windows 11 Home 21H2
* CPU: AMD Ryzen 7 5800U with Radeon Graphics 1.90 GHz

# あとがき
最新Versionにした方がいい場合の方が多い気がするけど、Versionを１つ戻すことで問題が解決するという選択肢もあることを学んだ。
Amazon aws s3 動的変数を使用したアクセス制御

# Amazon aws s3アクセス制御

## やりたいこと
- 特定のバケット配下のユーザ名のフォルダのみファイルの作成や削除をさせたい。 
- ログインしたIAMユーザ名のフォルダのみ操作可能になる
- 権限がないバケット名は参照できる

## 手順
- `AdministratorAccess`権限があるIAMユーザで実施

### 1. グループ作成
`IAM`->`Group` で適当な名前のグループを作成する。
```
例) alluser
```

### 2. Policy作成
`IAM`->`Policy`でポリシーを作成する。

```
例) test-s3-alluser
```

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::bucketroot0001"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::bucketroot0001/${aws:username}/*"
        }
    ]
}
```

### 3. ポリシーのアタッチ
`IAM`->`Policy`で`作成した`test-s3-alluser`を選択しグループにアタッチする

### 4. バケットを作成する。
s３から`<BACKET-NAME>`/`IAMユーザ名`を作成する。
ソリューションアーキテクト対策_SGとNWACL篇

## はじめに
試験勉強した際のメモを自分用に記事化。
内容は公式やBlack Beltの写経ですので目新しいことはありません:pray:

## セキュリティグループとネットワークACLsの相違点
### セキュリティグループ
・サーバー単位で適用
・ステートフル(インバウンドのみ設定すればアウトバウンドも許可される)
・許可のみをIn/Outで指定
・デフォルトでは同じセキュリティグループ内通信のみ許可
・全てのルールを適用

### ネットワークACLs
・VPC/サブネット単位で適用
・ステートレス：インバウンド設定だけではアウトバウンドは許可されない
・許可と拒否をIn/Outで指定
・デフォルトでは全ての通信を許可する設定
・番号の順序通りに適用

## デフォルトのセキュリティグループの特徴
・セキュリティグループ外からのインバウンドの通信は全て拒否
・同一セキュリティグループ内からのアウトバウンドの通信は全て拒否
・同一セキュリティグループ内での双方向の通信は全て許可

## プライベートサブネットのRDSにパブリックのWebサーバーからSSHを行う場合
WebサーバーのSGのインバウンドルールに22、RDSに3306を設定する。
インバウンドの22は無意識だったのでメモ。基本は一般的な考え方でよい。


## おわりに
引き続き追記します！

簡単ですが以上です。
[Rails]  コメントの削除方法

# はじめに
この記事は、コメント機能が実装できているのが前提で進めています。それでは実装していきましょう。

実装内容の一覧
1. ルーティングの設定
2. コントローラーの設定
3. ビューの設定


# 1. ルーティングの設定
削除機能を実装するので、以下のように、routes.rb に destroy アクションを加えましょう。

```ruby:routes.rb
<!--省略-->
  resources :gurumes do
    resources :likes, only: [:create, :destroy]
#追記箇所
    resources :comments, only: [:create, :destroy]
#ここまで
  end
<!--省略-->
```

# 2. コントローラーの設定
comments_controller.rb にも、以下のように destroy アクションを加えましょう。

```ruby:comments_controller.rb
<!--省略-->
#追記箇所
  def destroy
    comment = Comment.find(params[:gurume_id])
    comment.destroy
    redirect_back(fallback_location: root_path)
  end
#ここまで
<!--省略-->
```
簡単に解説すると、該当するコメント見つけて comment に代入し、comment を削除したら元のパスに戻るということです。

# 3. ビューの設定
最後にビューの設定です。show.html.erb に以下のコードを追記して下さい。
```ruby:show.html.erb
<!--省略-->
<% @comments.each do |c| %>
    <div>
        <%= c.user.email unless c.user.blank? %>
        <br>
        <%= c.content %>
    </div>
#追記箇所
    <% if user_signed_in? && current_user.id == c.user_id %>
        <%= button_to "削除する", gurume_comment_path(c.id), method: :delete %>
    <% end %>
#ここまで
<% end %>
<!--省略-->
```

追記箇所について簡単に解説します。
```
<%= button_to "削除する", gurume_comment_path(c.id), method: :delete %>
```
については、削除ボタンを実装しています。rails routes によって遷移先のパスを確認してみて下さい。また、今回は delete メソッドであるので、link_to ではなく、button_toにしました。
```
<% if user_signed_in? && current_user.id == c.user_id %>
<!--省略-->
<% end %>
```
については、コメントした本人だけがコメントを削除できるように設定しています。自分のコメントを他人に削除されたら困りますよね。そのことを防止するためにこのコードを書いています。
以上で実装は終わりです。


# さいごに
最後まで読んでいただきありがとうございました。
コメントの削除機能を実装したい方は、是非この記事を参考にしてもらえると嬉しいです。
また、間違いやその他意見など、ありましたらコメントいただけると幸いです。
味の素のサイトの郷土料理一覧をpdf化するPGM&そのフォルダからランダムに一つファイルをオープンするPGM

<h3>味の素のサイトの郷土料理一覧をpdf化するPGM&そのフォルダからランダムに一つファイルをオープンするPGM</h3>

味の素のサイトの郷土料理一覧をpdf化するPGM&そのフォルダからランダムに一つファイルをオープンするPGMをpowershellで作りました。

2022.09.18 スペイン料理の一覧サイトのpdfファイル化のテキストファイルもgithub上に追加しました(spanishRecipe1.txt)
<hr>
スクリーンショット
![scnshot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412430/6f2cb59e-9ab7-adc5-3110-295aca7a33e6.png)

githubURL:　https://github.com/NanjoMiyako/printPDF

<hr>
pdfファイルリスト作成の使い方<br>
printPDFKoukaiyou.ps1のスクリプトのURLを修正したうえで実行し、クロームの
待ち受け画面にして待機すると自動でキーボード入力し、レシピリストのpdfファイルリスト
が作成されます。クロームのキーボードショートカットを作成するため予め「印刷」画面のセレクトボックスの内容を「PDFファイルを保存」に変更しておいてください。
URLの内容はkyodoRyoriSyu1.TXTを使用してください<br>

<br>

ランダムファイルピックアップの使い方<br>
予めpdfファイルのタイトル名リストを作成し、randomLinePickUpKoukaiyou.ps1を
実行することでランダムにファイルをオープンします。<br>

<hr>
素材サイト<br>
<a href="https://park.ajinomoto.co.jp/recipe/corner/world/kyoudoryouri/">日本全国の郷土料理・ご当地グルメ｜レシピ特集｜レシピ大百科（レシピ・料理）｜【味の素パーク】たべる楽しさを、もっと。</a><br>

<a href="https://disseny.jp/kimama/spain/recipe/">スペイン料理簡単レシピ集｜おうちで楽しくスペイン料理</a>

<hr>
参考にしたサイト
<a href="https://mitosuya.net/automation-input-keyboard">PowerShellでキーボード入力を自動化する方法 | 水戸スヤのSE備忘録</a><br>
<a href="https://sakura-editor.github.io/bbslog/sf/general/4438.html">正規表現で否定の書き方を教えて下さい。 | サクラエディタ過去ログ</a><br>
<a href="https://eps-r.hatenablog.com/entry/2019/09/08/randomplay">ファイルをランダムに開くPowerShellスクリプト - eps_r</a><br>
<a href="https://support.google.com/chrome/answer/157179?hl=ja&co=GENIE.Platform%3DDesktop">Chrome のキーボード ショートカット - パソコン - Google Chrome ヘルプ</a><br>
M1 Mac MySQL8.0をインストールしてみた

SQLの練習用にローカル環境にMySQLをインストールしたので記録です。

#### 手順🦄
1. ダウンロード
1. インストール
1. PATHを通す
1. ログイン

Step1:  MySQLをダウンロード
--

https://dev.mysql.com/downloads/mysql/

![スクリーンショット 2022-09-18 16.31.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602337/952c3bbb-04bf-e0d8-ae22-8694cab4d53b.png)
※2022年9月現在のバージョンです

**Downloadをクリック→下部にある「No thanks, just start my download.」をクリックしダウンロード開始**

Step2:　パソコンにMySQLをインストール
---
ダウンロードが完了したら、アイコンをクリックしてください。
インストール画面が表示されるので、「続ける」をクリックして行ってください。
途中でパスワードの設定を要求されるので任意のパスワードを設定してください。
![スクリーンショット 2022-09-18 16.39.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602337/eb603b37-da49-a168-8b95-3029500dfe86.png)
![スクリーンショット 2022-09-18 16.40.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602337/dde850e5-e940-c9a3-04dc-0b83cbd9d78d.png)

Install Successfulが表示されたらインストーラーは不要になりますので削除してOKです。

Step3: MySQLが正常にインストールされているかチェック
--
システム環境の一番下にMySQLが入っているか念の為確認してみます。
![スクリーンショット 2022-09-18 16.47.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602337/f40f36ee-6384-b71c-4c91-2cd8d0b3cdb5.png)

Step4: パスを通す
---
下記のコマンドを叩き、.zprofileというファイルを編集します。
```
$ ls -a
$ open -t .zprofile

#ファイルに下記を追記
export PATH=${PATH}:/usr/local/mysql-8.0.30-macos12-arm64/bin
```
**MySQLのパスの確認方法**
(1) メニューバーのFinderで**移動**をクリック
(2) 次の階層へ移動`/user/local/mysql`
(3) binの上で右クリックし、optionを押すと"binのパスをコピー"と表示されるのでコピーしてください
![スクリーンショット 2022-09-18 16.55.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602337/a5deda98-bdc4-f1b0-3adf-0133386e527c.png)

Step5: ログインする
---
```
$ mysql -u root -p 
password: 設定したパスワードを入力
```

以上の順序でインストールを行いました！
Ubuntu 22.04.1 LTSのキーボード設定をMacOS風に変更する

## はじめに
今回始めてUbuntuをインストールして、Macユーザーとして使いやすいキーボード設定ができずに詰まったので備忘録として残します。

## 対象者
- Ubuntu 22.04.1 LTSを使用
- Macユーザー
- JISキーボードユーザー
- 日本語(Mozc)を入力ソースとして使用する

## 設定内容
### CapsLockキーをControlキーに変更
CapsLockは基本使わない、その場所にはCtrlがいてほしいので変更。
自分はnanoを使うが、viでも可。
~~~:bash
sudo nano /etc/default/keyboard
~~~
XKBOPTIONSを以下の内容に編集。
~~~diff:/etc/default/keyboard
- XKBOPTIONS=""
+ XKBOPTIONS="ctrl:nocaps"
~~~
編集が終わったら下記コマンドを実行。
~~~:bash
sudo systemctl restart console-setup
~~~
---
### 変換・無変換でIMEのオンオフ
Macと同じように、かな・英数を切り替えられるように設定する。

Mozcのプロパティからキー設定を変更する。
すべてのモードで「Henkan」を「IMEを有効化」、「Muhenkan」を「IMEを無効化」にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681943/2be6c93e-6dc5-e1c8-8f4a-a81cf0d080f5.png)
![Screenshot from 2022-09-18 16-27-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681943/941970a1-6c75-37ea-20c5-bc0df9b9babb.png)

### プロパティが開けない場合
/usr/lib/mozc/mozc_tool がない場合は設定ができないようなので、以下のコマンドでインストールする。
反映されていなかった場合は再起動を行う。
~~~:bash
sudo apt install -y mozc-utils-gui
~~~
---

### mozcのキーボード配列をJISにする
この設定をしていないとUS配列のままで認識されている可能性があるため、設定を行う。
編集のために下記コマンドを実行。
~~~:bash
sudo nano ~/.config/mozc/ibus_config.textproto 
~~~
layout部分を「jp」に編集して保存。
~~~diff
- layout : "default"
+ layout : "jp" 
~~~

## おわりに
WindowsでもMac風のキーバインドにしているので、Ubuntuでもなんとか設定できてよかった！
快適な作業のためにキーボード設定はこだわりたいですね。
[Docker] build失敗時のDo you want to continue? [Y/n] Abort. への対処



```shell
#5 144.0 1 upgraded, 218 newly installed, 0 to remove and 15 not upgraded.
#5 144.0 Need to get 171 MB of archives.
#5 144.0 After this operation, 632 MB of additional disk space will be used.
#5 144.0 Do you want to continue? [Y/n] Abort.
```

docker コンテナファイルを更新して↑のようなメッセージとともに失敗した場合、
インストール時に聞かれるYes/Noに答えるオプションを設定する必要がある。

```Dockerfile
FROM openjdk:11-slim

ENV DISPLAY host.docker.internal:0.0

RUN apt-get update && \
    apt-get install -y openjfx
WORKDIR /usr/src
```

apt-get コマンドのその他オプションも必要に応じて追加する

https://linux.die.net/man/8/apt-get

https://qiita.com/karaage0703/items/f01db1cf49b151022b7c
雀魂 牌譜画面の抜きドラを見やすくする 他

:::note warn
**スクリプトの利用は、自己責任でお願いします。**
:::


# 牌譜画面の抜きドラ

牌譜のコントロールバーにカーソルを乗せていないとき、バーを半透明にして抜きドラを見やすくするスクリプトです。開発者ツールで実行できます。

```JavaScript
var replay = uiscript.UI_Replay.Inst.me.getChildByName("root");
var replayOnMouseOver = () => {
    replay.alpha = 1;
};
var replayOnMouseOut = () => {
    replay.alpha = 0.3;
};
replayOnMouseOut();
replay.on("mouseover", null, () => replayOnMouseOver());
replay.on("mouseout", null, () => replayOnMouseOut());
```



# スタイル

雀魂のプロフィールに載っているスタイルの計算式です。

* **<font color="#FC627C">攻</font>** = 平均打点 ÷ 50 - 60
（3000 ～ 8000）

* **<font color="#FC627C">攻</font>** (三麻) = 平均打点 ÷ 80 - 50
（4000 ～ 12000）

* **<font color="#46D277">防</font>** = 112 - 340 × 放銃率
（33% ～ 3.5%）

* **<font color="#39B9BE">速</font>** = (和了率 - 0.1) × 1000 ÷ 3
（10% ～ 40%）

* **<font color="#BE7B39">運</font>** = 懸賞役数 ÷ 合計飜数 × 150
（0% ～ 67%）

**<font color="#FC627C">攻</font>** / **<font color="#46D277">防</font>** / **<font color="#39B9BE">速</font>** は、直近100局のデータ（**100戦ではありません**）、**<font color="#BE7B39">運</font>** は直近20回の和了から計算された数値です。懸賞役は、ドラ（表 / 裏 / 赤 / 北）と一発です。
整列アルゴリズム

# 問題２の気づき
問題文を読んでいなかった。
```この操作をデータ列の左端から右端まで繰り返す処理を一回のパスとする。```
ここで間違えた。

# 問題3の気づき
## 分割統治とは?
ある者が統治を行うにあたり、被支配者を分割することで統治を容易にする手法。 
出典 https://artsandculture.google.com/entity/m01ckt5?hl=ja
### 気づき
分割しているものを選べばいいのかな。

## 基数ソートとは？
* 1の位のみのソートを行う。
* 1の位のソートが済んだら次は1つ上の10の位のソートを行います。
* これと同じ作業を上の桁がある限り続けていきます。
出典 https://it.sumahotektek.com/it-radix-sort/
### 気づき
位ごとに比較していき整列させるのか。

## クイックソート
中間的な基準値を決める。
それより小さな値のグループと値の大きなグループに振り分ける。
これを繰り返す。

https://qiita.com/masatom86650860/items/b57c7ed522c17539e3a0#%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%BD%E3%83%BC%E3%83%88 

# 問題４の気づき
手順１〜３までの回数を求める問題だった。
全体の配列を３で割って、割られた配列をまた３で割る。
それが割り切れる回数を求められていた。

問題に慣れるしかないのか。

# 問題5の気づき
問題文をよく読む。
```親の節の値が子の節の値より小さいヒープがある。```
ここで親よりもこの方が小さい関係があることに気づく。
```その要素が親よりも小さい間、親と子を交換することを繰り返す。```
親よりも子の方が小さい場合、交換できる。

これにより７を追加した場合、２５と交換でき、また親の１１と交換することができるので
答えは１１
DockerでBungeeCordとMinecraft鯖を同時に構築する


こんにちは。

先日Docker Compose を使ってBungeeCordとMinecraftサーバー(Paper)を構築することがあったのでその手順を書きました。

この記事を見ている人はBungeeCord, Paper, Docker については知っていると思うので説明は割愛します。

## ディレクトリ構成

|パス|内容|
|:-| :-|
| ./data | Minecraftサーバーのデータをバインド |
| ./backups | サーバーデータのバックアップを格納 |
| ./proxy | BungeeCord のデータをバインド |

## docker-compose.yml を書く

早速docker-compose.ymlを書きます。

各種サーバーの細かい設定は省きました。

```YAML:docker-compose.yml
version: '3'

services:
  # BungeeCord
  proxy:
    image: itzg/bungeecord
    ports:
      - 54621:25577/tcp
    tty: true
    stdin_open: true
    restart: always
    # データ永続化
    volumes:
      - ./proxy:/server
    environment:
      TYPE: "BUNGEECORD"
      MEMORY: "512M"

  # Paper
  server:
    image: itzg/minecraft-server
    ports:
      - 22233:25565/tcp
    environment:
      EULA: "TRUE"
      TYPE: "PAPER"
      VERSION: 1.19.2
      TZ: Asia/Tokyo
      MEMORY: 6G # メモリ設定は各自変更
      ONLINE_MODE: "false" # BungeeCordを使うのでfalseにしています
      MAX_TICK_TIME: -1
    tty: true
    stdin_open: true
    # データの永続化
    volumes:
      - type: bind
        source: ./data
        target: /data
    restart: always

  # バックアップ
  backup:
    image: itzg/mc-backup
    environment:
      - TZ=Asia/Tokyo
      - INITIAL_DELAY=2m
      - BACKUP_INTERVAL=4h
      - PRUNE_BACKUPS_DAYS=3
    volumes:
      - type: bind
        source: ./backups/
        target: /backups
      - type: bind
        source: ./data
        target: /data
        read_only: true
    network_mode: "service:server"
```

## Paper の設定をする

BungeeCordの管理下におくサーバーは、特別な設定が必要です。

今回はMinecraftサーバーのデータは./dataに格納しているため、そこにあるspigot.ymlを編集します。

spigot.ymlにあるbungeecordという項目をfalseからtrueに変更してください。

```YAML:spigot.yml
settings:
  # 途中省略
  bungeecord: true # falseからtrueへ
```

## BungeeCord の設定をする

Minecraftサーバーを適切に動作させるためにはBungeeCord側も設定が必要です。

今回はBungeeCordデータを./proxyにバインドしているため、./proxy/config.ymlを編集します。

**この二か所の変更は絶対に行ってください**。

```YAML:config.yml
# 途中省略
ip_forward: true
online_mode: true
```

## BungeeCord にサーバーを登録する

MinecraftサーバーをBungeeCordの管理下に置くためにはBungeeCordのconfig.ymlにサーバーを登録する必要があります。

同一のdocker-compose.ymlから起動したサーバーを登録する場合は、すこしだけ工夫が必要になります。

通常のようにIPアドレスとポートを指定せず、docker-compose.ymlで登録したサービス名とそのコンテナの内部ポートをそのまま指定します。

今回使用したdocker-compose.ymlではMinecraftサーバーをserverというサービス名で登録しており、コンテナ内部ポートは25565です。

このサーバーを登録する場合は以下のように記述します。

```YAML:config.yml
# 途中省略
servers:
  main:
    address: server:25565 # サービス名:内部ポート
    restricted: false
```

## 実際に検証してみる

サーバーに接続するときは通常と同じようにマシンのIPアドレスとポートを指定して接続します。


## おわりに

最初は順調に起動できたのですが、サーバーの登録に少し手間がかかったので同じように困っている人の参考になれば幸いです。

## 参考文献

今回の環境構築においてとても参考になりました。

ありがとうございました。

https://github.com/itzg/docker-bungeecord

https://qiita.com/Gorayan/items/365ba57364a2825f484f
OSSへのパッチの送り方

こんにちは．[だいみょーじん](https://twitter.com/Egh2Deywos)です．
最近[QEMU](https://www.qemu.org/)にパッチを送ったので，OSSへのパッチの送り方をまとめておきます．

OSSへのパッチの送り方といっても，OSSごとに方法やルールが異なることがあります．
例えばQEMUの場合[ここ](https://www.qemu.org/docs/master/devel/submitting-a-patch.html)に詳細が書いてあります．
ただし，gitでバージョン管理されているOSSであれば，大体の流れは同じでしょう．
ここでは私がQEMUにパッチを送った際の手順を説明します．

# リグレッションテスト

まずは，自分が加えた変更が，他の機能などに影響を及ぼさないかどうか確認しておきましょう．
QEMUの場合，リポジトリのトップのディレクトリにおいて，

```
$ make check
```

でテストを実行します．自分が加えた変更の前後におけるテスト結果のdiffを取り，退行がないことを確認しましょう．

# コミット

QEMUでは`--signoff`オプションを付けてコミットするというルールがあります．
こうすることでコミットメッセージの末尾に`Signed-off-by:<アカウント情報>`という行が追加され，このパッチを取り込んでもいいですよという宣言になります．
`--signoff`オプションが不要なOSSもあるので，調べておきましょう．

```
$ git commit --signoff
```

上のコマンドを叩くと，コミットメッセージの編集画面になります．
レビュアーなど多くの人に読んでもらうものなので，なぜこのような変更を行ったのか分かるように丁寧に書きましょう．
また，コミットメッセージの行の長さに制限が設けられていることがあるので，いい感じに改行を入れて調整しましょう．
QEMUの場合76文字を超える行は禁止されています．
事前にコミットメッセージに関するルールを確認したり，`git log`で過去のコミットメッセージを読んで参考にするとよいでしょう．

# パッチ生成

コミットできたら，次はそのコミットからパッチを生成します．

```
$ git format-patch -1
```

上のコマンドでは，最新のコミットのパッチをひとつ生成します．
オプション`-1`はパッチを生成するコミット数を意味し，`-N`で直近のN個のコミットのパッチを一気に生成します．
拡張子`.patch`のパッチファイルが作成されます．
中身はただのテキストファイルで，コミットメッセージや変更内容が書かれています．

# パッチ送信

いよいよパッチを送信しますが，gitのメール送信機能を追加でインストールする必要があります．
Ubuntuの場合以下のコマンドでインストールできます．

```
$ sudo apt-get install git-email
```

さらに，メールを送信できるように設定をいじります．
私の場合Office365のメールアドレスを使用しているので，こんな感じで設定します．

```
$ git config --global sendemail.confirm auto
$ git config --global sendemail.smtpserver smtp.office365.com
$ git config --global sendemail.smtpencryption tls
$ git config --global sendemail.smtpuser <Office365のメールアドレス>
$ git config --global sendemail.smtpserverport 587
$ git config --global sendemail.smtppass <Office365のパスワード>
```

`.gitconfig`に直接書き込んでしまってもよいでしょう．

```
[sendemail]
        confirm = auto
        smtpserver = smtp.office365.com
        smtpencryption = tls
        smtpuser = <Office365のメールアドレス>
        smtpserverport = 587
        smtppass = <Office365のパスワード>
```

パスワードを書きっぱなしにするのは危ないので，パッチの送信が終わったら消しておきましょう．

次に宛先を調べておきましょう．
QEMUの場合`qemu-devel@nongnu.org`を宛先とし，自分が変更を加えた個所の担当者をCCに追加するとよいそうです．
QEMUのリポジトリのトップのディレクトリにおいて，以下のコマンドで担当者のメールアドレスが出力されます．

```
$ ./scripts/get_maintainer.pl -f <自分が変更を加えたファイル>
```

これでパッチを送信する準備が整いました．
あとはパッチを送信するコマンドを叩くだけです．

```
$ git send-email <パッチファイル> --to=<宛先> -cc=<CCひとつめ> --cc=<CCふたつめ>
```

CCは指定しなくてもいいし，複数指定することもできます．
あとはレビューを待ちましょう．
レビュアーも人間ですし，QEMUのような大規模なOSSであれば大量のメールを受け取っているはずなので，気長に待ちましょう．
1週間から2週間待っても返信が来ない場合，確認を促すpingメールを送りましょう．
pingを送るタイミングについてもOSSごとに明記されていたりするので，調べておきましょう．
エンジニア騎士とクエリの魔女 精霊の村 （paizaランク：B相当）SQL で解いてみた

精霊の村 （paizaランク：B相当）

https://paiza.jp/code_and_sql/challenges/cas_s_b_3001

>Hellテーブルから、属性名が「Air」、階級が「Boss」のレコードをすべて出力してください。
なお、属性名はHellテーブルのelement_idを外部キーとしてElementテーブルを、階級はHellテーブルのgrade_idを外部キーとしてGradeテーブルをそれぞれ外部参照してください。
レコードを出力する際に表示するカラムはHellテーブルのid, Hellテーブルのname, Elementテーブルのname, Gradeテーブルのnameとし、Elementテーブルのnameには「element」を、Gradeテーブルのnameには「grade」と名付けてください。

# 解答例(SQL)
問題文に沿って解いてみました。２つのテーブルをJOINして、WHEREの条件をANDするのがポイントです。
```sql
-- Let's チャレンジ！！
SELECT Hell.id, Hell.name, Element.name AS "element", Grade.name AS "grade"
FROM Hell
JOIN Element
ON Hell.element_id = Element.id
JOIN Grade
ON Hell.grade_id = Grade.id
WHERE Element.name = "Air" AND Grade.name = "Boss";
```
Ubuntuで外付けUSBメモリの取り出しをシェルスクリプト（端末）で実行するには？（ejectとumountの挙動の違いについても）

# 調べた背景

充電と入れる曲の更新を兼ねて、家に帰ると携帯音楽プレイヤーをUSBでUbuntuに繋いでます。
（携帯音楽プレイヤー ≒ USBメモリ）

でもお出かけの前に下記のように、いちいちUbuntuの画面上で『ディスクの取り出し』をするのが面倒…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/bc4f32d9-ee14-02ed-f176-9be14a849d65.png)

そこで…

1. 『ディスクの取り出し』のシェルスクリプトを作成。
1. 上記をCronとかで毎日早朝（5時とか）に定期実行。

の環境を作れば…

1. お出かけから **帰ってきたら** 携帯音楽プレイヤーをUbuntuに **物理的に繋ぐだけ** 。
1. お出かけに **行く時は** Ubuntuから携帯音楽プレイヤーを **物理的に外すだけ** 。

となって、お出かけ準備が楽になるのでは？と考えました。

それに向けて、まずはUSBメモリの取り外し周りのコマンドはどれがいいかを調べました。

# ejectコマンド

```eject``` コマンドを使う時は…

```shell
eject デバイスのパス
```

もしくは下記でもいい。

```shell
eject マウントポイントのパス
```


例えば下記のようなディスク状態の場合…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/af88439a-eb6e-61c3-f8bb-56ffc15b0b5f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9ef0565f-02e6-9ffa-a1d7-13e6430e5a83.png)

```shell:空き領域 で指定
eject /dev/sdd
```

でもいいし

```shell:パーティション1 で指定
eject /dev/sdd1
```

でもいいし

```shell:マウントポイント で指定
eject /mnt/vico
```

でもいい。

ejectを実行すると下記のように、GUIで『ディスクの取り出し』をやったのと同じ状態になりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b57b2204-fb2d-7e2c-1b10-f15f62aaceac.png)

# umountコマンド

下記を実行すると…

```shell:空き領域 で指定
umount /dev/sdd
```

下記文言でエラー。
（マウントしてないから当たり前といったら当たり前…）

>umount: /dev/sdd: not mounted.

じゃあ別の方法を試そう。

下記を実行すると…

```shell:パーティション1 で指定
umount /dev/sdd1
```

下記のようにマウントが外れただけの状態になる。
『ディスクの取り出し』をした時は何か違う…。
あくまで **アンマウントしてるだけ** 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ac7c311f-21b4-5098-560d-651e408026da.png)

ちなみに、下記のようにマウントポイントで指定した場合も、同じように『アンマウントしてるだけ』の状態でした。

```shell:マウントポイント で指定
umount /mnt/vico
```

# まとめ

```eject``` と ```umount``` では挙動（結果）が若干違う。
GUIで『ディスクの取り出し』した時と同じ結果になったのは ```eject``` 。
なので、 ```eject``` を採用。

# 注意点（権限）

```eject``` について、root以外のユーザーでログインした状態で、端末から実行する場合は注意。
下記のように先頭にsudoが必要。

```shell
sudo eject /mnt/vico
```

これは ```umount``` においても同様。

# 注意点（取り出し済なのにeject実行時）

取り出し済なのに ```eject``` すると下記エラーになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/42c9627b-47ff-cf96-8397-6c0eb2c6e479.png)

```eject``` を使うシェルスクリプト作る時は『マウントされている場合のみejectを実行する』というロジックにしておいた方がいい。


# 参考サイトさん

https://www.youtube.com/watch?v=c8YWhRNza5Y

# バージョン

Ubuntu 20.04.5 LTS
keystone.jsをお試したい

# はじめに
　Keystone.jsをお試したい！
　でもMongodbって初期設定がめんどう
　なのでdocker-composeでお試したい！
　だからといってKeystone.jsのdocker-composeで組まれたのを探してみても、なかなか見つからない。そこで一つ、簡単に組んでて理解がしやすそうなGitリポジトリを発見したので、お試してみたというお話です。
　発見したGitリポジトリは次のやつ。

https://github.com/hugominas/recipe-docker-keystonejs-nginx

# エラー

　バージョンの違いなのか何なのか、Gitクローンからdocker-composeでアップしてみても、このkeystoneは立ち上がってもエラーを吐きます。
　内容としてはmonogdbにアクセス出来ていないというもののようで、これを改善すればなんとかなるかなと、デバッグ…と呼んでいいんですね？開始しました。

```
keystone_1  | ------------------------------------------------
keystone_1  | Mongoose connection "error" event fired with:
keystone_1  | Error [MongoError]: failed to connect to server [mongodb:27017] on first connect [Error: connect ECONNREFUSED 172.29.0.2:27017
keystone_1  |     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1247:16) {
keystone_1  |   name: 'MongoError'
keystone_1  | }]
keystone_1  |     at Pool.<anonymous> (/usr/src/app/node_modules/mongodb-core/lib/topologies/server.js:336:35)
keystone_1  |     at Pool.emit (node:events:513:28)
keystone_1  |     at Connection.<anonymous> (/usr/src/app/node_modules/mongodb-core/lib/connection/pool.js:280:12)
keystone_1  |     at Object.onceWrapper (node:events:628:26)
keystone_1  |     at Connection.emit (node:events:513:28)
keystone_1  |     at Socket.<anonymous> (/usr/src/app/node_modules/mongodb-core/lib/connection/connection.js:189:49)
keystone_1  |     at Object.onceWrapper (node:events:628:26)
keystone_1  |     at Socket.emit (node:events:513:28)
keystone_1  |     at emitErrorNT (node:internal/streams/destroy:151:8)
keystone_1  |     at emitErrorCloseNT (node:internal/streams/destroy:116:3)
keystone_1  |     at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
keystone_1  | Error: KeystoneJS (Website Template) failed to start - Check that you are running `mongod` in a separate process.
keystone_1  |     at NativeConnection.<anonymous> (/usr/src/app/node_modules/keystone/lib/core/openDatabaseConnection.js:62:10)
keystone_1  |     at NativeConnection.emit (node:events:513:28)
keystone_1  |     at /usr/src/app/node_modules/mongoose/lib/connection.js:824:17
keystone_1  |     at connectCallback (/usr/src/app/node_modules/mongodb/lib/mongo_client.js:527:5)
keystone_1  |     at /usr/src/app/node_modules/mongodb/lib/mongo_client.js:418:11
keystone_1  |     at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
```

　思ったよりもdocker-composeのバージョン2と3との違いを知らないため悪戦苦闘(1時間)しながら、何とかアクセスできるkeystoneのリポジトリを作成しました。

# お試す

　リポジトリに上げておいたので、それをクローンしてからdocker-composeで立ち上げましょう。dockerだとかdocker-composeのインストールをしていない人は、ぱぱっとしてきちゃってください。

```
git clone https://github.com/DogKingFun/recipe-docker-keystonejs-nginx.git
cd recipe-docker-keystonejs-nginx
docker-compose up -d
```

　立ち上がれば

IPを適当に変更して　http://ip:8080/keystone

でアクセスすることが出来ると思います。

https://github.com/DogKingFun/recipe-docker-keystonejs-nginx

# 終わりに
　でもkeystoneで使いたかったblogの機能は搭載されていないタイプのやつでしたので、たぶんまた今度、blog機能も搭載されたやつを作り直すと思います。
エンジニア騎士とクエリの魔女　大海の渦 （paizaランク：B相当）JavaScript で解いてみた

大海の渦 （paizaランク：B相当）

https://paiza.jp/code_and_sql/challenges/cas_c_b_3001

をJavaScriptで解いてみました。

>あなたは参加したパーティで見た、飴を使った手品が印象に残っていました。 その手品は子供達に好きな分だけ飴を取ってもらい、それぞれの取った飴の数を当てるというものです。
この手品の手順を詳しく述べると以下になります。

>1. 子供たちに好きな数だけ飴を取ってもらう。 
>2. 子供たちに横一列に並んでもらう。 
>3. それぞれの子供に、自分自身と両隣の子供の持っている飴の個数の和を言ってもらう。 　・両端の子供には、自分自身と隣の子供の持っている飴の個数の和を言ってもらう。 
>4. 左端の子供の持っている飴の個数だけから、それぞれの子供の持っている飴の個数を当てる。

>あなたはこの手品をプログラムで再現しようと思いました。 各子供たちの宣言した飴の数と左端の子供の飴の数を与えられたときに、 子供たちの持っている飴の個数を特定するプログラムを作成してください。

解答例1(JavaScript)
それぞれの子供の発言dと最初の子供の飴の個数x_1から、それぞれの子供の持っている飴の個数を求めていきます。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N, x_1] = lines[0].split(" ").map(Number);
const d = lines[1].split(" ").map(Number);

let x = [x_1];//それぞれの子供たちが持っている飴の個数の配列
for (let i = 0; i < N - 1; i++) {
    if (i === 0) { //最初の子から次の子を求める
        x[i + 1] = d[i] - x[i];
    } else { //次の子以降
        x[i + 1] = d[i] - x[i] - x[i - 1];
    }    
}
//それぞれの子供が持っている飴の数を半角スペース区切りで出力
console.log(x.join(" "));
```
解答例2(JavaScript)
reduceを使いました。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N, x_1] = lines[0].split(" ").map(Number);
const d = lines[1].split(" ").map(Number);

console.log(
    d.reduce((acc, cur, i) => {
        if (i === 0) {　
            //次の子を最初の子から求める
            acc[i + 1] = cur - acc[i];
            return acc;
        } else if (i === d.length - 1) {
            return acc;//最後の子はそのまま返す
        } else {
            //それ以外
            acc[i + 1] = cur - acc[i] - acc[i - 1];
            return acc;
        }
        
    },[x_1]).join(" ")    
);
```
【PowerAppsデメリット集(その2）】データベースやコレクションの更新処理を関数化できないので同じ処理を何回もコーディングすることになる

データベースやコレクションに対して更新を行う処理は、アプリ内でデータの追加や更新、削除を行うたびに、同じ更新処理を行うことが多い

同じ処理を何度もコーディングするのを避けたい

そのためコンポーネントでコレクションのカスタムプロパティで共通利用させたいが、
カスタムプロパティで対象のDBを追加しているにもかかわらず、DBを認識しない
（翻訳：DBやコレクションを扱う処理を関数化しようとしたが、DBを参照できるようにしているのにも関わらず、関数内においてはDBやコレクションを扱えない
（2022/09/18時点）

コンポーネントでコレクションのカスタムプロパティの作り方はこちら
https://qiita.com/tanakaminoru55555/items/ed9513d50ffd7bf793cf


上記のリンクの通り、カスタムプロパティでClearCollectしようとしたが、コレクションが扱えない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2783140/cff11cab-f093-7b50-99fe-49565aeed6f6.png)
Salesforce認定SalesCloudコンサルタント　合格体験記

# 始めに
2022年7月、Salesforce認定SalesCloudコンサルタント試験（spring'22）を受験し、なんとか合格できました。これから受験される方へ少しでもお役に立てればと思い体験記を投稿します。

本試験のためにかけた勉強時間は約50時間です。1ヶ月半ほど、普段の仕事終わりに1,2時間勉強していました。

# やったこと
### 試験範囲と体験談読む（約1時間）
まずは公式が出している試験要項を確認しました。そして先人たちの受験体験記をたくさん読みました。皆さんたいてい同じような勉強法で、試験範囲確認・対象のTrailheadやハンズオン環境で手を動かして習得・過去問演習（・ポイントスタディ受講）といった感じでした。

https://quip.com/vCvRAKtDaNn1

### 公式のTrailmix・関連のTrailheadの演習（約20時間）
素直に公式のTrailmixに取り組みました。試験要項や過去問をちらっと見て全く知らない用語がたくさんあって絶望したのと、せっかく受けるならちゃんと知識を定着させたかったので、地道に取り組みました。（アドミン試験ではほぼ過去問演習だけで臨み、合格はできたものの知識が全然定着しておらずむなしくなったという反省もあり、今回ちゃんと手を動かして習得しようと考えました。）

また、学習の際はメモをとるようにし、単元毎に2,3行程度に内容・ポイント・キーワードをまとめていました。試験範囲が広く普段の業務で利用しない機能も多くあり学習してもすぐ忘れがちでしたが、メモを後から振り返ることができ知識を定着させることができたと思います。

https://trailhead.salesforce.com/ja/users/welcome4/trailmixes/certified-sales-cloud-consultant-ja


### 過去問演習（約30時間）
Trailmixを1周した後、ひたすら過去問演習をしていました。間違えた問題はその対象分野に関してググり、仕様を確認しました。仕様のイメージがあまりわかない場合はハンズオン環境で実際に手を動かして確認していました。シンプルに、過去問解く⇔間違えた問題を理解する を地道に繰り返していました。

# 参考にしたサイト
いろんなサイトを閲覧しましたが、特に参考になったサイトをいくつかピックアップします。
### 合格体験談・学習の進め方

https://blog.logical.co.jp/entry/2020/11/25/165841

### 試験範囲のTrailheadまとめ

https://savepo.com/trailheadlist_for_sales_cloud_consultant

### 過去問系

https://keneloper.com/salescloud-consultant-exam-prep/

https://quizlet.com/jp/407709074/sales-cloud-%E3%82%B3%E3%83%B3%E3%82%B5%E3%83%AB%E8%A9%A6%E9%A8%93-flash-cards/


# 結果
合格することができました！
↓認定証（黒色部分はマスキング箇所です。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735298/3a10e4e7-5a15-392a-10c5-3e77ce37471a.png)



各分野の得点率は以下の通りでした。

| 分野 |出題比率 |得点率 |
|:-:|:-:|:-:|
|Industry Knowledge（業界の知識） |7%|75%|
|Implementation Strategies（実装戦略）|12%| 85%|
|Sales Cloud Solution Design（Sales Cloud ソリューションの設計）|21%| 38%|
|Marketing and Leads（マーケティングとリード）|8%| 60%|
|Account and Contact Management（取引先と取引先責任者の管理）|13%| 87%|
|Opportunity Management（商談の管理）|13%| 75%|
|Sales Productivity（営業の生産性）|9%| 80%|
|Sales Cloud Analytics（Sales Cloud 分析）|9%| 100%|
|Integration and Data Management（連携とデータ管理）|8%| 40%|


各分野の出題比率と得点率から全体の得点率を計算したところ68.7%でした。合格ライン62%に結構ぎりぎりでした笑
出題比率が一番高いSales Cloud Solution Design（Sales Cloud ソリューションの設計）で全然正答できていないのが恥ずかしいです、、、

あくまで私の体感ですが、問題文が過去問とほぼそのままの問題が1,2割、過去問では見たことない問題が7,8割、そもそもこんなの試験範囲にあったかな？（笑）てなった問題が1割出題されました。またアドミン試験と同様に、英語から日本語への翻訳が上手くいってないためか問題文の意味がわからない設問や、全く同じ選択肢が2つある設問もいくつかありました。

また、以下の分野の問題がよく出題されたと記憶してます。これから受験される方はこのあたりは確実に解けるようしっかり勉強しておくと良いと思います。
・承認プロセス
・マルチ通貨
・売上予測
・テリトリー管理

# まとめ
今回の試験受験に当たっては、「急がば回れ」の精神で十分な準備時間を設けて臨みました。
その結果、なんとか合格することができました。

いろんな方がおっしゃっていますが、過去問とは設問のシチュエーションや問われ方が全然違う問題が本番では多く出題されます（現に私も、過去問では見たことない問題ばかりで試験中に面食らってました笑）
なので、過去問演習だけの付け焼き刃で臨むのではなく、事前にtrailhead等でしっかり学習しておくことをおすすめします。

試験範囲が広く、日常業務と試験勉強の両立が結構大変になると思いますが、地道に頑張ってください！
この体験記が少しでも参考になりましたら幸いです。
【Laravel】artisanコマンドでエラーになった時の対処法

## はじめに
- Laravel9でアプリ作成中に、artisanコマンド実行後にエラーになって、色々試したので残しておきます。

## 状況

- Laravel9で、ルート確認するコマンド実行後に、下記エラーあり。

```
$ php artisan route:list 

# エラー内容                        
PHP Fatal error:  Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.0.2". You are running 7.4.27. in /Users/xxxxxx/Desktop/project/laravel-study/vendor/composer/platform_check.php on line 24

Fatal error: Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.0.2". You are running 7.4.27. in /Users/xxxxxx/Desktop/project/laravel-study/vendor/composer/platform_check.php on line 24
```

- エラー文みると「Composerの依存関係にはPHPバージョン8.0.2が必要だけど、7.4.27になってるよ」と怒られています。


## 原因
- パスの設定ができていなかったため、エラーになっていた様子。


## 実際に行った事
- ①PHPが7.4か確認。

```
$ php -v

#出力結果
PHP 7.4.27
```

- ②composer updateする前に、PHPのバージョンを指定してから実行。

```
$ composer config platform.php 8.0.2
$ composer update
```

- ③PHPのバージョンを指定したけど、下記エラーあり。
```
[ErrorException]                                                                                                                 
  Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.0.2". You are running 7.4.27.                                               
```
- ④PHPのバージョン指定してupdateしたのに、反映されていない？！ので、変更が反映されていない又はキャッシュの影響？（Laravelはキャッシュが溜まりやすいと先輩からアドバイス頂いたことを思い出しました。）と思い、まずはキャッシュクリアを実行

```
$ php artisan cache:clear
```

- ⑤再度updateを実行するも、変わらず。composerをインストールし直す。

```
$ rm composer.lock
$ composer clear-cache
$ composer install
```

- ⑥インストール中に、再度下記のエラーあり。
```
[ErrorException]                                                                                                                
  Composer detected issues in your platform: Your Composer dependencies require a PHP version ">= 8.0.2". You are running 7.4.27. 
```

- ⑦その他の設定が必要そうなものを考えると、パス？？かなっと思ったので、パスを確認する。

```
$  which php         

# 出力結果
/usr/local/opt/php@7.4/bin/php
```

- ⑧パスは、PHP7.4をみる設定をしているので、PHP8.0には繋がらないよねーと原因判明！パスを変更する。

```
$ export PATH=/Applications/MAMP/bin/php/php8.0.8/bin:$PATH
```

- ⑨パスが記述されていることを確認
```
$ vi ~/.zshrc
```

- ⑩反映させる

```
$ source ~/.zshrc 
```


- 11.パスもしっかり設定できたので、PHPのバージョン確認とartisanコマンドを実行する。artisanコマンドの実行ができました！

```
$ php -v  

# 出力結果                                                   
PHP 8.0.8 
```

```
$ php artisan list       

# 出力結果                                          
Laravel Framework 9.30.1
Usage:
  command [options] [arguments]
(略)
```


## まとめ
- 「composer」や「artisan」で色々ググってましたが、パスが原因だとは・・・。時間はかかりましたが、解決できたのでヨシっとしよう。実際の業務では、気軽に削除とか全部をupdateしたら大変なことになるので注意しなくちゃ・・・。


## 参考記事
- [【PHP】composer updateをしても変更が反映されていない場合の対処方法](https://engineer-ninaritai.com/composer-update-cache/)
- [Laravel キャッシュクリア系コマンドなど](https://qiita.com/Ping/items/10ada8d069e13d729701)
- [PHPの環境構築（パスを通すとは）](https://qiita.com/te-k/items/7fa800488dc29228d7fd)
【TypeScript】new Date()で取得した時刻と現在時刻を単純比較する時は注意が必要

# 注意点
下記でサブスク型サービスを一例にあげておりますが、基本的にJavaScriptは改ざん可能です。
本来であれば契約期間等の厳密な時間を比較する場合は、サーバーサイドで時間比較を行わなければいけません。
そのため、下記方法で解決で完全解決はできないです…
ご注意ください。

# はじめに
new Date()で取得した時刻と現在時刻を単純比較する時は注意が必要です。
例えば下記のようなソースコードです。
※固定時刻を生成するために`new Date(2022, 0, 1, 0, 0, 0)`を使用していますが、ここはDBから取得した時刻でもなんでもよいです。

```tsx
const date1 = new Date(); // 現在時刻
const date2 = new Date(2022, 0, 1, 0, 0, 0); // 2022/1/1 00:00:00
console.log(date1 > date2? true : false);
```

このソースコード間違いではないんです。
ただサブスク型サービス等で単純比較すると痛い目に合います。
※私が痛い目に合いました（笑）

理由はnew Date()はクライアントの時刻を取得しているからです。
例えば、サブスク型サービスで契約期間があったとします。
その契約期間とnew Date()で取得した時刻を比較します。
通常であれば問題はありません。※PCは自動で現在時刻を補正しているためです。
ただし、PCの時刻を強制的に変更して期間終了日前の時刻に設定することで永久にサービスを使用することができます。

じゃあどうしたらよいか🤔

# 結論
サーバー時刻を取得することで一部解決することができます。
ajaxでサーバー側と通信を行い、レスポンスヘッダに含まれる時刻を取得します。
※完全解決するためにはサーバーサイドで時間比較を行う必要があります。
```tsx
try {
  let serverTime: Date = null;
  const request: XMLHttpRequest = new XMLHttpRequest;

  const date = await new Promise((resolve, reject) => {
    request.open('HEAD', window.location.href, true); // ヘッダ情報だけ取得するのでHEAD指定。
    request.send(null); // 送信データないためnull指定。
    request.onreadystatechange = () => {
      if(request.readyState === 4 && request.status !== 0) {
        serverTime = new Date(request.getResponseHeader('Date'));
        return resolve(serverTime);
      } else if(request.readyState === 4 && request.status === 0) {
        return reject("通信に失敗しました");
      }
    }
  });
  console.log(date);
} catch(error) {
  console.log(error); // 通信に失敗しました
}
```

# 参考文献
[mdn web docs:Date() コンストラクター](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/Date)
[mdn web docs:XMLHttpRequest](https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest)
【便利】phpでpdoするときにSQLクエリエラーを表示したいなぁ

## 初めに
僕・phpで無限ループを使って、MySQLサーバーをいじめるプログラムを作ったよ！でも、なんか動かないみたい。サーバーくん、どうして?

サーバー・無限ループを仕掛けて俺をこき使うような奴には教えねーよ

俺・しょぼん


俺・あ、そうだ、MySQLサーバーくんに聞いてみたらいいかもw

俺・MySQLサーバーくーん、教えて〜

## エラー表示の魔法のコード
```php
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
```
pdoの途中に、このコードを挟み込みましょう。
例えば、
```php
try {
    // DB接続
    $pdo = new PDO(
        'mysql:host=ホスト名;dbname=データベース名;',
        '',
        '',
        [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
    );

    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);//⇦ココ
    $stmt = $pdo->prepare('SELECT * FROM tablename');

    $stmt->execute();
 
    foreach ($stmt as $row) {

    }
} catch (PDOException $e) {
    // エラー処理
    echo $e->getMessage();
   } finally {
    // DBを閉じる
       $pdo = null;
   }
```

MySQLサーバー・あいよ
　　　　　　　　「Error Code 1046 No database selected.」

俺・「あ、データベース作り忘れてたw」

サーバー「ドアホがw」


めでたしめでたし
探索アルゴリズム

# 番兵法
```先頭データから順に探索キーを検索していく線形探索```で用いる手法。
探索するキー値をあらかじめ```データの最後に追加(これを番兵という）```しておき、```必ず探索キーが見つかる```ようにする。
```必ず探索キーが見つかる```ようにする。
探索対象範囲の```終了判定が不要```になるため効率が良い。

# ２分探索法
２分配列は```配列要素が昇順（降順）に整列```されていることが前提になる。

* 配列の中央値の要素を基準とする。
* 中央値と探したい値を比べて大きいか小さいかで２つに分割した配列のどちらかを探索する。
* 中央値から-１すると最大値
* 中央値から+1すると最小値
* 探索する配列の中央値の要素を基準と決める
* ２番目以降を繰り返す

# 線形探索法
先頭から順に探索したいデータを探索する
N個の配列の場合は、最大でN回、最小で一回

# ハッシュ法
ハッシュ関数を使って、探索するので一回
最大、最低でも一回

# 問題3の気づき
大きさ10のハッシュ値は０〜９である。（これは関係ない）
５つのデータが衝突しない確率を求め、この確率を全体から引くことができれば５つのデータのいくつかが衝突する確率を求めることができる。
1*9/10*8/10*7/10*6/10でも止めることができる。
こう考えてみるとただの確率を求めているだけだった。
専門用語が出てくるが専門性がいらない問題だった。

# 出典 
https://gihyo.jp/book/2022/978-4-297-12375-8
Windows7のインターネット共有でFreeBSDからインターネットアクセス

インターネット共有はいろいろなページにあるので省略

![winfreebsd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/e10e02fd-8afa-3550-c8dd-64612e683106.png)

FreeBSDの設定は以下になります。

```
# ifconfig arge0 inet 192.168.137.100/24
# route add default 192.168.137.1
add net default: gateway 192.168.137.1
# cat > /etc/resolv.conf 
nameserver 192.168.137.1
# ping -c 1 www.yahoo.co.jp
PING edge12.g.yimg.jp (182.22.25.252): 56 data bytes
64 bytes from 182.22.25.252: icmp_seq=0 ttl=53 time=31.116 ms

--- edge12.g.yimg.jp ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 31.116/31.116/31.116/0.000 ms
```

192.168.137.1はpingに返答しないようです。

Onion OmegaでEthernetケーブルはストレートで試しました。
ログを見るときは`tail -f`よりも`less +F`を使おう

# 概要

開発時や障害発生時等にログファイルを見るとき等に`tail -f`コマンドで垂れ流してエラー内容を確認したりすると思いますが、その際`less +F`の方が便利かもしれないですよーという話です。

# 詳細

```sh
$ less +F /var/log/httpd/error_log
```

またはオプションを指定せずに

```
$ less /var/log/httpd/error_log
```

で開いた後で`Shift + F`と入力することで、`tail -f`と同じく追記されていくファイルの内容を見ることができます。

この状態のときは画面下部に`Waiting for data... (interrupt to abort)` と表示されます。
![2022-09-18_00h38_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127686/d2373079-4bf3-5d20-e36d-1a895ae60e6d.png)

この状態から抜けるには`Ctrl + C`で抜け、ファイル自体を閉じるには`q`で閉じます。

## メリット/デメリット

`less +F`を使うメリットとして

- `less`の場合、`Shift + F`でログの垂れ流しモード、`Ctrl + C`で垂れ流しを止めて(ファイルの開き直しをすることなく)詳細を見ることができる
    - また、垂れ流しを止めた状態であれば検索やページスクロール等のコマンドを使うことができる


デメリットとして

- `tail -f`の場合、Enterを連続して押して空行を開けて次に表示されるログをわかりやすくすることができますが、`less +F`の場合はEnterを押しても空行を開けることができない
- スクロールするときには一旦`Ctrl + C`でコマンドが受け付けられる状態にする必要がある

という点で自分は多少デメリットに感じました。

また、`tail`では

- `tail -F`とすることでローテートしたファイルを追従してくれる
- `tail -f file1.log file2.log`のようにすると複数ファイルを追従することができる

といったメリットもありますが、自分は使ったことがなかったので、あまり大きなデメリットには感じませんでした。


## 使用例

他のオプションと併用した使用例を記載します。
※tailでも可能な場合はtailのコマンドも記載しています。

### 文字列検索(ハイライト)しながら表示する

```sh
### less の場合
$ less +F +/ERROR /tmp/test.log
```

|コマンド|説明|
|---|---|
|+F|追記される分も表示する|
|+/文字列|指定文字列で検索(ハイライト表示される)します。(正規表現可)|

### フィルターしながら表示する

```sh
### less の場合 (コマンド入力後、Enter2回押す必要あり)
$ less +F +\&ERROR /tmp/test.log
### または
$ less +F +'&ERROR' /tmp/test.log

### tail の場合
$ tail -f /tmp/test.log | grep ERROR
```

|コマンド|説明|
|---|---|
|+F|追記される分も表示する|
|+&文字列|指定文字列が含まれる行のみ表示する|

※フィルターを解除するには`Ctrl + C`で垂れ流し状態を終了し、
`&`を押すと`&/`(フィルター文字列指定状態)の表示になるため、何も入力せずにEnterを押します。
(別な文字列でフィルターを掛けるときは`&/`が表示されている状態でフィルター文字列を入力しEnterを押します)


### 長い行を折り返さず表示

折り返さずに表示(エラーの発生時間と種類ぐらいが見れればいいとき等)したいときに使用

```
$ less +F -S /tmp/test.log
```

|コマンド|説明|
|---|---|
|+F|追記される分も表示する|
|-S|右端で折り返さずに表示|

ただし、表示しきれていない横の範囲を表示するには一旦`Ctrl + C`で`+F`が効いている状態を抜けてからでないとカーソル左右が効かないので注意


### 行番号も表示する

(ログの表示とかではあんまり使わないかも。。。)

```sh
$ less +F -N /tmp/test.log
```

# Lessコマンド使用時に使うオプションやコマンド等まとめ

よく使いそうなものだけ記載します。

|コマンド|内容|
|---|---|
|+F|追記される分も表示する|
|-N|行番号表示の切り替え|
|-S|右端で折り返しの切り替え|
|/文字列|文字列で検索を行い、ハイライト表示する|
|-J|/文字列で検索にヒットした行の左に * マークを表示する|
|&文字列|文字列で検索を行い、ヒットした行のみを表示する|


# 備考等

## パフォーマンスについて

参考: [Stack Exchange: Is `tail -f` more efficient than `less +F`?](https://unix.stackexchange.com/questions/193620/is-tail-f-more-efficient-than-less-f)

lessはファイル全体を読み込むのに対し、tailはファイルの最後の方しか読み込まないので大きなファイルを読み込む場合にはlessはパフォーマンスが悪くなるようです。
また、tailの場合、ファイル変更通知サービスを使って新しいデータを表示するのに対し、lessはループでチェックをするため、最大1秒のラグがあるそうです。
(QAサイトの回答参照で、コマンド実装のソースを見るまでは至っていませんが、上記のような理由でtailの方がパフォーマンスで劣る面もあるらしいです。)