OmniAICreator/Qiita-1.07M huggingface dataset:
Spring Boot で実装した Web アプリケーションに最小限の手順で Spring Security を導入する

# 前提
- Spring Boot で Web アプリケーションを実装している
    - Spring MVC などによる
- Spring Boot のバージョンは 2.7.x

# 手順
1. ビルドスクリプトに Spring Security を追加
    ```groovy:build.gradle
    	implementation 'org.springframework.boot:spring-boot-starter-security'
    ```
2. 以下のクラスを新規作成
    ```java
    package com.example.demo.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    @EnableWebSecurity
    public class SecurityConfig {
    
    	@Bean
    	UserDetailsService userDetailsService() {
    		User.UserBuilder userBuilder = User.withDefaultPasswordEncoder();
    		UserDetails user1 = userBuilder.username("user1")
    				.password("password1")
    				.roles("USERS")
    				.build();
    		UserDetails user2 = userBuilder.username("user2")
    				.password("password2")
    				.roles("USERS")
    				.build();
    		return new InMemoryUserDetailsManager(user1, user2);
    	}
    }
    ```
3. アプリケーションを起動する
4. 適当なページにアクセスする
5. ログインページが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517184/829fa6fd-1803-a107-d80e-613efb0fcb7f.png)
6. 2. で定義したユーザIDとパスワードでログインできる
書き方がよくわかんないからとりあえずテスト投稿

```Python
from random import randint
import time

OPENNING_MESSAGE='''
===============
時間制限付きの計算問題です。
===============
'''

#ゲームの中身
def game():

    print(OPENNING_MESSAGE)

    question = 0 # 問題数
    miss=0 # 間違えた数
    correct=0 # 正解数

    # 問題生成
    while question<10:
        a=randint(1,100)
        b=randint(1,100)
        ans=a+b
        q=f"{a}+{b}は？："

        # 問題文表示
        value=input(q)

        # 回答入力
        if value=="q":
            break
        if value==str(ans):
            correct+=1
            question+=1
            print("正解です！次！")
        else:
            miss+=1
            question+=1
            print("違います！次！")

    # 10問終了
    print("-"*20)
    print("ゲーム終了！結果発表！")
    print(f"正解数：{correct}、間違い数：{miss}")

    score=correct*10
    print(f"点数は・・・{score}点！" )

    # 入力直後
def play():
    op=input("ゲームを開始します。よろしいですか？(y/n)：")
    if op=="y":
        print("ゲームを開始します。")
        game()
    elif op=="n":
        print("ゲームを終了します。")
    else:
        print("無効なコマンドです。")

play()
```
OpenComm by ShokzでZoomするときに自動ミュートされてしまう問題の解決方法

Zoomミーティングをするのに、[OpenComm by Shokz](https://jp.shokz.com/products/bone-conduction-headphone-opencomm)を愛用してます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84173/56dd6a18-9d23-fb6c-0148-ba411d51ab85.png)

OpenCommには、ヘッドセット内でミュートする機能がついています。
が、Zoom中に発言しようとすると、すぐにミュートされる症状が発症して苦労していました。。。
（ミュートされた後は、＋と−の音量ボタンを同時長押しすると解除されます）

# Zoomの「マイク音量を自動調整します」が原因

Zoomの設定画面から、オーディオを選択すると、「マイク音量を自動調整します」のチェックボックスがあります。

![スクリーンショット 2022-09-08 13.43.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84173/b5b79ae2-e50a-0fd5-21fb-61745ee28719.png)

このチェックボックスがオンになっていると、喋り始めた瞬間に入力音量が小さくなっていくのが確認できます。
入力音量が小さくなると、OpenCommで自動ミュートされる仕様のようです。

# 解決策

「マイク音量を自動調整します」チェックボックスをオフにします。
そして、入力音量を2メモリ以上にしておきます。

自分の場合は、これで解決しました。
同じようにOpenCommで苦労している方たちの役に立ちますように・・・
Aura フレームワーク

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)


[Salesforce開発の勉強方法について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JdMStSAN)

上記質問に答えた中でフレームワークについて簡単に説明しています。確かにApexとかJava Scriptとかプログラミング言語も覚える必要がありますが、このフレームワークを理解していないとどこにどの言語を使ってコーディングするかが分からないと思います。

# 簡単な説明

そうそう、auraをやって初めに戸惑ったのがフレームワークのところです。
おそらくLWCでも基本的には同じです。

このフレームワークではクライアント側のPCで動くプログラムとサーバー(Salesforceのクラウド）で動くプログラムの２種類があります。
画面系はクライアントでうごきます。画面自体はAuraでは独自のマークアップ言語で、LWCではHTMLそのものになります。 この画面のボタンをクリックした時等の動作はJava Scriptで書きます。またサーバー側にデータの参照等を問い合わせるためにもJava Scriptでプログラミングします。（あくまでも問い合わせるメソッドを呼び出して結果を得るという部分で、実際の問い合わせ作業(DML操作）は サーバー側のプログラムになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/586c55ad-ce71-9fdf-8531-f536ded0097f.png)


サーバー側ではApexでコードを書いていきます。この中でSOQLを使ってデータを参照します。SQLとは違って更新処理はSOQLでなくてDML操作という方法で行います。
この部分が理解できればSalesforceでの開発については習得できると思います。
残念ながらVisualforceはすべてサーバー側で動いているので上記フレームワークとは別物になりますね。（とかなりややこしいです。プログラミング言語というよりフレームワークがややこしいです。）

この部分がわかれば理解は進むと思いますよ。

# 個別の関数

+ [e.force:createRecordで日付型を使う時の注意](https://qiita.com/Keiji_otsubo/items/3c1f42762548b0a2ecd1)
【Laravel】記事の並び順をランダムにしたいけど、１度表示した記事は後のページに表示させたくない Laravel版

以前MySQLのクエリーで対応する方法をご紹介しました。

https://qiita.com/maitakajp/items/667b39881f5e51484ad9

ですが、Laravelのクエリビルダにもメソッドが実装されていました。inRandomOrder() というメソッドです。

https://laravel.com/docs/9.x/queries

公式ドキュメントには記載がないですが、inRandomOrder()には引数（seed）を与えることができ、同じ引数を指定すると同じ並びになるようです。
Oracleでテーブルの作成日時と更新日時を取得するSQL

# やり方

```sql
SELECT
object_name,
created,
last_ddl_time
FROM user_objects
WHERE object_type = 'TABLE'
AND object_name = 'テーブル名'
```

# 参考サイトさん

https://oracle.programmer-reference.com/oracle-create-time/

# バージョン

Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
ALB リスナールールchromeのキャッシュで更新できなかった話

# はじめに
学習のためにALBのリスナールールのactionを変更して、pathによって、いろんなwebサイトにリダイレクトさせていました。
そんな時にactionの設定値を変更したのにも関わらず、遷移画面が変わらないという沼にハマりました。
結論は単純なものだったのですが、備忘録として残したいと思います。

# 構成図・前提条件
[![Image from Gyazo](https://i.gyazo.com/f65a9707868116dedbc0948ad08f1276.png)](https://gyazo.com/f65a9707868116dedbc0948ad08f1276)

EC2インスタンスには簡易なwebアプリが動いています。
通常通りにアクセスでき場合はこのようなトップ画面遷移します。
![ad11e1baa76e5692e43c8cd099f91d43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1431393/95f46be1-c365-74d2-8902-7d4640916842.png)

まずリスナールールを次のように設定しました。
![8e687bef573a73657faf149cbaa3e580.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1431393/043c2d49-f660-32ee-415e-8e507b25704b.png)
URLのパスが/のリクエストを送信するとGoogleのページへ遷移させる設定です。
ブラウザにアプリのURLを打ち込んでみます。
[![Image from Gyazo](https://i.gyazo.com/c2f3fd1b85fdf6291b1e32e740f9ec83.png)](https://gyazo.com/c2f3fd1b85fdf6291b1e32e740f9ec83)
このようにGoogleに遷移しました。
ここからさらにリスナールールのactionを変更し、さらに違うwebサイトへ遷移するように設定してみます。

# 課題
リスナールールのリダイレクト先を変更しました。
![0d1ef140d9a1687400a4647a41a23917.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1431393/c3342de7-3b3e-aee5-b362-f9bd4d453e58.png)
ブラウザにアプリのURLを打ち込んでみます。
[![Image from Gyazo](https://i.gyazo.com/c2f3fd1b85fdf6291b1e32e740f9ec83.png)](https://gyazo.com/c2f3fd1b85fdf6291b1e32e740f9ec83)
しかし、リダイレクト先は変わりません。
どうしてだ・・・・

# 仮説
- リスナールールの設定誤り
シンプルにリスナールールが誤っており、リダイレクトができていない可能性を考えました。
でも、その場合でも前の設定にリダイレクトされるのはおかしい・・・

- ブラウザにキャッシュが残っている
302は一時的なリダイレクトなのに対し、301は恒久的なリダイレクトなので強くキャッシュが残っているのではないかと思いました。このキャッシュを削除しなければいけないという仮説です。

# 解決
リスナールールに間違いはなさそうだったのでブラウザのキャッシュを疑いました。
結果としてビンゴで、chromeブラウザのキャッシュによって引き起こされていることがわかりました。
解決する方法は次のとおりです。

1. デベロッパーツールを開きます。
デベロッパーツールの開き方はWindowsであれば F12キー、MacOSであればCommand＋Option＋Iキー。
右クリックから「検証」をクリックしても開くことができます。

1. NETWORKを選択します。
![533c2356ed0593ef5de8cff90513c574.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1431393/753977c0-3413-9000-feeb-2820ab54cc80.png)

1. Disable cacheにチェックをつけます。
[![Image from Gyazo](https://i.gyazo.com/f27ea6ae0cb6836d7a21edbdcdddbd9a.png)](https://gyazo.com/f27ea6ae0cb6836d7a21edbdcdddbd9a)

これでchromeのキャッシュが削除されているはずです。
ブラウザに再度ドメインを入力してみましょう。
[![Image from Gyazo](https://i.gyazo.com/bb2cedcb204cb5a1bf592fd786834574.jpg)](https://gyazo.com/bb2cedcb204cb5a1bf592fd786834574)
無事画面が遷移しました。

# おわりに
調べてみると301リダイレクトはブラウザにキャッシュされ、302等であればブラウザにキャッシュされないようです。
301リダイレクトでも、ヘッダにおいて
~~~
Cache-Control: no-store
~~~
を設定すればキャッシュされなくなるようですが、302リダイレクトにすれば事足りるようですね。

# 参考
https://dev.classmethod.jp/articles/trouble-that-301-redirect-was-cached-in-chrome/

https://www.shonenjump.com/j/rensai/hunter.html
エリック・エヴァンスのドメイン駆動設計 3章を読んでまとめてみた

# はじめに
私はエンジニア未経験です。現在はエンジニアへ転職活動中です。
なのでここに記載してあることは一個人の考え方・理解であり、間違っている箇所は多々あります。
とあるきっかけでこの本を買い、読んでいるので、自分なりにまとめていこうと思います。

1部 1章について記載してあります。
https://qiita.com/Hiyokokeko/items/02f4cc40dfad70dee6a6
2章について記載してあります。
https://qiita.com/Hiyokokeko/items/15b7f43f41a98c425c39

# 3章 モデルと実装を結びつける
作った**モデル**と**コード**は分離せずに一つのものとして使っていく。

コードを作る前（モデル）には**分析**と**設計**が必要である。
分析・・・基本的な概念をわかりやすく表現力豊かなに。
設計・・・プログラミングできるようにする。ビジネスの課題を解決する。

分析と設計においても切り離さず両方の目的に使えるモデルを探求することを**モデル駆動設計**という。
<br>
- 使用するモデルは1つとして、開発は分析・設計・コードをひとまとめとして考える。
→何かを変更したらそれに合わせて他も変更していく。
- 前章であったように、モデルの変更はユビキタス言語の変更なので共通化していく。

- コードがより効果的にモデルを表現できるような設計と実装技術を使っていく。（オブジェクト指向プログラミングなど）

### オブジェクト指向についてざっくりおさらい
オブジェクト指向＝いかに効率良く開発を行うかを突き詰めた考え方。
③つの考え方をもとに設計をしていく。

①他のプログラムから干渉されないように作る考え方。（カプセル化）
②同じようなプログラムは共通化していく。（継承）
③汎用性な形にしていく。（ポリモーフィズム）
　　　　　↓これらをもとに
物と物の関係性を考えて作成・設計していく。

## モデルを実装するためのプログラミング
手続き型言語だとモデル駆動設計を表現するのは難しい。
なのでオブジェクト指向プログラミングを使ってモデル（分析・設計）をコード化していくと、紐付けがしやすい。
　　　　　↓そうすることで
開発者が表現しやすくなる。
<br>
ユーザーが見えている物（UI）にもモデルを反映させていく（別物としない）ことで、**ユーザーにとってもサービスが扱いやすいものに。**
　　　　　↓なぜなら
モデルは本来ユーザーとドメインエキスパートの関心ごとを表現した物であるから。

## 実践的モデラ
ここまでで大切なことは、**モデルとコードを密に関係付けること。**
　　　　　↓そのためには
モデルを作る人とコードを作る人を分離させないことが大切となる。
分離はすなわち、モデル駆動設計を失敗させる。（ソフトウェアと無関係なモデルや実装の制約を反映できていないモデルができてしまう）

例えば・・・高いスキルの人が設計して低いスキルの人がコードを書くのは、ウォーターフォール開発や大規模開発で起きがち。

モデルをコードに反映し、それをまたコードで表現できないならモデルはどういった考え方なのかモデルへフィードバックし、モデルを成長させ続ける。（ループ）
<br>
全ての開発者はドメインエキスパートとモデルに関する議論に参加しなくてはいけない。
　　　　　↓
- モデルに貢献する技術者は、一定のコードに触る。
- コードの変更に責任を負う人は、コードを通してモデルを表現するスキルを持つ。

# １部まとめ
ドメイン駆動設計はモデルがアプリケーションの問題を解決できるようにする。
知識をかみ砕くことで、ルールが明確となり実用的なモデルへと具体化されていく。
モデル駆動設計はモデルとコードを密に結びつける。
ユビキタス言語はそれら全てに影響し、開発者・ドメインエキスパート・ソフトウェア間で知識をかみ砕くために重要な役割を果たしている。

これにて1部は終了します。
ModuleNotFoundError: No module named 'xxxxx'

Pythonで
```
import xxxxx
```
と書いたら
```
ModuleNotFoundError: No module named 'xxxxx'
```
と怒られた。

でも
```
pip install xxxxx
```
して成功してるしもう一回やったら
```
Requirement already satisfied: xxxxx in /path/to/python-in-somewhere/lib/python3.x/site-packages (X.Y.Z)
```
とでていてちゃんと入っているよ?

というケース。

間違ったものをインストールしちゃった可能性もまれにあるけれど、大抵は「自分が今どこにあるPythonを使っているか把握してない」ことがほとんど。


まず
```
pip -V
```
する。（pip3で入れたよ! って人は`pip3 -V`）
```
pip X.Y.Z from /path/to/python-in-somewhere/lib/python3.x/site-packages/pip (python 3.x)
```
とでてきて、pipの位置が分かる。
pipのインストールでひねくれたことをやってなければ、`/path/to/python-in-somewhere/`にインストールされたPythonを使っていると考えていい。

次に
```
python -c 'import sys; print(sys.executable)'
```
を実行する。(python3を実行してたよ! って人は`python3 -c 'import sys; print(sys.executable)'`）
困っているのがPythonの対話環境や、Jupyterみたいなものだったら
```
import sys
print(sys.executable)
```
を実行する。
```
/path/to/python-in-somewhere/bin/python
```
とでてくる。
これは`/path/to/python-in-somewhere/`にインストールされたPythonを使っているということ。

自分の環境がいったいどうなっているのかは自分で把握しなきゃならないし、どうしたら解決するかは自分で考えなきゃならない。2種類あるPythonのどっちを使えばいいのか? にスパッと他人が答えられるケースはあまりない。
Pull requestを作成したユーザーを自動的にAssignするGithub Actions

# TL;TD

```
name: Auto-Assign

on:
  pull_request:
    types: [ opened, unassigned ]

jobs:
  assign:
    runs-on: ubuntu-22.04
    if: ${{ !(github.actor == 'dependabot[bot]' || github.actor == 'github-actions[bot]') }}
    timeout-minutes: 1

    steps:
      - run: gh pr edit $NUMBER --add-assignee $ASSIGNEE
        env:
          GH_TOKEN: ${{ github.token }}
          GH_REPO: ${{ github.repository }}
          NUMBER: ${{ github.event.pull_request.number }}
          ASSIGNEE: ${{ github.event.pull_request.user.login }}
        if: ${{ toJSON(github.event.pull_request.assignees) == '[]' }}
```
126.promise

### promiseとは
非同期処理をより簡単に、読みやすくするための方法として存在しています。
非同期処理をpromiseなしで記述した場合、
どのくらいめんどくさいかは以下の記事で記述しておきます。（ベージ下部分）
https://qiita.com/gucho-n/items/93eac48bac8e0a8cfa72
## 書き方
#### promiseの基本形
```js
new Promise(function(resolve,reject){}
).then(

).catch(

).finally(

);
```
#### 説明
①.第一引数resolveと第二引数rejectはコールバック関数
②-1.resolveが呼ばれると
    * 1.then()が実行される
    * 2.finally()が実行されて終了する

②-2.rejectが呼ばれると
    * 1.catch()が実行される
    * 2.finally()が実行されて終了する
☆thenの中でエラーを生成するとcatch()に飛ぶ
```js
then(
    // throw new Error
)
```
point
   finallyは必ず実行される！

#### 例
```js
new Promise(function(resolve, reject) {
  console.log('promise');
  // reject("bye");
  setTimeout(function() {
    resolve("hello");
  }, 1000);
}).then(function(data) {
  console.log('then:' + data);
  // throw new Error();
  return data;
}).then(function(data) {
  console.log('then:' + data);
  return data;
}).catch(function(data) {
  console.log('catch:' + data);
}).finally(function() {
  console.log('finally');
})

console.log('global end');
```

#### 1.Promise内のコンテキストが呼ばれる(Promise自体は同期通信なので、通常通り上から実行されている)
1-1 setTimeout(function() { resolve("hello");}, 1000);
         が実行されている。1秒後にresolve()が発動
```js
new Promise(function(resolve, reject) {
    // 
})
```
#### 2.グローバルにあるconsole.logがいつも通り呼ばれる
```js
console.log('global end');
```
#### 3.1-1 setTimeoutが完了したので、resolve()が実行される
```js
console.log('global end');
```
#### 4 resolve()が実行されているので
```js
.then(function(data) {
  console.log('then:' + data);
  // throw new Error();
  return data;
}).then(function(data) {
  console.log('then:' + data);
  return data;
})
```
以上が実行
#### 5. finallyで終了
```js
.finally(function() {
  console.log('finally');
})
```
PipeRider 0.8.0 リリース

![piperider-spotlight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/799036bd-1aea-e60c-8fb0-9a2034e21b83.png)

[Piperider](https://www.piperider.io/)はオープンソースデータ品質検査CLIツールとして、データプロファイリングとリポートを掲げて、データ観測プラットホームを目指す。

# 0.8.0 リリースの概要

![Screen Shot 2022-09-08 at 11.47.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/981febb9-a410-1d7c-54a2-cf1cccd38bff.png)

```
pip install 'piperider[duckdb]'
```

https://docs.piperider.io/data-sources/duckdb-connector

https://duckdb.org/


## CSVのサポート

```
pip install 'piperider[csv]'
```

https://docs.piperider.io/data-sources/csv-connector

## Apache Parquetのサポート

```
pip install 'piperider[parquet]'
```

https://docs.piperider.io/data-sources/parquet-connector


データソースのサポートの一覧

https://docs.piperider.io/data-sources/supported-data-sources


## 新たなカラム細部情報

![pr-08-col-detail.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/7284090f-1815-5554-f7ca-5d5caf521dc5.gif)
👆[credit: [https://www.kaggle.com/datasets/abcsds/pokemon](https://www.kaggle.com/datasets/abcsds/pokemon)]

### ワンランレーポト

[🌟お試しレーポト👈](https://piperider-github-readme.s3.ap-northeast-1.amazonaws.com/run-0.8.0/index.html)

![run.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/df997d1f-5f06-705a-4123-889b45a79c96.gif)




### 対照レーポト

[🌟お試しレーポト👈](https://piperider-github-readme.s3.ap-northeast-1.amazonaws.com/comparison-0.8.0/index.html)

![pr-08-compare.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623438/279d74f5-f79d-7d37-1c64-173fb84efd3c.gif)



## ハンズオン

[Pokemon: [https://www.kaggle.com/datasets/abcsds/pokemon](https://www.kaggle.com/datasets/abcsds/pokemon)]

<iframe width="560" height="315" src="https://www.youtube.com/embed/h9GHrtuzx-s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## 他の参考

https://docs.piperider.io/quick-start

https://github.com/InfuseAI/piperider

<iframe width="560" height="315" src="https://www.youtube.com/embed/03MyOkIo8Hg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
LeetCode Problems解いた：58. Length of Last Word

LeetCodeの問題集、```58. Length of Last Word```がacceptされたので、備忘録として。

## 概要
アルファベットとスペースのみで構成された文章に対して、最後の単語(ないし文字列)を抜き出す問題。
## コード
今回はPythonでの記述。

<details>
<summary>コード全容</summary>

```python: Solution.py
class Solution(object):
    def lengthOfLastWord(self, s):
        result = s.split()[len(s.split()) - 2] if s.split()[len(s.split()) - 1] == "" else  s.split()[len(s.split()) - 1]
        return(len(result))
```
</details>

## 考え方
pythonのsplit関数は、引数無しでタブ、改行、(連続する)スペースを区切り文字として分割してくれるので、文字列を分割して、一番最後の要素の長さを取得する。

:::note warn
文字列の最後がスペースだった場合分割後の配列の最後の要素が""になるので、その場合は最後から2番目の要素の長さを取得する。
:::


<details>
<summary>処理の詳細フロー　(例)s="we␣have␣two␣␣␣dogs␣␣␣␣"</summary>
s.split() → ["we","have","two","dogs",""]<br>
s.split()[-1] == "" がTrue → 対照はs.split()[-2] → result="dogs"<br>
len(result)=4<br>
</details>

## 自分の結果
計算速度：上から数えて約45%のところ(真ん中らへん)
メモリ使用量：上から数えて25%ぐらいのところ(ちょっと上の方)
普通ぐらい。
## 備考
splitを使ってはずるいような気がするのだが、どうなのだろうか。
Kali LinuxをOCIにデプロイする

ペネトレーションテストやハッキングツールの学習・デモなど、セキュリティな人たちに愛用されているKali Linuxですが、OCIではマーケットプレイスから簡単にデプロイして使うことができます。
実際の手順はドキュメント化されていないようだったので、デプロイして使用できるようになるまでの流れをイチからご紹介します。


- OCIのマーケットプレイスから、Kali Linuxを選択し、インスタンス起動をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/6756b749-781b-75a5-884e-3bd30be26075.png)

- 通常のVMインスタンス作成フローと同じようにシェイプやパブリック・サブネット等を指定して作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/dd9bfba4-b1ac-8a6e-237e-d99ade660e8d.png)


- 作成したインスタンスにローカルで接続する。コンソール接続 -> Cloud Shell起動をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/99f48149-3168-58db-1f2c-8a27061c8788.png)

- Cloud Shellからユーザー名:debian, パスワード:debianでログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/926cb804-3a94-650a-e682-5dcbe4fb77aa.png)

```
#パスワード変更を忘れずに
sudo passwd debian

#SSHの接続を有効化する
sudo apt update
sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh

#リモートデスクトップのインストール
sudo apt-get install kali-desktop-xfce xorg xrdp

#リモート接続時、画面が黒で表示されない(BUG?)ようなのでパッケージをアップデートしておく
sudo apt-get update && sudo apt-get dist-upgrade

#再起動
sudo reboot
```

- リモートデスクトップで接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/f22dde7a-4590-baa0-aa90-a09f40322f3d.png)

- Kali Linux画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/552a7fb3-c9e1-4029-951a-4d4b95475224.png)

ちょっと使いたい時に、すぐにデプロイできるのでおススメです。
最近リリースされたOCI Network Firewallのペンテストとかにも使えます。
Linux shistem-journaldとjournalctlコマンドについて（自分用メモ

systemdの動作するシステムではsystemd-journaldデーモンを動作させ、ログの一元管理を行う。systemd-journaldはsystemdから起動したプロセスの標準出力やsyslogへのログメッセージをバイナリ形式で記録、syslogの規格にも対応、同じファシリティやプライオリティが指定できる。

sytemd-journaldの設定は「/etc/systemd/journald.conf」で行う。デフォルトの設定では、バイナリ形式のログは「/run/log/journal」配下にシステム固有のディレクトリを作成し、その中の「system.journal」というジャーナルファイルに記録。システム固有のディレクトリ名は、インストール時に実行された systemd-machine-id-setup コマンドにより「/etc/machine-id」に記録されたものを使用。

「/run」ディレクトリはメモリ上に作成されたファイルシステム上のディレクトリのため、再起動するとデータが消えてしまう。
ログが再起動によってクリアされないようにするには、「/etc/systemd/journald.conf」でジャーナルファイルの保存先を制御する設定項目「Storage=persistent」を設定する。この設定により、systemd-journaldは「/var/log/journal」ディレクトリを作成し、その配下にログを記録するようになる。

※デフォルトの設定は「Storage=auto」

●systemd-journaldが書き込むジャーナルファイルはバイナリ形式のため、catコマンドなどで中を表示できない。systemd-journaldのログを表示するには journalctl コマンドを使用。

journalctl [オプション] [検索文字列]

オプション
・-a(—all)　画面表示できない文字も含めて全て表示
・-b(—boot) 特定のシステム起動時のログを表示。0は今回の起動時を意味。ログの古い方から1(最古のログ),2・・・と指定するか、−1(前回起動時)、−2(2回前の起動時)・・・と指定。
・-f(—follow) 新規に追加されたログをリアルタイムに表示(tail -fと同じ)
・-k(—dmesg)　カーネルからのメッセージを表示(dmesgコマンドと同じ出力)
・-l(—ful)　画面表示可能なすべてのログを表示
・-n(—lines) 直近のログから指定行数分を表示(未指定時のデフォルトは10行)
・—-no-pager デフォルトで使われるlessコマンドを使用しない
・-o(—output) ログの出力形式を指定(verboseやjsonなど指定できる)
・-r(—reverse)　最新のログから表示。デフォルトは最古のログからの表示
・—since　指定した日付時刻以降のログを表示
・—until　指定した日付時刻までのログを表示
・-u(—unit) 指定したユニットからのログを表示

■検索条件指定の代表的なもの
・_PID= プロセス番号の指定
・_SYSTEMD_UNIT= Unit名の指定(-uオプションと同じ)


●loggerコマンド
生成したログメッセージをジャーナルファイルに書き込むことができる。

logger [オプション] [メッセージ]

「-p」オプションを使用すると、メッセージのファシリティ、プライオリティが指定できます。未指定時はファシリティ、プライオリティを「user.notice」として送信

また、loggerコマンドと同様に、systemd-catコマンドで指定したコマンドの実行結果をジャーナルファイルに書き込むことができる。

systemd-cat コマンド
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その017

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: 構成、設定とオブジェクト
オブジェクトマネージャと Lightning アプリケーションビルダーの確認
　にある練習問題5問目をご紹介します。
https://trailhead.salesforce.com/ja/content/learn/modules/administrator-certification-prep-setup-and-objects/practice-user-setup

なお、こちらの内容はYouTubeでも公開しております

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

<iframe width="560" height="315" src="https://www.youtube.com/embed/plzqeWameqw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

オブジェクトマネージャと Lightning アプリケーションビルダーの確認
練習問題5問目はこちらです

![００５.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4868e60b-c065-17db-637b-6d9a25fca1fc.png)


正解はAですね

例えば最終更新日が30日以上の場合赤旗を表示させる
という場合、数式は以下となります


IF (
DATEVALUE(LastModifiedDate ) < TODAY() - 30 ,
IMAGE ( "/img/samples/flag_red.gif", "red", 15, 15 ),
IMAGE ( "/img/samples/flag_green.gif", "green", 15 , 15 ))

この数式を商談オブジェクトに作成すれば、最終更新日が10日以内なら緑色の旗。
最終更新日が10日以上なら赤色の旗を表示させることが可能です


では、Bが間違っている理由について説明します

Bについて
数式項目でテキストの色を変更することができないので誤りです

Cについて
数式項目では背景色の変更ができないので間違いです

Dについて
かなりひっかけの問題ですね
最終ログイン日を確認しても今回問われているように「過去30日間更新されていない商談」という確認はできませんね
よってDは間違いです

フラグを設定する数式項目のヒントはヘルプに記載されているのでご確認ください

https://help.salesforce.com/s/articleView?id=000320754&type=1

今日の内容はここまでです。
皆さん楽しく元気にSalesforceを学びましょう！
Cypher　よく使うクエリ

ne4jのクエリ言語であるCypher。
よく使うクエリをピックアップしました。

## 検索
全てのリレーションを検索する
`MATCH ()-[r]-() RETURN r;`

全てのリレーションとそのリレーションに繋がるノードを検索する
`MATCH p=()-[]->() RETURN p`

## 削除

全てのリレーションを削除する
`MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r;`

## Constraints

ユニーク制約を課す
`CREATE CONSTRAINT ON ( paper:Paper ) ASSERT (paper.id) IS UNIQUE`

設定した制約を確認
`call db.constraints`
Pardot API 開発に乗り出すための第一歩

Pardot 改め Account Engagement、使ってますか。以下は面倒なのでPardotと書きます。
Pardotではこれまでアクセス解析データを使って、ホットなリードをあぶり出しましょうみたいな取り組みをしていたり

https://note.com/geeorgey/n/need90730e418

データをSalesCloudに同期することで、新鮮な情報を取り出すことができますよね、という情報を発信してきました。

今回はこれとは違って、社内的な情報管理をするにあたり、PardotAPI経由で欲しい情報があるということで、そのためにPardot API開発を行っていこうというところまできました。
今回のミッションとしては、Salesforceからのバッチ処理でPardotAPIを叩き、必要な情報を取得した上で、Sales Cloud上のオブジェクトにコピーするというものです。
いざ開発を始めてみようと思い立つと分かると思うのですが、ものすごく基本的なTrailheadがクリアできないという罠にハマります。

https://trailhead.salesforce.com/ja/content/learn/modules/pardot-api-requests/make-a-call-with-apex

そりゃそうです。これまでPardotのSandbox環境なんて使ってこなかった私には、開発環境で使うことの出来るPardotがありませんでした。
今回は

- PardotのSandboxの取得
- Sales CloudのSandboxとの接続
- 先程のTrailheadをクリアする

という3ついついてクリアしていきたいと思います。

## PardotのSandboxを取得するには

https://help.salesforce.com/s/articleView?id=sf.pardot_sf_connector_sandbox.htm&type=5

ここに書いてあるとおりです。

- ビジネスユニットを作成します。
-- マーケティングの [設定] から、[Pardot アカウントの設定] を選択します。
-- ビジネスユニットの名前を入力します。
-- ビジネスユニットの管理者を選択し、作業内容を保存します。

しばらくすると、Salesforceからメールが届くはずです

![Your_new_Pardot_account_is_ready_to_set_up__-_y_lne_st_-_株式会社リバネス_メール.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/0fffc4b7-4743-8872-8c38-e312dd989f05.png)

これが届けば開設完了です。ログインしてみましょう。
本番環境と若干ドメインが違いますので注意

https://pi.demo.pardot.com

に行って、Sandbox環境のSales Cloudアカウントでログインすれば入ることができるはずです。

## Sandbox環境と接続するには
コネクタ欄を見てみましょう

https://pi.demo.pardot.com/connector

恐らく、Salesforceコネクタが「Verification in progress」となっているはずです。これを解消しましょう。

結構やることが多いです

Sales CloudのSandbox環境で


## b2bmaintegrationアプリをインストールする
https://test.salesforce.com/packaging/installPackage.apexp?p0=04t2E000003kYIi
ここからインストールします。Sandbox用のURLです。
対象Sandbox 環境システム管理者でログインし、"管理者のみインストール” を選択して [ インストール ] をクリックします
インストールが完了しましたら、”名前空間プレフィックス” 箇所の表示が ” pi3 ” になっているか確認します

## 接続アプリケーションにプロファイルを追加する
先程のパッケージのインストールにて追加される「接続アプリケーション」を確認すると、プロファイルが追加されていないと思います。

・b2bma_canvas
・Pardot_to_SF_Integration_Secure_Connected_App

1) [設定] | [接続アプリケーションを管理する] へアクセスします。
2) Pardot_to_SF_Integration_Secure_Connected_App へアクセスします。
3) プロファイルセクションを確認し、プロファイル「B2BMA Integration User」(または、別のコネクターユーザーがいる場合は、そのユーザーのプロファイル) がリストにあることを確認します。
4) 表示されていない場合は、[プロファイルを管理する]をクリックして追加します。
5) 手順 2 で表示される b2bma_canvas へアクセスします
6) プロファイルセクションを確認し、Pardot Lightning アプリケーションへアクセスするユーザのプロファイルが追加されていることを確認します

## 「B2BMA Integration User」のプロファイルにて 「ログイン IP アドレスの制限」が設定されている場合
IPアドレスを追加する必要があります

1) Salesforceの設定を開きます
2) クイック検索にて「プロファイル」と入力し「プロファイル」にアクセスします
3) ”B2BMA Integration User”をクリックします
4) “ログイン IP アドレスの制限” の関連リストの「新規」をクリックし、それぞれ以下の IP アドレスを追加します

52.202.69.186
52.21.178.134
35.174.150.168
35.174.151.106
35.174.78.146
18.232.28.189
18.236.48.198
35.160.68.143
35.162.236.194
34.213.32.13
35.164.254.110
52.42.59.7
34.236.235.55
34.231.125.55
52.20.28.237
34.193.125.247

ここまででコネクタの状態が一時停止中に変更されるはずです。
アクション欄のボタンより同期を開始し、データの同期が始まるか確認しましょう。

## Trailheadを実行してみる
Sales Cloudの設定より、リモートサイトの設定を開きます

![リモートサイトの設定___Salesforce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/fb505eb4-d781-1b40-476b-f14cfd449e97.png)

PardotDemoという設定が無効になっていると思いますので、これを有効化してください。
こうすることで、エラーが解消されるはずです。
Systems ManagerからCloudWatch Agentインストールできない【解決済み】

Docsの書き方が不親切で、
そのままだとSystems ManagerからCloudWatch Agentがインストールできなかった。
原因を解消できたので備忘のため記載する。

# 前提条件
OSはRHEL8.6を使用
必要なネットワーク設定やIAMロールは設定済み

# Run Command「AmazonCloudWatch-ManageAgent」でインストール失敗
## 【エラーメッセージ】
なんのことなのかよく分からない。
```
2022/08/31 06:42:32 Reading json config file path: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ssm_AmazonCloudWatch-linux.tmp ...

2022/08/31 06:42:32 I! Valid Json input schema.

failed to run commands: exit status 1
```

## 【原因】
サーバの統計情報を収集するためのcollectDが、
デフォルトではRHEL8.xには存在しないにもかかわらず、
collectDを監視すると設定していた。
```
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
```
```
Do you want to monitor metrics from CollectD? WARNING: CollectD must be installed or the Agent will fail to start
1. yes
2. no
default choice: [1]:
```

## 【対処法1】
collectDをインストールする
- collectDのEPELパッケージのインストール
```
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
```

- CodeReady Builderリポジトリの有効化
```
sudo /usr/bin/crb enable
```

- collectDのインストール
```
sudo yum install -y collectd
```

- 自動起動
```
sudo systemctl enable collectd.service
```

- 起動
```
sudo systemctl start collectd.service

sudo systemctl status collectd.service
```

## 【対処法2】
そもそもcollectDを使わないようにする。
```
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
```
コマンド実行時に聞かれる質問のうち、
```
Do you want to monitor metrics from CollectD? WARNING: CollectD must be installed or the Agent will fail to start
1. yes
2. no
default choice: [1]:
```
で2. noを選択する。

その後Run CommandでAmazonCloudWatch-ManageAgentを実施する。

# 所感
設問のdefault choiceがyesなのであれば、
AgentにcollectDもパッケージしておいて欲しい。
デフォルト値を別の選択リストフィールドから取得する

[Answersで回答する時に使う情報のまとめ](https://qiita.com/Keiji_otsubo/items/9e6e0e946826133eddc7)


選択リストの値なのでTextを使うと思いきや、デフォルト値のところではエラーになる。
仕方ないのでCaseでベタ打ちして回避です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3db52bc8-a2ea-d23a-76d4-2ad268260a70.png)


[選択リストのカスタムメタデータ型デフォルト設定について](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JdOdw)


# ログインしているユーザの情報からデフォルト値をセットする。

テキストフィールドに選択リストの値とセットしたかったので　TEXT を使ったら何故かエラーになります。
何でだろう？

仕方ないのでCaseを使ってみたらうまく行きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/677fad53-b650-0a2f-4fb6-1cff8d1ae1ef.png)

今までは、迷わずApex トリガーで対応していましたが、デフォルト値に数式を使ってもできるようです。

# デフォルト値で数式が使えない

+ [Unable to use createddate in picklist field default value formula editor](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000PjT3s)

Q: フィールドの既定値の式でレコードのフィールドを参照しようとしていますが、使用できません

A: デフォルト値は、レコードの作成時にのみ使用できます。その時点で、レコードが保存されるまでフィールドに値がないため、レコード自体のフィールドを参照できないのはなぜですか。

レコードによってトリガーされるフローを使用してフィールドに入力することもできますが、これは保存後にのみ表示されるか、クイック アクションを使用してこの特定のフィールドに事前定義された値を追加することができます。」


Please have a look at this article:

https://help.salesforce.com/s/articleView?id=000392562&type=1&language=en_US

Q: I am trying to reference a field on the record in the formula for the default value of a field, but it is not available

A: Default values are only available on creation of a record. At that point, no field has any value until the record is saved, hence why you cannot reference any field on the record itself.

You could use a record-triggered flow to populate the field, but this would only show after saving, or you could use a Quick Action and add a predefined value for this specific field

# 複数選択リストでの重複確認

+ [複数選択リスト値の入力チェック方法](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007X7T4V)

```
OR(
  IF( INCLUDES( 複数選択リストA , "1" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストB , "1" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストC , "1" ) , 1 , 0 ) > 1 ,
  IF( INCLUDES( 複数選択リストA , "2" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストB , "2" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストC , "2" ) , 1 , 0 ) > 1 ,
  IF( INCLUDES( 複数選択リストA , "3" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストB , "3" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストC , "3" ) , 1 , 0 ) > 1 ,
  IF( INCLUDES( 複数選択リストA , "4" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストB , "4" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストC , "4" ) , 1 , 0 ) > 1 ,
  IF( INCLUDES( 複数選択リストA , "5" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストB , "5" ) , 1 , 0 ) + IF( INCLUDES( 複数選択リストC , "5" ) , 1 , 0 ) > 1
)
```
初心者のためのPython Tip #1－Input編


# はじめに

初めまして、Qiitaでの初投稿です。
Pythonプログラミングをしている皆さんもご存知の簡単なテクニックを記載します。
初心者向けの説明ですがたまに普通のエンジニアの方でも紛らわしい部分も探っていきます。
(日本人ではないので、日本語の間違いは指摘してください。)

## Input(入力）

入力はこれが基本ですよね。


```Input.py
a = input()　# Stringで入力
_list = input().split() # string type listで入力
a, b = input().split() # a, bで分けて入力
```
**Q:**　それならInt型で入力してもらうにはこうすれば良い？

```Int_wrong.py
A, B = int(input().split())
```
**A:** 　**Int**型で入力を受けても、**list**型にすぐ変換できませんので、このコードは機能しません。
この時は**map**を使用します。**map**は基本的に適用する関数、使用できる資料のタイプを指定します。
```Int_correct.py
A, B = map(int, input().split())
```
**Q:** 　では、**list**を生成するなら、このように作成すればいいでしょうね？


```Int_list_map.py
_list = [*map(int, input().split())]
_list = list(map(int, input().split()))
```


**A:** 　Pythonはリストを簡単に、短く一行にすることができます。
**list comprehension**は反復と条件、宣言と割り当てを一行で解決できるPythonの文法です。
**[(変数の活用 "i*2のような"）for (変数の名前）in (巡回"range, setのような見つけることができるもの")]**


それで、Int型Listはこのように作ることができます。

```Int_list_comp.py
_list = [int(x) for in input().split()]　"Int_list_map.pyと同じです！"
```

list comprehensionの内容はかなり多いので、後でまとめて他の投稿で説明します。
一方、Pythonは変数を使用するときに独特な使用方法があります。
**Packing**と**Unpacking**というものです。

```Packing_n_Unpacking.py
numbers = 1,2,3,4,5 # numbers = (1,2,3,4,5) / Packing
a,b,c,d,e = numbers # Unpacking
```
皆さんもご存知のようにPacking/Unpackingは、
**Tuple**も**Parameter**も可能で_を通じて除外したり、範囲の指定ができます。
これを少し応用すれば数を入力してもらう時、前と後の入力を別々に受け取ることができます。

```Packing_n_Unpacking.py
First, *Middle, Last = map(int, input().split())
# Input -> 1, 2, 3, 4, 5
# Output -> 1 [2, 3, 4] 5
```

# おわりに

Pythonはライブラリーや文法が簡単で手軽ですが、その分機能が多くテクニックが必要な言語だと思います。 
私も初心者なので一緒に成長することが出来たらと思います！
Qiitaでの記事の書き方

使いそうなやつだけ抜粋。自分用メモ。<br>


## 目次
#### 1.基本記述編
- 1.1.hタグ
- 1.2.水平線
- 1.3.なんかコード(コードブロック)の左上に書いてあるファイル名みたいなやつ
#### 2.追加情報編
- 2.1.補足事項
- 2.2.引用


## 1.基本記述編
<p>

  #### 1.1.hタグ

  ```text:hタグ
  <h1>こんにちは</h1>

  もしくは

  # こんにちは                                  # 「#」の右に1つ以上半角スペースが必要。「h2=##」、「h3=###」以下同様。
  ```

</p>

<br>

<p>

#### 1.2.水平線
```text:水平線
「---」とか「***」で表示できる。h1とh2には自動で付くのでわざわざこっちを使うことは無いかも。
```


</p>

<br>

<p>

  #### 1.3.なんかコード(コードブロック)の左上に書いてあるファイル名みたいなやつ

  「```」か「~~~」を使うと指定できる。

  ~~~text:記述方法1
  ```text:test.txt                             # :の左に使用言語、右に表示内容を記述する
      This is text for test                    # コードブロック内で「```」や「~~~」を使う場合、外側で使用した記号でない方を使う
  ```
  ~~~

  または

  ```text:記述方法2
  ~~~text:test.txt
      This is text for test
  ~~~
  ```

  ↓

  ```text:test.txt
      This is text for test
  ```
</p>

<br>


## 2.追加情報編

<p>

#### 2.1.補足事項
背景に色が付くので目立たせたいときに便利。
重大さに応じて「info」、「warn」、「alert」の3種類が存在。
```text:補足事項
:::note info
一般的な補足事項に使えそう。「info」は省略可能だけどあったほうがわかりやすいよね。
:::

:::note warn
注意事項くらいの情報に使う。
:::

:::note alert
禁止事項を書くときはこれ。
:::
```

↓

:::note info
一般的な補足事項に使えそう。「info」は省略可能だけどあったほうがわかりやすいよね。
:::

:::note warn
注意事項くらいの情報に使う。
:::

:::note alert
禁止事項を書くときはこれ。
:::
</p>

<br>

<p>

#### 2.2.引用
「>」で記述。「>>」とかするとネスト状にできる。どこまで多重にできるんだろう......無限？？？
```text:引用
> 引用
> > 引用の引用
> > > 引用の引用の引用
> > > > 引用の引用の引用の引用
```

> 引用
> > 引用の引用
> > > 引用の引用の引用
> > > > 引用の引用の引用の引用
2022/09動作確認済み　Windows10(WSL)でmikutterを使う

# 本筋の流れ

まず、mikutteについて 
[mikutter](https://ja.wikipedia.org/wiki/Mikutter)

始める前に自身のtwitterアカウントのCK/CSの発行が必要（申請受理に6時間はかかるらしいのでこちらをまず先に行う。）

参考サイト
[CK/CSの作成方法](https://bulletscizor.hatenablog.com/entry/2014/11/01/000000)

# [Windows10(WSL)で最新版のmikutterを使う](https://qiita.com/EbiflyBB/items/895e4cf020efac706518)
こちらのサイトを主に使用し使っていく。
(mikutterの最新バージョンは[ここ](https://mikutter.hatenablog.com/)←から確認できる（上記サイトのバージョンは3.6であることがわかるだろう）)

こちらのサイトも参考になる。
[Windows Subsystem for Linuxのインストールからmikutterをそれらしく動かすまで](https://cobodo.hateblo.jp/entry/2018/03/31/034144)

2022年9月8日追記
「Windows Subsystem for Linuxのインストールからmikutterをそれらしく動かすまで」こちらのほうが互換性が良さそうなのでこちらのほうを推奨
追記終

以下、変更点などの記述

# Windowsのバージョンの違いでWSLの表示が異なる場合がある。

[Windows Subsystem for Linuxが表示されない](https://qiita.com/taraka/items/0b5919ac8ee02d81f7ff)


エラー周りについて
[Windows 10 WSL を有効にする方法](https://kb.seeck.jp/archives/8788)

# Ubuntuのバージョン

参考サイトより、
> 本記事は16.04を対象にしています。

とのことから、現在はMicrosoft StoreではUbuntu16.04はないため、手動でインストールする必要がある。

[Manual installation steps for older versions of WSL](https://docs.microsoft.com/en-us/windows/wsl/install-manual)

後は参考サイトの通りに行えば（多分）うまくmikutterを起動することができる(はず)。

プラグイン回り
[mikutterでWebのURLを開こうとした時、メニューで"Open URL over WSL"を押すとWindowsのブラウザで開ける](https://github.com/moko256/mikutter_wsl_plugin)

VcXsrv周り
[VcXsrv をインストールする方法](https://kb.seeck.jp/archives/17038#:~:text=VcXsrv%20Windows%20X%20Server%20%E3%81%AF,%E5%81%B4%E3%81%AB%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

やはりrubyのバージョンを変えなくてはいけない様だ
[Ubuntu 16.04にRuby 2.5.0をインストールするメモ](https://qiita.com/kure/items/d45dd7acf76294296f02)
[rbenv: no such command `install' となってinstallできない時の対処](https://qiita.com/ktanoooo/items/37d80727b55099b09480)
[rbenvでバージョンがうまく切り替わらなかった時にやったこと](https://qiita.com/akatsuki174/items/c0384b9903b4b5cbbdaf)


2022年9月8日追記
~~いろんなサイトでsourceのコマンドが出てくるが、ここでは~~
~~/.bash_profileではなく~~

    source ~/.bashrc

~~のほうで入力すること~~
追記終

2022年9月8日追記
rubyの互換性でロードエラーが発生してしまう。

    cp ~/.bashrc ~/.bash_profile
    source ~/.bash_profile

を推奨する

~~rubyを実行したときにgtk2系のエラーが出たら~~

    sudo apt-get install ruby-gtk2

~~をインストールする~~

gemのエラーの場合

    gem install gtk2

こちらを利用する

error list

Run `bundle install` to install missing gems.
https://stackoverflow.com/questions/34557887/run-bundle-install-to-install-missing-gems
追記終

# メモ
・VcXsrvの確認方法はxeyesコマンドを使用すればWindowsに目のポップアップがでてきたら機能している。

![スクリーンショット 2022-09-08 205101.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813031/f7d3b270-ab27-9fc6-75a0-f4270c90e20c.jpeg)

・ubuntuの（.bashrcか.bash_profileのどちらか）で入力するexport DISPLAY=:0.0にはwindows側のipをいれるように、（例export DISPLAY=192.168.1.1:0.0）
確認方法はコマンドプロンプトでipconfigと入力すれば出てくる（が、動的かどうかで再発行され変わる可能性もある）
動作確認済み画面（自分はAPIの取得に失敗したのでTwitterにAPI申請するときはデベロッパーツールの許可申請のメールときちんと書くのがよいらしかった…）

![スクリーンショット 2022-09-08 205154.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813031/aea182c1-33cf-8b19-63b7-c984453527c9.jpeg)
【AppSheet】入力値で複数行を一括処理する方法


## ※2022/9/20　バグ？現在使用不可

以下の手順で実装できますが、バグっているのか肝心のスマホで使えません。


## 下記の手順で行うと実現できます。

### ①アクションを作る
1\. Behavior > New Action
2\. 「For a record of this table」 = 更新したいテーブルを選択
3\. 「Do this」 = 「Data: set the values of some columns in this row」を選択
4\. 「Set these columns」 = 「更新したい列名 = INPUT("hoge", TEXT(""))」
5\.  Appearance > Prominence = 「Display prominently」

### ② UX > View の「Action」に上記のアクションをセットする
6\.  UX > View > View Options > Actions = 上記で作ったアクション名を選択

### ③SAVEして実装完了。プレビュー画面で動作確認する。
7\. プレビュー画面を横表示にする（私の環境では縦表示だとバグってうまく動き
動きませんでした。）
8\. Actionsを登録したViewの上部メニューにチェックボックスが出現するので、これを押すと複数選択モードに切り替わる。
9\. チェックボックスの隣にActionボタンが追加されているので、複数選択した状態でこれを押す。
10\. コンボボックスが表示されるので、更新したい値を直接選択するか入力候補を選択して「save」を押す。（※プレビュー画面が縦表示だとこのsaveがうまく動きませんでした。）
11\. 複数行の一括更新完了。
回転体の体積(一葉双曲面)「2022年芝浦工業大学・工 数学第４問」をsympyでやってみた。 

A(0,1,1),B(1,2,0),P(x,y,z)...x=0,X-1で囲まれた立体の体積...

オリジナル
ますいしい様

https://ameblo.jp/mathisii/entry-12762641239.html

大学入試数学問題集成＞東京都＞未掲載

https://mathexamtest.web.fc2.com/daigakubetumj/index.html#tokyo


# sympyで(ますいしい様の手順で)
答えは、一致？させました。

```python
from sympy import *
var('t x y z')
A=Point(0,1,1)
B=Point(1,2,0)
P=Point(x,y,z)
P_t=A+t*(B-A)                               # ①
print("#(1)",P_t)
H=Point(x,0,0)
P=Point(H.x,P.y,P.z)                        # ???  OH ⊥ HP --> OH+HP
HP2=H.distance(P)**2
S1=HP2.subs({z:0}).simplify()
S2=HP2.subs({y:P_t.y,z:P_t.z}).simplify()   # ②
print("#(2)",Eq(S1,S2.subs({t:x})))
print("#(3)",integrate(pi*S2,(t,0,1)))
#(1) Point3D(t, t + 1, 1 - t)
#(2) Eq(y**2, 2*x**2 + 2)
#(3) 8*pi/3
```

# 参考

双曲面（そうきょくめん、英語: Hyperboloid）＞　一葉双曲面

https://ja.wikipedia.org/wiki/%E5%8F%8C%E6%9B%B2%E9%9D%A2

https://en.wikipedia.org/wiki/Hyperboloid
【夏休み企画】#IT用語一問一答【毎朝投稿19日目】IndexedDB

# この記事を読むと、、
- 「関連用語」を使って「IndexedDB」を説明できるようになる
- 「IndexedDB」がもっと好きになる(多分)

# 関連用語
object store / index / Web Storage API

[**復習用**] 記事の内容を見る前に上記の言葉で「IndexedDB」を説明してみよう！

# 企画説明
- クラウドって何？って人に聞かれて説明してるけど俺もよく知らないや、、
- ドキュメント読んでみてるけど半分くらい何言ってるか分かんない、、
- 今日の夕飯はナスの炒めものにしよっかな〜、あれ、NASってなんだっけ？

みたいなことが結構あったので、知ったかしていたIT用語を毎日一個ずつちゃんと学んでいこうっていう企画です！

昨日の記事はこちら↓

https://qiita.com/acta/items/14107dfa22f41be7de08

# IndexedDBとは
IndexedDB = 大きめのデータをブラウザ上で扱うNoSQLデータベース
- ファイルやBLOB = Binary Large OBjectも保存できる
- **object store**( = RDBでいうテーブル)からDatabaseが構成される
    - object storeのvalueのJSでの型に一貫性は必要ない
- **index**というobject storeを用いて、他のobject storeのデータが読み込まれる
- same-origin policyに従い、同一ドメインからのみアクセスできる
- cf. **Web Storage API**
    - IndexedDB同様、ブラウザ側でデータを保存するAPI
    - key/valueの組を保存できる
    - IndexedDBより扱うデータは小規模
    - ブラウザやタブが閉じると消えるsessionStorageと、閉じても消えないlocalStorageがある

# 参考資料
- https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
- https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
- https://web.dev/indexeddb/#terms
- https://cloud.google.com/learn/what-are-transactional-databases
vistaでandroid studio その18

# 概要
vistaでandroid studio 1.1.0やってみた。
jniが、やりたいので調査。

# jniの仕組み

cソースをコンパイルして、soを作る。
- ndkをインストール。
- src/main/jniフォルダを作る。
- src/main/libsフォルダを作る。
- hello.cを書く。
- Android.mkを書く。
- ndk-buildにpathを通す。
- ndk-buildを実行して、hello.soを作る。

apkにsoを挿入する。
- gradleを書いて、soを挿入。

```
sourceSets {
	main {
		jni.srcDirs = []
		jniLibs.srcDir "src/main/libs"
	}
}
```
javaソースを、書いて、jniを呼び出す。
- System.loadLibrary("hello")
- private native

以上。
～魔法使い(ウィザード級ハッカー)への道～初心者エンジニアの積み上げ日記

## はじめに

### セキュリティエンジニアの必要性

![](https://i.imgur.com/NsAsETH.jpg)


近年，組織の情報システムにおけるモバイル機器やクラウドサービスなどの普及によって，情報セキュリティ（Information Security）の重要性が改めて高まっている．総務省のセキュリティリスク発生率のデータを見6割近くあり，その重要性は示されている．

![](https://i.imgur.com/IO99OFN.png)



そのため，セキュリティエンジニアはひと昔前のデータサイエンティストのように花形になると考えられる．しかし，セキュリティエンジニアは幅広い知識が求められ道のりは長いが，今後の不安定な世界情勢でも生き残れるのがセキュリティエンジニアだと信じ初心者ながら知識を積み上げていく．

### 積み上げプラン

![](https://i.imgur.com/r1ueIPD.jpg)


知識を積み上げる際に実践形式のHTBと座学中心の情報処理安全確保支援士（旧セキュリティスペシャリスト）の勉強の2正面作成で進めていこうと考えている．これは，座学だけでは飽きてくるため実践形式のHTBを組み込んでいる．しかし，実践形式のHTBだけでは知識が偏ってしまう可能があるため，座学も同時に行う．

### 魔法使いへの道

![](https://i.imgur.com/CCR7vNW.jpg)


ハッカーの中でも特に優れた上級ハッカーのことをウィザード級ハッカーと言われています．これは魔法使いの意味でコンピュータを自在に操る者とのことでこの名前が付けられています．そこで本企画は初心者が魔法使いになるまでの道のりを綴っていこうと思います．



## 情報処理安全確保支援士

>情報処理安全確保支援士は、サイバーセキュリティ分野の日本国の国家資格。有資格者は情報処理安全確保支援士の名称を使用して、政府機関や企業等における情報セキュリティ確保支援を業とする。

![](https://i.imgur.com/T6hcgKn.png)

情報セキュリティ関係の資格は国内・国外でいくつか存在するが，今回は国家資格である「情報処理安全確保支援士」を使って座学の勉強を行っていく．

https://hamaruki.com/2022/09/07/wizard_class_hacker_0001/

## Hack the box(HTB)


![](https://i.imgur.com/M9X3TMM.jpg)

「Hack The Box」はペネトレーションテスト(ハッキング)のスキル向上に役立つオンラインプラットフォームです．このプラットフォーム上には、ラボと呼ぶクラウドの検証環境があります。これらのラボにハッキングを仕掛けることによってハッキングを学ぶことができます．

https://hamaruki.com/2022/07/26/hackthebox-thewaytothewizard-part01-walkthrough/

## おわりに

今後の世界で生き残るために魔法使いを目指して頑張ります．
124.コールバック関数と非同期処理　125.非同期処理のチェーン

# 覚えておくべき前提条件
#### 1.実行について
＊関数は実行されて初めて処理が始まる
例)
1.Func();--処理が始まる
2.btn.addEventListener()--『ボタンを押して初めて』実行されている
#### 2.キューについて
非同期処理にすることによってメインの処理を待たずに他の関数を実行できる
ただ非同期処理内でも、先入先出しなので、順番は守らなければならない。
#### 3.setTimeoutについて
setTimeout（）は
第一引数に処理を、第二引数に待機時間を記入するが
第二引数がないと、コールスタックが吐き切るまで、実行されない
#### 例
```javascript
function a() {
// 2.コールスタックが全て終了するまで待機 
  setTimeout(function task1() { 
    console.log('settimeout done');
  });

  console.log('fn a done');
}

function b() {
  console.log('fn b done');
}
// 1 aが呼ばれる
a();
// 3.setTimeoutはパスして3を実行する
b();
```
結果
![スクリーンショット 2022-09-08 10.04.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/bdc1caf2-5eb9-1828-bb80-deab8867c963.png)
ではコールスタックにあるb()を差し置いてsetTimeoutを実行してからb()を呼ぶにはどうすればいいのか？

## b()を道連れにしよう
どういうことかというと
関数b()をコールバックして、setTimeoutの実行中にb()を呼び出すようにする
setTimeout内で実行するのだ。
#### フロー
1.a(b) bをaのコールバックにしてs
2.b() setTimeoutのコンテキスト内にb()記述し、setTimeoutが実行してから,b()を実行できるようにする
```javascript
function a(b) {
  setTimeout(function task1() { 
    console.log('task1 done');
    b();
  });

  console.log('fn a done');
}

function b() {
  console.log('fn b done');
}

a(b);

// b();
```
![スクリーンショット 2022-09-08 10.26.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/714631/7f89396a-27cf-2f91-3b90-afdab632ec1a.png)

無事修正完了！

## 2.キュー内で関数をどんどん生成していく方法
```js
function sleep(callback,val){
	setTimeout(function(){
  	console.log(val++);
    callback(val);
  },1000);
}

sleep(function(val){
	sleep(function(val){
  	
  },val)
},0)
```

#### 例
```js
function sleep(callback,val){
	setTimeout(function(){
      	console.log(val++);
        callback(val);
  },1000);
}

sleep(function(val){
	sleep(function(val){
  		sleep(function(val){
  		},val)	
  },val)
},0)
```
#### 例の解説
関数の実行
```js
// 1.sleep関数が実行されます。
sleep(
    //入れ子関数
},0)
//この時の第一引数は入れ子関数で、第二引数は0です　
```
```js
// 2.sleepが実行されるので、先ほど渡した第二引数の0を用いてval『0』に1を追加します
function sleep(callback,val){
	setTimeout(function(){
      	console.log(val++);
       
  },1000);
}
```

```js
// 3.callback(val)の正体は1.で記述した第一引数の入れ子関数です。先ほど作成したval『1』を引数日して実行していきましょう」。
function sleep(callback,val){
	setTimeout(function(){
      	console.log(val++);
    // 3.
        callback(val);
  },1000);
}
```
```js
// 4.　3.で入れ子関数を実行しろという命令が出ました。
sleep(function(val){
	sleep(function(val){
  		sleep(function(val){
  		},val)	
  },val)
},0)
```
これをみると1-4をずっと繰り返すことになりますvalはインクリメント（増加）していくので、結果的にvalが入れ子の数だけ増えていくしくみになりました

## 結論
このコード読みにくくない？！
ということで可読性を向上させるために作成したのが
promiseでした。
MediaSourceHandle creation is currently supported only in a dedicated worker

少し古いバージョン (v7.10 未満) の Video.js を使っているサイトを、 M105 の Chrome / Edge で見た時 (HLS streaming 開始時?) に、以下のエラーが発生する場合があるようです。

```
DOMException: Failed to read the 'handle' property from 'MediaSource': MediaSourceHandle creation is currently supported only in a dedicated worker.
```

(2022-09-08 現在の状況をまとめます。Android/iOS 版でも同様に起きるようですが、以下の内容は Desktop 版の状況についてです)

M105 stable がリリースされた、昨月末以降チラホラ報告があるみたいです。

[Chrome Releases: Stable Channel Update for Desktop](https://chromereleases.googleblog.com/2022/08/stable-channel-update-for-desktop_30.html)

これは Chromium 105 に含まれている "Media Source Extensions in Workers" ([MediaSource in Worker · Issue #175 · w3c/media-source](https://github.com/w3c/media-source/issues/175)) 機能のリリースによって起きているそうです。

[Chromium Blog: Chrome 105 Beta: Custom Highlighting, Fetch Upload Streaming, and More](https://blog.chromium.org/2022/08/chrome-105-beta-custom-highlighting.html)

commit 的にはこちら。

https://chromium.googlesource.com/chromium/src/+/09e5fb1a68416f65ef2255c846b81a46f6aa8e52

以下のチケットで、この issue について、話し合われています。

[1358542 - [User Feedback - Stable] User reports of video playback not working as expected on M105 stable - chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=1358542)

いったん、該当の機能 (`MediaSourceInWorkers`, `MediaSourceInWorkersUsingHandle`) は `stable` -> `experimental` status に戻されています。つまり、いったん revert された形になっています。

https://chromium.googlesource.com/chromium/src/+/d5cef2e293c12d33ca25955897d090018a3fe7d3

Chrome M105 では、このパッチが既に当てられた 105.0.5195.102 がリリースされているため、最新版にアップデートすれば、エラーは解消します。 M106 beta にも既にこの修正が取り込まれているとのこと。 (M107 以降は、現時点では未定です)

Edge の最新版 105.0.1343.27 にはまだ含まれていないです。

Video.js 側でも issue のチケットが上げられていますが、 Video.js v7.10 (2020-10-15 リリース) 以上では起きないようです。

[Failed to read the 'handle' property from 'MediaSource': MediaSourceHandle creation is currently supported only in a dedicated worker. · Issue #7905 · videojs/video.js](https://github.com/videojs/video.js/issues/7905)

またしばらくしたら状況をウォッチしておきたいと思います。
記載内容に誤りがあれば、ご指摘お願いします！

---

ウミトロンでは、私たちと一緒に「持続可能な水産養殖を地球に実装する」仲間を積極的に募集しています。
このミッションのもと、テクノロジーを用いて水産養殖の課題に挑む航海に共に出てみませんか?

https://umitron.com/ja/career.html
vistaでandroid studio その17

# 概要
vistaでandroid studio 1.0.1やってみた。
jniが、やりたいので調査。

# android studio調査

|バージョン|発表時期|vistaで確認|
|:--|:--|:--|
|2021.2.1.16| 29 8月 2022
|2021.2.1.15| 27 5月 2022
|4.2.2| 2 7月 2021
|4.2.1| 18 5月 2021
|4.1.3| 25 3月 2021
|4.1.2| 22 1月 2021
|4.1.1| 11 11月 2020
|4.0.2| 7 10月 2020
|4.0.1| 17 9月 2020
|4.0.0| 24 6月 2020
|3.6.3| 22 4月 2020
|3.6 (64-bit)| 25 2月 2020
|3.5.2| 2 12月 2019
|3.4.2 (64-bit)| 1 8月 2019
|3.4.1 (64-bit)| 18 6月 2019
|3.2.1.0| 25 1月 2019
|3.1.4.0| 14 9月 2018
|2.3| 3 3月 2017
|2.2.3| 15 2月 2017
|2.2.2.0| 3 11月 2016
|2.2.0.12|20 9月 2016|インストーラー起動しない
|2.1.3.0|20 9月 2016
|2.1.2|8 6月 2016
|2.1.1|18 5月 2016
|2.1.0.9|28 4月 2016
|2.0.0.20|7 4月 2016|インストーラー起動しない
|1.5.0.4|20 11月 2015|adb起動しない。ndk有り。
|1.4.0.10|7 10月 2015|adb起動しない。ndk有り。
|1.3.1|17 8月 2015
|1.3.0|31 7月 2015|adb起動しない。ndk有り。
|1.2.2|20 7月 2015
|1.2.0|4 5月 2015|インストールOK、起動しない
|1.1.0|19 2月 2015|動く。ndk無し。
|1.0|9 12月 2014|動く。ndk無し。
|0.8.14 Beta|25 11月 2014
|0.8.9|11 9月 2014
|0.8.0|4 8月 2014|動く。ndk無し。
|0.5.2|20 6月 2014
|0.4.6|7 4月 2014
|0.4.2|24 3月 2014

# 結果

android studio v1.0.1を削除。
v1.1.0
android-studio-bundle-135.1740770-windows.exeを
インストールする。


以上。
任意のテクスチャをリピートした線を LineRenderer で描画してみた

# 目的

ゲーム中で ↓ のような線を描画するメモを残す
![MoveLIne.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/ef0884bc-d1a5-e6ff-1153-58facd353e53.gif)

# LineRenderer の生成と設定
* LineRenderer コンポーネントのついたGameObjectをHierarchy生成する
* 適当にラインの頂点を設定する
* Texture Mode を Tile に設定する

# Shader の生成と実装
* Projectビューの適当なところで、Create > Shader Graph > URP > Sprite Lit Shader Graph でシェーダーを生成する
* シェーダーの中身は ↓ を参照
![move_line_shader_graph.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2803164/97ecc332-989c-df53-3d67-4b94978a51c5.jpeg)
* シェーダーができたら、シェーダーファイルを右クリックして Material を生成する
* 完成したMaterialをLineのMaterialに設定する。

# 少々ハマったところ
* LineRenderer の width を小さくするとテクスチャが細長く伸びた状態になる
* Tiling And Offset の、Tiling 項目の、X の値を調整することで、UVの U値 にオフセットをかけることで調整可能
IBM RPAでWindowsキーを含むショートカットキーを使いこなしたい

## はじめに
ショートカットキーとは、様々なアプリケーションでの操作でマウスを動かさず、キーボードのみで操作できるキーの組み合わせです。
今までも便利だなと思い使っていましたが、RPAでボットを作成している時にショートカットキーの偉大さに気付かされました。

今回は、IBM RPAでショートカットキーを使う方法(特にWindowsキー)を書きたいと思います。

## ショートカットキーをRPAで使う方法
まず初めに、IBM RPAでショートカットキーを扱えるのが「キーの送信」コマンドです。
CtrlキーやFunctionキーをはじめ様々なキーに対応しています。
例えば、コピー(Ctrl + c)などは「^c」で実現できます。
細かい書き方は[こちら](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.sendkeys?view=netframework-4.8)をご覧ください。
![「キーの送信」Ctrl+c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737895/d8bc823c-6ca0-6767-48a4-7700e97fa240.jpeg)

Windowsキーのショートカットとして「Ctrl + Esc」があることから、Windowsキーは「キーの送信」コマンドだと「^{ESC}」で実現できます。
![「キーの送信」Ctrl+Esc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737895/1bd3a262-7f82-19e7-6780-c12f3daba724.jpeg)
しかし、Windowキーと一緒にほかのキーを押すことは「キーの送信」コマンドではできません。

## Windowsキーを含むショートカットキーの実現方法
そこで出てくるのが「キーの押下または解放」コマンドです。
このコマンドで「LWin」もしくは「RWin」を選択することで、Windowsキーを押すことができます。
![「キーの押下または解放」LWin押したまま.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737895/fdfd82bb-4c12-e82c-d1b7-67b985ae90e3.jpeg)

例えば、「Windowsキー + d」でデスクトップ画面を開くことができますが、その場合は「キーの押下または解放」コマンドの下に「キー」を「d」に設定した「キーの送信」コマンドを置きます。

注意としては「キーの送信コマンド」と違い、Windowsキーは「キーを押したままにする」ことになるため「キーを放す」操作を行う「キーの押下または解放」コマンドを入れる必要があります。このコマンドを忘れると、ずっとWinodwsキーが押された状態となってしまいます。
![「キーの押下または解放」LWin放す.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2737895/5db732ff-34ba-d736-394b-6a70595449e2.jpeg)

## おわりに
ご覧いただきありがとうございました。
実行中のRubyサーバ上でsidekiqプロセスが動いているか確認するコマンド

ググっても出てこなかったのでメモ
```ruby
Sidekiq::ProcessSet.new.map {|ps| ps['hostname'] }.include?(Socket.gethostname)
# または
Sidekiq::ProcessSet.new.map {|ps| ps['hostname'] }.include?(`hostname`.strip)
```
これで、
「現在のサーバでsidekiqプロセスが動いている場合はtrue、動いていない場合はfalse」が取得できます。
複数サーバでsidekiqプロセスを動かしていることがあると思いますが、
そのような時に有用かと思います。

ちなみに上記のコマンド内で出てくる `Socket.gethostname`や`` `hostname`.strip `` は「Ruby のプロセスが稼働しているサーバの hostname を取得する」コマンドのようです。
`Socket.gethostname`の方は、ruby 2.7以降ではdeprecatedとのことなので、
どちらかというと後者の`` `hostname`.strip ``が推奨されます。

#### 参考
- https://qiita.com/notakaos/items/368f2e1b3c4d672e2c04
- https://stackoverflow.com/questions/42566/getting-the-hostname-or-ip-in-ruby-on-rails

#### 活用場面
「起動中のサーバでsidekiqプロセスが起動中かどうか」をif文にした処理を実装する場面で使用しました。

#### 環境
ruby 2.6.6
rails 5.2
sidekiq 5.2.9

#### 最後に
もっと良いコマンドがあれば教えていただけますと幸いです、、！！