OmniAICreator/Qiita-1.07M huggingface dataset:
【投稿記事一覧】

# はじめに
随時更新していきます。

## 言語
<!-- ＝＝＝＝＝＝＝＝＝HTML＝＝＝＝＝＝＝＝＝　-->
### HTML
| 投稿日| タイトル |
|:-:|:-:|


<!-- ＝＝＝＝＝＝＝＝＝CSS＝＝＝＝＝＝＝＝＝　-->
### CSS
| 投稿日| タイトル |
|:-:|:-:|
|2022年07月24日| [BEMについて](https://qiita.com/Rice_Cooker/items/5dfd14cb7fb1577fb59a)  |
|2022年07月24日| [OOCSSについて](https://qiita.com/Rice_Cooker/items/334ec5341fe2bd224a1d)  |





<!-- ＝＝＝＝＝＝＝＝＝JavaScript＝＝＝＝＝＝＝＝＝　-->
### JavaScript
| 投稿日| タイトル |
|:-:|:-:|


## テンプレートエンジン

<!-- ＝＝＝＝＝＝＝＝＝Pug＝＝＝＝＝＝＝＝＝　-->
### Pug
| 投稿日| タイトル |
|:-:|:-:|
|2022年08月6日| [distフォルダの生成場所を変更したい](https://qiita.com/NonGlutinousRice/items/339b97df5929076d6aa4)  |

## 書き方

<!-- ＝＝＝＝＝＝＝＝＝Emmet＝＝＝＝＝＝＝＝＝　-->
### Emmet
| 投稿日| タイトル |
|:-:|:-:|
|2022年07月24日| [コメントを出力する（VScode）](https://qiita.com/Rice_Cooker/items/d5639938edb3d74e7ee7)  |

<!-- ＝＝＝＝＝＝＝＝＝Markdown＝＝＝＝＝＝＝＝＝　-->
### Markdown
| 投稿日| タイトル |
|:-:|:-:|
| 2022年07月22日  | [画像サイズの変更](https://qiita.com/Rice_Cooker/items/d9723eb4a9697274c0b3)  |

## 模写

<!-- ＝＝＝＝＝＝＝＝＝模写＝＝＝＝＝＝＝＝＝　-->
| 投稿日| タイトル |
|:-:|:-:|
|2022年07月13日| [ループするスライドショーをJavaScriptのみで実装した](https://qiita.com/Rice_Cooker/items/6f814ddcfa1ad54dedc3)  |
| 2022年06月28日  | [スターバックスのHPを模写する](https://qiita.com/Rice_Cooker/items/a44f08544eb8c7e7967d)  |
|2022年06月25日| [縦のヘッダーを制作する](https://qiita.com/Rice_Cooker/items/363d3a4c4bda929e9109)  |
|2022年06月24日| [お知らせ一覧のようなリンク集を制作する](https://qiita.com/Rice_Cooker/items/81293a61c0376985584b)  |
|2022年06月21日| [グリッドレイアウトで2列の記事集を制作する](https://qiita.com/Rice_Cooker/items/1c7870f5d0e4838d35a0)  |

## OS
<!-- ＝＝＝＝＝＝＝＝＝Linux＝＝＝＝＝＝＝＝＝　-->
### Linux
| 投稿日| タイトル |
|:-:|:-:|
| 2022年01月09日  | [ファイル操作](https://qiita.com/Rice_Cooker/items/c6c7d9d52da2c195e668)  |


## ツール
<!-- ＝＝＝＝＝＝＝＝＝VScode＝＝＝＝＝＝＝＝＝　-->
### VScode
| 投稿日| タイトル |
|:-:|:-:|
|2022年01月10日| [Draw.io](https://qiita.com/Rice_Cooker/items/09fa60cc9805002ba015)  |
| 2022年01月09日  | [マインドマップ](https://qiita.com/Rice_Cooker/items/7d47001d41a6e0b3f820)  |


<!-- ＝＝＝＝＝＝＝＝＝＝＝Git＝＝＝＝＝＝＝＝＝＝＝　-->
### Git
| 投稿日| タイトル |
|:-:|:-:|
|   | [タイトル](#)  |


<!-- ＝＝＝＝＝Google Chromeデベロッパーツール＝＝＝＝＝　-->
### Google Chromeデベロッパーツール
| 投稿日| タイトル |
|:-:|:-:|
| 2022年07月22日  | [HTMLとCSSのパネルを縦に配置する](https://qiita.com/Rice_Cooker/items/3ec0fec6834aebebd978)  |

## 共通
<!-- ＝＝＝＝＝＝＝＝＝技術書＝＝＝＝＝＝＝＝＝　-->
### 技術書
| 投稿日| タイトル |
|:-:|:-:|
| 2022年07月23日  | [自分用_読んだ技術書を簡単にまとめていくための記事](https://qiita.com/Rice_Cooker/items/da876be553b02796b4f7)  |

<!-- ＝＝＝＝＝＝＝＝＝資格 ＝＝＝＝＝＝＝＝＝　-->
### 資格
| 投稿日| タイトル |
|:-:|:-:|
| 2022年01月09日  | [組込みエンジニアの資格一覧](https://qiita.com/Rice_Cooker/items/27ec0a3902d0d4c16ae8)  |




<!-- ＝＝＝＝＝＝＝＝＝タイトル ＝＝＝＝＝＝＝＝＝　-->
<!-- コピペ用

### タイトル 
| 投稿日| タイトル |
|:-:|:-:|
|   | [タイトル](#)  |
|   | [タイトル](#)  |
|   | [タイトル](#)  |
|   | [タイトル](#)  |
|   | [タイトル](#)  |
-->
未経験インフラエンジニア約１か月！

＃＃ざっくり経歴
学歴は高卒。（大学中退）
今までは、飲食業や塾講師などのアルバイト、フリーターをしていました。


そろそろ仕事につかないとと思いIT業界に入ることを決め、AWSで２つの資格を取ってから就活を始めました。将来的にはAWSを使ったクラウド環境で食っていきたいと考えています。

そんななか人材派遣会社でインフラエンジニアからキャリアがスタートしました。

##入社約１か月

まずは１か月CCNA取得に向けて学習し始めました。
cisco、ハブなにそれ状態から始まり、約２週間でテキスト１週目終了。
その後はping tのサイトでひたすら演習問題を解いてはやり直しを繰り返しています。

営業の人とも面談が終わり、クラウドよりの案件や少しでもたくさん手を動かせる案件がいいなぁなんて思いながらすごす日々。
ちなみに、勤務所間はAM10:100～PM19:00　通勤時間1,2h程度

少しでも早くインフラまわりのことが知りたいので、19時まで勉強して21時まで１人で残って勉強してます。同時にITパスポートも勉強中なので欲張りすぎたかも...

初めてこんなに文書いてるけど、思ってることきれいに書けないし、うまくまとまらない
でもインプットだけでなくアウトプットもしていきたいと思ったので書いてます。

趣味程度でこれから勉強してることとか、書きたいと思ったこと書いていこ。
【Python】CPU使用率10%未満になるとGmailで報告

はじめまして、ガンちゃんです。
こちらは、前回記事の続きです。
https://qiita.com/mugiGAN/items/1985e6b3eb4576569f35
本記事は、”CPU使用率10%未満になると、Gmailで知らせてくれる”という記事です。
お読みいただければ幸いです。

## 概要
本プログラムでは、CPU使用率10%未満になるとGmailで知らせてくれます。
前回はアラームだったので、外出中の場合終了したことが分かりません。
そこで、メールで報告してくれるようにしました。

## Pythonを用いたGmail送信方法
```cpu_email.py
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate

smtpobj = smtplib.SMTP('smtp.gmail.com', 587)

smtpobj.ehlo()

smtpobj.starttls()
smtpobj.ehlo()
smtpobj.login("メールアドレス@gmail.com", "パスワード")

mail_from = "メールアドレス@gmail.com"
mail_to = "メールアドレス@gmail.com"

text = "CPU使用率が10%未満となりました。\n経過時間は、" + str(end_time) + "[sec]です。\n"

msg = MIMEText(text)
msg['Subject'] = "CPU使用率10%未満の連絡"
msg['From'] = mail_from
msg['To'] = mail_to
msg['Date'] = formatdate(localtime=True)
```
下記のリンクを参考にしました。
【Python】メール（Gmail）を送信する方法を解説：
　https://www.learning-nao.com/?p=1765

## プログラム全体
プログラムの全体は、下記になります。
処理内容として、
毎５秒ずつCPU使用率を取得し、10％未満になるまで行っていきます。
10％未満になると、まずコマンド上で経過時間と終了時CPU使用率を出力します。
最後に、GmailでCPU使用率10％未満と経過時間を報告し、プログラム終了です。

```cpu_email.py
import psutil
import time
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate

start = time.time()

while True:
    time.sleep(5)
    cpu = psutil.cpu_percent(interval=1)
    print('cpu:', cpu)
    if cpu < 10:
        break

print('Finesh:')

end_time = time.time() - start
print('Time ', end_time)
print('CPU[%] ', cpu)


smtpobj = smtplib.SMTP('smtp.gmail.com', 587)

smtpobj.ehlo()

smtpobj.starttls()
smtpobj.ehlo()
smtpobj.login("メールアドレス@gmail.com", "パスワード")

mail_from = "メールアドレス@gmail.com"
mail_to = "メールアドレス@gmail.com"

text = "CPU使用率が10%未満となりました。\n経過時間は、" + str(end_time) + "[sec]です。\n"

msg = MIMEText(text)
msg['Subject'] = "CPU使用率10%未満の連絡"
msg['From'] = mail_from
msg['To'] = mail_to
msg['Date'] = formatdate(localtime=True)

smtpobj.sendmail(mail_from, mail_to, msg.as_string())

```
Gmailに下図のようなメールが届きます。
![email_report.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1893155/8813a26b-4fc1-bf4c-0222-bf9e4aa14e4a.png)


## 最後に
PythonでGmailを送信するにあたり、Googlアカウントの設定が必要でした。
下記に参考にしたサイトを記載いたしました。

Pythonでメール(gmail)を送信できない場合の解決法
https://www.gocca.work/python-mailerror/
Googleアカウントの2段階認証を有効にする
https://www.howtonote.jp/google-account/2step-verify/index1.html

#### （修正）
Pythonでプログラミングを書いている場合、CPU使用率を見ずとも処理終了時にGmailで通知すればいいです。
上記のCPU使用率を取得している処理を消し、その部分に自身が行いたい処理を追加すれば実現可能だと思います。
SvelteのChrome拡張devtoolが動かないときの対処法

## 環境

### パッケージ
- "@sveltejs/vite-plugin-svelte": "1.0.0-next.30"
- "svelte": "3.44.0"
- "vite": "2.9.7"

### Chromeのバージョン
- Google Chrome: "102.0.5005.115（Official Build） （64 ビット）"

___
## 起こったこと
Chrome拡張の[Svelte Devtools](https://chrome.google.com/webstore/detail/svelte-devtools/ckolcbmkjpjmangdbmnkpjigpkddpogn)が上記の環境で動きませんでした。

正確に言うと動いてはいるのですが、

>To connect to  Svelte  perform a hard refresh (ctrl+F5) or click here .

というメッセージが出ました。
リロードしてもコンポーネントの情報は表示されません。

Firefoxの拡張は確認したところ動いていたので、一番早い対処法はFirefoxで確認することです。
わざわざメインで使用するブラウザを変更するのも気が引けたので、何か方法はないか調べてみました。

## 対処法

### Chrome拡張のアンインストール
まずChrome拡張をアンインストールします。

chrome://extensions/にアクセスすると「Svelte Devtools」があると思うので削除します。

### 拡張をgitからcloneする
[https://github.com/RedHatter/svelte-devtools#chrome](https://github.com/RedHatter/svelte-devtools#chrome)

僕は特にこだわりがなかったので C:\Users\ユーザー名 で

```sh
git clone https://github.com/RedHatter/svelte-devtools.git
cd svelte-devtools
npm install
```

こちらを実行しました。

### 記述を一部書き換える
先ほどの操作でsvelte-devtoolsディレクトリに移動しているはずです。

srcディレクトリにbackground.jsがあるのでエディタで開きます。
4行目に以下のコードがあるので、こちらを

```js
if (port.sender.url == chrome.runtime.getURL('/devtools/panel.html')) {
```

こちらに書き換えます。

```js
if (port.sender.url.replace('//devtools', '/devtools') == chrome.runtime.getURL('/devtools/panel.html')) {
```


その後

```sh
npm run package:chrome
```

を実行してビルドします。
こちらを参考にしました。
[https://github.com/RedHatter/svelte-devtools/pull/70/commits/7edf051cf204e4c9d7b780681aa07cb73e4c3d77](https://github.com/RedHatter/svelte-devtools/pull/70/commits/7edf051cf204e4c9d7b780681aa07cb73e4c3d77)

2022/06/29時点ではまだマスターにマージされていないようです。（拡張自体しばらく更新されていないような…）
これであとはこの拡張をChromeに読み込ませるだけです。

### Chrome拡張として読み込ませる
chrome://extensions/に戻ります。

パッケージ化されていない拡張機能を読み込む というボタンがあるので、それをクリックします。
どのディレクトリを見るのか聞かれるので、さっきビルドで作成されたdestディレクトリを選択します。

\svelte-devtools\dest ですね。
エラーが出ていますが無視しても動きます。

これで検証ツールにSvelteコンポーネントを周りの表示がされるようになりました。

すでに開発サーバーを立ち上げたりブラウザで開いたりしている人は一旦終了させてサイド開いてから、`ctrl+F5`を押すと表示されると思います。

ちょっと画面が見づらいなと思いますが、ないとかなりしんどいので使えるだけでかなりありがたいです。感謝ですね。
Nuxt3で$fetchのレスポンスに型をつけるには

Nuxt3だとaxiosではなく$fetchやuseFetchの利用が推奨されているみたいです。
その使い方の備忘録として。
2022/06/28時点での情報です。もっといい方法あるよって方はコメントまで！
## 作るもの
あらかじめ郵便番号を指定してその都道府県を返すだけのもの。

http://zipcloud.ibsnet.co.jp/doc/api
## ディレクトリ構造
必要なものだけピックアップしてます。
```
.
├── app.vue
├── interface
│   └── address.ts
└── server
    └── api
        └── getAddress.ts

```

## interface
zipcloudにレスポンスフィールドが記載されてるのでその通りのinterfaceを用意します。
```ts:interface/address.ts
export interface Address {
  message: string,
  results: AddressDetail[],
  status: number
}
export interface AddressDetail {
  address1: string,
  address2: string,
  address3: string,
  kana1: string,
  kana2: string,
  kana3: string,
  prefcode: string,
  zipcode: string
}
```

## server
serverの詳しい説明は公式ドキュメントにて

https://v3.nuxtjs.org/guide/features/server-routes

```ts:server/api/getAddress.ts
import { Address } from "~~/interface/address"

export default defineEventHandler(async(event) => {
  const response = await $fetch<string>('/api/search',{
    baseURL: "https://zipcloud.ibsnet.co.jp",
    params: {zipcode:1000000}
  })
  const result = JSON.parse(response) as Address

  return {result}
})
```
レスポンスの型にAddressを指定するとVSCode上ではAddressで取得出来てそうなんですが、実行後に型を確認するとstringになってしまい苦戦。
解決策としてここでは$fetchのレスポンスをstringで受け取って、JSON.parseでキャストしてます。

## page
ページ側は表示させるだけです。
```vuejs:app.vue
<template>
  <div>
    <p>{{api.result.results[0].address1}}</p>
  </div>
</template>

<script setup lang="ts">
const {data:api} = await useFetch('/api/getAddress')
</script>
```

## 実行
ちゃんと型がついた状態で取れてますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54771/fd66a543-922b-7ffd-22ac-1953b77dac06.png)
photon fusion 実装入門(マルチプレイヤー)@Mac

基本的に、[fusion-101](https://doc.photonengine.com/ja-jp/fusion/current/fusion-100/fusion-101)を見て、初期セットアップを行ったが、実装中に「あれ、何これ？！」のところをこの記事で記載します。

うまく動作できた環境は下記の通りです。(下記のバージョンではないと、うまく動作できない場合があリます。)
・unityバージョン：2021.2.6f1
・Mono.Cecil：com.unity.nuget.mono-cecil@1.10.2
・SDKバージョン： [Fusion SDK 1.1.2 Nightly Build 522](https://doc.photonengine.com/en-us/fusion/current/getting-started/sdk-download)
・MacOS： Platfrom settings ：Apple SiliconからAnyCPUに変更。(Asserts/Photon/Fusion/Plugins/NanoSockets/macOS/AppleSilicon/libnanosockets.cs を開く。変更しないと、実行中に下記のエラーが出ていました。)
```
On M1 mac, Fusion always fails with: DllNotFoundException: nanosockets assembly<unknown>
```

Fusion Hub Welcomeタブというのは、↓です。
Fusion > Fusion Hub
![スクリーンショット 2022-06-28 23.14.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/c10afe7c-6191-8c18-e919-5107971dae45.png)
Fusion Hubを押すと、Weclome to Photon Fusion画面が出た。Fusion SetupでFusion App IDを記入します。
![スクリーンショット 2022-06-28 23.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/ddb4fa63-fe4a-a2cc-e6b1-f3e4ac31c539.png)

次は、[fusion-102](https://doc.photonengine.com/ja-jp/fusion/current/fusion-100/fusion-102)ですが、一旦、これを無視して、下記の方法で実装してみました。
Hieraichy で右クリップ、
fusion >Setup Basic fusion Scene で簡単なfusionシーンが自動的に作成されました。

![スクリーンショット 2022-06-28 14.40.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/31e0fc48-ac71-2618-b3f4-2136c3221eaf.png)

Prototype Floor
![スクリーンショット 2022-06-28 23.21.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/f8d4a686-28d0-3ba1-4f2c-b2cb84ed8a8d.png)

Prototype Network Start
![スクリーンショット 2022-06-28 23.21.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/8111aa61-a782-701f-0317-e2ee0d3c7b42.png)

Prototype Runner
![スクリーンショット 2022-06-28 23.21.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/33cf748e-f98e-b934-41d2-fc8aba7d2097.png)

Player1：File >Build Runでビルドして、起動します。(start host)
Player2：UnityでのPlayで起動します。(start client)
![スクリーンショット 2022-06-28 23.34.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/1b70ab91-a0d2-518b-ed73-6b566179ba50.png)

下記のように、二人はそれぞれWASDキーで操作できれば、OKです。
![スクリーンショット 2022-06-28 14.32.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181748/98ded2d5-421a-2ea2-da73-d2c8ceeda329.png)



参考： 
１、[fusion-102](https://doc.photonengine.com/ja-jp/fusion/current/fusion-100/fusion-102)
２、[PhotonFusionセットアップ備忘録](https://qiita.com/TakaoIto/items/86716dfaf68273f269c3)
【Next.js】useSWRのテスト【Jest】

## useSWRのテスト
``` _test_/TaskPageSWR.test.tsx
import '@testing-library/jest-dom/extend-expect'
import { render, screen, cleanup } from '@testing-library/react'
import { SWRConfig } from 'swr'
import { rest } from 'msw'
import { setupServer } from 'msw/node'
import TaskPage from '../pages/task-page'
import { TASK } from '../types/Types'
import 'setimmediate'

const server = setupServer(
  rest.get('https://jsonplaceholder.typicode.com/todos/', (req, res, ctx) => {
    const query = req.url.searchParams
    const _limit = query.get('_limit')
    if (_limit === '10') {
      return res(
        ctx.status(200),
        ctx.json([
          {
            userId: 1,
            id: 1,
            title: 'Task A',
            completed: false,
          },
          {
            userId: 1,
            id: 2,
            title: 'Task B',
            completed: true,
          },
        ])
      )
    }
  })
)
beforeAll(() => {
  server.listen()
})
afterEach(() => {
  server.resetHandlers()
  cleanup()
})
afterAll(() => {
  server.close()
})
describe(`Todos page / useSWR`, () => {
  let staticProps: TASK[]
  staticProps = [
    {
      userId: 3,
      id: 3,
      title: 'Static task C',
      completed: true,
    },
    {
      userId: 4,
      id: 4,
      title: 'Static task D',
      completed: false,
    },
  ]
  it('Should render CSF data after pre-rendered data', async () => {
    render(
      <SWRConfig value={{ dedupingInterval: 0 }}>
        <TaskPage staticTasks={staticProps} />
      </SWRConfig>
    )
    expect(await screen.findByText('Static task C')).toBeInTheDocument()
    expect(screen.getByText('Static task D')).toBeInTheDocument()
    //screen.debug()
    expect(await screen.findByText('Task A')).toBeInTheDocument()
    expect(screen.getByText('Task B')).toBeInTheDocument()
    //screen.debug()
  })
  it('Should render Error text when fetch failed', async () => {
    server.use(
      rest.get(
        'https://jsonplaceholder.typicode.com/todos/',
        (req, res, ctx) => {
          const query = req.url.searchParams
          const _limit = query.get('_limit')
          if (_limit === '10') {
            return res(ctx.status(400))
          }
        }
      )
    )
    render(
      <SWRConfig value={{ dedupingInterval: 0 }}>
        <TaskPage staticTasks={staticProps} />
      </SWRConfig>
    )
    expect(await screen.findByText('Error!')).toBeInTheDocument()
  })
})
```
inline-blockの右側にゴミ文字が表示される（原因わからず）

表題の件、CSSで`font-family`に日本語のGoogle Fontsを指定したテキストを旧バージョンのiOSで表示した時に、特定のフォントのいくつかで発生することがわかり、原因がわからずお手上げだったので備忘録としてここに書きます。
現象はこのとおり。(iPhone X, iOS12.2, font-family: BIZ UDGothic）
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/8c34dabe-21bc-a14c-1ed4-cd43718d8ef9.png)
ここで、先頭の青い矩形はinline-blockで内容は空です。矩形の右側に現れているバツ印の四角がゴミ文字で、「情」という文字に被さっています。下側の例は「情」の前に全角スペースを入れたものです。全角スペースの位置にバツ印が出てしまってます。

```html:html
<p class="justify"><span class="ib"></span>情に棹させば流される。智に働けば角が立つ。</p>
```

```css:css
.justify {
  text-align: justify;
}
.ib {
  display: inline-block;
  width: 2em;
  height: 1em;
  outline: 1px solid blue;
}
```

2022年6月現在Google Fontsに登録されている日本語sans-serif, serifフォント44種類で試した結果、発生する条件や特徴がわかってきました。

1. テキストのブロックに`text-align: justify`が設定されている。
1. テキストの折り返しがある。
1. １文字目が漢字や全角スペースなどで発生。１文字目が「かな」「カナ」の場合は発生しない。
1. 発生するフォントは下記CodePen参照。なお、Noto Sansでは発生しなかった。
1. 発生を確認できたiOSのバージョンは、v12.2, 13.2。v14.2や15.2では発生しなかった。（他のバージョンはこちらの環境にないため未確認）
1. v12.2で発生していても13.2では発生しなくなったフォントもあった。
1. バツ印が表示されている箇所を含めてコピペしてデータを確認したが、バツ印部分に制御文字など無かった。
1. フォントによってはバツ印の幅が狭かったり、別の潰れた図形だったりする。
![iOS-issue_1920.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/3da27c36-cdd6-a1f4-d784-560addf20f08.png)

再現テストに使ったコードはこちら： https://codepen.io/kaz_hashimoto/pen/NWYKRdE

現象が発生したフォント名は、上記コードのjavascript内の配列にコメントで記入してあります。
Power BI workout - Copy-PowerBIReport

Power BI レポートをコピーする。ワークスペースを跨いだり、データセットを差し替えるようなこともなんとかなるはず。

# Power BI Cmdlets for Windows PowerShell and PowerShell Core
- [Power BI Cmdlets for Windows PowerShell and PowerShell Core | Docs](https://docs.microsoft.com/en-us/powershell/power-bi/overview)
## DEMO | Copy Power BI report
### Define
:::note warn
レポート名はワークスペース内でも重複して存在できる。
:::
```powershell
$WorkspaceName = "DEMO2"
$ReportName = "Report1"

$TargetWorkspaceName = "DEMO2"
$TargetDatasetName = "Dataset2"
```
### Login Power BI
- [Connect-PowerBIServiceAccount (MicrosoftPowerBIMgmt.Profile) | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.profile/connect-powerbiserviceaccount)
```powershell
Login-PowerBI | Out-Null
```
### Get Power BI workspace | Get Power BI report | Get Power BI dataset
- [Get-PowerBIWorkspace (MicrosoftPowerBIMgmt.Workspaces) | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.workspaces/get-powerbiworkspace)
- [Get-PowerBIReport (MicrosoftPowerBIMgmt.Reports) | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.reports/get-powerbireport)
- [Get-PowerBIDataset (MicrosoftPowerBIMgmt.Data) | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.data/get-powerbidataset)
```powershell
$Workspace = Get-PowerBIWorkspace -Name $WorkspaceName
$Report = Get-PowerBIReport -Name $ReportName -Workspace $Workspace
$TargetWorkspace = Get-PowerBIWorkspace -Name $TargetWorkspaceName
$TargetDataset = Get-PowerBIDataset -Workspace $Workspace |
    Where-Object Name -EQ $TargetDatasetName
```
### Copy Power BI report
- [Copy-PowerBIReport (MicrosoftPowerBIMgmt.Reports) | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.reports/copy-powerbireport)
#### Copy to My workspace
```powershell
Copy-PowerBIReport -Report $Report
```
```powershell
Copy-PowerBIReport -Name "Copy of $ReportName"  -ReportId $Report.Id
```
```powershell
Copy-PowerBIReport -Name "Copy of $ReportName"  -ReportId $Report.Id `
    -TargetDatasetId $Dataset.Id.Guid
```
#### Copy to workspace
```powershell
Copy-PowerBIReport -Report $Report -Workspace $Workspace
```
```powershell
Copy-PowerBIReport -Name "Copy of $ReportName" -ReportId $Report.Id `
    -Workspace $Workspace
```
```powershell
Copy-PowerBIReport -Name "Copy of $ReportName" -ReportId $Report.Id `
    -TargetDatasetId $TargetDataset.Id.Guid -TargetGroupId $TargetWorkspace.Id.Guid
```
### Logout Power BI
- [Disconnect-PowerBIServiceAccount (MicrosoftPowerBIMgmt.Profile) | Microsoft Docs](https://docs.microsoft.com/en-us/powershell/module/microsoftpowerbimgmt.profile/disconnect-powerbiserviceaccount)
```powershell
Logout-PowerBI
```

# 思ったこと🙄
Power BI コマンドレット で充分なので、Power BI REST API を使っていない。
# その他
https://powerbi.connpass.com/

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
React+mapでラジオボタン、丸を大きくした

React、mapでラジオボタンを実装したときのメモです。
・配列で選択肢を定義し、mapで回してレンダリング
・Typescript
・シニア向けのデザインだったのでラジオボタンの文字と丸を大きく
・今回はOKボタン押したときにアラートで選択したものを表示

```javascript
import { useState } from "react";
import "./Test3.css";

export const Test3 = () => {
  const data = [
    { id: 0, message: "選択肢１" },
    { id: 1, message: "選択肢２" },
    { id: 2, message: "選択肢３" },
  ];

  //選択肢１が初期値
  const [radioButtonNumber, setRadioButtonNumber] = useState<number>(0);

  const radioButtonChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
    console.log(e.target.value);
    setRadioButtonNumber(Number(e.target.value));
  };

  const buttonClicked = () => {
    alert(`${data[radioButtonNumber].message}`);
  };

  return (
    <>
      <div className="RadioButtonArea">
        {data.map((val) => (
          <label className="test3Label" key={val.id}>
            <input
              className="test3Input"
              type="radio"
              name="name1"
              value={val.id}
              checked={radioButtonNumber === val.id}
              onChange={radioButtonChanged}
            />
            {val.message}
          </label>
        ))}
      </div>
      <button className="test3Button" onClick={buttonClicked}>
        OK
      </button>
    </>
  );
};
```

シニア向けに文字を大きくしてもラジオボタンの丸は大きくならなかった。
![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/41093f33-fb69-19cc-a02d-9f0dbb2cdad3.jpeg)


inputのcssで丸を大きくすると、丸の位置がおかしくなった。
```javascript
input {
  transform: scale(2.5);
}
```
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/46230eff-af3c-a6a7-5001-c3200b9f5089.jpeg)


translateとmarginで位置を調整。
```javascript
input {
  transform: translate(0%, -35%) scale(2.5);
  margin-right: 1em;
}
```
![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/de18bacc-c61a-ebee-a1b1-b0651a1325b9.jpeg)
相関係数の標準誤差

# 相関係数の標準誤差

母集団から抽出された標本より統計量を得るとき、統計量の標準偏差を標準誤差という。

相関係数の標準誤差としては、相関係数の有意性の検定の文脈で、帰無仮説$\rho=0$のもとでの以下がよく紹介される。
```math 
SE_{\rho} = \sqrt{ 1-\rho^2 \over n-2 }　　　　　　(1)
```
これを確認するためにシミュレーションを行い標準誤差を計算すると、$\rho$が大きくなるに従い上式にはあわなくなる。上式は帰無仮説のもとでの標準誤差なので当然である。なおここでいうシミュレーションとは、乱数で複数セットの標本を用意しそれぞれについて相関係数を計算し標準誤差を計算することをいう。

そこで調べたところ一般には$\rho$の標準誤差は次式になるようである。
```math 
SE_{\rho} = {1-\rho^2 \over \sqrt{ n-2 }}　　　　　　(2)
```
これは以下の二つのwebサイトとその引用文献による。
[1] https://teramonagi.hatenablog.com/entry/20170928/1506611938
[2] https://stats.stackexchange.com/questions/226380/derivation-of-the-standard-error-for-pearsons-correlation-coefficient

シミュレーションすると不偏性はない。とくに標本サイズが小さいときにズレが大きい。このズレを小さくするために分母を$\sqrt{ n-3 }$にしたほうが、よいのではないかという議論もあった。一致性はあるようである。

# matlabによる検証

(2)式、シミュレーション、ブートストラップ法により標準誤差をmatlabで計算した例を下記に示す。標本サイズを100とし、シミュレーションでは100セットの標本を用いた。ブートストラップは標本サイズ100のデータを用い1000回のリサンプリングを行った(このあたりの数字は特に調整を行なっておらず意味がない)。

(2)式とシミュレーションの結果はよく一致するが、$\rho$が小さいときにズレが大きい傾向がある。この場合(1)式の方がシミュレーションによく一致する。

ブートストラップ法はただ100個のデータのみを用いてある程度標準誤差を評価できる。乱数生成したデータによりブートストラップの結果はゆらぐ。

```terminal 
母集団の相関係数 rho = 0.300000 0.500000 0.700000 0.900000 
(1-rho^2)/sqrt(n-2) 0.091924 0.075761 0.051518 0.019193 
シミュレーション　     0.099243 0.077898 0.051749 0.020465 
ブートストラップ　　　  0.105727 0.067170 0.042296 0.017960 
```

```matlab 

N = 100;
L = 100;
std1 = [];
std2 = [];
std3 = [];
for rho = [ 0.3 0.5 0.7 0.9]
  std1(end+1) = (1-rho^2)/sqrt(N-2);
  std2(end+1) = sim( N, L, rho );
  std3(end+1) = boot(N, L, rho );
end

fprintf( '母集団の相関係数 rho = %f %f %f %f \n', 0.3, 0.5, 0.7, 0.9 );
fprintf( '(1-rho^2)/sqrt(n-2) %f %f %f %f \n', std1 );
fprintf( 'シミュレーション　     %f %f %f %f \n', std2 );
fprintf( 'ブートストラップ　　　  %f %f %f %f \n', std3 ); fprintf( '\n' );


function ret = sim( N, L, rho )
cors = zeros( L, 1 );
for i = 1:L
    x = mvnrnd( [0;0], [1 rho; rho 1], N);
    tmp = corr( x );
    cors(i,1) = tmp( 1, 2 );
end
ret = std( cors );
end

function ret = boot( N, L, rho )
   x = mvnrnd( [0;0], [1 rho; rho 1], N);
   [ci, st] = bootci( L*10, @corrx, x ); 
   ret = std( st );
end

function ret = corrx( x )
  tmp = corr( x );
  ret = tmp( 1, 2 );
end
```
【GitHub】コミット同士の差分を確認する方法

# コミット同士の差分を確認するには
~~~
https://github.com/ユーザ名/リポジトリ名/compare/古いコミットID...新しいコミットID
~~~

上記URLを叩くだけです。

割と使いたいタイミングがあるはずなのに、ちょっと調べないと出てこなかったのでメモ代わりに記事に起こしました。
【VBA】関数(SubTotal)とAutoFilterを使った楽な集計法

何かしらの集計を行う際に、MAX関数やSUM関数等を使用した集計を行う事がよくあります。
しかし、フィルター機能を使った場合は上記関数だと集計出来ない事があります。
フィルターを使う場合は、SubTotal関数を使用します。

例として、下記のような処理Start~Stopの動作している時間帯の計算と最大値の集計を行う事を想定した処理を書きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710307/29b1a791-c521-1730-b60c-6c3f6a950eff.png)

まず、処理名(C列)でフィルターしながらSubTotal関数で集計を行う為に配列に処理名の格納から行っていきます。
ワークシートの適当な部分に、処理名を記載しておきます。(G列に記載しました。画面に収まってないですが、処理_1_Start ~ 処理_20_Stop で40個分の処理名を作成しました。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710307/cdc82c07-e935-edf7-a5c1-6403ddbfcc9b.png)
下記コードを実行して、ウォッチウィンドウ等で格納されたか確認して下さい。

```:配列に格納
    Dim Job_Collection(39) As Variant
    
    For i = 2 To 41
        
        Job_Collection(i - 2) = Cells(i, 7)
        
    Next i
```

処理時間の計算を行います。
シンプルに、終了時間 - 開始時間 = 動作時間 で計算します。
書式も、hhmmssに変更します。

```:動作時間の計算
Dim i,j,k As Long

For i = 2 To Cells(Rows.Count, 4).End(xlUp).Row Step 2
    
    Cells(i + 1, 5) = Cells(i + 1, 4) - Cells(i, 4)
    
Next i

Columns(5).NumberFormat = "hh:mm:ss"
```

今回一番大事なところです。
処理名を格納した配列でフィルターをかけ、SubTotal関数で最大値の取得を行います。
下記のような処理を書きました。

```:メイン
For j = 2 To 41 Step 2
    
        Range("C1").AutoFilter 1, Job_Collection(j - 2), xlOr, Job_Collection(j - 2 + 1)
        Cells(k, 11) = WorksheetFunction.Subtotal(4, Columns(5))
        
        k = k + 1
        
Next j
    
Range("C1").AutoFilter
Columns(14).NumberFormat = "hh:mm:ss"
```


最終的には、下記のようなコードになりました。
集計がすぐ終わるので、楽です。


```:VBA_Sample
Sub Main_Process()

    Dim i, j, k As Long
    Dim Job_Collection(39) As Variant
    
    #G列から処理名を取得し、Job_Collectionに格納
    For i = 2 To 41
        
        Job_Collection(i - 2) = Cells(i, 7)
        
    Next i
   
    #動作時間の計算処理
    Call Calculation
    
    k = 2
    
    #フィルター後に、最大処理時間をK列に転記
    For j = 2 To 41 Step 2
    
        Range("C1").AutoFilter 1, Job_Collection(j - 2), xlOr, Job_Collection(j - 2 + 1)
        Cells(k, 11) = WorksheetFunction.Subtotal(4, Columns(5))
        
        k = k + 1
        
    Next j
    
    Range("C1").AutoFilter
    Columns(14).NumberFormat = "hh:mm:ss"

End Sub



Sub Calculation()

Dim i As Long

For i = 2 To Cells(Rows.Count, 4).End(xlUp).Row Step 2
    
    Cells(i + 1, 5) = Cells(i + 1, 4) - Cells(i, 4)
    
Next i

Columns(5).NumberFormat = "hh:mm:ss"

End Sub
```

実行すると、E列に動作時間/K列に最大値が記載されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710307/8e19c6c7-74e4-847b-dc56-0a25a9caf547.png)

↓実行後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710307/8a5b3156-8ecc-68ba-030c-4f8f23a524ff.png)


集計作業によっては、一日かかる事もありますが
記載した内容を応用すれば、すぐ集計を終わらせる事が出来そうです。
AppSync+GraphQLを5分だけ触ってみた

## 目次

- [はじめに](#はじめに)
- [AppSync+GraphQLを触ってみる](#appsyncgraphqlを触ってみる)
  - [APIの作成](#apiの作成)
  - [mutation(CreateEvent)の実行](#mutationcreateeventの実行)
  - [queryの実行](#queryの実行)
- [まとめ](#まとめ)
- [参考](#参考)

## はじめに

業務でGraphQLを今後使うチャンスがありそうなので、AWSのAppSyncを触ってみました。

## AppSync+GraphQLを触ってみる
### APIの作成

AppSyncを開く、**APIを作成**を選択します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/f8855d07-4013-f255-5bd0-d4cf6116b744.png)

**サンプルプロジェクトから開始する**の中の**イベントアプリ**を選択して、**開始**をクリックします。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/0ab94f38-6441-5d83-a940-c8238105c569.png)

API名を適当に入力し、**作成**をクリックします。
![AWS AppSync Console 2022-06-28 20-48-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/eb4da148-17a4-4571-6238-741acc4555cf.png)

以下のような画面が表示されればOKです。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/f03d8e0b-ec0d-c752-f69d-514ee423882c.png)

このサンプルプロジェクトでは事前に以下のクエリが用意されているようです。
それぞれ動かしてみます。

- CreateEvent
- ListEvents

### mutation(CreateEvent)の実行
mutationとはデータを**更新**するための形式のようです。

また、この画面は左側でポチポチ必要な項目を取捨選択すると真ん中の画面でクエリが自動生成されるようです。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/d601481b-2a22-3a26-3fbc-41cad68a02f5.png)

適当に選択して、以下の要領でCreateEventを実行してみます。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/bdee9867-87b3-8115-6bb7-745c98e71fa5.png)

以下赤枠のようにログが出ます。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/aa1446fe-1ab5-cb94-6242-357715c9fae9.png)

また、DynamoDBを確認すると、データが登録されていることが分かります。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/812eebb4-0a85-a171-1ec5-495af6657787.png)

### queryの実行

queryはデータを取得する際の形式のようです
(こちらはなじみがあると思うので理解しやすいかもです。)

同じ要領で、以下のクエリを実行します。

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/9f22f9a6-407b-e336-0f18-6de1afcd23a3.png)

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/856d2022-7e7f-4030-85e9-3c3aaeaaaed1.png)

以下のように、先ほどのCreateEventで登録したデータを取得できました。

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882682/372f5c66-8c9c-7b2a-58fb-19eae7859968.png)

## まとめ

今回はサンプルプロジェクトを使ってAppSync+GraphQLを触ってみました。

サンプルを動かしただけですが、GraphQLによりSQLライクで書くことでほしい情報を取得したり登録できることを確認できました。

次回は自分のクエリを作成したり、プログラムから実行してみたいと思います。

## 参考
https://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/quickstart.html
UE4 IK MEMO


https://youtu.be/h2BiQ3nDJmY?t=153

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/92580959-da43-bea3-fee3-2cc4bae8fbff.png)

Alpha 割合で変化
Transform 設定位置
Junit

## Enclosed, Theories
```java
@RunWith( Enclosed.class )
public class TestHogeDto {

    @RunWith( Theories.class )
    public static class TestConstructor {

        @Builder
        static class TestData {
            private final String hoge;
        }

        @Builder
        static class Fixture {
            private final TestData testData;
            private final String fuga;
            private final String hogehoge;
        }

        @DataPoints
        public static Fixture[] getFixture() {
            return new Fixture[] {
                    Fixture.builder()
                            .testData( TestData.builder()
                                    .hoge( "hoge" )
                                    .build() )
                            .fuga( "fuga" )
                            .hogehoge( "hogehoge" )
                            .build(),
                    // ■ 接道状況が""
                    Fixture.builder()
                            .testData( TestData.builder()
                                    .hoge( "" )
                                    .build() )
                            .fuga( "" )
                            .hogehoge( "" )
                            .build(),
            };
        }

        @Theory
        public void create_hogeDto( Fixture fixture ) {

            HogeDto result = new HogeDto( fixture.testData.hoge );

            assertEquals( fixture.fuga, result.getFuga() );
            assertEquals( fixture.hogehoge, result.getHogehoge() );
        }
    }
}
```

### enclosedで共通の使いたい場合
staticだからクラス外にアクセスできないので継承を利用する
```java

    /**
     * Abstract common settings class.
     */
    abstract public static class CommonSetting {

        static final String SESSION_ID = "session_id";
        static final String TRIAL_APP_ID = "tal-1";

        @Mock
        public AuthClient authClient;
        @InjectMocks
        public HogeService service;

        @Before
        public void setUp() {
            MockitoAnnotations.initMocks( this );
        }
    }
```

### @AutoConfigureTestDatabase
実際のDBでテストしたい時に使用する

## PowerMock
- whenNewのバグ
withAnyArgumentsを使ってwhenNewをする時に、コンストラクタの引数にnull値が来ると挙動がおかしくなる

## mockstatic

```java
            try ( MockedStatic<DigestUtils> mockedDigestUtils = mockStatic( DigestUtils.class );
                    MockedStatic<DateUtils> mockedDateUtils = mockStatic( DateUtils.class ) ) {
                mockedDigestUtils.when( DigestUtils::createHashId ).thenReturn( "ta1" );
                mockedDateUtils.when( DateUtils::now ).thenReturn(
                        ZonedDateTime.of( LocalDateTime.of( 2022, 1, 1, 0, 0, 0 ), DateUtils.DEFAULT_ZONE_ID ) );
```
[ruby] each_with_index, each.index_with, each_indexの違い

### はじめに
paizaで出てきたメソッドの違いをまとめました

[参考にさせていただきました！](https://udemy.benesse.co.jp/development/system/ruby-each-with-index.html)

### 結論
```ruby
.each_with_index
  通常のeach + ０からカウントするindexを得る
.each.with_index
  動きは上と同じ
.each_index
  要素分+1 indexを得る
```

#### each_with_indexとeach.with_indexの違い
`each_with_index`はindexが0からスタートする
`each.with_index（1）`と引数を渡すと（０ではなく）1番目から始められるため`i+1`とやる必要がなくなる

### 使い方
```ruby
array = ["a", "b"]

array.each_with_index do |a, i|
  puts "「#{i} #{a}」"
end
#=> 結果
#   「0 a」 
#   「1 b」 

array.each.with_index(20) do |a, i|
  puts "「#{i} #{a}」"
end
#=> 「20 a」
#   「21 b」 

array.each_index do |i|
  puts "「#{i}」"
end
#=> 　「0」
# 　　　　　「1」 
```

#### ちなみに
[リファレンス](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_with_index.html)によるとeach_with_indexにも引数を渡せて、`split`のような動きをしてくれる？っぽいです
```ruby
require 'stringio'
StringIO.new("foo|bar|baz").each_with_index("|") do |s, i|
  p [s, i]
end
# => ["foo|", 0]
#    ["bar|", 1]
#    ["baz", 2]
```

### 最後に
間違いがあればお知らせいただけると幸いです
閲覧ありがとうございました！
【#13 エンジニア転職学習】Linux基礎　アーカイブ・圧縮

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

体力がもたず昨日分飛ばしてしまいましたが、サイクルを戻して投稿させていただきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日はLinuxのアーカイブと圧縮の一部コマンドについて学習しました。

* **アーカイブ・圧縮コマンド　←Topics!!**

# アーカイブ・圧縮コマンド
私たちが普段使うWindowsやMacOSXで使うzipファイルはアーカイブと圧縮を同時に行います。
一方Linuxはそれらを別個処理するのが通常らしいです。
以下アーカイブと圧縮のコマンドについてのメモになります。

### tar（アーカイブコマンド）
* オプションにハイフンをつけない
* ファイル属性もそのまま引き継げるためバックアップ用途に優れいている
### gzip・bzip2（圧縮コマンド）
* gzipとbzip2は圧縮率と圧縮・展開時間の優劣があるので使い分ける
* 標準出力はバイナリファイルになるので直接表示せず、パイプで渡す等処理する
* 現在はtarのオプションでtar+gz（bz2）形式のファイルを作成できる

使用している書籍はこちら↓

https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84Linux%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E4%B8%89%E5%AE%85-%E8%8B%B1%E6%98%8E-ebook/dp/B072K1NH76/ref=sr_1_1?adgrpid=113196705062&gclid=Cj0KCQjwzLCVBhD3ARIsAPKYTcR4WAb_4QVrwuBM_1mIPMFsQ6kNDJ-o4yIofVSAI7_eHpWCeva8kKwaAstgEALw_wcB&hvadid=489559881279&hvdev=c&hvlocphy=1009363&hvnetw=g&hvqmt=e&hvrand=10125867468998217428&hvtargid=kwd-1152146940662&hydadcr=21814_10996132&jp-ad-ap=0&keywords=%E6%96%B0%E3%81%97%E3%81%84+linux+%E3%81%AE+%E6%95%99%E7%A7%91%E6%9B%B8&qid=1655473534&sr=8-1




# おわりに
最後までお読みいただきありがとうございました。
明日もLinuxの続きを行います。
アドバイス・応援コメント等いただけますと幸いです。
PEG.jsを使う

パーサジェネレータのPEG.jsを使うと手軽に構文解析器が作れます。
ここに使い方をメモしておきます。

# 始め方

PEG.jsは[Web上で試すことができ](https://pegjs.org/online)、そこで文法チェックができるのがJSならではの素晴らしさです。それでも、Node.jsを使って、ローカルで使えれば便利なので、その方法で紹介できます。

```install.sh
# グローバルインストールの場合
npm install -g pegjs
```

# 一番簡単なサンプル

足し算・掛け算を行う文法を定義するには、以下のように書きます。

```sisoku.pegjs
start = add

add = left:mul "+" right:add { return left + right; }
    / mul

mul = left:val "*" right:mul { return left * right; }
    / val

val = _ nums:[0-9]+ _ { return parseInt(nums.join('')); }

_ "whitespace" = [\s ]*
```

この文法規則ファイルをJavaScriptの構文解析（パーサー）にコンパイルするために以下のコマンドを実行します。すると「sisoku.js」というCommonJSのファイルが生成されます。

```compile.sh
pegjs sisoku.pegjs
```

そして、これを利用するメインファイルを書きます。

```main.js
// ライブラリ取り込み
const parser = require('./sisoku.js')
// 適当な計算を実行
const ans = parser.parse('1 + 2 * 3')
console.log('答え:', ans)
```

　実行してみましょう!すると、「答え: 7」と表示されます。

```run.sh
$ node main.js
答え: 7
```

使い方は簡単ですね。

# 四則演算する文法

次に、四則演算およびカッコの計算をする文法は以下の通り。超簡単に実装できる。

```sisoku.pegjs
start = add

add = left:mul "+" right:add { return left + right; }
    / left:mul "-" right:add { return left - right; }
    / mul

mul = left:val "*" right:mul { return left * right; }
    / left:val "/" right:mul { return left / right; }
    / left:val "%" right:mul { return left % right; }
    / val

val = _ "(" _ expr:add _ ")" _ { return expr }
     / _ nums:[0-9]+ _ { return parseInt(nums.join('')); }
 
_ "whitespace" = [\s\n ]*
```



# 参考

- [PEG.js(本家)](https://github.com/pegjs/pegjs)
- [Qiita/PEG.jsの構文規則の書き方](https://qiita.com/uwaai/items/b735038eb5a16c93ed7d)
業務でよく使用するDockerコマンドをまとめる

# 宣伝
https://www.isoroot.jp/blog/4714/

自社ブログに自身のDockerコンテナ起動までのハンズオン記事を投稿しました。

# 業務でよく使用するDockerコマンド集

## イメージビルド系
### Docker イメージをビルドする
```
$ docker image build -t [イメージ名] .
```

## コンテナ起動系
### コンテナ起動と同時に中に入る
~~~
$ docker container run --name [コンテナ名] -it [イメージ名] /bin/bash
~~~

## 削除系
### イメージ一括削除
~~~
$ docker rmi -f $(docker images -q)
~~~
### コンテナ一括削除
~~~
$ docker container prune
~~~

## レジストリを移行する時の流れ
~~~
$ docker pull [移行元のdockerイメージ]
$ docker tag [移行元のdockerイメージ] [移行先のdockerイメージ]
$ docker push [移行先のdockerイメージ]
~~~

上記をシェルスクリプトで自動化する
~~~move-docker-image.sh
set -ex 

FILE_PATH=$1

while read line || [ -n "${line}" ]; do
  src_image=$(echo ${line} | cut -d'' -f 1)
  dst_image=$(echo ${line} | cut -d'' -f 2)
  docker pull $src_image
  docker tag $src_image $dst_image
  docker push $dst_image
done < $FILE_PATH
~~~

~~~docker-images.txt
[移行元のdockerイメージ1] [移行先のdockerイメージ1]
[移行元のdockerイメージ2] [移行先のdockerイメージ2]
︙
~~~

~~~
$ bash move-docker-image.sh docker-images.txt
~~~
駆け出しエンジニアがモジュールについてまとめてみた！

今年、転職したばかりのやさまです。

職場でモジュール(自動更新)動いている？など使っていますが、最初は何のことか、さっぱりわかりませんでした。ですので、今回は、モジュールについてまとめてみました！

ぜひ、最後まで読んでください。

## モジュール 【module】
モジュールとは、機能単位、交換可能な構成部分などを意味する英単語。機器やシステムの一部を構成するひとまとまりの機能を持った部品で、システム中核部や他の部品への接合部（インターフェース）の仕様が明確に定義され、容易に追加や交換ができるようなもののことを指す。

実際、そんなこと言われてもよくわかんない…
と思いませんか？

モジュールの意味をきちんと理解して、定義するのは大変だと思います。
私が「モジュール」と聞いて思い浮かぶイメージを例を挙げると、

### ソフトウェア開発での「検索機能」「登録機能」「削除機能」がそれぞれ1つのモジュールです。

##### １．単独(検索機能・登録機能・削除機能)だけも動く
　→　単体でも「機能」としては成立している

この単独でも動作する機能のことを「モジュール」と呼びます。

##### ２．普通は単独では動かさない　
　→　普通は合体(登録機能と削除機能・登録機能と検索機能・登録機能と削除機能と検索機能)させて動かす

機能別に分けて、その機能に対して担当を分担して、機能単位で「製造」、「単体テスト」を行うと、開発効率をあげれます。
また、機能別にすると、機能を入れ替えたり、新しく機能を追加したり、不要となった機能を削除したりの対応もできます。

また、モジュールを繋ぎ合わせるテストが「結合テスト」であり、モジュールを繋ぎ合わせることで、システム（ソフトウェア）が完成します。


モジュールに似たものに、ライブラリやコンポーネントがあります。
次回は、モジュールとライブラリの違いについて説明していきます。
楽しみにしていてください。
AWS CLI バージョン1とバージョン2を併存させる

# AWS CLIをバージョン1とバージョン2を併存させる
## こんな人向け
既にAWS CLIバージョン1がインストールされていて、諸事情でバージョン2も使いたい人

## 前提条件
* CentOS 7

## AWS CLI バージョン 1 インストール
```
cd
mkdir -p tmp
cd tmp
rm -rf aws*
wget "https://s3.amazonaws.com/aws-cli/awscli-bundle-1.19.0.zip" -O "awscli-bundle.zip"
unzip awscli-bundle.zip
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws

```
* AWS CLI のインストール、更新、アンインストール
https://docs.aws.amazon.com/ja_jp/cli/v1/userguide/cli-chap-install.html

## AWS CLI バージョン 2 インストール
```
cd
mkdir -p tmp
cd tmp
rm -rf aws*
wget "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -O "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install -i /usr/local/aws-cli -b ./aws-cli-v2
sudo mv ./aws-cli-v2/aws /usr/local/bin/aws2
sudo mv ./aws-cli-v2/aws_completer /usr/local/bin/

```
* AWS CLI の最新バージョンをインストールまたは更新します。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

## AWS CLI バージョン 2 アンインストール
```
sudo rm -f /usr/local/bin/aws2
sudo rm -f /usr/local/bin/aws_completer
sudo rm -rf /usr/local/aws-cli

```
* AWS CLI バージョン 2 のアンインストール
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/uninstall.html
Numer0n作ってみた！

# Numer0nって知ってる？
みなさんはヌメロンを知っていますか？
ヌメロンとは、今から10年ほど前に、あるテレビ番組でやっていた1対1の対戦ゲームです。

ルールも簡単でプログラミングの練習にちょうど良いと思って作ったので、備忘録として解説していきます。


# ルール
基本的なルールは簡単です。
- 1対1の対戦ゲームです
- プレイヤーは0~9を使って3桁の数字を選びます。
  - ただし、同じ数字を使ってはいけません 
- 先行後攻を決め、相手の選んだ数字を予想し合い、お互いの数字を先に当てた方が勝ちです。

ただし、ヌメロンには相手が予想した数字が合っているかどうかの答え方に決まりがあります。
それが、**EAT**と**BITE**です。
| EAT | BITE |
|:-:|:-:|
| 数字と桁が合っている  | 数字は合っているが桁は合っていない  |

例えば、自分の選んだ数字が”135”のとき、相手が"123"と答えたら、
1:数字も桁も合っている。（1EAT)
2:数字も桁も合っていない。
3:数字は合っているが桁は合っていない。（1BITE)
このとき、「1EAT, 1BITE」と答えます。

今回は、PCが自動で生成した3桁の数字を10回以内に当てられたら勝ちというルールで作成します！


# 処理の流れ
1. ランダムな3桁の数字を生成し、配列として格納する。
1. 予想する3桁の数字を入力
1. 入力の仕方が正しいかチェック
1. 予想された3桁の数字を配列に格納する
1. 配列のそれぞれの数字を比較し、EATとBITEを計算する
1. 数字を当てて勝利or10回以内に当てられなくて敗北で終了


```mermaid
graph TD;
    スタート-->
    ランダムな3桁の数字を生成し,配列として格納-->
    予想する3桁の数字を入力-->
    入力された文字チェック-->
    文字入り-->
    再入力;
    入力された文字チェック-->
    桁数違う-->
    再入力;

    入力された文字チェック-->
    正しい-->
    予想された3桁の数字を配列に格納する-->
    配列のそれぞれの数字を比較し,EATとBITEを計算する-->
    数字を当てた-->
    勝利;
    配列のそれぞれの数字を比較し,EATとBITEを計算する-->
    10回以内に当てられなかった-->
    敗北;
```



# 使用技術
言語：Python
エディタ：Visual Studio Code

Pythonを使ったことがなかったので、使ってみたいという気持ちだけで採用してみました。



# コード
```python
import random


numlist = list(range(10))

num1 = numlist.pop(random.randint(0, len(numlist) - 1))
num2 = numlist.pop(random.randint(0, len(numlist) - 1))
num3 = numlist.pop(random.randint(0, len(numlist) - 1))

answer = [num1, num2, num3]



def check_digit(num):
    return len(num) != len(set(num))


def eat_judge(answer, num_3dig):
    eat = 0
    for n in range(len(answer)):
        if answer[n] == num_3dig[n]:
            eat += 1
    return eat


def bite_judge(answer, num_3dig):
    bite = 0
    for n in range(len(answer)):
        for m in range(len(answer)):
            if answer[n] == num_3dig[m] and n != m:
                bite += 1
    return bite



print("Let's start Numer0n!")

n = 1
while n < 11:
    print("Challenge " + str(n))

    num_3dig = input('Please enter a 3-digit number : ')

    while True:
        if len(num_3dig) != 3:
            num_3dig = input('Please enter a 3-digit number again : ')
        elif check_digit(num_3dig):
            num_3dig = input('Please enter a 3-digit number again : ')
        elif not num_3dig[0].isdigit() or not num_3dig[1].isdigit() or not num_3dig[2].isdigit():
            num_3dig = input('Please enter a 3-digit number again : ')
        else:
            break

    num_3dig = list(map(int, num_3dig))

    
    if answer[0] == num_3dig[0] and answer[1] == num_3dig[1] and answer[2] == num_3dig[2]:
        print("!!---------------------------------!!")
        print("Congratulations!! You won this game!!")
        print("!!---------------------------------!!")
        break
    else:
        if n != 10:
            print("EAT : " + str(eat_judge(answer, num_3dig)))
            print("BITE : " + str(bite_judge(answer, num_3dig)))
            print("It's wrong.\n")
        else:
            answer = map(str, answer)
            print("You lose this game. The answer is " + ''.join(answer) + ".")

    n += 1

```


# 参考までに
↓github載せときます
github : https://github.com/ryudaitakai/Numer0n
VirtualBox上のUbuntuで、Matplotlib is currently using agg ... と言われ、Matplotlibのグラフ描画が使えなかった話

現在、``VirtualBox + Ubuntu``の環境でいろいろ開発を行っている。
その時、点群データをグラフ描画したかったが、タイトルのエラーを吐かれてできなかったのでメモ。
# 環境
- VirtualBox 
- Ubuntu22.04
- Python 3.10.4

# 解決方法
tkinter を入れる。
これが無いとGUIでの描画ができないようだった。

```terminal:terminal
sudo apt-get install python3-tk
```

これで解決。
カスタムオブジェクトの削除

ユーザがカスタムオブジェクトを削除しても、Salesforce はそのカスタムオブジェクトをごみ箱に追加しません。代わりに、[削除済みオブジェクト] リストに 15 日間表示されます。この期間、オブジェクトとそのデータは論理削除されます。つまり、オブジェクトとそのデータを復元することも完全に消去 (物理削除) することもできます。15 日を過ぎると、オブジェクトとそのデータは自動的に物理削除されます。

論理削除したカスタムオブジェクトとそのデータは組織の制限の対象として考慮されますが、物理削除したものは考慮されません。

カスタムオブジェクトを削除する手順は、次のとおりです。

1.カスタムオブジェクトのオブジェクト管理設定から、削除するオブジェクトの横にある [削除] をクリックします。
2.確認を促されたら、[カスタムオブジェクトを削除します] をオンにして、[削除] をクリックします。
■特定のカスタムオブジェクトを削除できない理由は?
次の場合は、カスタムオブジェクトを削除できません。

・主従関係の主側にある。
・別のオブジェクトの積み上げ集計項目で使用されるカスタム項目が含まれている。
・Apex、Visualforce ページ、またはレポート作成スナップショットで参照されている。
・重複ルールまたは一致ルールによって参照されている。
・100,000 件を超えるレコードが含まれている。削除するオブジェクトに 100,000 件を超えるレコードが含まれている場合は、まず適切な数のレコードを削除してからオブジェクトを削除します。

■カスタムオブジェクトの削除結果
カスタムオブジェクトを削除すると、次のようになります。

・削除されたカスタムオブジェクトレコードの URL へのブックマークをクリックすると、「Insufficient Privileges (アクセス権がありません)」というメッセージが表示されます。
・オブジェクトが Salesforce AppExchange パッケージから削除されます。
・削除したオブジェクトが主従関係の従側になっている場合は、主従関係を参照関係に変更します。
・次のものが削除または消去されます。
  　-オブジェクトのカスタムタブ
  　-オブジェクトのリストビューとワークフロールール
  　-データセット、モバイルビュー、除外項目などのモバイル設定
  　-削除されたオブジェクトが主従関係の従側になっている場合の、オブジェクトに関連付けられている標準レポートタイプ、および標準レポートタイプに基づくレポート
・次のものを非表示または無効にします。
  　-カスタムオブジェクト定義および関連定義
  　-ごみ箱の中にあるレコードを含む、オブジェクトのレコードおよび関連レコード
  　-削除したオブジェクトを主オブジェクトとしているカスタムレポートタイプ
  　-削除したオブジェクトを主オブジェクトとしているカスタムレポート
  　-オブジェクトのカスタム数式項目
  　-オブジェクトのカスタム入力規則および承認プロセス

メモ:削除された項目、非表示の項目、無効の項目の多くは、カスタムオブジェクトを復元することで復元できます。削除されたカスタムオブジェクトの復元についての詳細は、「削除されたカスタムオブジェクトの管理」を参照してください。

■カスタムオブジェクトの物理削除結果
カスタムオブジェクトが手動で、または 15 日後に自動的に物理削除された場合、次のようになります。

・カスタムオブジェクトの定義およびデータは完全に削除され、復元できなくなります。
・カスタムオブジェクトとそのデータは、組織の制限の対象に含まれなくなります。
・主レコードが削除された結果として 1 つ以上の従レコードが自動的に削除されていて、削除されたオブジェクトが主従関係の従側である場合、現在ごみ箱にある主レコードは復元できません。主レコードを復元しようとすると、エラーになります。

メモ:これは、主レコードがごみ箱にあるときに、削除された従レコードのカスタムオブジェクト定義が物理削除される場合にのみ発生します。
core dump ってなに？

## 勉強前イメージ

カーネルっぽい何かって感じがする
coreやし

## 調査

### core dump とは

システム、またはプログラムが異常終了した際にシステムから作成されるファイルを指します。
中身は異常に停止した際のメモリの一部のコピーでアプリケーションの最終の状態を確認することが出来ます。
プログラムの開発者がデバッグ用に確認します。
linuxカーネルはcore dumpの機能が有効の際は自動的に記録し、
またアプリケーションが実行中のときにcore dumpのシグナルを送るとcore dumpファイルを作成することが出来ます。

core dumpのファイルの出力先は `sysctl -a` で確認することが出来ます。
プロセスのディレクトリに出力されます。

```
[root@localhost ~]# sysctl -a | grep core_pattern
kernel.core_pattern = core
```

CentOS7はデフォルトでは出力されない設定になっています。
core dumpファイルを吐かせるには設定を行う必要があります。
また、core dump のファイルはファイルサイズが大きくなるので不要になると削除するのがよいです。

## 勉強後イメージ

メモリの一部を切り抜いたのをファイルに出力させたり、
ログを吐くとファイルサイズ大きくなるよね・・・
だからデフォルトでは吐かないような設定にしてるのかな？

## 参考

- [コアダンプ 【core dump】](https://e-words.jp/w/%E3%82%B3%E3%82%A2%E3%83%80%E3%83%B3%E3%83%97.html)
- [第21章 クラッシュしたアプリケーションのデバッグ](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/developer_guide/debugging-crashed-application)
6.15 (易) クラメール・ラオ不等式2

## 方針

CR不等式については6.12の方針で詳しく述べた．

## 答案

![6. 2周目-36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/a0fb11af-097f-d94f-65cc-f627f92a162e.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
【Qiita初心者】記事の投稿で使えるサンプル集

必要な分をコピペして使ってください。

# ページ内リンク
    [表示文字](#タイトル）
* [見出し](#見出し)
* [箇条書きリスト](#箇条書きリスト)
* [番号付きリスト](#番号付きリスト)
* [表](#表)
* [コードの書き方](#コードの書き方)
* [取り消し線](#取り消し線)
* [引用符](#引用符)
* [リンク](#リンク)

# 見出し
#+半角スペース+見出し文字
※シャープの数が多くなるほど文字サイズが小さくなります。（#6個がMAXです）

```
# 見出し1
## 見出し2
### 見出し3
#### 見出し4
##### 見出し5
###### 見出し6
```
# 見出し1
## 見出し2
### 見出し3
#### 見出し4
##### 見出し5
###### 見出し6
####### 見出し7（ありません！）

# 箇条書きリスト
-+半角スペース+見出し文字
※リストの前後には空行を入れること

```
- リストA
    - リストA. 1
        - リストA. 1. a
        - リストA. 1. b
    - リストA. 2
- リストB
- リストC
```

- リストA
    - リストA. 1
        - リストA. 1. a
        - リストA. 1. b
    - リストA. 2
- リストB
- リストC


# 番号付きリスト
数値+半角ドット
※リストの前後には空行を入れること
```
1. 番号付きリストA
    1. 番号付きリストA．1
    1. 番号付きリストA．2
1. 番号付きリストB
1. 番号付きリストC
```

1. 番号付きリストA
    1. 番号付きリストA．1
    1. 番号付きリストA．2
1. 番号付きリストB
1. 番号付きリストC


# 表
```
|りんご|みかん|もも|
|:--|--:|:--:|
|左寄せ|右寄せ|センタリング|
|a|b|c|
```


|りんご|みかん|もも|
|:--|--:|:--:|
|左寄せ|右寄せ|センタリング|
|a|b|c|


# コードの書き方
※先頭の#は不要

・複数行まとめての場合
```
# ```
# 半角バッククォートで囲う（```）
# 私のキーボードだと、英数入力でShift + @で「`」は出てきます
# ```
```

・１行ずつの場合

    # 先頭に半角スペース4つ(or タブ)

タブ入力は、デフォルトだとフォーカス移動します。
Chrome拡張機能で入力可能となるそうですが、上記の方法で私は満足なので割愛します。
    


# コードの書き方（ハイライト）
<div>~~~+言語で、指定した言語に合わせて自動的にハイライトして表示してくれます。</div>

    ~~~java
     public class HelloWorld {
        public static void main (String[] args) {
            System.out.println("Hello World");
        }
    }
    ~~~

表示結果↓
~~~java
public class HelloWorld {
    public static void main (String[] args) {
        System.out.println("Hello World");
    }
}
~~~

# 取り消し線
    ~~取り消し線~~
~~取り消し線~~

# 引用符
    > 引用
    >> 引用
> 引用1
>> 引用2

# リンク
（表示文字）［URL］で、文字でリンクが表示されます。
```
[グーグル(https://www.google.co.jp/)
```
[グーグル](https://www.google.co.jp/)

URLを直書きした場合は、自動的にいい感じにしてくれます。
```
https://www.google.co.jp/
```
https://www.google.co.jp/
Linuxのしくみ コンピュータシステムの概要

久しぶりの投稿になります

最近Linuxの仕組みという本を読んで、その要約をしようと思います

コンピュータシステムが動くとき、4つの手順を繰り返しています

①キーボードなどを介して、コンピュータにある処理を依頼する
↓
②メモリにある命令を読み込み、それをCPUで実行。その結果をデータを保持する領域に書き込む
↓
③ハードディスクやストレージデバイスをに書き込む
OR
別のコンピュータに転送する
OR
人間にモニターなどを使って、人間に見せる
↓
④ ①に戻る

この手順を繰り返して、ユーザーが使える一連の処理を***プログラム***といいます

プログラムには3種類あります
①アプリケーション
→ユーザーに直接役立つもの。LINEとかGoogleなどといったものです

②ミドルウェア
→アプリケーションの実行を助けるためのもの
webサーバーやDBなどがそれです

③OS
→ハードウェアを操作して、アプリケーションやミドルウェアの処理に必要な機能を提供するもの
いわば仲介役です
Linux windows MacOSがそれにあたります

イメージは以下の通りで、互いに連携しながら動いています
![86F6838C-DCBC-4465-894A-4DF3190A9B05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485775/589abb50-7430-5925-f0aa-f9c0ce084b56.png)

この図に出ているOSは各種プログラムはプロセスという単位で実行され、複数のプロセスを同時に実行できるようになっています。

## Linuxとハードウェアの関係
Linuxはアプリケーション、ミドルウェアとの関係もありますが、ここではハードウェアとの関係について話していこうと思います

Linuxの大事な役割の1つにデバイス操作があります。
Linuxには、デバイスドライバというものあって、そのおかげでPCからプリンターを使って印刷ができて、今話題のUSBにデータを送ることもできるわけです

もし、LinuxのようなOSがなかったら、プロセスごとにデバイス操作処理が必要になります。

具体的にいうと、エクセルで作った資料をUSBに保存したいときに、「エクセルで作った資料をUSBに保存する用のプログラム」を書かないといけないんです。Wordを保存したいときはまた別のプログラムを自分で書かなきゃいけなくなるんですね。
マジだるいですね

Linuxではデバイスドライバというのを使って、プロセスを管理し、それによって外部デバイスを操作していきます
でも、コンピュータというのはいつも思い通りに動かないのです。
デバイスドライバを経由せず、デバイスを操作しちゃおうとすることがあるんです

そこでLinux では、***ユーザーモード***と***カーネルモード***というのがあって、後者のカーネルモードで動いているときのみ、デバイスにアクセスできるようになるんです

デバイスドライバはカーネルモード、プロセスはユーザーモードで処理するという流れになっているんです。

【参考資料】

https://it-trend.jp/development_tools/article/32-0044
OOM Killer とは

## 勉強前イメージ

メモリとかCPUのクリーニング的な？

## 調査

### OOM Killer とは

Out of Memory Killer の略で、Linuxのカーネル機能になります。
物理のメモリまたSwapメモリが枯渇した際に、必要なメモリ領域を確保出来ない時
プロセスを強制的に終了させてメモリ領域を確保する仕組みになります。
プロセスが終了するより、メモリが足らずにシステムが停止することを避けるために用意されています。

OOM Killerによって殺されるプロセスは
各プロセスのoom_score値が高いものを選択して強制終了させます。
oom_scoreの値は `/proc/pid/oom_score` で確認できます。
コマンドとしては `grep "" /proc/*/oom_score` で確認できます。

```
[root@localhost ~]# grep "" /proc/*/oom_score
/proc/1/oom_score:0
/proc/10/oom_score:0
/proc/1012/oom_score:10
/proc/1013/oom_score:2
/proc/1014/oom_score:0
/proc/1016/oom_score:0
/proc/1018/oom_score:0
```

もしOOM Killerでもプロセスを殺されたくない場合は /proc/pid/oom_adj に -17 を書き込むことで除外できます。
oom_adj の中身は以下のように数値が入っています。

```
[root@localhost ~]# cat /proc/1011/oom_adj
0
```

## 勉強後イメージ

OOM Killer聞いたことあったけど、これは知らなかった。
どういうときに除外対象にするんだろう？
できるだけシステムを動かしたいプロセスってことかな

## 参考

- [メモリ不足時に大事なプロセスが OOM Killerに殺されないようにする](https://pcvogel.sarakura.net/2016/05/03/31584)