OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘】S3静的ウェブサイトホスティングで403エラーが出る時


S3の静的ウェブサイトホスティングで思わぬエラーに遭遇してしまったため、備忘です。
AWS初心者の一助になれば幸いです。

### やりたい事

S3の静的ウェブサイトホスティング機能を使用して、htmlファイルにパブリックにアクセスできることを確認したい。

### エラー内容
以下のとおり403エラーとなる。
![スクリーンショット 2022-05-04 11.29.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428179/2a64bb60-4e91-e355-1049-32c0cdaaf87e.png)


### 原因
バケットポリシー誤り。
Resourceのarnにはバケット名だけではなく、「/*」まで含める。

```diff_json
{
    "Version": "2012-10-17",
    "Id": "1",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "S3:GetObject",
-            "Resource": "arn:aws:s3:::[バケット名]"
+            "Resource": "arn:aws:s3:::[バケット名]/*"
        }
    ]
}

```

上記に問題がない場合は、ブロックパブリックアクセスが無効となっていることを確認する。
無効になっていればバケット名の下に「パブリックにアクセス可能」と表示される。
![スクリーンショット 2022-05-04 11.33.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428179/4d498a43-99bc-0523-713e-a9cb9af3bd2b.png)

以上
久しぶりにReactつかったらcreate-react-appができなかった

# version
```:入力：node -v
v16.14.0
```
```:入力：npm -v
8.3.1
```
# 何があったか
夏のエンジニアインターンに向け、開発物を作ろうとReactを使おうとしたところ
```ターミナル:入力
npx create-react-app my-app
```
```ターミナル:出力
 'create-react-app' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```
と出力され実行できなかった。


# 調べてみた
`create-react-app`を使用するには、node.jsやらnpmのversionが一定以上ないとダメっぽいけど、バージョンの要件は満たしていた。

# 試したこと
パッケージがぐちゃぐちゃしてしまったのかと思い、一度node.jsかnpmかnpxのアンインストールを試みた。(何をしたか忘れてしまいました)
その後`create-react-app`を使うも、うまく実行されなかったが、
```:入力
npm init react-app my-app
```
を実行すると、Reactの開発環境を立てることができた。

# おわりに
`create-react-app`を実行することができていないので、根本的な解決には成っていないが、`npm init react-app my-app`することで、現状打破が可能だとわかった。
次は、node.jsを再インストールして、最新バージョンで`create-react-app`を試してみようと思う。
あとは、記事を書くまでに解決手順を忘れてしまうので、詰まった段階から記事を書き始めることで、うまく解決方法を記していければと感じた。
【GradCAM】ResNetで学習させた都市景観画像の判断根拠

# 概要

私事で恐縮ながら、社会人になって一人暮らしを始めました。
今住んでいるのは都心の近くなのですが、実家は郊外なので、それぞれの景観は異なってきます。路地を歩いているとなんとなく街並みが○○区っぽいな、とか、ここは○○市らしいなとか、感じたことがある方も多いと思います。
とはいえ、その差は結構微々たるもので、その市区町村にあるな”雰囲気”の差のようなものがある気がします。
今回は東京都の町田市と中央区の画像を教師あり学習で識別モデルを学習し、GradCAMを用いて判断根拠が何なのか確認してみます。
モデルには定番のResNetを用います。

実装や詳細は下記のサイト（M3 Tech Blog様）を参考にさせていただきました。
[機械学習で逆ストリートビューを作り、写真から港区らしさを判定する](https://www.m3tech.blog/entry/photo2geo)

ご指摘・疑問などございましたらコメントよろしくお願いいたします。

# 学習
![図形 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583727/85aeb21a-386f-dac0-9ec6-1009f51accd9.jpeg)

上記のようなモデルを考えます。
都市の景観画像データセットを用意し、ResNetに学習させます。
識別はパターンで、東京都町田市のものと、東京都中央区のものを用意します。
パラメータ・詳細は下記のとおりです。

・学習率：1e-4
・バッチサイズ：10
・データ総数：約4,000[枚]
・フレームワーク：PyTorch

学習の定量的評価は行いませんでしたが、町田市と中央区は人間の目で見ても景観の乖離が大きいので単純なタスクかと思います。そのためvalidation dataに対する正解率は98%を超えていました。

# 学習データの収集

今回最も面倒だったのがデータの収集です。数千枚の景観データを手作業で収集するのは現実的ではないため、Googleのstreetview APIを使用しました。
[https://developers.google.com/maps/documentation/streetview/overview](https://developers.google.com/maps/documentation/streetview/overview)

locationに位置座標、sizeに取得したい画像サイズを指定することで簡単に景観画像を取得可能です。

ご注意いただきたいのが、一回叩くごとに0.007USD請求されます。（上記サイト参照）
私はあまりに気にせず叩きまくった結果、１万円を軽く超える請求が来たため、慎重なご利用をお勧めします。（Google Cloud Platformの無料利用枠対象内でしたので実質無料でしたが、、）

また、折角お金をかけて叩いたのに、取得できないケースがあります（取得画像に”sorry we have no image here”と表示される）
データセットに悪影響を及ぼすため、こうした画像は排除することをお勧めします。

# GradCAM
大変わかりやすい記事がQiitaにも多くありますので詳細は割愛しますが、平たく言うと識別モデルの判断根拠を出力する手法です。
[https://qiita.com/kinziro/items/69f996065b4a658c42e8](https://qiita.com/kinziro/items/69f996065b4a658c42e8)

下記の画像の例では、"cat"の判断根拠をヒートマップ画像で可視化しています。
猫の下半身周辺にモデルが注目し、"cat"と識別していることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583727/05ed8609-d321-0b15-bec7-3bf81f67e9fb.png)
上記画像は下記論文から確認できます。
[Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization](https://arxiv.org/abs/1610.02391)



# 結果
東京都町田市の画像をランダムに抜き出し、”町田市”と判別された画像の根拠をGradCAMにより可視化しました。

![図形 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583727/926ffbf3-48ff-5362-8ec3-5ccbad8860d2.jpeg)

ResNet的には緑の多い畑周辺に注目していることがわかりますね。
反対にアスファルトで舗装された道や、空には注目していません。中央区にも共通して確認できる特徴だからでしょうか。


中央区も同様にトライしてみました。


![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583727/53b06bd4-9fe0-6d6a-8f09-171c66389ea0.png)

少し偏りがありますが、高層ビル周辺に注目しているようです。
道路や空には目もくれていません。

# 考察・おわりに
今回はResNetに都市画像を学習させ、GradCAMで判断根拠を可視化しました。
町田市→緑、中央区→ビル群に着目していることがわかりました。うまくいくかわからなかったので単純なタスクを設定しましたが、今後はもう少し差がない区や市でも判別が可能か、そして判断根拠はどこなのかやってみようと思います。
最後までご覧いただきありがとうございました。
確率・統計

## 確率
<b>ある事象の起こる可能性の度合いのこと。

<b>確率 = ある事象が起こる場合の数
　　　＿＿＿＿＿＿＿＿＿＿＿＿
     　　　起こりうる事象の全ての場合の数

### 場合の数
<b>全部で何通りかということ。
複数の事象が同時に起こる場合の数を考えるときは乗算する。
複数の事象が別々に起こる場合の数を求めるときは加算をする。
## 順列
<b>n個の中からr個取り出して並べてもの。
![zyunretsu-zukei1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600460/1d88be9b-c7eb-f58f-8987-589f1e757a8a.png)
n!は「nの階乗」といわれる。
## 組合せ
n個の中から並び順を考慮せずにr個取り出したもの。
![kumiawase-zukei1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600460/e29aa4bf-2695-e721-f2fc-d1b30e49091b.png)
## 統計
<b>データを集めて全体の傾向を割り出すもの
### 統計の指標
<b><font color = blue>平均値</font>は、各データの合計をデータの個数で割って求めた値
<font color = blue>メジアン(中央値)</font>は、データを順番に並べて中央に位置する値
<font color = blue>モード(最頻値)</font>は、出現頻度の最も高い値
<font color = blue>レンジ(範囲)</font>は、データの最大値と最小値の差。
<font color = blue>分散</font>は、平均値からのばらつきを表す、偏差(平均値との差)の2乗の総和の平均値
<font color = blue>標準偏差</font>は、分散の平方根。これが大きいほど平均値周りのデータのばらつきが大きい。小さければばらつきは小さい。
## 正規分布
<b>平均値を中心とした左右対称の<font color = blue>釣り鐘型の分布</font>
HTTPリクエストとは

# HTTPリクエストとは
ホームページを見るときに使うソフト（Webブラウザ）からホームページのファイルが置いてあるコンピュータ（Webサーバ）に対して出される「このページをちょうだい」の要求のことです。
## ホームページが表示されるまでの流れ
**1. httpリクエスト**
ホームページを見ようとすると、まず、ホームページを見るときに使うソフト（Webブラウザ）からホームページのファイルが置いてあるコンピュータ（Webサーバ）に対して「このページを頂戴」と要求します。
**1. httpレスポンス**
その要求に対して、WebサーバからWebブラウザに「このページだよ」とお返事がきます。
**3. 表示**
 お返事を受け取ったWebブラウザは、受け取った内容（ホームページのファイル）を画面上に表示してくれます。

# 参考文献
HTTPリクエストとは
https://wa3.i-3-i.info/word1841.html
Linux Ping-t勉強の記録6 デスクトップ環境の利用

### X Window System
GUIを実現するためにLinuxなどで使用されている
クライアント・サーバ方式を使用しているのでXクライアント、Xサーバがそれぞれ別のマシンで動いていても使用できる
### Xサーバ
ハードウェアを管理するソフトウェア
### Xクライアント
GUIアプリケーション
### ディスプレイマネージャ
ランレベル５の時にGUIでログイン画面を提供し、ログイン認証、デスクトップ環境の準備を行う。
___
### X.Org
Linuxで標準的に使用されているX Window System
#### /etc/X11/xorg.conf
X.Orgの設定ファイル
### X.Orgのセクション構成
#### ServerLayout
入出力デバイスに関する設定
#### Files
RGBカラーデータベース,Font等の格納場所に関する設定
#### Module
モジュールの指定
#### InputDevice
入力デバイスの設定
#### Monitor
モニタータイプの設定
#### Device
ビデオカードの設定
#### Screen
画面サイズ、ディスプレイの表示色数などの設定
## xhostコマンドの主なオプション
#### + ホスト名
指定したホストを許可リストに追加
#### - ホスト名
指定したホストを許可リストから削除
#### +
許可リストに関わらずすべてのアクセスを許可（アクセス制御を無効にする）
#### -
許可リストのホストのみ接続許可（アクセス制御を有効にする）
___
### xhostコマンドはホスト単位でアクセスを許可する
### xauthコマンドはユーザ単位でアクセスを制限する
### xauth list
Xサーバへの接続に使用される資格情報を表示
___
#### twm
ウィンドウマネージャ
___
#### startx
GUI環境が起動する？
#### init 3 init 5
CUIモード、GUIモードにする
___
### 環境変数DISPLAY
#### 書式 Xサーバ:ディスプレイ番号.スクリーン番号
___
### 統合デスクトップ環境
ディスプレイマネージャやウィンドウマネージャなどのGUI環境とアプリケーションを統合したデスクトップ環境
代表例
#### GNOME
#### KDE
ServiceNow - GlideDateTime.getMonth()は使わないように

JavaScriptで月を取得する場合は.getMonth()を利用する。同じようにServiceNowのGlideDateTimeの月を取得するのに.getMonth()を使うと間違えた結果になる場合がある。

その原因はGlideDateTime.getMonth()はJVMのタイムゾーンを利用するからだ。
多くの場合は問題は起きませんが日付が1日の0時の場合に前月になる。問題を回避するためには.getMonthLocalTime()又は.getMonthUTC()を利用する。

例：
```
var strDate = '2022-05-01 00:00:00';
var gdt = new GlideDateTime(strDate);
gs.print('getMonth:' + gdt.getMonth());
gs.print('getMonthLocalTime:' + gdt.getMonthLocalTime());
gs.print('getMonthUTC:' + gdt.getMonthUTC());
```
実行結果：
```
*** Script: getMonth:4
*** Script: getMonthLocalTime:5
*** Script: getMonthUTC:5
```

## 余談
JVMのタイムゾーンを調べてみるとUTC-7のようです。07:00:00以降になると.getMonth()でも正しい月を取得できます。
UTC-7はPDTでCA, USAです。

以上
コマンドラインから入力した数値が3で割り切れるか教えてくれるプログラム(Python)

コマンドラインから入力した数値が3で割り切れるか教えてくれるプログラムをPython言語で紹介します。

以下ソースコードです。

```python
text = input()
data = 0

for s in text:
    data += int(s)

if data%3 == 0: print("3で割り切れます！")
if data%3 != 0: print("3で割り切れません！")
```

実行結果

```
3
3で割り切れます！

333333333333333333333333333333333333333333333333333
3で割り切れます！

12
3で割り切れます！

14
3で割り切れません！

18
3で割り切れます！

300000000000000000000
3で割り切れます！

30000000000000000000000000000000000000001
3で割り切れません！

3000000000000000000000000000000000003
3で割り切れます！

19238902138902180321380921903812013812903021380
3で割り切れます！

```
React useEffect で無限ループを避ける方法

# 無限ループする例

![Qiita-gif用.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/2680ce09-4fff-4df0-4627-d6da89dcddc9.gif)

`useEffect` 内で state を更新しているため、無限ループになる。

```React:App.js
import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const [boolean, setBoolean] = useState(false);

  useEffect(() => {
    setBoolean(true);
    setCount(count + 1);
  });

  return (
    <div>
      <p>Boolean is {boolean.toString()}.</p>
      <p>Count is {count}.</p>
    </div>
  );
}
```

# 無限ループを避ける方法

`useState` の第二引数に、値が変化したときにレンダリングしてほしい state の配列を指定する。

https://ja.reactjs.org/docs/hooks-effect.html

> これはよくある要求なので、useEffect フックの API にはこの動作が組み込まれています。再レンダー間で特定の値が変わっていない場合には副作用の適用をスキップするよう、React に伝えることができるのです。そのためには、useEffect のオプションの第 2 引数として配列を渡してください。

```React:App.js

import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const [boolean, setBoolean] = useState(false);

  useEffect(() => {
    console.log(boolean);
    setBoolean(true);
    setCount(count + 1);
  }, [boolean]);

  return (
    <div>
      <p>Boolean is {boolean.toString()}.</p>
      <p>Count is {count}.</p>
    </div>
  );
}
```

# 参考記事

https://ja.reactjs.org/docs/hooks-effect.html
A detailed guide to run Docker WordPress instance on AWS EC2 Debian/GNU Linux

# A detailed guide to run Docker WordPress instance on AWS EC2 Debian/GNU Linux

## Preparing EC2 Linux Instance (AMI)
1. Goto console.aws.amazon.com/ec2/

### Generate ssh-key pair
[on Client PC]
1. Run Command prompt and generate ssh key pairs
C:\>ssh-keygen -t ed25519 -C "my@example.com"
Then you'll get id_ed25519.pub(public key) and id_ed25519(private key)
you can rename it to id_aws.pub / id_aws

2. Launch "Puttygen.exe" and convert .ppk to .pem
(for Use /w SCP.exe)
2-1. Load '.ppk' -> choose the .ppk key
2-2. Click menu 'Conversions' -> 'Export OpenSSH key'
2-3. Close the app

3. Use SCP.exe to transfer the public key to remote server.
C:\>scp -4 -C -P 22 -i deb10.pem id_aws.pub admin@aws-server:/tmp/

### Run the AMI and create user
1. Login as admin
/w ED25519 key with Tera Term Pro

2. Create user
$ sudo useradd -d /home/charles -s /bin/bash -m charles
$ passwd charles
$ sudo visudo

3. Register ssh public key
$ sudo su - charles
charles$ mkdir ~/.ssh; chmod 700 ~/.ssh
charles$ cd ~/.ssh
charles$ cat /tmp/id_aws.pub >> authorized_keys

Now you can login to aws ec2 instance as user.

### Install Docker, Docker-compose
1. Update the apt pkg index and install pkgs to allow apt to use a repos over HTTPS
$ sudo apt -y update
$ sudo apt -y install ca-certificates curl gnupg lsb-release

2. Add Docker's official GPG key
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

3. Set up the stable repository
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

4. Install docker engine
$ sudo apt -y update
$ sudo apt -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin
$ sudo gpasswd -a charles docker

5. Install Docker Compose
$ sudo curl -L https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-aarch64" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose

Now you can run your own docker container with docker-compose.yml!
PowerAutomateを使ってファイル加工を自動にしてみた

# 1.はじめに
　私は小売業でネット販売の運営を仕事としております。今回はPowerAutomateを使って、週1回作業しているエクセルCSVファイルをシステムにアップロードする前に、登録先の仕様に合わせるために　項目1行目を自動で消して保存するフローを作成しました。

## 2.ファイル加工作業を自動化しました

　私もしくは同僚のルーティン業務として週1回エクセルCSVファイルをシステムにアップロードする前に、登録先の仕様に合わせるために項目1行目を消して、保存する作業があります。ファイルアップロードは権限上、他部署にお願いしております。作業忘れが発生すると相手先はファイルのアップロードエラーをフィードバックして、修正ファイルを待ち、修正したファイルを再度アップロードして完了したことをフィードバックするというやり直し分の工数が発生します。この課題に対してPowerAutomateを使って解決に近づけたいと思いました。

### 3.PowerAutomateでの作成
【ファイル、登録先の仕様・条件】
加工元となるCSVファイルは1行目に項目が入っているファイルです。
登録先のCSVファイルアップロード仕様は、CSVファイルの1行目の項目を削除しないと登録エラーになります。登録先のシステムには登録権限がないため登録依頼が必要です。

【業務フロー】
　業務フローにすると下記のようになります。

１．管理ツールよりCSVファイルをダウンロードする→2．PowerAutomateを立ち上げる→３．加工するエクセル起動（PowerAutomate）→４．エクセルの1行目を削除（PowerAutomate）→５．エクセルを保存して閉じる（PowerAutomate）→６.電子メールに添付してアップロード実施者に送信→７．CSVアップロード用の専用ツールでアップロード→８．電子メールでアップロード完了報告をもらう



![画像1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2624365/efb50aa2-fa8e-8426-93dc-1ec1f8e35744.png)

【ソース】
``` 
Excel.LaunchExcel.LaunchAndOpen Path: $'''C:\\Users\\user\\Downloads\\サンプルデーター.csv''' Visible: True ReadOnly: False LoadAddInsAndMacros: True Instance=> ExcelInstance
Excel.DeleteRow Instance: ExcelInstance Index: 1
Excel.CloseExcel.CloseAndSave Instance: ExcelInstance

# [ControlRepository][PowerAutomateDesktop]

{
  "ControlRepositorySymbols": [],
  "ImageRepositorySymbol": {
    "Name": "imgrepo",
    "ImportMetadata": {},
    "Repository": "{\r\n  \"Folders\": [],\r\n  \"Images\": [],\r\n  \"Version\": 1\r\n}"
  }
}
```

#### 4.同僚に使ってもらいました

　同僚にまずPowerAutomateを設定してもらい、今回作ったソースを渡して実際のデーターを使い加工してもらいました。うまくファイル加工がされました。同僚にもらった感想は複数ファイルを同時に加工できたらいいなということでした。

##### 5.筆者の後記

　今回はPowerAutomateを使い、CSVファイルの項目1行目を自動で消して保存するフローを作成しました。同僚にも試しに使ってもらい自分の作ったもの役立つことを実感しました。今後はエクセルのマクロ機能を覚えて、PowerAutomate機能と組み合わせることで複雑な処理が自動でできるようにしていきたいと思います。
4.15 (標準) 三次元確率変数の変数変換

## 方針

二次元の場合と同様に一対一変換によって同時密度関数を計算する．(1)より，それぞれの確率変数が独立であることがわかるため周辺密度関数を求める際は同時密度を積分するよりも全確率1を用いて正規化定数を求める方が楽．

## 答案

![4.-20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/b5204bf5-f359-a7b9-fb08-8dd11d07af4a.jpeg)
![4.-21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/1d22edd9-b546-694a-0636-61e1eccf1ded.jpeg)
![4.-22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/30efcec2-0374-bbea-be3e-3d5b7f3680af.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
HerokuでGoogle認証情報・環境変数を扱う方法

# HerokuでGoogle認証情報・環境変数を扱う

## 前置き
通常ローカル開発環境では.envファイルにkey:valueペアの定数を定義したり、Google APIの認証情報をJSONファイルに保持していたりするが、HerokuなどのPaaSでGithubリポジトリ連携する場合、資格情報を公開しない状態でアプリ側で扱えるようにする必要がある。

Google資格情報のJSONファイルの一例：
![gcredentials_hidden.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2395846/7955b169-1fcc-9a17-4adc-4df7c327017c.png)

```bash
$ heroku config:set GOOGLE_CREDENTIALS="$(< /home/charles/Programs/heroku/google-credentials.json)" --app "myapp"
```

## Herokuでの確認
のSettingsタブ > Config Varsで確認
![heroku-env_hidden.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2395846/f197371a-a0cf-e0c1-8db8-31bb97952884.png)

## 環境変数について

Node.jsのdotenvパッケージを使用して.envファイルに保存された環境変数を読み込んでいる場合も、Heroku環境変数から読み出すようにソースの記述を変更する。

```javascript:Firebase.js
import firebase from 'firebase'

// We read Config Vars from Heroku, so no need to load .env
// const dotenv = require('dotenv')
// dotenv.config()

const {
	API_KEY,
	AUTH_DOMAIN,
	PROJECT_ID,
	STORAGE_BUCKET,
	MESSAGING_SENDER_ID,
	APP_ID
} = process.env

const fb_config = {
	apiKey: API_KEY,
	authDomain: AUTH_DOMAIN,
	projectId: PROJECT_ID,
	storageBucket: STORAGE_BUCKET,
	messagingSenderId: MESSAGING_SENDER_ID,
	appId: APP_ID
}

const firebaseApp = firebase.initializeApp(fb_config)
//firebase.firestore().settings({ experimentalForceLongPolling: true, merge: true })
const db = firebaseApp.firestore()

export default db;
```
Salesforce オブジェクトの詳細を取得するツールを作りたい (1)

# はじめに
学習に当たり、Salesforce の各オブジェクトの項目やリレーションを知りたくなりました。
オブジェクトマネージャなどを利用すれば、項目は確認できますが、
画面遷移を複数回する必要があり、若干めんどくさいなぁ、と思っていたので、
なにか作れないか、と思いました。

- Salesforce インスペクター などを利用する方法もありますが、勉強のために「VisualForceページ」「Apexクラス」を利用して、自作してみます。
    - [Salesforce Lightning Inspector Chrome 拡張機能](https://developer.salesforce.com/docs/atlas.ja-jp.214.0.lightning.meta/lightning/inspector_intro.htm)

# 作ってみましょう

1）「標準オブジェクト」「カスタムオブジェクト」の情報を取得するにはどうすれば良いでしょうか。

SchemaクラスのgetGlobalDescribeメソッドを利用することで、オブジェクトの情報（ｓObjectType）を取得することができます。
```java
Map<String, sObjectType> sObjectTypeMap = Schema.getGlobalDescribe();
```

- [getGlobalDescribeメソッド](
https://developer.salesforce.com/docs/atlas.ja-jp.234.0.apexcode.meta/apexcode/apex_methods_system_schema.htm#apex_System_Schema_getGlobalDescribe)


2）前述の Map のキーを取り出して、ｓObjectType を取り出します。
さらに、sObjectType の getDescribe メソッドで DescribeSObjectResult クラスを取得します。

```java
for (String key : sObjectTypeMap.keySet()) {
    sObjectType sObjectType = sObjectTypeMap.get(key);
    DescribeSObjectResult sObjectDescribe = sObjectType.getDescribe();
```
- [DescribeSObjectResult クラス](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_sobject_describe.htm)

以下のように、メソッドを呼ぶことで、対象のメソッドのラベル名などの情報を取得することができます。

```java
DescribeSObjectResult sObjectDescribe = sObjectType.getDescribe();

this.Prefix          = sObjectDescribe.getKeyPrefix();
this.Label           = sObjectDescribe.getLabel();
this.Name            = sObjectDescribe.getName();
this.IsAccessible    = sObjectDescribe.isAccessible();
this.IsCreateable    = sObjectDescribe.isCreateable();
this.IsCustom        = sObjectDescribe.isCustom();
this.IsCustomSetting = sObjectDescribe.isCustomSetting();
this.IsDeletable     = sObjectDescribe.isDeletable();
this.IsQueryable     = sObjectDescribe.isQueryable();
this.IsSearchable    = sObjectDescribe.isSearchable();
this.IsUndeletable   = sObjectDescribe.isUndeletable();
this.IsUpdateable    = sObjectDescribe.isUpdateable();
```

さらに、各項目は以下のように取得します。
sObjectDescribe の fields に対して、getMap メソッドで 項目の詳細情報を取得します。

```java
Map<String, SObjectField> fields = sObjectDescribe.fields.getMap();

for (String key : fields.keySet()) {
    DescribeFieldResult field = fields.get(key).getDescribe();

    YGG_ObjectItem item      = new YGG_ObjectItem();
    item.ByteLength          = field.getByteLength();
    item.CalculatedFormula   = field.getCalculatedFormula();
    item.DefaultValue        = field.getDefaultValue();
    item.DefaultValueFormula = field.getDefaultValueFormula();
    item.Digits              = field.getDigits();
    item.InlineHelpText      = field.getInlineHelpText();
         :
         :
```

必要とする情報が揃いましたので、実際に組み立ててみましょう。

https://qiita.com/xx_mana/items/82b35a38f0603d14dcf1



# 参考としたサイト

参考とさせていただきましたページも合わせて載せておきます。感謝。

https://qiita.com/hrk623/items/79e101e1ca2e09d43b01

https://qiita.com/s_hayashida/items/517da55c05c6099805dc

# ご了承ください
- まだまだ勉強中の部分もあります。間違っている箇所もあるかもしれません。
- Salesforce は、この時点のバージョン(2022年4月～5月頃) での内容になります。今後、仕様変更が変わることによって、内容の通りにならない可能性もあります。ご了承ください。
 - また、URLなども変更になっている可能性もあります。
CloudFunctionsのデプロイエラーの対処方法 error fetching storage source: generic::unknown: retry budget exhausted (3 attempts): fetching gcs source: unpacking source from gcs: source fetch container exited with non-zero status: 2

こんにちは。[virapture株式会社](https://virapture.com)の[もぐめっと](https://mogmet.com)です。

本日はCloudFunctionsのトラブルシューティング記事になります。

結論から言うとnodeのバージョンを変えよう！というお話になります。

## 問題の発生

ある日M1 macの環境でCloudFunctionsをデプロイしようとしたら下記エラーでデプロイができませんでした。
```
functions[onCreate(asia-northeast1)]: Deployment error.
Build failed: Build error details not available.Please check the logs at https://console.cloud.google.com/cloud-build/builds;region=asia-northeast1/xxx-xxx-xxx-xxx-xxx?project=xxx. Please visit https://cloud.google.com/functions/docs/troubleshooting#build for in-depth troubleshooting documentation for build related errors.
```

出力されたURLをたどってみると下記エラーが発生しているようでした。

```
ERROR: error fetching storage source: generic::unknown: retry budget exhausted (3 attempts): fetching gcs source: unpacking source from gcs: source fetch container exited with non-zero status: 2
```

なるほどわからん。
他にも同じエラーで困っている人もいましたが解決方法はわからない模様。

https://teratail.com/questions/460bl9x8yd5t55

## 解決方法

自分の場合の解決方法は簡単で、この時のnodeのバージョンが**v16.13.2**だったのですが、**v15.12.0**に下げてみたところ無事実行することができました。

cf:

https://qiita.com/strsk/items/925644e124efcc964625

## まとめ

普段動いてたのに動かなくなったらnodeのバージョンを疑ってみよう！
他のプロジェクトとかでもnpm iができなかったりしたので、v15が割と安定して動いてる気がします。

最後に、[ワンナイト人狼オンライン](https://online.1nite-jinro.com/link/blog)というゲームを作ってます！よかったら遊んでね！

https://online.1nite-jinro.com/link/blog

他にも[Camecon](https://camecon.me/)や[Offcha](https://offcha.com/)といったサービスも作ってるのでよかったら使ってね！

https://camecon.me/

https://offcha.com/

また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。

https://virapture.com/
[GIMP]ローポリ用カラーパレットを作る

# 概要
Blender,Unity,UnrealEngineなどのローポリ用カラーパレットをGIMPで作る手順です。
![スクリーンショット 2022-05-04 8.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/13f77131-37f2-fe71-3b01-2558a452199a.png)
# 本文
## ファイルの作成
メニューから「ファイル」 > 「新しい画像...」を選びます。
カラーパレットに登録する色の分だけ幅と高さを確保します。（今回は３×３で９色分）
単位はpxを選んでください。
![スクリーンショット 2022-05-04 8.25.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/a2d0fa09-a070-296c-4642-47c6615a35c9.png)

画像サイズがすごく小さいので拡大表示しておきます。画面下側にある表示倍率を大きくします。
![スクリーンショット 2022-05-04 8.25.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/94f37e13-38f2-2ff8-0f22-f787c5e8d542.png)

## 下地の作成
色を塗りやすくするための準備をしておきます。
![スクリーンショット 2022-10-02 21.31.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/109d6b35-c254-ee31-a930-29c8f04f0fee.png)

ポップアップが表示されますので、赤枠部分を好みで設定します。今回の例ではWidthとHeightに一マス分のサイズ1×1。Offsetは0。色は白と黒にしました。
![スクリーンショット 2022-10-02 21.31.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/f107977a-ee74-1c3a-52a4-ac9a7e969d2a.png)

後は分割したマスを塗り潰しツールで塗るだけです。
![スクリーンショット 2022-10-02 21.32.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/6a35e813-7a4f-0509-588f-c15ac9b55654.png)
キャンバスに色を塗ったら
![スクリーンショット 2022-10-02 21.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/901bbbe6-d6d4-c869-1b1d-03b4b50792c9.png)

エクスポートを選んでpng形式で保存します。
![スクリーンショット 2022-05-04 8.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/8afa9fba-6b57-4790-1bff-3a197b2f6166.png)

# 作成したカラーパレットをBlenderで使う場合
Texture interpolationにClosestを選んでおくと色がまばらにならなくなります。
(Layoutタブの例)
![スクリーンショット 2022-10-02 22.12.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/0d9d45ea-e196-605d-83c9-ffcbceacd176.png)
(Shadingタブの例)
![スクリーンショット 2022-10-02 22.17.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/e09b95cd-113b-a17a-8ffc-8329cdbf316d.png)
# 作成したカラーパレットをUnityで使う場合
取り込んだカラーパレットの設定をこのようにしておけば色がまばらにならなくなります。
![スクリーンショット 2022-10-02 22.44.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/01882549-1d84-c4a2-61ed-e059cb9e5f7f.png)
wordpress の galleryをカスタマイズ

Wordpressの記事に対して、画像を関連づけることができます。
あまり知られていない。というかひっそりと存在している機能で、ギャラリーと言う機能です

投稿に対して画像を配置させるやり方はそれなりにわかりやすいインターフェースが存在しているのですが、それとは異なる機能になります

(調査対象のwordpressバージョン 5.5.3) 

## ギャラリー追加のやり方


1. (記事に画像を配置するのと同様に）新規投稿画面・投稿編集画面で「メディアを追加」をクリックします
    1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/adf43468-287a-2646-0245-4ce017860414.png)
1. メディアを追加画面から新規ファイルを選択するか、今まで登録した画像を選択します
    1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/8135cc40-2e9e-67dc-1d77-f95776561eed.png)
1. すると、テーブル [***]_posts に、記事idをpost_parentにもつ post_type = attachment のデータが追加されます
1. 今度は「メディアを追加」から「ギャラリーを作成」をクリックします
    1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/59cec5f7-af7b-d55c-bf1b-3dd6f6de8f7f.png)
1. ここでもファイルをアップロード・メディアライブラリから選択 が選べます
1. メディアを追加の場合は、imgタグが埋め込まれますが、ギャラリーの場合は gallery ショートコードが追加されます
    1. ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/a4d12821-2a3c-ea9a-2223-906ecfe22196.png)
1. データとして、「ファイルをアップロード」により追加された画像についてはpost_parentがその投稿になりますが、「メディアライブラリ」から選択された画像についてはデータが増える訳ではないようです

## ショートコード galleryを読み解く
https://wpdocs.osdn.jp/%E3%82%AE%E3%83%A3%E3%83%A9%E3%83%AA%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9 によると、 wp-includes/media.php にショートコードの実装があるということで、そちらを確認してみます

コードは `function gallery_shortcode( $attr ) {`

* property idsが指定されていたらinclude変数にそのまま渡す。orderbyが指定されていなければ post__inをorderbyに割り当てる
* filter post_galleryを呼び出す。post_galleryで何らの文字列が返ってきたらそれをショートコードに置き換える
* post_galleryが定義されていない、もしくは空白が返ってきた場合はデフォルトの処理が行われる
* 
property "include", "ids"が指定されていたらそのidを元にpost_type=attachment, post_mime_type=imageの postを取得する(get_posts)
* property "id"が指定されている場合は、そのidをpost_parentにもつ、post_type=attachment, post_mime_type=mageのpostを取得する。property "exclude"が指定されている場合はそのidに一致する画像を除いて取得する (get_children)
* 取得されたpostを元に画像一覧のhtmlを生成する
4.14 (標準) 二次元確率変数の変数変換8 ベータ分布

## 方針

ガンマ分布にそれぞれ独立に従う確率変数から，ベータ分布の導出ができる，ということを誘導付きで確認する問題．この事実は第7章のF分布を導出する際も使うので重要．一対一変換になっているので素直に式変形する．

## 答案

![4.-19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/d45d4b22-4390-67a2-5452-c0c1f0a79a2c.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
100日後くらいに個人開発するぞ！day016

## 今日はHTMLとCSSの環境構築をしてみた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/02e84276-c3ec-cfb3-ff77-56da956651dd.png)
参照：https://prog-8.com/docs/html-env

## エディタ「Visual Studio Code（VSCode）」をダウンロード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/3603648c-5e32-5dd9-51d3-b1858c18742b.png)


## フォルダを作成しHTMLとCSSを記述

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/5b72b15d-51b0-70ab-3a12-9d62ce564aef.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/b15911a4-c246-e2c6-9c22-947e477093b5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/44b6bd3b-5aa3-2dd5-9696-ea2ae9141747.png)

## Google chromeで反映

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2632394/7acb1369-570d-a5ed-0156-dfdd7c94b04d.png)
Raspberry Pi(Raspbian)のTimeZoneとViの設定を変更する

# 概要
Raspberry Piでプログラムを動作させている際に、ログに出力される時刻が数時間ズレていたり、Viで設定ファイルを編集しようとしたら、←→↑↓キーやBackSpaceなどが効かず、いにしえのviキーを検索して操作するのを解消させる備忘録です。

# 前提条件（というかRaspbian）
* Raspberry Pi 3B+（別に型や版は関係ないが・・・）
* Raspbian
```
pi@raspberrypi:~ $ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)"
NAME="Raspbian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
```

# 手順
## TimeZoneをJSTに変更する
Raspbianのデフォルトタイムゾーンは、BST（英国時間）のようです。
ある時、定期実行させたプログラムのログを見ていると時刻が8時間ズレていることで気づきました。（まぁ、時刻が関わることをしてなければなんてことない）

BST（英国時間）は「UTC+0100」。JST（日本標準時）は「UTC+0900」なので、8時間のズレは当然ですね・・・・

さて、これをJSTに修正します。

まずは、現在の状況を確認
```
pi@raspberrypi:~ $ date
Tue 3 May 23:33:55 BST 2022
pi@raspberrypi:~ $ timedatectl
               Local time: Tue 2022-05-03 23:34:33 BST
           Universal time: Tue 2022-05-03 22:34:33 UTC
                 RTC time: n/a
                Time zone: Europe/London (BST, +0100)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
```

BSTですね、、、、

JSTに変更します。（変更の反映は**即時**です）
```
pi@raspberrypi:~ $ sudo timedatectl set-timezone Asia/Tokyo
```

確認してみます。
```
pi@raspberrypi:~ $ date
Wed  4 May 07:50:57 JST 2022
pi@raspberrypi:~ $ timedatectl
               Local time: Wed 2022-05-04 07:51:00 JST
           Universal time: Tue 2022-05-03 22:51:00 UTC
                 RTC time: n/a
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
```
無事、JSTになりました。

## Vi操作を設定する（.vimrc)
RaspbianでVi操作をするときに、方向キーやBackSpaceを日頃から使っているのに使えないのか・・・・と、Vi操作をググって「え～と、1文字削除はｘと・・・」とやっているのが辛いのでVi操作をいつもの状態にします。

これ、難易度が高い原因は、Raspbianのviが「Small version without GUI」だから。
```
pi@raspberrypi:~ $ vi --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Oct 01 2021 01:51:08)
Included patches: 1-2434
Extra patches: 8.2.3402, 8.2.3403, 8.2.3409, 8.2.3428
Modified by team+vim@tracker.debian.org
Compiled by team+vim@tracker.debian.org
Small version without GUI.  Features included (+) or not (-):
```

と言っても、設定ファイルを作ってあげればかなり解消するので、設定ファイル（.vimrc)を**作成**する。

```
pi@raspberrypi:~ $ cd　←一応、自分のHomeに戻しておく
pi@raspberrypi:~ $ echo "set nocompatible" > .vimrc
pi@raspberrypi:~ $ echo "set backspace=indent,eol,start" >> .vimrc
```

おしまい。

あとは、自分の好みに合わせて設定を追記する。
ご参考：

https://qiita.com/reireias/items/230c77b3ff5575832654


良きラズパイライフを。
非エンジニアOLのPython忘備録的ブログ

初めに
この記事ではmacbook airにインストールしたpython3.9.7を使っています
今回はこんな感じのアプリをYoutubeで見て作り類似したものを自作しました。
参考にしたのはこちらです。
https://www.youtube.com/watch?v=pk6fgvKQ7q4
その手順をコードの解説とともに忘備録的に載せておきます。

・注文ボタン押す前
![BBDDFF52-5E82-4EF0-B4C6-CC24C32C88EB_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/992222/aabc1617-e93a-aa68-2627-38bb245d7a0c.jpeg)
・個数選択して注文ボタン押した後

コードは以下の通りです。
![CBD208CB-8A84-4000-A70C-2AD50F4009EB_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/992222/d3516b71-d118-ba97-9a90-3f32114e418d.jpeg)



以下、コードの説明をします。

```py:コード1行目
import PySimpleGUI as sg
```

　PySimpleGUI(モジュール)をインポートしてモジュール名sgとして使用するという意味です。
　Python言語でGUI(グラフィカルユーザーインターフェース)を構築できます.
　※あらかじめPySimpleGUIをインストールする必要があります。

・PySimpleGUIのインストール方法
　1. ターミナルコマンドを開く
　2. pip3 install PySimpleGUIと記入
これでインストール完了です。

```py:コード2行目
import math
```

　mathモジュールをインポートするという意味です。
　ここでは小数点以下の切り捨てにmath.floor(小数点以下を切り捨てしたい自然数)を使用するためにインポートしています。

```py
layout =[
[sg.Text('みかん(1箱500円(税抜))'),sg.Combo(list(range(1,4)),key='-QUANTITY-'),sg.Text('個')],
[sg.Button('注文',key='-SUBMIT-')],
[sg.Text(key='-AMOUNT-',size=(120,10))]
]
```

　後の`window = sg.Window('注文',layout,size=(300,150))`のlayoutの部分を作成しています。

　layoutの部分は配列になっています。
　
先程のせた写真の説明だと

```py
layout = [
[みかん(1箱500円(税抜)),コンボボックス(プルダウン選択できるもの),個],
[注文],
[まだ見えない部分(個数選択して注文ボタンを押すと'金額:税込の金額'が表示される部分)]
]
```

となります

配列の例を出しておきます。
　コード例.

```py
layout = [[1,2,3],[4,5],[6]]
print(layout)
```

　コード例の出力結果

```py
[1,2,3]
[4,5]
[6]
```

```py
window = sg.Window('注文',layout,size=(300,150))
```

　変数windowにsg.Window('注文',layout,size=(300,150))を代入しています。
　sg.Window('注文',layout,size=(300,150))でタイトルが注文の横が300,縦が150の配列layoutがレイアウトされた画面を作成します。

```py
while True:
    event,values = window.read()
    if event == '-SUBMIT-':
        total = math.floor(500 * 1.1 * int(values['-QUANTITY-']))
        window['-AMOUNT-'].update(value=f'金額:{total}')
    if event == sg.WIN_CLOSED:
        break
```

```py
while True:
     event,values = window.read()
```

で画面が閉じてしますのを防ぎます。

```py
    if event == '-SUBMIT-':
        total = math.floor(500 * 1.1 * int(values['-QUANTITY-']))
        window['-AMOUNT-'].update(value=f'金額:{total}')
```

で、もし`-SUBMIT-`を割り当てたボタンが押されたら
変数totalに500x1.1x選択された個数の結果を代入して
`-AMOUNT-`を割り当てたテキストの表示を`金額:変数totalに先程代入された結果`に更新する
という意味です。

説明は以上です。

最後までご覧いただきありがとうございます。

編集リクエストして下さったsiracamus様へ
編集リクエストして下さり、ありがとうございました。
おかげ様でとても見やすくなりました。
VirtualBox nagiosサーバーの監視アラート無効化・有効化の手順

### はじめに
nagiosサーバーのアラートを無効化と有効化を以下のサイトを参考に検証してみました。
http://blog.livedoor.jp/aloha_net/archives/42368137.html
https://cloudpack.media/9627

### 動作環境
VirtualBoxでnagiosサーバーを構築
以下のサイトを参考にしてください。
https://qiita.com/gama1234/items/6869d23c5bc287403f78

### アラートの無効化作業
#### 左側ペインのServiceをクリックし、対象ホストをクリックする
Limit Resultsは、すべてのホストを表示させるために「All」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/ecc91b8f-2f37-294f-3d67-cd0933ff1d53.png)


#### 左側にあるアラートを無効化する設定をクリックする
Disable notifications for all services on this host
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/6c9532bc-0bc8-6c5f-4b7b-228f87b08acb.png)

#### Disable For Host チェックを入れて、commitをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/836cadbe-69ff-1e6d-07a7-54ff8ac9a310.png)

#### 以下のメッセージが表示されること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/601b7892-a69e-692a-de03-6316b146b54e.png)

#### アラートが無効化されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/26c0967d-2359-c013-92cb-2f497f50078e.png)

### アラートを有効化する方法
#### 左側ペインのServiceをクリックし、対象ホストをクリックする
Limit Resultsは、すべてのホストを表示させるために「All」を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/ed7576d7-c3ec-9c10-7071-be20aaf91bf3.png)

#### 左側にあるアラートを有効化する設定をクリックする。
Enable notifications for all services on this host
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/214d3d1d-e1ad-609b-5800-bf88146c489c.png)
#### Enable For Host チェックを入れて、commitをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/969e584b-b0e5-4ebd-6a19-2fb0ef33c5a2.png)
#### 以下のメッセージが表示されること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/113870d6-e77e-2b13-46e5-a0f3bdd27157.png)

#### 有効化されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/a50e743b-3aa0-b237-72b3-84d42dc34ebf.png)
Synology DiskStation Manager (DSM) 7.x の NAS に cifs-utils(SMBv2) でマウント出来ない場合の対処 ※DSM7でNTLMv1認証が無効化された・・・

# 経緯

**Synology DiskStation DS118** で、先月まで **DSM6.2** を使っていたが、下記の脆弱性情報を確認。

https://www.nichepcgamer.com/archives/synology-and-qnap-nas-multiple-vulnerabilities-in-netatalk.html 

ほかにも、**DSM6.2**にインストールしていたパッケージ(**WordPress**等)の更新が止まっていたので、
その他諸々の解決策として**DSM7.0**へのアップデートを実施。
続けて、**DSM7.1-42661 Update 1**へアップデートを実施。

その後、**Ubuntu 20.04.4 LTS** のパッケージ **cifs-utils** でマウントが出来なくなった。

# 根本原因
* **DSM 7.x** より **NTLMv1 認証** は**無効化**された・・・。

https://kb.synology.com/ja-jp/DSM/tutorial/I_cannot_access_shared_folders_from_WinXP_computer

* **cifs-utils** のデフォルトの認証が `sec=ntlm` **(NTLMv1)** なので、変更する必要がある。

# 解決方法
* **cifs-utils** の認証を **NTLMv2** に変更する。
具体的には `mount.cifs` のオプションに `sec=ntlmv2` を追加する。

```console:/etc/fstab
//SynologyDiskStation.local/home/_Workfolder/   /mnt/NAS_DSM  cifs    noauto,vers=2.0,sec=ntlmv2,dir_mode=0777,file_mode=0777,username=USERNAME        0       0
```
:::note
 **DSM7.x** 以前から **cifs(SMBv1)** が**無効化**されているので、
 接続するには、オプションで `vers=2.0` **(SMBv2)** が必須です。
:::

# ぼやき
**cifs-utils** は、何で上位バージョンのプロトコルで接続してくれないのだろ？？
~~パッケージ名が示す通りcifs(SMBv1&NTLMv1)しか接続しないのかな・・・~~
2022/5/4主にITとかセキュリティの記事

Microsoft Azure、PostgreSQLに不正アクセスできる脆弱性【修正済み】(5/2)
https://news.mynavi.jp/techplus/article/20220502-2334455/

東映アニメ、不正アクセスの調査結果を公表--業務ソフト配布元が改ざん(5/2)
https://japan.zdnet.com/article/35187047/

ハッカー集団「Anonymous」、ロシア主要電力組織や銀行などからデータ流出(5/2)
https://news.mynavi.jp/techplus/article/20220502-2334519/

ランサムウェア「Yanluowang」暗号化アルゴリズムに脆弱性、カスペルスキーが復号ツールをリリース(5/4)
https://gunosy.com/articles/eaw2L

資産形成コンサルティングの明光トレーディングにランサムウェア攻撃、顧客情報等が流出した可能性(5/2)
https://s.netsecurity.ne.jp/article/2022/05/02/47548.html

病院のＰＣ画面に「ｐａｙ」、身代金ウイルス感染か…数万人分の電子カルテ閲覧できず(5/2)
https://www.yomiuri.co.jp/national/20220502-OYT1T50149/

日本年金機構やau、NHKなどをかたる詐欺の特徴とは？ 4月に注目を集めたフィッシングの手口をチェック(5/2)
https://internet.watch.impress.co.jp/docs/special/1406584.html

河村電器及び子会社にランサムウェア攻撃、サーバに被害(5/2)
https://s.netsecurity.ne.jp/article/2022/05/02/47550.html

注意！スマートフォンのテキスト予測でシードフレーズが推測される(5/2)
https://jp.cointelegraph.com/news/warning-smartphone-text-prediction-guesses-crypto-hodler-s-seed-phrase

2022年2月のウイルスレビュー ― マルウェア活動の増加等(5/2)
https://japan.cnet.com/release/30674750/?ref=rss

FBIによる米国人データの「令状なし捜査」 20年から21年にかけて倍増(5/2)
https://mb.epochtimes.jp/2022/05/105340.html

Windows 11向け更新プログラム適用で画面がちらつく問題が発生(5/2)
https://news.mynavi.jp/techplus/article/20220502-2336033/

QNAPに重要な脆弱性、一時的にAFPの無効化を呼びかけ(5/2)
https://news.mynavi.jp/techplus/article/20220502-2333958/

Windows 11のシェア停滞とWindows 10のサポート終了期間を考える(5/2)
https://www.itmedia.co.jp/pcuser/spv/2205/02/news062.html

データ拠点電力4割減　富士通など7社、30年度までに技術(5/2)
https://www.nikkei.com/article/DGXZQOUC139Q30T10C22A4000000/

「Windows 11」、マイクロソフト社内のアップグレードプロセスはいかに(5/2)
https://japan.zdnet.com/article/35186957/

ソラナ（SOL）ブロックチェーンが一時クラッシュした背景、7時間にわたりネットワーク停止(5/2)
https://coinpost.jp/?p=346526

Google、検索での個人情報削除申請の適用範囲を拡大(5/2)
https://pc.watch.impress.co.jp/docs/news/1406973.html

シンガポール金融管理局、仮想通貨ライセンス承認プロセスを強化(5/2)
https://nextmoney.jp/?p=50078

日本のメタバース関連団体は「メタバース」をどう捉えているのか？各団体に問う(5/2)
https://www.moguravr.com/metaverse-related-organizations-questionnaire/

米ディズニー・ワールドで「不審なAirTagに追われた」家族。悪意あるAirTag使用から身を守る設定(5/2)
https://gunosy.com/articles/eQWyu

「MDM」で業務用の端末を管理(5/3)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/092100119/042100008/
vite/vuejsでビルドしたアプリを相対パスで利用できるようにする

vite/vuejsでビルドしたアプリはルートパス(https://\<domain\>/)でしか利用できないため、これを任意のパス(https://\<domain\>/\<path\>/)で利用できるようにしたいです。

以下の二つの設定を行うことで実現できます。

* `package.json`と同じフォルダに`vue.config.js`を作成し以下の内容を記述します  
```
module.exports = {
    publicPath: './'
}
```

* `vite.config.ts`を編集し`base: "./"`を追記します(以下は例です)
```
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base: "./"
})
```

上記を実施してビルドを行うと、`dist`フォルダに生成された`index.html`のパスが以下のように相対パスになっていることが分かります(favicon.ico、javascript、cssのURLが相対になっています)。
```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <link rel="icon" href="./favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Vite App</title>
  <script type="module" crossorigin src="./assets/index.7e76e188.js"></script>
  <link rel="stylesheet" href="./assets/index.752813db.css">
</head>
<body>
  <div id="app"></div>
</body>
</html>
```
Laravel　サービスへの切り離しについて

# サービスへの切り離し→重複を防ぎ、ファットコントローラを防ぐ

## 関数みたいにして、処理を別のファイルから読み込むイメージ
Reactとかやってる場合はコンポーネントと考えが似てるかも。。。

## とりあえずやってみる
### 今回は、ファイルアップロード機能をいろんなところで使いたいのでそれを切り離す

1. app直下に「Services」フォルダを作成　　（大抵の場合フォルダ名を「Services」にするといい）
1. 今回の場合は「ImageService.php」ファイルを作成　（App\Services\ImageService.php）
1. 渡す引数（今回は、$imageFile,$folderName）に注意しながらコードを持ってくる
```php
<?php
namespace App\Services;
use Illuminate\Support\Facades\Storage;
use InterventionImage;

class ImageService
{
  public static function upload($imageFile,$folderName){

    $fileName = uniqid(rand().'_');
    $extension = $imageFile->extension();
    $fileNameToStore = $fileName. '.' . $extension;
    $resizedImage = InterventionImage::make($imageFile)->resize(1920, 1080)->encode();

    Storage::put('public/' . $folderName . '/' . $fileNameToStore, $resizedImage );

    return $fileNameToStore;
  }

}
```
4.読み込む

```php
 use App\Services\ImageService;//これがないと使えない


 public function update(UploadImageRequest $request, $id){
        $imageFile = $request->image; //PC側に一時保存 
        if(!is_null($imageFile) && $imageFile->isValid() ){
            $fileNameToStore = ImageService::upload($imageFile, 'shops');//ここで読み込み
        }
        return redirect()->route('owner.shops.index');
    }
```
powershellでワンライナーのコマンドを書く方法

## 環境

Windows 10

## 方法

powershellではコマンド間の区切り文字として`;`を使うだけでワンライナーが書けます。

## 例

例えば、「カレントディレクトリから親ディレクトリに移動して、ディレクトリ内のフォルダ/ファイルを表示する」には、下記のコマンドを実行します。

`cd ../ ; dir ;`

## あとがき

私は、ちょっとした時間のかかる処理などに対して、作業予約をする感覚でコマンドを複数まとめて入力して使ったりしています。
コンパイラ言語という言い方がしっくりこないので調べてみた

# 経緯

C言語やJavaなどのコンパイルを経て動くタイプのプログラミング言語の総称。

これをどう呼ぶだろうか。
私はコンパイル言語と呼んでいた。
人によってはコンパイラ言語と呼ぶ人もいる。

**[結論はこちら](#結論)**

「コンパイラー」「コンパイラ」のような感じなら発音の違いかと言ってもいいが、
「コンパイル」と「コンパイラ」だと動詞と名詞だし意味も異なってくるのではないか。

実際のところどちらが正しいの？
ふと思い立ってググってみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/48169499-4845-64bd-a418-f372c92789ff.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/57cc0f00-90eb-c570-f7a0-2599851f5733.png)
検索件数だと「コンパイル言語」が多そうに見えるが、
検索結果の2ページ分ぐらいのタイトルをザっと見た感じだと「コンパイラ言語」という表現が多そうに見える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/7dcc924f-e55d-5591-38ee-c8efbd6a960a.png)

### wikipediaさんの見解

なるほど、納得だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/41de0d7e-bbb6-15c6-86b8-206950e30d8f.png)
（引用 wikipedia）

### 結局英語だしどうなの？

めっちゃ納得だ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224453/261d41d5-a371-bfc2-d694-6e68fe01eeee.png)
（引用 wikipedia）

# 結論

「コンパイル言語」でも「コンパイラ言語」でもなかった。
コンパイルするタイプの言語、つまり「コンパイル型言語」。

言葉を整理してみる。

|単語|意味|
|---|---|
|コンパイル compile|機械語に翻訳する（動詞）※私を含めみながコンパイルするという不思議な言葉を使っている|
|コンパイラ compiler|ソースコードなどを機械語や元のプログラムより低水準コードに変換するプログラム|
|コンパイル型言語 compiled language|コンパイルするタイプのプログラム言語|
|インタプリト interpret|解釈する（動詞）※インタプリトするとはあまり聞かない（使う場面があまりないのだろう）|
|インタプリタ interpreter|ソースコードを解釈しながら実行するプログラム|
|インタプリタ型言語 interpreted language|インタプリタで実行するタイプのプログラム言語|

# おまけ

コンパイル型なのかインタプリタ型なのかは、その言語の標準的な実装がどちらなのかを意味するもの。
どちらの方法でも実行可能な言語がほとんどで、言語によっては組合せて使っていたりする。

また、スクリプト言語は簡易的な言語記述の種類を指しているそうだが、厳密な定義はないらしい。

スクリプト言語の代表例のJavascript、Ruby、Pythonはとても簡易的とは思えないのだが。。
JavaScriptは自分でスクリプトと名乗っているけど、RubyやPythonはスクリプト言語とは呼べない気もする。
aws-lc のビルドのメモ

## 背景

Linux, macOS, Windows で HTTP/3 な C/C++ アプリを自作したい...
QUIC, TLS 含めソースからビルドでモノリシックなアプリ作りたい...
cmake でビルドしたい...

TLS で libcrypto(通常 OpenSSL)が必要だけど, OpenSSL は cmake 対応しておらず perl や nasm が必要でビルドめんどくさすぎ...
(prebuild という手もあるけどやっぱり一式ソースからビルドしたいよね)

aws-lc を使ってみましょう!

https://github.com/awslabs/aws-lc/

s2n-tls で libcrypto backend として使えます. https://github.com/aws/s2n-tls

## ビルド

aws-lc, BoringSSL と OpenSSL をベースにしているとあります.
cmake が用意されています! :pray:

しかも! ビルドオプション設定すれば Perl, (N)ASM, Go なしでビルドできます!

https://github.com/awslabs/aws-lc/blob/main/CMakeLists.txt

cmake ブートストラップオプションに `-DDISABLE_PERL=On -DDISABLE_GO=On DOPENSSL_NO_ASM=1` すればいけます!

(perl は git をインストールしていれば(Windows だと git for Windows)入っているけどね)

Visual Studio でビルドするならこんな感じです!

```
$ mkdir build
$ cd build
$ cmake.exe -G "Visual Studio 17 2022" -A x64 -DDISABLE_PERL=On -DDISABLE_GO=On -DOPENSSL_NO_ASM=On ..
```

Happy HTTP/3 app development!

## TODO

* [ ] picotls + mini
* [ ] Botan に TLS 1.3 対応されたら Botan ためしてみる: https://github.com/randombit/botan/issues/2714
Laravel7のAuthenticatesUsersの場所

# 概要
Laravel7においては `php artisan ui vue --auth`コマンドを実行すると、認証機能のスカフォールドが作成される。

その作成されるファイルの一つに`LoginController.php`というファイルがあり、そのファイルにおいて、`AuthenticatesUsers`というトレイトをuseしているのだが、ファイル元がなくなっていたので調べてみた。

ファイル元とは下記の`Illuminate\Foundation\Auth\AuthenticatesUsers`のこと。
```LoginController.php
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;
```

## 結論
Laravel7以降、該当のファイルはLaravelのコアではなく、uiパッケージとして提供されているとのこと。

下記の`autoload_classmap`にて参照場所が定義されている。


```vendor/composer/autoload_classmap.php
    'Illuminate\\Foundation\\Auth\\AuthenticatesUsers' => $vendorDir . '/laravel/ui/auth-backend/AuthenticatesUsers.php',

```

これから、`AuthenticatesUsers`を確認したい方は、`/laravel/ui/auth-backend/AuthenticatesUsers.php`を確認してみてください。

## 参考
下記でLaravelの開発者が言及している。

https://github.com/laravel/framework/commit/aebd93d5f67de55473f3f0ff5056abbfc5972102
Mac の ｢オーディオ再生｣を判定する or 検知する (OSコマンド)

# ご紹介するトピック
macOS の OSコマンドで、以下2点を行うコマンドの使い方です。 
1. Macでオーディオ出力中を判定する 
1. Macでオーディオ再生の 「開始」 / 「停止」 を監視する

ほとんどのMacBookユーザーが検討するであろう Amphetamine を使用していますが、細かいところで満足できなくなり、蓋を閉じた時の挙動を制御することを検討中です。 MacBookの蓋を閉じた時、音楽などを再生中ならスリープせず、再生が終わればスリープする。そんな事をしたくて調べています。

# 環境
- MacBook Pro 2019
- macOS Monterey 12.2.1

# 1. Macでオーディオ出力中を判定する 
```sample.sh
#!/bin/bash
pmset -g | grep -e "sleep" | grep -e "coreaudiod"
# 行が見つかればオーディオ再生中
```
### 説明
- 現時点で オーディオ出力しているか否か を判定します。
- pmset コマンドは、macOSの電源管理設定コマンド。 
- -g オプションで現在の電源関連の設定値を出力します。
- コマンド出力に「スリープ」に関する設定が含まれており、スリープ防止プロセスの名前が付記されています。
- スリープ防止プロセスに「coreaudiod」が含まれていると、「出力中」という事になります。
- オーディオ出力を止めれば、上記から「coreaudiod」は消えます。
※ スリープ防止と言っても、MacBookの蓋を閉じた時のスリープには効きません。

### 補足
- 判定できるオーディオ出力の音源は何でも良さそうです。 音を出していれば。
ミュージック.appでの音楽再生、ブラウザでの動画再生、他の機器(iPhone等)からAirPlay経由で受信した音源の再生など判定できました。
- オーディオの出力先も何でも良さそうです。本体のスピーカー、Bluetoothスピーカー、AirPlayの再生先でも判定できました。

### その他
- オーディオ出力をミュートした場合は 「出力していない」 扱いになります。 (個人的にはその方が良い)
- 再生は即時反映されますが、出力停止の反映は、数秒かかります。
 
# 2. Macでオーディオ再生の 「開始」 / 「停止」 を監視
```sample.sh
log stream --style compact \
| grep --line-buffered -e "CoreAudio" \
| grep --line-buffered -e "::StartIO" -e "::StopIO"
```
### 説明
- 音を出すプロセスからの 出力開始 / 出力停止 リクエストを拾うコマンド使用法です。
- log stream は、macOS の システムログを tail -f のように、待ち受け表示します。
- システムログには、coreaudiod のイベントが頻繁に書き込まれています。
- その中にオーディオ出力の 「開始」 / 「停止」 のイベントが含まれており、それを拾います。
- grep は、抽出結果をバッファリングするので --line-buffered をつけます。

### 注意点
- 厳密には、coreaudiod が、音を出すプロセスからの StartIO / StopIO リクエストを受け付けた/処理したイベントを拾っているだけ、オーディオ出力の有無を総合的に判断できるわけではありません。
- OSの通知音(ポーン等)でも StartIO / StopIO が発生します。
- 音楽の再生などでは、曲と曲の切れ目でも StopIO / StartIO が発生します。
- つまり、音楽再生など、イメージしているオーディオ出力以外にも、時報読み上げ、通知音、何かの警告音など、細かいことに反応する事が想定されます。
- ちょっと敏感で使えないかも。


近いうちに、活用編を投稿したいものです。。。
[Python]Seleniumでスマホ表示をエミュレートする

# 概要
Seleniumにおいて、モバイル端末の表示をエミュレートするための方法のメモです。
[Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/)（CDP）の機能を使って、画面サイズとユーザエージェントの変更を行います。実機の完全な再現とはなりませんが、おおよその表示の目安にはなると思います。

## 環境
- Windows 10
- Python 3.10.4
- Selenium 4.1.3
- Chrome 101.0.4951.41

# コード
```python:emulate-mobile.py
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os
import time

with webdriver.Chrome(service=Service(ChromeDriverManager().install())) as driver:
    # iPhone 13用のパラメータ
    viewport = {
        "width": 390,
        "height": 844,
        "deviceScaleFactor": 3,
        "mobile": True
    }
    ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1"
    # デバイスのスクリーンサイズの設定
    driver.execute_cdp_cmd("Emulation.setDeviceMetricsOverride", viewport)
    # ユーザエージェントの変更
    driver.execute_cdp_cmd("Emulation.setUserAgentOverride", {"userAgent": ua})
    # 気象庁トップページにアクセス
    driver.get('https://www.jma.go.jp/jma/index.html')
    time.sleep(5)
    # スクリーンショットを取得し保存
    filename = os.path.join(os.path.dirname(os.path.abspath(__file__)),
            "screenshot_mobile.png")
    driver.save_screenshot(filename)
```

- [webdriver-manager](https://github.com/SergeyPirogov/webdriver_manager)を使って、最新のWebDriverをインストールします。
- CDPの[Emulation.setDeviceMetricsOverride](https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setDeviceMetricsOverride)で、スクリーンサイズの設定を行います。
- 個別のデバイス向けのパラメータは、Puppeteerの[DeviceDescriptors.ts](https://github.com/puppeteer/puppeteer/blob/main/src/common/DeviceDescriptors.ts)から拝借しました。
- [Emulation.setUserAgentOverride](https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-setUserAgentOverride)を使って、ユーザエージェントの変更をしています。

# 表示例
[気象庁](https://www.jma.go.jp/jma/index.html)のページに「iPhone 13」と「iPad Pro11」のエミュレート設定でアクセスした際の表示例です。

## iPhone 13
![screenshot_mobile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1423540/1358a544-7417-bc30-67b7-7ad400880360.png)


```python:パラメータ
viewport = {
    "width": 390,
    "height": 844,
    "deviceScaleFactor": 3,
    "mobile": True
}
ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1"
```

## iPad Pro 11
![screenshot_mobile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1423540/a2df9525-1508-2d85-49b9-a1747535916a.png)

```python:パラメータ
viewport = {
    "width": 834,
    "height": 1194,
    "deviceScaleFactor": 2,
    "mobile": True
}
ua = "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Mobile/15E148 Safari/604.1"
```

# 参考
本記事の作成にあたり、以下を参考にさせていただきました。

https://note.com/shift_tech/n/naa242e11ebaa

https://chromedevtools.github.io/devtools-protocol/tot/Emulation/

https://www.selenium.dev/documentation/webdriver/bidirectional/chrome_devtools/
シェルスクリプトで変数が数値かどうか判定する

シェルスクリプトで変数が数値かどうか判定する際の備忘録です
※N番煎じですみません

[こちら](https://rcmdnk.com/blog/2018/09/05/computer-bash-zsh/#expr-x--1)を参考にさせて頂いたところいくつか方法があるようだが、以下の[expr](http://itdoc.hitachi.co.jp/manuals/3020/30203S3530/JPAS0248.HTM
)を使う方法がシンプルであり保守性が高そうだったため使用した。ただ実行速度は比較的遅いようなので、、速度が求められる処理は正規表現で書いたほうがいいかもしれない。

```sh:test.sh
NUMBER=1
NUMBER=`expr $NUMBER + 1`
RET=$?
if [ $RET -ge 2 ];then
    # if not a number
    # expr return code is 2 or greater then 2
    NUMBER=1
fi
echo $NUMBER
```

```sh
$ bash test.sh
2
```

# 参考

http://itdoc.hitachi.co.jp/manuals/3020/30203S3530/JPAS0248.HTM

https://rcmdnk.com/blog/2018/09/05/computer-bash-zsh/#expr-x--1