OmniAICreator/Qiita-1.07M huggingface dataset:
GEPS (電子調達システム) 利用環境を民間電子証明書でセットアップ

GEPS。政府の電子調達システムを利用するための PC 設定。

Java 版の電子入札システムに比べるとまだ楽だけれど、やっぱりやたらめったらややこしい。


# 環境

- 2021/08/31 ~ 2021/09/16 での検証
- MS-Windows10 Pro 64bit / MS-Windows8.1 Pro 64bit
- Internet Explorer ( 笑 ) 
 - バージョン 21H1 OSビルド 19043.1237 (Windows10上)
 - 11.0.9600.20120 (Windows8.1上)
- 同じ PC で Java 版の電子入札システムをセットアップ済み
- AOSign の電子証明書 IC カードを電子入札用に使っているので、これを GEPS でも使う


# 事前準備


ここで利用者登録をしておく必要があります。
「利用者登録方法選択」
https://www.p-portal.go.jp/pps-web-biz/UZA01/OZA0102



電子証明書種別は、「民間電子証明書（ＩＣカード）」を使うことにします。

# 設定資料

必要環境は以下を見て、合わせます。

https://www.geps.go.jp/how_to_use
Internet Explorer が 32bit の指定がありますが、以下の「設定」の「拡張保護モード」の設定で 32bit に設定するので特に気にする必要はありません。

# 設定

https://www.p-portal.go.jp/pps-web-biz/UZA01/OZA0122
このページに沿って、以下を行います。

- プラグイン（アドオン）セットアップ
- 拡張保護モードの無効化
- ブラウザ拡張の有効化
- 信頼済みサイトの登録
- セキュリティレベルのカスタマイズ設定
- ポップアップの許可設定
- プラグイン(アドオン)の確認

# プラグイン（アドオン）セットアップ

調達ポータル・電子調達システムプラグイン をインストールします。

「ICカードを利用する場合のインストーラー（zip形式：1.2MB）」
を先のリンクからダウンロードして展開、Setup-ICを実行します。


# 拡張保護モードの無効化

IE の 「ツール」- 「インターネットオプション」の「詳細設定」の「セキュリティ」セクションで以下が無効になっていることを確認

- 拡張保護モードで 64 ビット プロセッサを有効にする
- 拡張保護モードを有効にする

# ブラウザ拡張の有効化

以下が有効になっていることを確認
- サード パーティ製のブラウザー拡張を有効にする」

# 信頼済みサイトの登録



IE の 「ツール」- 「インターネットオプション」の「セキュリティ」の「信頼済みサイト」ゾーンで「このゾーンのセキュリティのレベル」を「中」にし、「保護モードを有効にする」を有効にし、「適用」ボタンを押す。

更に「サイト」ボタンを押して以下の Web サイトをゾーンに追加し、「閉じる」。


- https://www.p-portal.go.jp/
- https://www.geps.go.jp/
- https://www.nyusatsu.geps.go.jp/



# セキュリティレベルのカスタマイズ設定





IE の 「ツール」- 「インターネットオプション」の「セキュリティ」の「信頼済みサイト」ゾーンで「レベルのカスタマイズ」を押して「セキュリティせ設定」画面を出し、以下の設定をする。

- 「ActiveX コントロールとプラグイン」ブロックの「ActiveX コントロールとプラグインの実行」を「有効にする」
- 「ActiveX コントロールとプラグイン」ブロックの「スクリプトを実行しても安全だとマークされている ActiveX コントロールのスクリプトの実行」を「有効にする」
- 「スクリプト」ブロックの「java アプレットのスクリプト」を「有効にする」
- 「スクリプト」ブロックの「アクティブ スクリプト」を「有効にする」
- 「その他」ブロックの「サーバーにファイルをアップロードする時にローカルディレクトリのパスを含める」を「有効にする」

# ポップアップの許可設定

IE の 「ツール」- 「インターネットオプション」の「プライバシー」の「ポップアップ ブロックを有効にする」となっている場合は、「設定」で許可するサイトに以下を追加する

- www.geps.go.jp
- www.nyusatsu.geps.go.jp





# プラグイン(アドオン)の確認

IE の 「ツール」- 「アドオンの管理」の「表示：」を「すべてのアドオン」とし、「EpsMainCtrl」の状態を右クリックして「有効」にする。


# InternetExplorer の変更反映

InternetExplorerを再起動する
JavaScriptでイベントをキャンセルする方法

普段jQueryばかり書いている人間が、イベントキャンセル処理を通常のJavaScriptで書こうとしてハマったのでメモ。

## 概要
通常のJavaScriptでイベントをキャンセルしたい場合は、addEventLinstenerで`preventDefault()`と`stopPropagation()`を呼び出そう。
## 問題
jQueryであれば以下のように`return false`すれば、バブリング(親要素のalert)およびデフォルトアクション(画面遷移)を停止できるが

```html
<div class="parent">
  <a href="https://~~" class="child">テスト</a>
</div>
```
```jsx
$('.parent').on('click' ,function(){
    alert('parent');
});

$('.child').on('click' ,function(){
    alert('child');
    return false;
});
```

通常のJSのaddEventLinstenerで同じよう`return false`してもデフォルトアクションをキャンセルできない。
以下の書き方だと親要素のalertも表示され、画面遷移もしてしまう。

```jsx
const parent = document.querySelector('.parent');
const child  = document.querySelector('a');

parent.addEventListener("click", function(){
  alert("parent");
});

child.addEventListener("click", function(e){
    alert("child");
    return false;
});
```


## 解決策
js側で`return false`の代わりに`preventDefault()`と`stopPropagation()`を呼び出す。

```jsx
child.addEventListener("click", function(e){
    alert("child");

    e.preventDefault();　//バブリングの停止
    e.stopPropagation(); //イベントキャンセル
});
```

ちなみにhtml側のonclickで以下のようにreturn falseを指定すれば画面遷移はキャンセルできるが親要素のイベントは走ってしまう。

```html
<div class="parent">
    <a href="https://~~" class="child" class="child" onclick="return false;">テスト</a>
</div>
```
[こちらの記事](https://linkers.hatenablog.com/entry/2019/10/25/154301)によると、通常のJavaScriptで`return false`した場合には`preventDefault()`のみが呼ばれるとのこと。
jQueryの`return false`では`reventDefault()`と`stopPropagation()`の両方が呼ばれる。

## まとめ

コードの可読性を上げるためにも、通常のJavaScriptでもjQueryでもイベント伝播を停止する際は`preventDefault()`と`stopPropagation()`を使用し、明確に動作の意図を伝えたほうが良さそう。

## 参考

[JavaScriptでのイベントキャンセルの落とし穴 - Linkers Tech Blog](https://linkers.hatenablog.com/entry/2019/10/25/154301)

[addEventListener() のリスナーでreturn falseしてもイベントはキャンセルできない - いろいろ](https://igrc.hatenablog.com/entry/2018/07/27/145655)
Docker [基礎]

##Dockerとは？
・簡単に開発環境を構築できるツール。
・アプリの開発・デプロイが簡単になるツール。

OSによってWebアプリが動いたり動かなかったりするが、Dockerを使うことによって、OSごと１つのパッケージにまとめてくれるため、そのようなことは起きない。
開発環境、本番環境、問わず利用できる。

![スクリーンショット 2021-09-17 13.59.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/874721/d14e5a3b-1428-334b-163a-37ab95f5563f.png)

##Dockerのダウンロード
https://www.docker.com/

こちらからインストール可能。
![スクリーンショット 2021-09-17 14.03.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/874721/ce48e608-4413-db9b-4682-7c436da90c09.png)

赤枠のボタンをクリック。
Mac版、Windows版があるので自分のPCにあっている方をダウンロードする。

解凍してアプリケーションを開ける。

ターミナル(PowerShell)で

```
docker --version
```

と入力する。

```
Docker version xx.xx.x, build xxxxxxx
```

上記のようなコードが出てくる。
xの部分は個々人によって異なる。

##Dockerの基本の仕組み
![スクリーンショット 2021-09-17 14.41.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/874721/4c32bdb4-f2fe-7b98-16d0-18e1a1b9e7b4.png)

基本的な仕組みは上記の通り。

Q. Dockerデーモンとは？

A. 
>Dockerデーモンは Linux のデーモンプロセスで、Docker Engine API が呼び出されるのを待ち受けています。Dockerデーモンは、呼び出された Docker Engine API に応じて、イメージのビルドやコンテナの起動などを行います。

[さわって理解する Docker 入門](https://www.ogis-ri.co.jp/otc/hiroba/technical/docker/part6.html)　より

Dockerデーモンが命令を受け取ると、レジストリからイメージを取得。それを基にしてコンテナを作成する。

##Dockerの基本操作
####イメージ作成

```
docker image build -t sample/sample1:latest .
```

```
docker image build
```

このコマンドでimage(イメージ)をbuild(作成)している。

```
-t sample/sample1
```

このコマンドでタグを設定している。

雰囲気としては、以下の通り。

![スクリーンショット 2021-09-17 15.15.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/874721/8046a110-c5cb-0f07-e258-d882f037aa41.png)


今回は、sampleという領域の中にsample1というファイルを作成した、ということになる。

１つのイメージから複数のコンテナを作成することもあるため、タグで名前を分けておいたほうが後々、楽に操作することが可能。

```
:latest
```

最新バージョンを指定している。

```
.
```

最後の.(ドット)は現在のディレクトリであると示している。
Dockerfileのあるディレクトリで操作しているときに使う。

####コンテナ作成・起動

```
docker container run -d -p xxxx:xxxx --name test sample/sample1:latest
```

xxxx/xxxxの中にはポート番号を設定する。
Dockerfileで設定したportの番号をそのまま入力する。

#####コンテナ停止

```
docker container stop test
```

#####コンテナ削除

```
docker container rm test
```

##感想

内容のほとんどは備忘録でしたが、「Dockerとはなんぞや」という人の役に立てればいいなと思います。

Dockerを使うに当たり[Dockerファイル]が必須になるのですが、それについてはまた書きます。
Cartographer導入を簡単に？ on Turtlebot3

# 前章

Turtlebot3のデフォルトslam-methodはgmappingですが、生成されるマップの出来栄えにちょっと不満を感じたのてCartographerを使ってみることにしました．
[ROBOTISのサイト](https://emanual.robotis.com/docs/en/platform/turtlebot3/slam/#run-slam-node)にはCartographerはソースを落としてきてビルドインストールする方法が提示されています(`Read more about other SLAM methods`内)

しかしながらこの方法、ビルドが必ずしも成功するとは限らない（投稿者はprotobuf系でエラーしギブアップ）うえ、以降のワークスペースのビルドにはcatkin_make_isolatedを使用しなければいけません
ROSをある程度理解している個人が触る分にはいいのですが、その環境を他の人が使う場合に戸惑いを与えてしまいます．

というわけで他の方法を調べた結果，どうやらこの方法使えるんじゃないか？を記しておきます．記事もなかなかヒットしなかったので，常識の範疇なのかもしれません

# 環境

- Ububtu18.04
- ROS melodic


# 本文

このインストールだけでよかった…

```bash
$ sudo apt install ros-melodic-cartographer-ros ros-melodic-cartographer-rviz
```

本文終わり.

# turtlebot3 simulationで利用する場合
turtlebot3 Simulationにて，gazebo上でCartographerを使用したslamをする場合は
`Run SLAM Node`で

```bash
$ roslaunch turtlebot3_slam turtlebot3_slam.launch slam_methods:=cartographer configuration_basename:=turtlebot3_lds_2d_gazebo.lua
```

と，argを１つ追加で設定する必要があります．

デフォルトは`turtlebot3_lds_2d.lua`ですね．
違いは22行目だけで，そこのコメントには
`imu_link, If you are using gazebo, use 'base_footprint' (libgazebo_ros_imu's bug)`
と書かれていました．
いつかこのバグが解決されたら良いですね…
504 Gateway timeout 解決方法 on AWS

# 504 Gateway timeout 解決方法 on AWS

Webシステムで、バックエンドで少々長い時間が掛かる処理が終わるまで待つ必要があるケースがありますが、デフォルト設定だと、大体60秒程でタイムアウトとなり、「504 Gateway timeout」が発生するという事が多いです。

AWSで、ELB->Apache->PHPと言うよくある構成で、どの様に設定して行くと良いかをメモがてら残しておきます。

## 構成

クライアント(ブラウザ） -> ELB(ALB) -> WEB(Apache -> PHP) -> DB(RDS on MySQL)

今回、DBは割愛します。

## タイムアウト調整

ユースケース次第ですがAWSのナレッジでは、KeepAliveTimeoutなどをロードバランサーのアイドルタイムアウトよりも長いキープアライブタイムアウトにするように推奨されています。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/apache-backend-elb/

例）無限にはできませんので、システム要件等で、程よいタイムアウト値を検討する必要があります。
クライアント（デフォルト：ブラウザ依存）　＜　ELB（60)　＜　WEB(Apache 120)　＜　WEB(PHP　120)

## それぞれ設定すべき箇所

少々極端ですが、10分(600秒)タイムアウトさせたくないとします。

### クライアント(ブラウザ）　※多分ここで調整することは無いと思います。
- Chrome
調べましたが、Chromeでタイムアウト設定を変更することはできないようです
タイムアウトが何秒なのかなどのドキュメントも見当たらない・・・

- Firefox
about:configから、「network.http.connection-timeout」を調整

- IE
レジストリで、 KeepAliveTimeout、ServerInfoTimeoutのDWORD値を調整
https://docs.microsoft.com/en-US/troubleshoot/browsers/change-keep-alive-time-out

- Safari
SafariNoTimeoutをアプリとしてインストールすると可能とのこと

### ELB アイドルタイムアウト

![スクリーンショット 2021-09-17 15.02.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44351/5ca2d087-d5b7-4300-3126-674844922746.png)

### Apache /etc/httpd/conf.d/aws_elb.confを作成して設定

例）600秒なので、1.25倍して、750秒にしてみました。

```/etc/httpd/conf.d/aws_elb.conf
# クライアントヘッダータイムアウト
# ロードバランサーでアイドル接続を適切に切断できるように、ロードバランサーに設定されたアイドルタイムアウトよりも大きな値に設定します。
# ロードバランサーに適切に通知せずに、バックエンドサーバーで接続を終了すると、504 エラーが表示されることがあります。
Timeout 750

# キープアライブ
# CPU 使用率を削減し、応答時間を改善するには、キープアライブをオンにします。
# キープアライブをオンにすると、ロードバランサーで、HTTP リクエストの度に新しい TCP 接続を確立する必要がありません。
KeepAlive On

# キープアライブオプションが有効になっている場合は、ロードバランサーのアイドルタイムアウトよりも長いキープアライブタイムアウトを選択します。 
KeepAliveTimeout 750

# キープアライブリクエストの最大数
# このオプションでは、キープアライブがオンになった時に単一の TCP 接続で処理するリクエストの数を設定します。
# リソースの使用を最適化するために、キープアライブリクエストの最大数は 100 以上に設定します。
MaxKeepAliveRequests 100

# AcceptFilter
# AcceptFilter はデフォルトで有効になっており、接続に TCP_DEFER_ACCEPT オプションを使用するよう Apache に指示します。
# この設定では、TCP ソケットが「ハーフオープン」状態になることがあります。
# この場合、ロードバランサーでは接続が確立されているが、バックエンドインスタンスでは接続が確立されていないことを前提とします。
# ハーフオープン接続は、性能が高くないロードバランサーで最も一般的です。この場合、使用前の接続に時間がかかります。
AcceptFilter http none

# ELB access_log format
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" combined

# Set over AWS ELB connection time out default 60s
# 長時間にわたる少量ずつの読み込み/書き込み処理を悪用する攻撃 (Slowloris など) に対して接続を自動的に閉じる
RequestReadTimeout header=750
```

### PHP

1. おなじみのphp.iniでmax_execution_timeの値で定義する方法

ただし、全体的にスクリプトが実行可能な秒数が伸びてしまうので注意が必要

```/etc/php.ini
;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;

; Maximum execution time of each script, in seconds
; http://php.net/max-execution-time
; Note: This directive is hardcoded to 0 for the CLI SAPI
max_execution_time = 60
```

2. 処理中に、set_time_limit(int $seconds): bool　で実行時間の最大値を制限する

https://www.php.net/manual/ja/function.set-time-limit.php

```
<?php

set_time_limit(750);

while ($i<=10)
{
        echo "i=$i ";
        sleep(100);
        $i++;
}

?>
```
結合テストを書いていく①

#はじめに
単体テストコードはフリマアプリ作成時にしっかり書いたのですが、結合テストは書いていなかったのでオリジナルアプリでは書いていきたいと思います。

その中で学習したことをアウトプットとして投稿させて頂きます。

#単体テストと結合テストの違い（単体テストの場合）

単体テストは機能ごとにテストを行います。

例えばuserの単体テストコードの場合

```ruby:user_rspec.rb
describe 'ユーザー新規登録' do
   context '登録できるとき' do
      it 'nickname,email,password,company_name,profession_idが存在する場合は登録ができる' do
      end
   end
   context '登録ができないとき' do
   end
end
```

モデルやコントローラーの機能ごとに問題がないかバリデーションの挙動を確認します。

# 単体テストと結合テストの違い（結合テストの場合）
結合テストの場合はユーザーがアプリを使用する一連の流れを確認するものになります。

ホームページ　→　新規登録ボタンをクリック → 新規登録フォームに入力し完了ボタンをクリック → ホームページに遷移する

この結合テストを実行するためには**System Spec**という技術を使用します。

この技術を使用するためには**Capybara**というGemが必要ですが標準で記載されているかと思われます。

#ファイルの作成
実施にテストコードを記述していくためにファイルを作成します。
今回はユーザーについての結合テストコードを記述していきます。


```:ターミナル
rails g rspec:system users
```
これでファイルは作成されます。

それではexampleを整理していきます
新規登録できる場合を考えていきます。

この時のポイントは、「ユーザー目線で考える」ことです。あまり細かく考えずに、「ブラウザでどのような操作をすると、どうなるのか」を考えます。

```spec>system>users_spec.rb
require 'rails_helper'

RSpec.describe "新規登録", type: :system do
  before do
    @user = FactoryBot.build(:user)
  end
  context 'ユーザーが新規登録ができる時' do
    it '正しい情報を入力すればユーザー新規登録ができてトップページに移動する' do
      # トップページに移動する
      # トップページにサインアップページへ遷移するボタンがあることを確認する
      # 新規登録ページへ移動する
      # ユーザー情報を入力する
      # サインアップボタンを押すとユーザーモデルのカウントが1上がることを確認する
      # トップページへ遷移したことを確認する
      # ログアウトボタンが表示されることを確認する
      # サインアップページへ遷移するボタンや、ログインページへ遷移するボタンが表示されていないことを確認する
    end
  end
end
```

実際にはアプリを操作しながら書いていくと分かりやすいです。
次は実施にコードを書いていきます。
dockerコンテナに複数のドメイン名でアクセスする（Docker for Windows）

Dockerコンテナにドメイン名でアクセスする場合[jwilder/nginx-proxy](https://hub.docker.com/r/jwilder/nginx-proxy/)を使うと簡単です。ここでは、１つのコンテナに複数のドメイン名でアクセスする方法を記載します。

```yaml:docker-compose.yml
services:
  proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

  app:
    build:
      context: ..
      dockerfile: ./docker/php/Dockerfile
    volumes:
      - ../app:/var/www/html
      - ./php/php.ini:/usr/local/etc/php/php.ini
    environment:
      - VIRTUAL_HOST=domain_1.local,domain_2.local,domain_3.local
      - VIRTUAL_PORT=8
```

環境変数のVIRTUAL_HOSTにカンマ区切りで書きます。

> Multiple Hosts
> If you need to support multiple virtual hosts for a container, you can separate each entry with commas. For example, foo.bar.com,baz.bar.com,bar.com and each host will be setup the same.

# 参考

https://qiita.com/sigelinde/items/95c154dc807a4bbc9cf0
Code Composer Studio(CCS)でパーソナルアクセストークンを適用する方法

## パーソナルアクセストークンを発行
以下のサイトの手順に沿って，アクセストークンを取得する。
取得したアクセストークンは忘れないようにどこかに保存しておく。
https://docs.github.com/ja/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token

## CCSにパーソナルアクセストークンを適用
前までパスワード認証だったため，パスワードの代わりに取得したアクセストークンをパスワードの代わりに入力することでCCSでGitができるようになる。
【Swift】クロージャ、トレイリングクロージャとは

# クロージャ
文の中に直接埋め込むことができる命令のかたまり
メソッドの処理内容を引数にそのまま記述できる

## Button構造体の例
Button構造体（UI部品）のドキュメントを見ると、以下のように記述されている。
![スクリーンショット 2021-09-17 13.53.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614948/73ae083a-5e52-c978-6319-5b25576f8e6c.png)

``` swift
init(action: () -> void, label: () -> label)
```

``` () -> void ``` この書式は「関数の型」を表している。
```->```の左側が「引数」で、右側が「戻り値の型」
つまり、引数actionには、「引数なし」で「戻り値」がない、
関数を指定すればよいということが分かる。

メソッドは関数の１種なので、引数actionにはメソッドも指定することができる。

## Buttonのactionにメソッドを入れてみる
今までの説明から以下にようなコードを記載することができる

``` swift
// actionにメソッドを指定
Button(action: count){
　Text("カウント")
}
// メソッドの宣言
func count(){
 self.number += 1
}
```
上記よりButtonが押下されたnumberプロパティに1加算されることになる。

Viewなどの記述は省略しているが、プレビューだと以下のようになる
![スクリーンショット 2021-09-17 14.24.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614948/bd8f19fd-f206-7f7e-7ca0-0e6347d469ac.png)


## 引数にクロージャを指定する
上記の記述だと、毎回Buttonの引数action:に、
メソッド名を指定しなければならない。

これが一度しか使わないメソッドの場合、コードが煩雑に見える。
そこで現れたのが**「クロージャ」**である

クロージャは、引数にそのままメソッドの処理内容を記述できる。

``` swift
// 中括弧{}に処理を記述
Button(action: {self.number += 1}){
　Text("カウント")
}

// メソッドは不要になる
// func count(){
//  self.number += 1
// }
```

## クロージャの書式
今までのクロージャは「引数」や「戻り値」がないため、省略した記述をしたが、
戻り値が存在する場合は、以下の記述が必要になる

``` swift
// 書式
{(引数名: 型) -> 戻り値の型 in
 文
}

// Button
Button(action: {() -> void in self.number += 1}){
　Text("カウント")
}
```

# トレイリングクロージャ
トレイリングクロージャとは、以下の条件の場合、
そのクロージャを()の中から外に出して、引数名を省略できること。

- 最後の引数がクロージャの場合

Button構造体のドキュメントで以下の記述があったと思う。

``` swift
init(action: () -> void, label: () -> label)
```
引数actionは先程クロージャにできたので、
引数labelもクロージャにすることができる。
※　labelはButton内のテキストを指定する
つまり、以下の記述が可能になる。

``` swift
Button(action: { self.number += 1}, label: { Text("カウント") })
```

しかし、 トレイリングクロージャの条件に当てはめると、
以下の記述ができる。

``` swift
// トレイリングクロージャ未使用
// 引数の最後がクロージャ
Button(action: { self.number += 1}, label: { Text("カウント") })

// トレイリングクロージャを使用
// 引数名labelを省略
// クロージャを()の外に出して記述
Button(action: {() -> void in self.number += 1}){
 Text("カウント")
}
```
# まとめ

- クロージャとは、引数の中にメソッドの処理を記述することができる
- トレイリングクロージャとは、引数の最後がクロージャで終わる時、そのクロージャを外に出すことができる
PowerPoint の動画書き出し機能を使って作った動画を、動画編集ソフトに入力すると動画の後半になればなるほど音がズレる件の対策

#はじめに
PowerPoint のセッション録画機能と動画書き出し機能、使ってますか！？

PowerPoint には「スライドショーの記録」という機能があって、自分のプレゼンテーションに事前にナレーションをつけることができるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199379/93c8e884-fdce-4809-e586-dc138c9b2435.png)
そして、事前にナレーションをつけたスライドで「エクスポート」機能の「ビデオの作成」を行うと、自分のプレゼンテーションをビデオ化することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199379/09248958-ec95-e018-eea5-25ef35400242.png)
この機能は、簡単にプレゼンをビデオ化したいときに便利なのでぜひ覚えていただいて活用いただきたいと思っています！
# 今回ハマったこと
そんな便利な PowerPoint のビデオの作成機能ですが、ちょっとしたハマりポイントがあります。
それがここの部分！
![2021-09-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199379/43111e4b-a7de-bcf3-5690-505bbdfaef48.png)
なんと、動画のフレームレートが、映像業界で一般的な 30fps でも 29.97fps でもなく、30.30fps という超中途半端な値になっている！
これを、DaVinci Resolve （ほかの編集アプリがどうかは試してないのでわかりません…）に入力すると、この中途半端なフレームレートを正しくハンドリングできていないのか、ビデオの後半になればなるほど、映像と音声のズレが発生してしまいます。多分 30 分経過時点で 1-2 秒ズレてると思います。
# Workaround
これを回避するためには、30fps の固定フレームレートに変換してしまうのが一番安全策！と思ったので、フリーのトランスコードツール、[HandBrake](https://handbrake.fr/) で変換してしまいました。

やっている中で、いくつかのハマりポイントがあったので、それも共有しておきます。
## NVEnc を使うとトランスコードエラー
もしかしたら NVEnc が中途半端なフレームレートをハンドリングできないのかもしれないです。トランスコードが無事に走り切ったように一瞬見えるのですが、レンダーキューのログを見ると、最後にエラーになってしまっていました。出力された映像は、DaVinci Resolve に読み込ませた時と同じように、後半ほど音がズレていました。

それを防ぐために、自分の環境では Intel の Quick Sync Video (QSV) を使うことにしました。
これで、エラーを防ぎつつも、音声と映像のあった 30fps の固定フレームレートのビデオが出力できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199379/57fc6f16-8597-5448-f954-bbda55eba5fd.png)
## 音声を再トランスコードするとノイズが発生する場合がある
音声についてはもともと AAC で保存されていますので、再トランスコードする必要はないはずなのですが、HandBrake のデフォルトの設定だと AAC などで再トランスコードする設定になっています。
この設定のまま進めると、音声にブツブツとノイズが入る場合がありましたので、PowerPoint の出力した音声そのままでパススルーさせます。
音声トラックのコーデック設定を "AAC Passthru" に設定すれば OK です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199379/60b192ff-e8ac-0b29-bcd5-10869bd16167.png)

#まとめ
上記の設定を行って HandBrake で 30fps 固定フレームレート化したビデオを入力したところ、DaVinci Resolve に読み込ませても音声と映像のズレは発生しなくなりました。

もし同じような事象に困っている方がいらっしゃいましたら、役に立ったら幸いです。
## おまけ
そもそも、変なフレームレートで PowerPoint が出力しなければこんなことにはならないので、ちゃんと 30fps のビデオを出力するようにしてほしい…。
コマンドプロンプトのプロンプトに色をつける方法

# はじめに

コマンドプロンプトを初めて見た時、真っ黒い画面に白文字の表示が怖かった思い出がある
一方、一部のLinuxのBashのプロンプトには、色がついていてコマンドプロンプトに比べてそこまで怖く無かった

そこで、コマンドプロンプトにも色をつけて怖さを半減させませんか？って話

## で、結局どうなるの？

こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283899/bb06a33d-950b-ba70-3c94-ad3b25edfabc.png)

## やり方

```batch
PROMPT $E[32m$P$E[0m$G
```

## 解説

1. `PROMPT`というコマンドは、プロントの見た目を変更するのに使う
1. `PROMPT`コマンドでは、通常の文字と特殊文字が使える
1. 特殊文字の中にエスケープシーケンス(`＄E`)がある
1. これを使うと文字にスタイル(太字や色等)をつける事ができる
1. `$E[32m`で文字を緑にする
1. $Pでファイルパスを表示(`C:\User\hogehoge`)
1. `$E[0m`で文字についたスタイルをリセットする
1. $Gで `>`を表示

※ `$E[0m`をやらないとその後の文字もスタイルが適応されてしまうので注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283899/4e8d7285-903c-a6cb-ec87-b7847750a7af.png)

### 文字色の対応表

|  構文 | 色 |
| ----- | - |
| $E[30m | 黒 |
| $E[31m | 赤 |
| $E[32m | 緑 |
| $E[33m | 黄 |
| $E[34m | 青 |
| $E[35m | マゼンダ |
| $E[36m | シアン |
| $E[37m | シロ | 

**※ エスケープシーケンの詳しい書き方はこちらの記事にのっている(こちらの記事はC言語なので`$E`と`\e`を置き換えて読む必要あり)**

https://qiita.com/PruneMazui/items/8a023347772620025ad6

## おわりに
現状コマンドプロンプトを起動し直すとせっかく設定したpromptが初期化されてしまう
`AutoRun`(command prompt版 .bashrcのようなもの)を設定すると良いかもしれない

https://hail2u.net/blog/software/cmd-autorun.html
各桁の和をpython, C++で実行する

各桁の和をpython, C++で実装するためのメモです。
普段はpythonをメインに使っていますが、勉強中のC++でどうかけるかを考えたので共有したいと思います。

## pythonの場合

pythonであれば、以下のように短くかけて簡単です。

```python
List = list(map(int, str(n))))
ans = sum(List)
```

ただし、nは入力した数字を指します。
1行目では文字列にしたnに対して、各位の数字を一個ずつint型に変換してlistに格納します。その後、２行目でsum関数を使って総和をとるという形です。

例えば```n=12345```という数字の場合、

```python
List = [1,2,3,4,5] #１行目  List = list(map(int, str(n)))　の結果
ans = 15 #2行目  ans = sum(List)　の結果
```
という感じです。

## C++の場合(イテレータを使う方法)

上記の内容と同じことをC++でもやりたいと思います。すなわち、文字列の各位をintに直して足していくというものです。

```cpp
int digit_sum(string n){
    int sum = 0;
    for(auto itr=n.begin();itr < n.end();itr++){
        sum += *itr - '0'; // *itrはchar型のため、数値に直すには'0'で引き算する。
    }
    return sum;
}
int main(){
    string n= "12345";
    cout << digit_sum(n) << endl;
}
```

ここではイテレータ```itr```を使いました。数字列の各位の値は```*itr```で取得できます。ただし注意として、各位の値は```char```型として得られるので、整数の数値に直す必要があります。その操作が

```cpp
sum += *itr - '0';
```
に相当します。


## C++を用いた別の方法(イテレータを使わない方法)

以下のような求め方の記事をしばしば目にします。

```cpp
int digit_sum(int n){
    int sum = 0;
    while(n){
    sum += n%10;
    n /= 10; 
    }
    return sum;
}
```
例えば```n=123```の場合、while文で以下のような操作が実行されます。

```
123%10 = 3 -> sumに追加
123/10 = 12

12%10 = 2  -> sumに追加
12/10 = 1

1%10 = 1 -> sumに追加
1/10 = 0 //終了
```

こっちはイテレータを使わないので、イテレータに慣れてない僕にとってはわかりやすかったです。

## まとめ
各位の和を求める方法をまとめました。単純な内容でしたが、色々な解法を見れて楽しかったですし、イテレータに慣れる良い機会になりました。
少しでも有益になれば幸いです。また、間違いや不正確な部分があれば教えていただけると幸いです。

参考

[char型をint型に変換する方法と注意【数値化 キャスト 文字列変換】](https://marycore.jp/prog/c-lang/convert-or-cast-char-to-int/)

[各桁の和の求め方](https://hacknote.jp/archives/28531/)
E資格2021#2合格　2ヶ月でラビットチャレンジクリア

現在日本の民間資格でもっとも名高いAIの資格はJDLAのE資格でしょう。
私はこれまでに、統計学を実務で使ってきましたが統計学の限界を現場で感じ、AIに少しずつ1年前くらいからシフトしてきました。
勉強の過程として、一般的な医療統計学の本の次に
・メディカルAI学会公認コース　https://www.japan-medical-ai.org/
・統計検定2級　https://www.toukei-kentei.jp/about/grade2/
を取り、Pythonを読めるようになりたくて更に
・Pythonデータ分析エンジニア
・Python基礎エンジニア
を取りました。
・G検定はコロナで安かったときにとりました。
そして、E資格を取ることにしました。
医療系でAIに詳しい人は殆どいないものの、医療の世界は「資格」が重視されます。
専門医、看護博士、医学博士、公衆衛生修士MPHなどなど。資格がないと素人のように見られてしまうのがこの狭い医療界隈です。

メディカルAI学会公認コースだけでなく、一般的にも知られている資格が取りたくて、今回E資格受験することにしました。

事前の講義のプログラムを受ける必要があるのが、E資格受験者が増えないネックだと思います。
このプログラム意味ない、資格だけ取らせてほしい、というエンジニアの方々はたくさんいらっしゃると思いますが、エンジニアではない私にとってはこの講義こそが非常に勉強になりました。また、最先端の知識が問われるので、シラバスも常に改定されています。Up to dateするためにも講義は勉強になりました。

プログラムはStudy AIのラビットチャレンジを申し込みました。https://ai999.careers/rabbit/
理由は安いから、それだけです。
2021年6月下旬に申し込み、毎日3-4時間取り組みました。7月中旬には最終ステージまで完了できて、修了ナンバーを頂きました。

最後の1ヶ月は、ラビットチャレンジの模擬試験を何度もときつつ、黒本3週をしました。
https://www.amazon.co.jp/dp/B096YB4WLQ/ref=cm_sw_em_r_mt_dp_V3006ST4PAMDG1YSD86B?_encoding=UTF8&psc=1

黒本や講義でわからないことは、アイシアさんのYouTubeで復習しました。https://www.youtube.com/watch?v=TLY2NPpxd58

合格することを目的とするならば、
・応用数学→高校の復習だと思って絶対満点を狙う
・機械学習→これも理論的に理解する分野なのでちゃんと理解する
・深層学習→これは世界史の暗記のようなもの。しっかり理解する必要はなく、ある程度キーワード方式で暗記する。
・開発環境→これは重要だし、暗記と少し考えれば理解できる。最近重視されている項目。
という意識を持って、黒本と模擬試験を過学習すれば合格できると思います。ただ、丸暗記ではだめで、なんとなくその特徴的なフレームワーク内の機構の意味を理解している必要があります。今回の試験は、暗記じゃだめなんだな、と強く感じました。

いわゆるゼロつく、赤本は、講義の内容と丸かぶりですし、メディカルAIの脱ブラックボックスコースと内容もかぶっています。あえて勉強し直す必要はないかなと思いました。中古で買ってぱらっとよんですぐに売りました。

8月28日試験を受けました。他にも8人くらい受けに来ていました。
本番の様子は他の方のブログなどにあるとおりです。120分の内、100分くらいでとき終わって、見直しする時間はちゃんと有りました。電卓もあり、計算問題はそこまでたくさんではなく、もらったA4のホワイトボードの2/3くらいの使用量でした。

結果は試験の3週間後の金曜日の午前に発表されました。
下記の成績でちっとも良くはないですが、医療系でAIに詳しい人、とE資格をとったことで堂々と言うことができます。
=================
【　合　格　】
=================
総受験者数　 1,170名
合格者数　　　872名


■分野別の得点率

応用数学：82 ％
機械学習：67 ％
深層学習：76 ％
開発環境：86 ％

最近はアプリ開発会社からのお誘いもあるので、そちらの方で医療界隈をDX化していこうと思います。
簡単ではありますが、2ヶ月でどうにか合格した方法でした。


・
ラズパイのタイムゾーン変更

#本記事の内容
- ラズパイのタイムゾーンをJSTに変更する

ラズパイでdateコマンドを打ったらJSTでなかったので、わかりやすくするためにJSTに変更を行った。

#実施環境
- Windows 10
- TeraTarm Version 4.9.4
- Raspberry Pi 2 Model B
- PLANEX 無線LAN子機 GW-USNANO2A ※Raspberry Pi 2はWi-Fi通信モジュールがないため、無線LAN子機をUSBに接続しWi-Fi通信を行う。
- 家庭内の無線LANネットワーク環境にて実施

#手順の流れ 
1. TeraTarmでsshログインする
2. raspi-configでの設定
3. 設定の反映確認

## 1. TeraTarmでsshログインする

WindowsにてTeraTarmを起動して、ラズパイにSSH接続する。

## 2. raspi-configでの設定

`sudo raspi-config`コマンドを実行する。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/d4441cd8-e246-554a-817e-33693b34c0e0.png)
"5 Localisation Options"を選択

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/c92b67d3-fb0b-aff9-df0b-b560f7f9ecae.png)
"L2 Timezone"を選択

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/11fd52e0-59ac-19f4-b08f-84336d154ddc.png)
"Asia"を選択

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/5c5b91f2-9c4a-c73b-49c6-a64541177d64.png)
"Tokyo"を選択

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017667/1dcd3b82-f074-198a-2d0c-061715cffd9e.png)

"Finish"を選択

## 3. 設定の反映確認

`date`コマンドにてJSTに変わったことを確認する。

	pi@raspberrypi:~ $ date
	Thu 16 Sep 10:03:49 JST 2021
	pi@raspberrypi:~ $

JSTになったことを確認できた。

手順は以上。
htmlで丸付き数字を文字化けせずに表示させる方法

htmlで丸付き数字を入力すると文字化けした「？」になるのを防ぐ方法です。
対応するコードを入力すれば、丸付き数字を表示させることができます。

表示→コード
（白大）
①→ ```&#9312;```	⑪→ ```&#9322;```
②→ ```&#9313;```	⑫→ ```&#9323;```
③→ ```&#9314;```	⑬→ ```&#9324;```
④→ ```&#9315;```	⑭→ ```&#9325;```
⑤→ ```&#9316;```	⑮→ ```&#9326;```
⑥→ ```&#9317;```	⑯→ ```&#9327;```
⑦→ ```&#9318;```	⑰→ ```&#9328;```
⑧→ ```&#9319;```	⑱→ ```&#9329;```
⑨→ ```&#9320;```	⑲→ ```&#9330;```
⑩→ ```&#9321;```	⑳→ ```&#9331;```
（黒大 白小 黒小）
❶→ ```&#10102;```➀→ ```&#10112;```➊→ ```&#10122;```
❷→ ```&#10103;```➁→ ```&#10113;```➋→ ```&#10123;```
❸→ ```&#10104;```➂→ ```&#10114;```➌→ ```&#10124;```
❹→ ```&#10105;```➃→ ```&#10115;```➍→ ```&#10125;```
❺→ ```&#10106;```➄→ ```&#10116;```➎→ ```&#10126;```
❻→ ```&#10107;```➅→ ```&#10117;```➏→ ```&#10127;```
❼→ ```&#10108;```➆→ ```&#10118;```➐→ ```&#10128;```
❽→ ```&#10109;```➇→ ```&#10119;```➑→ ```&#10129;```
❾→ ```&#10110;```➈→ ```&#10120;```➒→ ```&#10130;```
❿→ ```&#10111;```➉→ ```&#10121;```➓→ ```&#10131;```
AWSIOT: デバイスデータを Kinesis データストリームに送信

data/sample にパブリッシュされたデータを
sample_kinesis_sep17 というKinesis データストリームに送信します。

次の５ステップになります。

1) IAM でロールを作成

>ロール名　role_sep17

2) IAM でポリシーをロールにアタッチ

>Kinesis にアクセスできるポリシーをアタッチ

3) Kinesis でデータストリームを作成
> ストリーム名　kinesis_sep17

4) IOT でルールを作成
>ルール名　rule_sep17

##ロールを作成##

```bash
ROLL_NAME="role_sep17"
#
aws iam create-role --role-name $ROLL_NAME --assume-role-policy-document file://iot-role-trust.json
```

```json:iot-role-trust.json
{
  "Version":"2012-10-17",
  "Statement":[{
      "Effect": "Allow",
      "Principal": {
        "Service": "iot.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
  }]
}
```

##ポリシーをロールにアタッチ##

```bash
ROLE_NAME=role_sep17
#
aws iam attach-role-policy --role-name $ROLE_NAME \
	--policy-arn "arn:aws:iam::aws:policy/AmazonKinesisFullAccess"
```

##Kinesis データストリームを作成##

```bash
STREAM_NAME="kinesis_sep17"
aws kinesis create-stream --stream-name $STREAM_NAME --shard-count 1
```


##IOT ルールを作成##

```bash
RULENAME="rule_sep17"
#
aws iot create-topic-rule --rule-name $RULENAME \
	--topic-rule-payload file://iot_kinesis.json
```

```json:iot_kinesis.json
{
  "sql": "SELECT * FROM 'data/sample'",
  "ruleDisabled": false,
  "awsIotSqlVersion": "2016-03-23",
  "actions": [
    {
      "kinesis": {
        "roleArn": "arn:aws:iam::123495704257:role/role_sep17",
        "streamName": "kinesis_sep17",
        "partitionKey": "${topic()}"
      }
    }
  ]
}
```

##テスト##

data/sample にデータをパブリッシュします。
パブリッシュをするスクリプトのサンプルはこちら
[AWSIOT: デバイスデータを DynamoDB に保存](https://qiita.com/ekzemplaro/items/7ac9f44e0d5ad6bf8e63)

ストリームにあるデータの数を数えます。

```py:record_coount.py
#! /usr/bin/python
#
#	record_count.py
#
#					Sep/17/2021
#
import boto3
import sys
#
name_stream='kinesis_sep17'
#
client = boto3.client('kinesis')
response = client.get_shard_iterator(
    StreamName=name_stream,
    ShardId='shardId-000000000000',
    ShardIteratorType='TRIM_HORIZON',
)

#
shared_iterator = response['ShardIterator']
#
response = client.get_records(
    ShardIterator=shared_iterator,
    Limit=10
)
#
llx = len(response['Records'])
sys.stderr.write("llx = %d\n" % llx)
#
```
CodeceptJSとPuppeteerでE2Eテスト（AutoLogin）

#初めに
[前回の記事](https://qiita.com/abe_n/items/5ae8cc17179dd27683d4)の続きです。
今回はAutoLoginの機能を触ってみました。

公式の通りにやろうとしてうまく動かず、他サイトを参考にコードを書きました。
fetchなどいろいろと理解が怪しいですが、できたところまでまとめていきます。

#AutoLogin
AutoLoginというプラグインがCodeceptJSにはあり、Cookieをメモリまたはファイルに保存することで自動的に再度ログインすることができます。

##コードを書く
インストールは前回記事と同様です。
追加でcodecept.conf.jsへの追記をすることで自動ログインさせることができます。

```
//codecept.conf.js

plugins: {
    
    //ここから追記
    autoLogin: {
      enabled: true,
      saveToFile: true, 
      inject: 'login',
      users: {
        user: {
          //Cookieを設定
          restore: (I, cookie) => {
            I.amOnPage('URL')
            I.setCookie(cookie)
          },
          //ユーザーがログインしていることを確認
          //例えばログイン時のみ表示されるものの確認など
          check: (I) => {
            I.amOnPage('URL')
            I.waitForElement('要素指定')
          },
          //checkでログイン状態でないと判定された場合は再度ログインする
          login: (I) => {
            I.amOnPage('URL')
            I.fillField('ユーザー名', 'ダミー')
            I.fillField('パスワード', 'ダミー')
            I.click(''要素指定')
            I.waitForElement(''要素指定')
          },
        },
      },
    },

  },

```

・saveToFile（デフォルト：false）：Cookieをファイルに保存
・inject（デフォルト：login）：使用するログイン関数の名前
・login：システムにサインイン
・check：ユーザーがログインしていることを確認
・restore：Cookieを設定

restoreが実行された後、checkによりログインしていることを確認します。
これらが失敗した場合、loginが実行されてログインします。
fetchの使い方がまだ分かりません……

login時にwaitForElementで完全にログインさせることがポイントのようです。
参考）[こちらのサイト](https://qiita.com/tsuemura/items/9b57dfd99277f0db48d7#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)

また、codecept.conf.jsに複数ユーザーの設定を書くことも可能です。
詳しくは[公式サイトへ](https://codecept.io/plugins/#autologin)


あとはテストコードを書きます


```
Feature('自動ログイン')

Scenario('サイトにログイン', async({ I, login }) =>{
  login('user')
  I.see('要素指定')
})

Scenario('サイトにログイン、二回目', async({ I, login }) =>{
  login('user')
  I.see('要素指定')
　I.fillField('検索:', 'ダミー')
  I.pressKey('Enter');
})

```

[公式サイト](https://codecept.io/plugins/#autologin)にはBeforeを使った方法で記載がありましたがうまく動かせず、[こちらのサイト](https://qiita.com/tsuemura/items/9b57dfd99277f0db48d7#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)を参考に書きました。

codecept.conf.jsでuserという名前で設定した情報を使ってログインしています。

前回同様、バージョンによって書き方が違うことに注意↓ （戒め）

```
async({ I, login })
```

これで実行すると、最初はログインするための情報を入力する動きが見られますが
二回目からは自動でログインして進んでいきます。

実行が終わるとoutputフォルダにuser_session.jsonのファイルが増えていると思います。
ここにuserのCookieが保存されています。

codecept.conf.jsで複数の情報を記載した場合、その分だけファイルが作られるはずです。
↓の場合user_session.jsonとtest_session.jsonのファイルができます。

```
//codecept.conf.js
users: {
        user: {
          //省略
        },
        test: {
          //省略
        },
      },
```


#終わり
公式サイトとしばらく睨めっこしてましたが参考サイトのおかげでなんとか動かせました。
ファイルに保存して使いまわせるのは便利ですし、テストコードが短いのも有難いです。


#参考
https://qiita.com/tsuemura/items/9b57dfd99277f0db48d7#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB

https://codecept.io/plugins/#autologin
【Unity】ラムダ式とデリゲート型

C++でお世話になっていたラムダ式を、Unityでも利用したいと思い調べました。

``` c:C++のラムダ式
auto Func = [](){};
Func();
```
``` c#:C#のラムダ式
using System;
using System.Threading.Tasks;

Action Func = () => {};
Func();
```

C++ のようにいちいちデリゲート型を宣言せずに型推論で利用したいところですが、「var」にラムダ式で生成した関数を入れようとするとコンパイルエラーになるので、どうしても利用したい場合には補助メソッドを作る必要がありそうです。(追記：`C# 10.0` ではすでに実装可能とのことです)

- **主なデリゲート(関数を入れる変数)**
    - Action
    - Action<引数の型>
    - Func<返り値の型>
    - Func<返り値の型, 引数の型>


ラムダ式やデリゲート型については下記サイト様が詳しく説明されています😊
　➡ https://qiita.com/toRisouP/items/98cc4966d392b7f21c30
【備忘録】開発環境の作り方 - PHP、GIT、Apache インストール -

# Git2 インストール

    # yum remove -y git
    # yum install https://repo.ius.io/ius-release-el7.rpm https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
    # yum install libsecret pcre2
    # yum install git --enablerepo=ius --disablerepo=base,epel,extras,updates
    # git --version
    # yum-config-manager --disable ius

# PHP7.4 インストール

    # yum install epel-release
    # rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
    # yum install --enablerepo=remi,remi-php74 php php-devel php-mbstring php-pdo php-gd php-openssl php-xml 
    # php -v

    (webサーバーを先に稼働させている場合は再起動する)
    # systemctl restart httpd.service

# Composer インストール

    # php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    # php composer-setup.php
    # php -r "unlink('composer-setup.php');"
    # mv composer.phar /usr/local/bin/composer

# Webサーバーインストール

    # yum install -y httpd
    # systemctl enable httpd.service
    # systemctl start httpd.service
    # firwall-cmd --add-service=http --permanent
    # firwall-cmd --reload
ZooKeeper とは

## 勉強前イメージ

なんか掃除するやつ？
クリーニングする的なやつかと思うけど・・・

## 調査

### ZooKeeper とは

分散プロセスとアプリケーションを調和させるソフトウェアで
簡単に言うと分散のアプリケーションを構築する上で必要な機能を提供するサービスです。
アパッチソフトウェア財団からオープンソースとして公開されています。
また、このようなサービスのことを `コンビネーションサービス` と呼びます。

### 主な機能

- 共有設定

複数のインスタンスで使用する設定の共有ファイルをZookeeperに保存し、
各インスタンスはZookeeperから設定ファイルを取得することで同一の設定を行うことが出来ます。

- 分散ロック

分散環境で同時にリソースを書き換えると整合性が取れなくなってしまうので、
そのためのロック機能があります。

- メンバー取得

インスタンスがエフェメラルノード(データの読み書きは出来るがプロセスが切れると自動消失)を設定しておくことで、
インスタンスの一覧が取得でき、アクティブ状態のインスタンスに接続できます。

- ウォッチ

ノードをウォッチの対象とすると、そのノードに変更があった際はプロセスに変更が通知され
設定ファイルのリロードなどのトリガーに使用されます。

- マスター選出

マスターのインスタンスがデータの管理を行うが、マスターがダウンすると残りのインスタンスからマスターが選ばれ、
更新を行うことが出来る。

### 特徴

- 高スループット/低レイテンシー

各データはメモリ内に保存されるので、高スループット 低レイテンシーが実現できます。

- 冗長化

複数のインスタンスにインストールし利用できます。
可用性を高め、性能向上も出来ます。

- 階層的名前空間

Zookeeperはデータをな前空間で保存します。
複数のインスタンスに分散しているプロセスを名前空間で共有することで分散処理を進めます。

## 勉強後イメージ

聞いたことあったけど全然知らなかった
分散処理のめんどくさいことを引き受けてくれるものなのね。
どうやって導入するとかはまだイメージついてないけど、そういうものって覚えておく。

## 参考

- [管理が困難―分散処理の常識はZooKeeperで変わる](https://atmarkit.itmedia.co.jp/ait/articles/1206/22/news142.html)
- [オープンソースの運用管理・運用自動化／Apache ZooKeeperとは](https://www.ossnews.jp/oss_info/Apache_ZooKeeper)
【備忘録】開発環境の作り方 - ホストとゲスト間のSSH接続 -

# SSH接続 (putty)
クライアント

    秘密鍵と公開鍵の作成 (作成済みの場合は次の手順へ)
        公開鍵をサーバーへ転送
            > cd C:\Users\[User]\.ssh
            > scp id_rsa.pub user@192.168.11.10:id_rsa.pub
            (yes -> password)

        認証ファイル指定
            Connection → SSH → Auth
                Private key file for authentication
                    C:\Users\(user)\.ssh\id_rsa.pub

        設定ファイル作成
            C:\Users\post\.ssh\config を編集
                Host bridge
                    HostName 192.168.11.10
                    User tonoaki_sato
                    IdentityFile C:\Users\post\.ssh\id_rsa.pem
                    Port 22
                    TCPKeepAlive yes
                    IdentitiesOnly yes

サーバー

    $ cd ~/
    $ ssh-keygen -i -f id_rsa.pub >> authorized_keys    // ファイル形式変換(putty -> openssh)
    $ mkdir .ssh
    $ chmod 700 .ssh
    $ mv authorized_keys .ssh
    $ chmod 600 .ssh/authorized_keys
    $ rm -f id_rsa.pub

# SSH接続 (VScode)

    上記の設定が済んでいる事
    VScode起動 → 左下の緑色の部分をクリック → 「Connect to host」→ 「bridge」をクリック
Apex の Mapの使い方

すぐに忘れるので、記録しておきます。

```
Map<Id, Account> mapAccount = new Map<Id, Account>([SELECT Id, Name FROM Account WHERE Id=:Trigger.New[0].AccountId]);
        	
for(Contact cont: Trigger.new){
    if(cont.Id != null && mapAccount.containsKey(cont.AccountId)){
       t.AccountName__c = mapAccount.get(cont.AccountId).Name;
    }
} 
```

[Hola a todo el mundo! Necesitaría asesoramiento personal sobre una pequeña prueba de salesforce](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Bs5q2SAB)


#関連情報
[効率的なSOQLの書き方](https://qiita.com/Keiji_otsubo/items/8d4e0cb869fbfc7410d8)
CSS remとemの単位 レスポンシブ

###理解しておく利点
親要素と子要素の比率の関係を変更したくない場合に実装が簡潔になる

#em
「現在指定されているフォントサイズ」に対して相対的な大きさを指定

##子要素のフォントサイズを指定しない場合
親要素のサイズが適用される。
例えば
親要素が```font-size: 40px;```のとき、
中の子要素は、```font-size: 40px;```の大きさに。

##子要素のフォントサイズを2emなどにした場合
親要素の二倍のサイズが適用される。
例えば
親要素が```font-size: 40px;```のとき、
中の子要素は、```font-size: 80px;```の大きさに。

###メリット
フォントサイズ（親要素）を変更すると、中の画像（子要素）も同じ比率で拡大縮小される

#rem
「htmlで指定さているフォントサイズ」に対して相対的な大きさを指定

##
htmlタグはデフォルトサイズが```font-size: 16px;```それに対して2倍や0.5倍



```
#デフォルトのフォントサイズを10pxに
html {
font-size: 62.5%;
}
#デフォルトのフォントサイズと同じ大きさにする
img {
width: 1rem;
}
```

###メリット
プロジェクト全体でhtmlのフォントサイズを指定してそれを基準にできる
dpkg-deb: error: 'sbt.deb' is not a Debian format archive でエラーになる

ubuntu/debian に sbt をインストールするときに、

```terminal
curl -L -o sbt.deb https://dl.bintray.com/sbt/debian/sbt-$SBT_VERSION.deb && \
   dpkg -i sbt.deb && \
   rm sbt.deb && \
   apt-get update && \
   apt-get install sbt
```

これだと、タイトルにある通りエラーになります。

```terminal
#26 0.377 dpkg-deb: error: 'sbt.deb' is not a Debian format archive
#26 0.377 dpkg: error processing archive sbt.deb (--install):
#26 0.377  dpkg-deb --control subprocess returned error exit status 2
#26 0.386 Errors were encountered while processing:
#26 0.386  sbt.deb
```

回避方法は、``https://dl.bintray.com``ではなく``https://repo.scala-sbt.org``からインストールするようにします。

```terminal
curl -L -o sbt.deb https://repo.scala-sbt.org/scalasbt/debian/sbt-$SBT_VERSION.deb && \
  dpkg -i sbt.deb && \
  rm sbt.deb && \
  apt-get update && \
  apt-get install sbt
```

これで、sbt をインストールできます。
AWS CLIとjqコマンド

# version
```
$ aws --version
aws-cli/2.0.25 Python/3.7.4 Darwin/20.6.0 botocore/2.0.0dev29
$ jq --version
jq-1.6
```

# 備考
記事は、読みやすいように、全てAWS CLIのレスポンスを直接jqコマンドで分析しているが、
ファイルに吐き出した方が後にモミモミしやすい

(例)

```
aws ec2 describe-instances > describe-instances.json
cat describe-instances.json | jq '.Reservations[].Instances[].Tags[] | select(.Key == "Name") | .Value' -r
```

# ec2 describe-instances
## インスタンス名一覧取得
```
aws ec2 describe-instances | jq '.Reservations[].Instances[].Tags[] | select(.Key == "Name") | .Value' -r
```

# elbv2 describe-load-balancers
## LoadBalancerName一覧取得
```
aws ec2 describe-load-balancers | jq .LoadBalancers[].LoadBalancerName -r
```

# cloudfront list-distributions
## DomainName一覧取得
```
aws cloudfront list-distributions | jq .DistributionList.Items[].DomainName -r
```

## カスタムドメイン一覧取得
```
aws cloudfront list-distributions | jq '.DistributionList.Items[] | select(.AliasICPRecordals) | .AliasICPRecordals[].CNAME' -r
```

# lambda list-functions
## FunctionName一覧取得
```
aws lambda list-functions | jq .Functions[].FunctionName -r
```
アバターアップロードするときに陥った罠(備忘録)

# 始めに
とても緩く行っているゆえに発生した罠。
もっとこうしたほうがいいよとかあればコメントしてもらえると喜ぶと思います。


#ここから本題↓

### ●アバターアップロード成功したけど透明だ……アバターの枠はあるけど表示される3Dモデルが透明だ……

 ●原因
"VRC Avater Descriptor(Script)"を入れている"hierarchy"の階層が変なところに入れていた。
<font color="Red">正解は、アバターのプレハブ一番上</font>
なぜかbodyに入れてもアップロードできたのが悪いｗ

```:仮想"hierarchy"
◆アバター（OK :ここに入れるのが正解）
　┠body　（NG :ここに入れてもアップロード成功するので起こった）
　┗アーマチュアーとか
　　┗Hips
　　　　┠以下省略
```

### ●アニメーションで表情をセットしたけどなんか表情が崩壊する……どこかのタイミングでなんで？

●原因
アニメーションは暗黙的に指定していないブレンドシェイプを0にしてくれないときが多い

●対策
<font color="Red">idol（初期状態）のアニメーションはすべてのブレンドシェイプを表示しておくこと。</font>
項目増やすとこうなるので入れているもので対応すること。
MMDもそんな仕様だった気がする（書いてないものは対応しない）

-------------
### this avater users Cisemes but the Face Mesh is not specified.
リップシンクの設定を忘れてた。（ブレンドシェイプautoにしてた）

LipSincのmodeを
"Vimes Vlend Shape”に設定してきちんと内容を設定しよう
ただし以下の項目は他のと被らないようにする必要があるとどこかで聞いた（ワニさんの動画だったかな？）
Vime:aa、Vime:E,Vime:ih,Vime:Vime:oh,Vime:ou

-------------

#締めの言葉
多分ちゃんと手順見れば書いてあったんだろうけど、遭遇しないと頭に入らないからね、仕方ないね。

-----
気が向いたときに更新

以上
Swift CustomNSErrorを利用して、より詳しいエラー情報を定義する

## 概要
`CustomNSError` を使ってより詳細なエラーを定義します。

## はじめに
Swiftでコーディングするとき、何かの失敗を表すときに `Error` を使うことがよくあるかと思います。

```swift
enum MyError: Error {
    case one
    case two
}
```

エラーを見て何が起こったかを調べて問題を解決していくことがあると思いますが、
例えば次の `analyzeError` のような、MyErrorに限らず何のエラーが来るかわからない`Error` を引数に取った場合、一度`NSError` に変換することによってdomainやcodeなど、より詳しい情報を得ることが可能です。

```swift
enum MyError: Error {
    case one
    case two
}

func analyzeError(error: Error) {
    let nsError: NSError = error as NSError
    print(nsError.domain) // __lldb_expr_1.MyError
    print(nsError.code) // 0
    print(nsError.userInfo) // [:]
}

analyzeError(error: MyError.one)
```

このように、単なる `Error` を設定すると、domainおよびcodeは自動で決定され、userInfoには空の辞書が入っています。


## CustomNSError
`CustomNSError` を使うと、domain、codeおよびuserInfoの定義が可能になります。
`errorDomain` はdomain、`errorCode` はcode、`errorUserInfo` はuserInfoとして表現されるようになります。


```swift
enum YourError: Error {
    case one
}

enum MyError: CustomNSError {
    case one([String : Any])
    case two

    var errorCode: Int {
        switch self {
        case .one:
            return 1
        case .two:
            return 2
        }
    }

    var errorUserInfo: [String: Any] {
        switch self {
        case .one(let userInfo):
            return userInfo
        case .two:
            return [:]
        }
    }

    static var errorDomain: String = "CustomMyError"
}

func analyzeError(error: Error) {
    let nsError: NSError = error as NSError
    print(nsError.domain) // CustomMyError
    print(nsError.code) // 1
    print(nsError.userInfo) // ["NSUnderlyingError": __lldb_expr_7.YourError.one]
}

analyzeError(error: MyError.one([NSUnderlyingErrorKey : YourError.one]))
```
ポリリズムを視覚的に理解できるメトロノームを作った！(JavaScript)


ポリリズムを視覚的に理解できるメトロノームを作りました！

https://mwsr.khufrudamonotes.com/polyrhythm-metronome

https://twitter.com/k1mu0419/status/1436971043080445952?s=20

実際に、自分がポリリズムを考えるときのイメージに近いものになっています。

# ポリリズムって何？

“ポリ(poly)“は、”**複数**の“、”**多数**の“などを意味する言葉です。
あの「ポリゴン（多角形）」や「ポリマー（重合体）」の”ポリ“でもあります。

つまり、ポリリズムとは

**複数の「リズムのまとまり」が重なって進行しているリズム**を指します。

（詳しくはこちら↓）

https://khufrudamonotes.com/polyrhythm-map

# なぜ作ったのか

### 現在の記譜法の弱点

![music_gakufu_open.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486558/b93c6d53-08b3-76e8-0745-804f12aa9f22.png)

現在の楽譜は、旋律（メロディー）や和声（コード）を記述するのに適しています。
しかし、律動（リズム）に関しては…ぶっちゃけイマイチな部分もあります。

その中でも大きな問題点が、"<b>対ポリリズム記述性能の低さ</b>"です。

複雑なポリリズムを含む曲は少ないので、困っている人は少ないと思いますけど。笑

…ただ、逆の視点から見れば「楽譜に書きにくいからアイデアが抑圧されている」とも考えられます。
（実際に、旋律（メロディー）や和声（コード）は、現在の記譜法の発展とともに複雑化していった歴史もあります。）

https://khufrudamonotes.com/rhythm-math


### ポリリズムを分かりやすく説明したい

この楽譜に表しにくいポリリズム。

「分かりやすく表せたらいいな～。でも、どうやってプログラム書いたら良いわからん…。」みたいな状態が続いていました。

しかし、独学で少しずつプログラミングの勉強を始めて約4年。

「あれ…今なら作れそうじゃね？」と思ったので、挑戦してみたら…なんとかできました！！


# 課題（現在は解決済み）

ただ、課題もあります。
端末によっては、（処理が重たいせいか）**ちゃんと動かない**可能性があるところです。

手持ちのPC(WindowsとMac)から使う分には、ちゃんと動いてる気がします。

…ただ、スマホ(iPnone)から使うと、処理が重たいせいか…ちゃんと動きません。
（友達に試してもらったら、友達のスマホ(Android)は大丈夫っぽかったです。）

あらゆる端末で安定的に動作させる方法を知っている方がいたら、教えていただけるとありがたいです。

ちなみに、現在はメトロノームの音や色付けの切り替えの実行はJavaScriptの<b>setInterval</b>を使っています。

```main.js
//以下のコードはイメージです。

//メトロノームの音を鳴らしたり色付けをする関数
function metronomePlay(){
 //処理の中身　ホントは100行以上ある
};

//指定した時間(intervalTime)ごとに、setIntervalで関数を実行する。
setInterval(metronomePlay() , intervalTime);

```

# 追記

コメントで「**Web Audio API**を使ってみたらよいのでは？」と教えていただいたものの、当時は難しくて断念してしまいました。

しかし、2年以上の時を経て、処理を**Audio Web Api**を使ったものに修正しました！

これが出来たのは自身のプログラミング能力の向上も多少はありますけど、**ChatGPT**の存在が大きいです。いやー、**ChatGPT**ってホント便利ですね。

ただ、結果的に元のコードの**95%以上**を書き直したのでかなり大変でした。笑

でも、新しく**プリセット機能**や**状態をURLにコピーできる機能**なども追加して、個人的には「**オンラインで動作するウェブメトロノームでこれ以上便利なものあるかな？**」と思えるクオリティになったので満足です。

## ちなみに

**変拍子対応のメトロノーム**も作りました。
こっちも（もしかしたらこっちの方が）便利ですよ。

https://mwsr.khufrudamonotes.com/metronome
共通ライブラリがみつからない(cannot open shared object file)エラー対処方法


# 環境

- Ubuntu Linux 20.04 (AWS)

# 用語

- 本記事では「共通ライブラリ = shared object file = soファイル = *.so」 としている

# トラブル

- shared libraries のパスを設定しているにも関わらず、ライブラリがみつからないという旨のエラーが発生
- 以下、エラーメッセージ（アプリケーションに依存したメッセージかもしれない）

```
error while loading shared libraries: *.so: cannot open shared object file: No such file or directory
```


# Ubuntu が shared libraries を探すパスの確認方法

- パスの一覧を以下のコマンドで確認
 
```
cat /etc/ld.so.conf.d/*
```

- 以下は実行結果
- `/etc/ld.so.conf.d/` に、共通ライブラリのパスを書いたconfファイルを保存する仕組みのようだ
- アプリは、このフォルダ内にあるconfファイルに書かれたパスをもとに soファイルを探すというようになる

```
# libc default configuration
/usr/local/lib
# Multiarch support
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
```


# Ubuntu が shared libraries を探すパスの設定方法

- 新規にパスを書いた `conf` ファイルを作成


```
vim /etc/ld.so.conf.d/additive_path.conf
```

- 以下は、ファイルの内容

```text:/etc/ld.so.conf.d/additive_path.conf
/usr/lib64
```

# トラブル（再確認）

- `additive_path.conf` に `*.so` があるパスを書いて保存しているにも関わらず、*.soファイルがないというエラーが発生

# 解決方法

- 以下のコマンドを実行
- shared libraries のパスが反映されて、Ubuntuがライブラリを発見することができた
- キャッシュが効くかもしれないので再起動が必要かもしれない、とのこと（筆者の環境では、再起動しても反映されず、 `ldconfig` 実行直後にパスが反映された

```
sudo ldconfig
```

# 理由

- 32ビットと64ビットのアーキテクチャを1つのシステムで実現できるようにしていて、それを実現するために `ldconfig` コマンドを実行する必要がある、ということのようだ（よくわかっていない）

# 付録

- 以下の環境変数でも、ライブラリのパスを設定できる

```
export LD_LIBRARY_PATH=/usr/lib64
```

- `LD` は、 `LOAD` または　`LOADER` の略のようだ


# 参考

https://askubuntu.com/questions/350068/where-does-ubuntu-look-for-shared-libraries

https://stackoverflow.com/questions/1814459/what-ld-stand-for-on-ld-library-path-variable-on-unix
OracleDBのセッションキルについて

TNSにTCP/IPのkeepAlive設定を組み込んだ後に、訳あってSQLdeveloperの強制終了とかをした時、なかなかセッションキルができなかったので備忘録として残しておきます。

参考リンク
①https://communities.curl.com/showthread.php?tid=1084
②https://dekiruengineer.com/engineer/how_to_find_os_processes_oracle_killing_session/

# keepAlive設定について
TNSに ENABLE=BROKEN を追加すると、OSのTCP/IPのKeepAliveが有効となる

```
XXXDB =
  (DESCRIPTION =
    (ENABLE=BROKEN) ←追加
    (ADDRESS_LIST =
～～～
  )
```

#### TCP/IPのkeepAlive設定
##### Windowsの場合※レジストリ設定の反映には要再起動なので注意
```
レジストリ HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
KeepAliveTime(DWORD 32ビット) の値
デフォルト: 7200000 (ミリ秒)
```

##### Linuxの場合
```
/etc/sysctl.conf の net.ipv4.tcp_keepalive_time の値
デフォルト: 7200 (秒)
```

# 肝心のOracleDBセッションキルについて
最初はSQLdeveloperのセッションモニターから、対象セッションを選択して右クリック→セッションの中断でキルしようとした（keepAlive設定前はだいたいこれだけでOKだった）が、一度実行した後もゾンビみたいなセッションが残り続けてしまう現象が発生。←多分SQL実行中に強制終了したせい…
再度セッションの中断を実行するが、ユーザーIDがない？とか言われてエラーとなり、セッションキルができない事態に。。

ググったところ、文頭記載の参考リンクにたどり着いた。
windowsマシンのoracleDBなら、①リンク先のorakillコマンドで停止できるそうだが、生憎linuxマシンのoracleDBだったので、②リンク先のプロセスキル方式で対応した。
その際のプロセスID確認SQLは①リンク先のものを使用して上手くいきました。引用先様ありがとうございます！ :bow:
【Swift】イニシャライザとは

# イニシャライザとは
構造体の初期設定を実行するメソッド
自身のプロパティに初期値を設定する
どのような用途で使用されるかというと、
初期値は必ず必要だが、その初期値がインスタンスによって異なるとき。

``` swift
// Macという構造体で言語、パスワードのイニシャライザを設定
struct Mac{
    var language:String
    var passcode:String
    
    init(language:String, passcode: String){
        self.language = language
        self.passcode = passcode
    }
}
// languageに"日本語"、passcodeに"password"が
// 設定された状態でインスタンスが作成される
var mac = Mac(language: "日本語", passcode: "password")
```

# イニシャライザの宣言
``` swift
init(ラベル1 引数名1:型, ラベル2 引数名2:型...){
 文
}
```
メソッドと似ているが、違いは識別子（名前）がないこと。

# 呼び出し方
構造体を呼び出す際に、イニシャライザの引数を設定する
通常メソッドのように、直接呼び出すことはできず、
インスタンスを作成する際に、間接的に呼び出している。

``` swift
// 上記例だと、ここでイニシャライザの初期値を設定して、インスタンスを作成している
var mac = Mac(language: "日本語", passcode: "password")
```

# デフォルトイニシャライザ
swiftが自動で生成するイニシャライザ。
以下の場合、生成される

- 構造体のプロパティすべてに初期値が設定されている場合

どういうことかというと、

``` swift
struct Mac{
var language = "日本語"
var passcode = "password"
}
```

上記の構造体はすべてのプロパティに初期値が設定されているので、
イニシャライザは必要ないように見える。
しかしこのような場合でも、swift内部ではイニシャライザが必要となる。

ただ、わざわざ私達がイニシャライザを記述しなくてもいいのは、
swiftが自動で補完してくれるから。
それが、デフォルトイニシャライザである。

実際は以下のような処理が内部で行われている。

``` swift
struct Mac{
 var language = "日本語"
 var passcode = "password"
 // 以下が自動で生成
 init(){
 }
}
```
【Docker+Laravel】よく使うコマンド集


# Laravelのバージョン確認
```
php artisan --version
```
or

```
php artisan -V
```

<br>
# キャッシュ削除
## applicationキャッシュクリア
```
php artisan cache:clear
```

## routeキャッシュクリア
```
php artisan route:clear
```

## configキャッシュクリア
```
php artisan config:clear
```

## viewキャッシュクリア
```
php artisan view:clear
```

<br>
# 定義されているルーティング一覧を確認
```
php artisan route:list
```

<br>
# デバッグ
## ファイルに出力して、デバッグや変数の内容を確認
```
logger()->debug($hoge);
```

### メソッド一覧

|メソッド|内容|
| -- | -- |
|emergency | システムが使用不可なレベル|
|alert|緊急に対処すべきレベル|
|critical|致命的なエラーレベル|
|error|一般的なエラーレベル|
|warning|警告レベル|
|notice|通知レベル|
|info|システム情報レベル|
|debug|デバッグ情報レベル|


## 作成中に変数の値を確認(web上で確認)
```
dd($hoge);
```
OMIGOD脆弱性について

Wizのセキュリティ研究者は、Azure上のLinux仮想マシンの主要な脆弱性を発見しました。

- [“Secret” Agent Exposes Azure Customers To Unauthorized Code Execution](https://www.wiz.io/blog/secret-agent-exposes-azure-customers-to-unauthorized-code-execution)

> 
お客様がクラウドにLinux仮想マシンをセットアップすると、特定のAzureサービスを有効にすると、OMIエージェントが知らないうちに自動的にデプロイされます。 パッチが適用されない限り、攻撃者はこれら4つの脆弱性を簡単に悪用して、root権限にエスカレートし、悪意のあるコードをリモートで実行できます（たとえば、身代金目的でファイルを暗号化する）。 

マイクロソフトは、次のCVEを発行ししました。

- [CVE-2021-38647](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38647) rootとして認証されていないRCE（重大度：9.8）
- [CVE-2021-38648](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38648) 特権昇格の脆弱性（重大度：7.8）
- [CVE-2021-38645](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38645) 特権昇格の脆弱性（重大度：7.8）
- [CVE-2021-38649](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38649) 特権昇格の脆弱性（重大度：7.0）

Azureユーザーの皆様このブログのを読んで、OMIが最新バージョン([v1.6.8-1](
https://github.com/microsoft/omi/releases/tag/v1.6.8-1))を確認してください。

## RHEL8でのアップグレード

- バージョン確認します。


```
# /opt/omi/bin/omiserver --version
/opt/omi/bin/omiserver: OMI-1.6.8-0 - Wed Jan 13 18:36:50 PST 2021
```
- **OMI-1.6.8-1**以下であれば、アップグレードしてください。

```
# wget https://github.com/microsoft/omi/releases/download/v1.6.8-1/omi-1.6.8-1.ssl_110.ulinux.x64.rpm
# rpm -Uhv omi-1.6.8-1.ssl_110.ulinux.x64.rpm
# /opt/omi/bin/omiserver --version
/opt/omi/bin/omiserver: OMI-1.6.8-1 - Wed Aug 11 20:52:52 PDT 2021
```

- **omid**サービスを再起動します。

```
# systemctl stop omid.service
# systemctl daemon-reload
# systemctl start omid.service
```
## CVE-2021-38647について
[CVE-2021-38647](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-38647)はリモートコード実行の脆弱性です。

**Azure Configuration Management**は**OMI**ポート5986を使用します。
**System Center Operation Manager** は**OMI**ポート1270を使用します。

**OMI**がどのポートでリッスンしているかを調べるには以下のコマンドを使ってください。

```
# grep httpsport= /etc/opt/omi/conf/omiserver.conf
httpsport=0
```
上記みたいに*httpsport=0*場合はセーフです。それ以外にはリモートコード実行のリスクがあります。

以上です。