OmniAICreator/Qiita-1.07M huggingface dataset:
【Laravel】UUIDカラムをURLに割り当てるとルートに割当されなかった場合の対策

# 概要

主キーを`UUID`にする必要があったので以下の記事を参考に導入した。

ルートモデルバインディングで`UUID`を割り当てると`404`エラーでルートに到達できない事象があったので解決方法をまとめる

```php:web.php
<?php
Route::prefix('post')->group(function () {
    Route::get('/edit/{uuid?}', [PostController::class, 'edit'])->name('admin.posts.edit');
});
```

https://qiita.com/ucan-lab/items/a8374ba421fe7828dcb9

# 環境
- PHP 7.4.25
- Laravel Framework 6.20.44
- laravel-eloquent-uuid v6.*


# 導入手順

https://github.com/goldspecdigital/laravel-eloquent-uuid

```bash
composer require goldspecdigital/laravel-eloquent-uuid:^6.0
```


# マイグレーション作成

```php:CreatePostsTable
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->uuid('uuid')->primary();
            $table->string('name', 255);
            $table->text('note')->nullable();
            $table->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
            $table->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'));
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}
```

# モデル作成

```php:Post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * モデルに関連付けるテーブル
     *
     * @var string
     */
    protected $table = 'posts';

    /**
     * テーブルに関連付ける主キー
     *
     * @var string
     */
    protected $primaryKey = 'uuid';

    /**
     * モデルのIDを自動増分するか
     *
     * @var bool
     */
    public $incrementing = false;

    /**
     * 複数代入可能な属性
     *
     * @var array
     */
    protected $fillable = ['uuid', 'name', 'note'];
}
```

# Bladeテンプレートを作成

- リンクをクリックすることで以下のルートに割り当てられる想定だったが`404`が返ってきた

```php:web.php
<?php
Route::prefix('post')->group(function () {
    Route::get('/edit/{uuid?}', [PostController::class, 'edit'])->name('admin.posts.edit');
});
```

```php:index.blade.php
@foreach ($posts as $post)
    <tr>
        <td>
            <a href="{{route('admin.posts.edit',['uuid'=>$post->uuid])}}">
                {{ $post->uuid }}
            </a>
        </td>
    </tr>
@endforeach
```

# 解決方法

- キーのカスタマイズを行う必要があるので以下のようにすることで　期待通りルーティングされる

https://github.com/michaeldyrynda/laravel-model-uuid/issues/104

https://laravel.com/docs/8.x/routing#customizing-the-key

```php:web.php
<?php
Route::prefix('post')->group(function () {
    Route::get('/posts/{uuid?}', [PostController::class, 'edit'])->name('admin.posts.edit');
});
```
General error: 1364 Field 'カラム名' doesn't have a default valueのエラー対処方法

## エラー概要
storeメソッドでDBへデータを挿入する際に、
エラー「General error: 1364 Field 'カラム名' doesn't have a default value ...」
が出た。

## 結論
migrate時にカラムのnullを許容していなかった。

## 対応
データ挿入前だったので、
nullable()を追記して、ロールバックしてmigrateをやり直した。

```zsh:ターミナル
$ php artisan migrate:status
$ php artisan migrate:rollback --step=1
```

```diff_php:migrationファイル
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddImgToDbnameTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('dbname', function (Blueprint $table) {
-            $table->string("file_name")->after('content');
+            $table->string("file_name")->after('content')-->nullable();

-            $table->string("file_path")->after('content');
+            $table->string("file_path")->after('content')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('dbname', function (Blueprint $table) {
            $table->dropColumn("file_name");
            $table->dropColumn("file_path");
        });
    }
}
```

```zsh:ターミナル
$ php artisan migrate 
```
最小コスト弾性マッチング問題

[問題](https://algo-method.com/tasks/316/editorial)

dp[0][0] = 0 だが c[0][0] = 0 ではない
```c++
// 入力
int N, M;
int C[110][110];

// DP テーブル
int dp[110][110]; //[a : i番目][b : j番目]

int main() {
  cin >> N >> M; //aの個数、bの個数
  for (int i = 0; i < N; ++i) for (int j = 0; j < M; ++j) cin >> C[i][j]; //コスト
  
  // 初期化
  for (int i = 0; i <= N; ++i) for (int j = 0; j <= M; ++j) dp[i][j] = INF;
  dp[0][0] = 0;

  // ループ
  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < M; ++j) {
      //if (i+1 <= N) //aの個数内
        dp[i+1][j+1] = min(dp[i+1][j+1], dp[i][j+1] + C[i][j]); //aのみ進める
      //if (j+1 <= M) //bの個数内
        dp[i+1][j+1] = min(dp[i+1][j+1], dp[i+1][j] + C[i][j]); //bのみ進める
      //if (i+1 <= N && j+1 <= M) //aの個数内 && bの個数内
        dp[i+1][j+1] = min(dp[i+1][j+1], dp[i][j] + C[i][j]); //どちらも進める
    }
  }

  cout << dp[N][M] << endl;
}
```
【Docker】Railsの環境構築

## はじめに
　本記事は、プログラミング初学者、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## DockerでRailsの開発環境を構築する方法
### 必要なファイルを作成
以下のコマンドを実行し、必要なファイルを用意します。

```:ターミナル
$ touch Dockerfile
```
```:ターミナル
$ touch docker-compose.yml
```
```:ターミナル
$ mkdir src
```
```:ターミナル
$ cd mkdir
```
```:ターミナル
$ touch Gemfile
```

### 作成したファイルの中身を記述
```Dockerfile
FROM ruby:3.1.1
# yarnとnode.jsをインストールするための記述
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
  && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
  && apt-get update -qq \
  && apt-get install -y nodejs yarn
# 作業をするディレクトリ
WORKDIR /app
# ./srcを/appにコピー
COPY ./src /app
# ライブラリのインストール先を指定してbundle install
RUN bundle config --local set path 'vender/bundle' \
    && bundle install
```

```docker-compose.yml
version: '3.9'
services:
  db:
    # M1Macを使用している場合には記述が必要。記述しないと docker: no matching manifest for linux/arm64/v8 in the manifest list entries. というエラーが発生。
    platform: linux/x86_64
    image: mysql:8.0.28
    # mysql8.0の認証形式に関する設定
    command: --default-authentication-plugin=mysql_native_password
    # コンテナを再度起動した際にデータを入れ直すことを防止
    volumes:
      - ./src/db/mysql_data:/var/lib/mysql
    # mysqlはパスワードを設定していないとエラーになるため以下は設定必須
    environment:
      MYSQL_ROOT_PASSWORD: password

  web:
    # イメージとしてカレントディレクトリ内のDockerfileを参照
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    # ./src以下を/app以下に同期
    volumes:
      - ./src:/app
    ports:
      - "3000:3000"
    # 依存関係。webはdbに依存しているの意。railsからmysqlに接続する際にDBのIPアドレスを直接記述するが、以下を記述することで当該箇所にdbと記述すればよくなる。
    depends_on:
      - db
```

```Gemfile
source 'https://rubygems.org'

gem 'rails', '~> 7.0.0'

```

### ターミナルでコマンドを実行する

```:ターミナル
$ docker-compose run web rails new . --force --database=mysql
```

### 再度イメージを`build`する
Gemfileに変更が加わっていますので、再度イメージを`build`します。

```:ターミナル
$ docker-compose build
```

### database.ymlを修正
database.ymlを修正してデータベースの設定を行います。

以下のpasswordとhostをdocker-compose.ymlの記述を確認して修正します。
```config/database.yml
：
：

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password   # docker-compose.ymlで設定したpasswordを記述
  host: db   # docker-compose.ymlのdepends_onで設定した値を記述

：
：

```

### データベースを作成する

```:ターミナル
$ docker-compose run web rails db:create
```

### コンテナを作成し、起動する

```:ターミナル
 $ docker-compose up
```

### ブラウザで確認する
http://localhost:3000/ にアクセスし、Railsの初期画面が表示されるか確認します。
【小ネタ】指定したtitleのEditorWindowを取得してをRepaintする

# 追記
いや、改めてググったら　EditorApplication.RepaintProjectWindow() が有るじゃん。

https://docs.unity3d.com/ScriptReference/EditorApplication.RepaintProjectWindow.html

という事でこっちを使います。
ただ「自由なTitle名を指定して、EditorWindowを引っ張ったり、Repaintしたりするための知見」として、下記の記事を残しておきます

# はじめに

ふと「ProjectWindowを描画更新したい」と思い、方法を調べていました。
# ProjectBrowserについて
先ず「とっかかり」は無いかなぁ、と探したところ　EditorUtility.FocusProjectWindow()　が有りました。

https://docs.unity3d.com/ja/current/ScriptReference/EditorUtility.FocusProjectWindow.html

「おっ、あっさり実装できそうじゃん」と思い、Riderで内部コードを見てみると、

```cs
Resources.FindObjectsOfTypeAll(typeof (ProjectBrowser));
```
でProjectBrowserを確保してフォーカスを当てているようですが、
どうやらProjectWindowことProjectBrowserクラスはUnityEditor.dllのinternalクラスのようです。
「うーん、わざわざRefrectionを使うほどの話でもないし、じゃあまぁEditorUtility.FocusProjectWindow()を呼べばRepaint()もかかるかなぁ」とも思いましたが、
別にフォーカスを当てる事まではしたいわけではないのです。
Repaint()が出来れば十分。

# EditorWindowで確保して名前比較
という事で、どうしたもんかなーと考えた結果、基底クラスのEditorWindowはinternalではないので、
そちらでFindObjectsOfTypeAll()を行いRepaintをすることにしました。
ProjectBrowserかどうか、についてはシンプルにtitleの文字列比較で。。
文字列比較は重めですが、まぁEditor用なのでそれほどヒステリックに負荷を気にしなくても良いでしょう。
※FindObjectsOfTypeAll()を使っている時点で負荷的な話は言及しない方向で…。

という事でコードはこちら。

```cs:コードの一部
    /// <summary>
    /// ProjectorWindowをRepaintする
    /// </summary>
    private static void RepaintProjectWindow()
    {
        const string projectBrowserTitleText = "Project";
        RepaintEditorWindow(projectBrowserTitleText);
    }
    
    /// <summary>
    /// 渡されたtitleのEditorWindowをRepaintする
    /// </summary>
    /// <param name="title">目的のEditorWindowのtitle</param>
    private static void RepaintEditorWindow(string title)
    {
        var editorWindows = Resources.FindObjectsOfTypeAll<EditorWindow>();
        var targetEditorWindow = System.Array.Find(editorWindows, editorWindow => editorWindow.titleContent.text == title);
        if (targetEditorWindow == null)
        {
            //見つからなかったら抜ける
            return;
        }

        targetEditorWindow.Repaint();
    }
```

という事で、単純にEditorWindowを引っ張ってきて名前で取得する形にしておきました。

```cs
RepaintProjectWindow();
```
を呼ぶことでProjectWindowを描画更新できます。

もしかするともっとイケている実装があるかもしれませんが、とりあえずわかりやすさ優先という事で。
titleさえ一致すればRepaintできるので
```cs
RepaintEditorWindow("Inspector");
```
とすればInspectorWindowを外部からRepaintする事も可能です。

# 注意点
当然ですが、他に「Project」というタイトルを付けたEditorWindowを作ってしまうと挙動が不安定になりますのでご注意ください…ってそんな名付け（既存ウィンドウと同名の名付け）する人はいないか。
最長共通部分列問題

[問題](https://algo-method.com/tasks/314)

```c++
// 入力
string S1, T1;

// DP テーブル
int dp[1010][1010]; //[S : i番目][T : j番目]

int main() {
    cin >> S1 >> T1; //文字列

    memset(dp, 0, sizeof(dp)); // 初期化
    for (int i = 0; i < S1.size(); ++i) {
        for (int j = 0; j < T1.size(); ++j) {
            if (S1[i] == T1[j]) dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j] + 1); //一致すれば
            dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i + 1][j]); //一致しなければ
            dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j + 1]); //一致しなければ
        }
    }

    cout << dp[S1.size()][T1.size()] << endl; //0が初期値なので
}
```
発電計画問題

[問題](https://algo-method.com/tasks/317)

dp[t]
 時刻 t までの総利得の最大値

区間[ i~j ]の利得はg[i][j-1]である

```c++

// 入力
int T1;
int g[110][110];

// DP テーブル
int dp[110];

int main() {
    cin >> T1; //時刻
    for (int i = 0; i < T1; ++i) for (int j = 0; j < T1; ++j) cin >> g[i][j]; //利得

    // DP テーブル初期化
    memset(dp, 0, sizeof(dp));

    // DP ループ
    for (int t = 1; t <= T1 + 1; ++t) { //時間
        for (int i = 0; i < t; ++i) { //始まり
            for (int j = i + 1; j < t; ++j) { //終わり
                dp[t] = max(dp[t], dp[i] + g[i][j - 1]); //すべての区間を試す
            }
        }
    }
    cout << dp[T1 + 1] << endl; //g[i][j - 1]より
}
```
redashのノウハウ

- アイコン変更
docker ps
docker exec -it --user root redash_server_1 bash

今のアイコン名：favicon-32x32.png
cd /app/client/dist/images
mv favicon-16x16.png favicon-16x16.png.bak
mv favicon-32x32.png favicon-32x32.png.bak
mv favicon-96x96.png favicon-96x96.png.bak

wget hogehoge.png
mv 
find / -name favicon.ico favicon-32x32.png

もしかしたら、commitしたほうが良いかもしれない

- google認証方法
envファイルに設定入れて再起動するだけ
[参考URL1](https://redash.io/help/open-source/setup#Google-OAuth-Setup) [参考URL2](https://tech.renosys.co.jp/entry/2019/11/23/155438)
vim /opt/redash/env
REDASH_GOOGLE_CLIENT_ID (Google OAuth Client ID)
REDASH_GOOGLE_CLIENT_SECRET (Google OAuth Client Secret)
docker-compose up -d server

- メール設定
https://blog.fire-sign.info/1274/

cd /opt/redash
sudo su
vim env

下記を入れてONにする
REDASH_FEATURE_EXTENDED_ALERT_OPTIONS=true
REDASH_MAIL_SERVER=
REDASH_MAIL_PORT=
REDASH_MAIL_USE_TLS=
REDASH_MAIL_USERNAME=
REDASH_MAIL_PASSWORD=
REDASH_MAIL_DEFAULT_SENDER=

$ docker-compose down
$ docker-compose up -d

テスト送信
docker-compose run --rm server manage send_test_mail
エラー出たらこれ見る https://help.sakura.ad.jp/206075182/
あれ？less thanだとアラートが流れない　greater thanは流れる
Node-REDで今日の日付を日本語の表示形式で出す


"2022年03月16日"という形式で日付を出力します。

> ![スクリーンショット 2022-03-16 1.34.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/44aa6eee-a3bc-d0b4-6317-0060ba0f9d30.png "スクリーンショット 2022-03-16 1.34.00.png")

参考記事をもとに[node-red-contrib-moment](https://flows.nodered.org/node/node-red-contrib-moment)を使ってみます。

> 参考: [Node-REDで日時取得とデータ結合](https://ameblo.jp/gameprograming/entry-12657550138.html)


## Date/Time Formatterノード

こちらを使います。

> ![スクリーンショット 2022-03-16 1.36.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b57031c5-421a-6904-e908-64deb5bc049e.png "スクリーンショット 2022-03-16 1.36.13.png")

以下のように設定しました。

enebular上のデバッグだと`+9時間`にする必要がありました。
このあたりは実行するサーバー環境によって変わるかもしれません。

> ![スクリーンショット 2022-03-16 1.36.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/89ff6161-b165-c80b-8878-0d213e8f96de.png "スクリーンショット 2022-03-16 1.36.49.png")

Output Formatで**YYYY年MM月DD日**とすることで日

## 全体の流れ

Inject -> moment -> debugの流れです。

> ![スクリーンショット 2022-03-16 1.39.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/5f1ba381-4f5c-5676-343c-5852d265d947.png "スクリーンショット 2022-03-16 1.39.49.png")

Injectノードは日時を出力するようにしておきます。

> ![スクリーンショット 2022-03-16 1.39.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/df7cbc11-f250-047b-41c5-f0e8a427412b.png "スクリーンショット 2022-03-16 1.39.26.png")

これでデバッグノードに日本語フォーマットで日付が表示されました。

> ![スクリーンショット 2022-03-16 1.40.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/777c0cc1-591c-57b3-2a36-9a0676d07eb1.png "スクリーンショット 2022-03-16 1.40.50.png")
VueでDOM更新後の要素取得(nextTick)

Vueでの機能でnextTickについてのメモ

Watchしてるdataの変数の変更を検知したとしても、それと連動しているDomの変更を検知することは難しいが、nextTickを使えば簡単に検知、またイベントハンドリングすることが容易である。

``` html
<button v-on:click="list.push(`list${list.length+1}`)">addList</button>
<ul ref="target">
    <li v-for="str in list">{{ str }}</li>
</ul>
```


```js
new Component({
    el: '#app',
    data: {
        list: [
            'list1',
            'list2',
            'list3',
            'list4',
        ]
    },
    watch: {
        list: () => {
            this.$nextTick(() => {
                console.log(`ulの縦幅:${this.$refs.list.offsetHeight}`);
            })
        }
    }
})
````

addListのボタンクリック時にはかれるconsoleは、`<li>`タグ５つ分の縦幅が出力されるだろう。

だがもし仮に、以下のように実装していたら...

```js
new Component({
    el: '#app',
    data: {
        list: [
            'list1',
            'list2',
            'list3',
            'list4',
        ]
    },
    watch: {
        list: () => {
            console.log(`ulの縦幅:${this.$refs.list.offsetHeight}`);
        }
    }
})
````
listの変数には`'list'`が追加されているが、このときDOMの変更はまだ行われていないため、
consoleは`<li>`タグ4つ分の縦幅が出力されるだろう。
MySQLのメモリー量を調べる

ここに詳しく載ってるのでこれみたら終わりですが、、、

https://qiita.com/kyrieleison/items/9f303dd046e2fb82fea3


ーーーーーーーーーーーーーーーーーーーーーー

メモリ使用量の計算式は

```
メモリ使用量 = グローバルバッファ + max_connections * スレッドバッファ (　+OSのメモリ使用量とか )
```


それを調べるsql

```sql
select
@@global.key_buffer_size + @@global.innodb_buffer_pool_size + @@global.innodb_log_buffer_size + @@global.net_buffer_length as global_buffer_size,
@@global.sort_buffer_size + @@global.myisam_sort_buffer_size + @@global.read_buffer_size + @@global.join_buffer_size + @@global.read_rnd_buffer_size as thread_buffer_size,
@@global.max_connections as max_connections,
@@global.key_buffer_size + @@global.innodb_buffer_pool_size + @@global.innodb_log_buffer_size + @@global.net_buffer_length + (@@global.sort_buffer_size + @@global.myisam_sort_buffer_size + @@global.read_buffer_size + @@global.join_buffer_size + @@global.read_rnd_buffer_size) * @@global.max_connections as total_memory_size

```

メモリーサイズは / (1024 * 1024 * 1024) をして単位をGBにした方が見やすいです。



参考

https://qiita.com/kyrieleison/items/9f303dd046e2fb82fea3

https://yakst.com/ja/posts/190
Homebrewでインストールできないときの確認点

下記のようなエラーがでたら
```
shell-init: error retrieving current directory: getcwd: cannot access parent directories: Operation not permitted
Error: The current working directory doesn't exist, cannot proceed.
```
現在の作業ディレクトリの権限ではインストールできないため親ディレクトリでインストールし直す
100日でSQLの達人になる@LeetCode! Day44 <RANK(), DENS_RANK(), ROW_NUMBER()の違い>

## 1369. Get the Second Most Recent Activity （問題レベル: Hard）要課金

今日からついに`LeetCode Curated SQL 70`の`Hard`問題に突入。

今日の問題はこれ。
ユーザー毎に二番目に新しい活動をリストアップするという問題。
ただし、1度しか活動がない場合には1番目の活動をリストする。というのが厄介。

悩みましたが自力で正答できました。提出したコードが下記。

```:SQL
SELECT a.username, a.activity, a.startDate, a.endDate
FROM (
SELECT username, activity, startDate, endDate, DENSE_RANK() OVER(PARTITION BY username ORDER BY enddate DESC) AS rank
From useractivity) a
WHERE a.rank=2
UNION ALL
SELECT b.username, b.activity, b.startDate, b.endDate
FROM useractivity b
WHERE b.username NOT IN (SELECT username FROM useractivity GROUP BY username HAVING COUNT(username) > 1)
```

もともとの課題テーブルには重複行があることもあるということで今回は`DENSE_RANK()`を使ったが`ROW_NUMBER()`でもOKがだったようだ。

今日のポイントは下記の使い分けとする。

|クエリ|説明|
| :--: | :--: | 
|ROW_NUMBER( )|行番号を１から振る。同順でも番号は変わる。|
|RANK( )|並び順に順位を付けるが、同順がある場合には同順位になる。次の順位は重複分飛ぶ。例：1位、2位、2位、4位|
|DENSE_RANK( )|並び順に順位を付けるが、同順がある場合には同順位になる。次の順位はそのまま続く。例：1位、2位、2位、3位|
* 並び順は、このクエリの後に続く`OVER(ORDER BY 変数名)`句で指定する。

`UNION`を使った解法もあったので理解しやすい解答だと思いますが、短くて勉強になったのは下記。
```:SQL
SELECT a.username, a.activity, a.startDate, a.endDate
FROM (SELECT *, COUNT(activity) OVER(PARTITION BY username) AS dup, 
ROW_NUMBER() OVER(PARTITION BY username ORDER BY startdate DESC) AS rnk FROM UserActivity) a
WHERE a.rnk=2 OR a.dup<2
```
`WHERE a.rnk=2 OR a.dup<2`という条件が自分では書けない気がします。

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
Oracle Cloud Infrastructure(OCI)で無料マネージドKubernetesクラスター(OKE)を作る

# はじめに
[OCI](https://www.oracle.com/jp/cloud/)、使ってますか？
太っ腹な[無料インスタンス枠](https://docs.oracle.com/ja-jp/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm)が用意されていることから、私は個人的な検証などでよく利用しています。

この無料枠を利用してKubernetesクラスターを作成する記事をブログなどで見かけますが、ほとんどがkubeadmを利用してインストールを行う手法となっています。
ここでは、OCIのマネージドKubernetesサービスである[OKE](https://www.oracle.com/jp/cloud-native/container-engine-kubernetes/)を無料で利用する手法を紹介します。

# おことわり
OKEが無料で使えるということについて、[公式ドキュメント](https://docs.oracle.com/ja-jp/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm)上では明言はされていません。
私個人が試した限りでは請求額は0円でしたが、必ずしも保障されるものでないことをご了承ください。

# 手順
OKEクラスターを作成する際に、
- シェイプでVM.Standard.A1.Flexを選択
- OCPU・メモリー量をAlways Freeの枠内に収まる大きさにする

というだけです。

下の画面のように2OCPU/12GBメモリー/2ノードであれば枠内に収まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/b4165f2b-9770-0176-05a0-6443971ecc60.png)

# 解説
OKEは[クラスター管理の料金は発生しません](https://www.oracle.com/jp/cloud-native/container-engine-kubernetes/)。
ワーカーノードのコンピュートインスタンスが課金対象となります。

で、OKEのワーカーノードはIaaSのインスタンス一覧に並んで表示されてます。（赤枠内がOKEのワーカーノード）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/a6023f70-4812-4ee0-c841-3f533e96526a.png)

OKEで管理されているけれども、OCI内の扱いとしてはIaaSのVMと同等ということのようです。
[公式ドキュメント](https://docs.oracle.com/ja-jp/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm)には「コンピュート仮想マシン(VM)インスタンスを作成するためのコンピュート・サービスで一連のAlways Freeリソースを取得します。」との記載があり、
「VMインスタンスを作成するためのコンピュート・サービス」＝OKEと解釈すれば、Always Freeの対象と捉えてOK…？

実績値としてはご覧の通り請求額0円です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274613/964c569c-e1a3-156b-a897-239b0e35e1cd.png)

以前からあったVM.Standard.E2.1.MicroのシェイプはOKEのノードとして選択できませんでしたが、
VM.Standard.A1.FlexがAlways Freeに加わったことで、OKEを実質無料で使うことができるようになったということのようです。
Oracleはこの縛りを想定していた…？

# 欠点
CPUアーキテクチャはARM64なので、コンテナイメージによって動かない（AMD64でしか公開されてない）ものもあります。
そういうイメージは稼働を諦める、もしくは自分でARM64アーキテクチャでイメージビルドして対応しましょう。

# おわりに
「ちょっとKubernetes触ってみたい、けどkubeadmとかよくわからないし…」という方には最適な選択肢ではないでしょうか。
お手軽勉強用（＋ちょっとしたワークロードなら余裕で動かせる）環境としてぜひ。
最小個数部分和問題

[問題](https://algo-method.com/tasks/311)

dp[i][j]
i 番目までの整数の中から(選ぶ、選ばない)
総和が j とする方法をすべて考えたときの
選んだ整数の個数の最小値

```c++
const int INF = 1<<29; // 十分大きい値にする, INT_MAX にしないのはオーバーフロー対策

// 入力
int n, A;
int a[110];

// DPテーブル
int dp[110][10010];

int main() {
  cin >> n >> A; //個数、総和
  for (int i = 0; i < n; ++i) cin >> a[i]; //整数

  // 一旦すべて INF に
  for (int i = 0; i < 110; ++i) for (int j = 0; j < 10010; ++j) dp[i][j] = INF;
  dp[0][0] = 0;                

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j <= A; ++j) {
      dp[i+1][j] = min(dp[i+1][j], dp[i][j]); //加算しない場合
      if (j >= a[i]) dp[i+1][j] = min(dp[i+1][j], dp[i][j-a[i]] + 1); //加算する場合
    }
  }

  if (dp[n][A] < INF) cout << dp[n][A] << endl;
  else cout << -1 << endl;
}

```
macOS MontereyでXcode12.5を開く方法

# 概要

MacのOSをMontereyへアップデートしたところ、使用していたXcode12.5が起動できなくなるということがあった。
どうやらMontereyではXcode13が必須な模様。

https://developer.apple.com/jp/news/?id=ufox7ci5

ただ、仕事で使用していたため勝手にバージョンを上げるわけにもいかなかった。
そのため、どうにかしてXcode12.5を起動する方法を調査したのでその方法を記載する。

# macOS MontereyでXcode12.5を開く方法

## コマンドでXcodeを起動する

Macのターミナルを開き、以下のコマンドを実行する。
※`Xcode12.5.app`の部分は自分でつけたアプリケーション名のため人によって違うはず。

```
$ /Applications/Xcode12.5.app/Contents/MacOS/Xcode
```

## 補足

ターミナルを終了するとXcodeも終了されてしまうので、ターミナルは起動したままにすること。
部分和数え上げ問題

[問題](https://algo-method.com/tasks/310)

dp[i][j]
i 番目までの整数の中から(選ぶ、選ばない)
総和を j とするパターン数

```c++
const int MOD = 1000000009;

// 入力
int n, A; 
int a[110];

// DPテーブル
int dp[110][10010]; //i番目、総和

int main() {
  cin >> n >> A; //個数、総和
  for (int i = 0; i < n; ++i) cin >> a[i]; //整数

  memset(dp, 0, sizeof(dp));   
  dp[0][0] = 1;                

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j <= A; ++j) {
      (dp[i+1][j] += dp[i][j]) %= MOD; //a[i]を加算する場合
      if (j >= a[i]) (dp[i+1][j] += dp[i][j-a[i]]) %= MOD; //a[i]を加算しない場合
    }
  }

  cout << dp[n][A] << endl; //n個以下、A以下のパターン数
}
```
基本情報技術者試験対策　6日目

基本情報技術者試験勉強　6日目
-
今年の5月に基本技術者試験を受けるために、模擬試験で間違った箇所をまとめるだけの記事


間違えた箇所
-
1,NAS(Network Attached Storage)
TCP/IPのコンピュータネットワークに直接接続して使用するファイルサーバで、コントローラとハードディスクから構成されています。ファイルサービス専用のコンピュータなので、専用化や用途に合うようにチューニングされたOSなどにより、高速なファイルサービスと容易な管理機能が実現

2,ソフトウェア管理ガイドライン
１、法人等におけるソフトウェアの使用状況を常時把握するため，すべてのソフトウェアの使用状況を記録したソフトウェア管理台帳を整備すること。
２、ソフトウェア監査等によりソフトウェアの違法複製等を発見した場合は，事情を調査した上で，違法複製されたソフトウェアを消去する等，適切な措置を速やかに講じること。
３、すべてのソフトウェアユーザを対象として，関係法令，ソフトウェア管理規則，使用許諾契約に規定された使用条件等の周知徹底を図ること。

３、キャパシティプランニングの実施
１、現行システムをモニタリングし現状の処理能力を把握する
２、将来的に予測される端末の増加、利用者数の増加などを分析する
３、2.の分析結果からシステム能力の限界時期を予測する
４、新たなシステム構成で実現すべき性能要件から必要なハードウェア増設を検討する

４、チャタリング
リレーやスイッチの接点が切り替わった際に、微細で非常に速い機械的振動によって、電気信号が断続を繰り返す現象

５、ハードリアルタイムシステム
システムに課せられたある処理がデッドライン内に終了しなかった時（デッドラインミス）、システム全体にとって致命的ダメージが生じる。

６、ファームリアルタイムシステム
デッドラインミスが起こった時、システム全体に致命的なダメージを与えることはないが、その処理自体の価値は即座に0となる。

７、ソフトリアルタイムシステム
デッドラインミスが起こっても、システム全体に致命的なダメージを与えることはなく、その処理自体の価値も、終了時間などにより徐々に落ちていく

８、リアルタイムシステム(Real-time System)
使える資源（リソース）に限りがある状態で、ジョブの実行が命令された時、その処理を決められた時刻（デッドライン）までに終了することに着目した制御工学における概念の一つ

振り返り
-
今日は時間があまり取れなくて、30問は解いたが、正解率は意外と高かった部分は良かった。一方で、一問一問調べる部分が疎かになってしまったことが改善点で、次回はもっと時間をかけて取り組む。

>引用
https://www.fe-siken.com
DataFrameの一括処理の時にpartialを使うと便利だった

# 概要

+ pythonの`functools.partial`の宣伝
+ 引数の一部を固定した新たな関数が作れる
+ DataFrameにmapで一括処理する時に便利だった

# partialとは

https://docs.python.org/ja/3/library/functools.html

> 関数 partial() は、関数の位置引数・キーワード引数の一部を「凍結」した部分適用として使われ、簡素化された引数形式をもった新たなオブジェクトを作り出します。例えば、 partial() を使って base 引数のデフォルトが 2 である int() 関数のように振る舞う呼び出し可能オブジェクトを作ることができます:

引数の一部を固定して新たな関数を作れるということらしい。

```python
from functools import partial

# ベースとなる関数
def linear(x, a, b):
    """ y = ax + b """
    return a * x + b

# y = 2x となる関数doubleを作る
double = partial(linear, a=2, b=0)
print(double(5)) # -> 10

# y = x + 3 となる関数offset3を作る
offset3 = partial(linear, a=1, b=3)
print(offset3(5)) # -> 8
```

# 便利だった使い方

+ DataFrameの複数の列に類似した処理を適応するときに便利だった

```python
def word_repeat(base, repeat=1):
    """ 単語を繰り返したい """
    return base * repeat

#[ ['a', 'b', 'c'],
#  ['d', 'e', 'f'],
#  ['g', 'h', 'i'] ]
test_str = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','i']).reshape(3,3)
df = pd.DataFrame(test_str)

# 1列目は1回、2列目は2回、3列目は3回繰り返す
df[0]=list(map(partial(word_repeat, repeat=1), df[0]))
df[1]=list(map(partial(word_repeat, repeat=2), df[1]))
df[2]=list(map(partial(word_repeat, repeat=3), df[2]))


#[ ['a', 'bb', 'ccc'],
#  ['d', 'ee', 'fff'],
#  ['g', 'hh', 'iii'] ]
print(df)
```

# まとめ

partialを使用すると引数の一部を固定した新たな関数が作成できる。
DataFrameにmapで一括処理する時に便利だった。
他にも良い使い方があったら教えてplease。

以上
グループ登録機能を追加してみた：改

前回deviseを使ってgroup機能の登録を試みたが、中間テーブルに保存されないという現象が起きてしまった。
３時間考えた末、いい解決方法が見つからなかったので、思い切って1から作り直すことに。

### 今回試みた事
* group機能の実装はdeviseではなく、``rails g model group``を使用する
* カラムにはパスワードを設定する

### 手順
まずはモデルの作成

```:ターミナル
rails g model group
```

次に必要なカラムを記述。
```ruby:db/migrate/xxxxx_create_group.rb
class CreateGroups < ActiveRecord::Migration[6.0]
  def change
    create_table :groups do |t|
# 以下の3行を追記
      t.string :group_name,  null: false, default: ""
      t.string :password_digest,  null: false, default: ""
      t.text :note

      t.timestamps
    end
  end
end
```
ターミナルで以下を実行。

```:ターミナル
rails db:migrate
```
次にgroup.rbに以下を記述する。
```ruby:app/models/group.rb
class Group < ApplicationRecord
  has_secure_password
end
```
これ一つを記述するだけで、パスワードが暗号化され、ログイン認証用のメソッドであるauthenticateが使用できるという優れもの。


### Gem  bcrypt
暗号化するためのgemを用意する。
以下のコメントアウトを外す。

```ruby:gemfile
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
gem 'bcrypt', '~> 3.1.7'  # ここの部分のコメントアウトを外す

# Use Active Storage variant
# gem 'image_processing', '~> 1.2'
```

最後に``bundle install``を実行する。
これでDBにデータが保存される。
C言語でファイルポインタからファイルサイズを調べる方法

# 概要

ファイルポインタで扱われているwavファイルが別のwavファイルと同じサイズかを調べたいことがあった。
そのため、ファイルポインタからファイルサイズを調べる方法を記載する。
言語はC

# ファイルポインタからファイルサイズを調べる方法

## 注意点

今回は`fgetpos()`を使用したが、この方法は推奨されておらず`fstat()`を使用するのが良いらしい。

https://www.jpcert.or.jp/m/sc-rules/c-fio19-c.html

## サンプルコード

以下のようにすることでファイルサイズを取得できる。

```C
FILE *fp = fopen("sample.wav", "rb");
fpos_t fsize;

fseek(fp, 0, SEEK_END); // ファイルポインタを末尾へ移動

fgetpos(fp, &fsize); // ファイルポインタの位置を取得

printf("ファイルサイズ(byte) = %ld\n", fsize);

fclose(fp);

return 0;
```
macのプロンプトダサくない？

## 環境
M1 Mac
zsh

## 前置き

最近プロンプトという言葉を知りました。
~より左のことらしいです。Linuxだと$ですね。
```shell
〇〇のMackBook Air 13inch ~ ls 
```

ターミナルを使い始めたばかりの頃すご〜く邪魔で、どうにかこうにかしようとしたのですが、
知識がなさすぎて断念してました。
macのGUIの標準設定でPCの名前を短くすることで対応していました。
これくらいにはできてました。
```shell
hogehoge ~
```

今回はこちらを下記のように変更できたので今後のために残しておきたいと思います。
めっちゃスッキリ!!
個人的な好みですが、$ってかっこいいですよね。 ~より
```shell
$ ls
```

## どのshellを使っているか確認しましょう
```shell
$ echo $SHELL

# zsh使っていたらオッケー!!
```

## `.zshrc`にプロンプトの設定を記述しよう
```shell
# vimで.zshrcファイルを編集します
$ vi ~/.zshrc

# vscodeで編集したい場合は下記
$ code ~/.zshrc
```

```shell:下記を追記
# プロンプトカスタマイズ
PROMPT='$ '
```

## 変更を反映させよう
ファイルを保存した後下記を実行
これは変更を反映させるためのコマンドです。
```shell
$ source ~/.zshrc
```

## 時間を表示したりカスタマイズする
カスタマイズ方法は素敵な参考リンクを掲載いたします。

https://qiita.com/hmmrjn/items/60d2a64c9e5bf7c0fe60
heroku + tweepyを使ってbotを作る際に大変だったところ(備忘録）


# Botを作りてぇ！！（唐突）
題名のまんまです。
TwitterでBotアカウントを初心者ながら作ってみたくいろいろ調べながら作成していく上で大変だったところをいくつかピックアップしていきたいと思います。（備忘録として）

今回作成したBotは以下のアカウントになります。
https://twitter.com/No_baibain

そうです。
ツイート内容を見たらわかるのですが一日づつ栗饅頭が二倍になっていくというだけのbotになっています。
英語があまり読めない私にとってこれだけの内容でもかなりてこずってしまったので、今回はその中でも大変だった部分をまとめていきたいと思います。

# 環境

- Windows 11
- python 3.8.12

pythonプログラムをheroku上で動かす場合、pythonのバージョンに注意してください。

対応バージョン
https://devcenter.heroku.com/ja/articles/python-support


# ファイル構成

ファイル構成は以下のようになります。

```
app/
　┣ src/
　┣ img/
　┃　　　　
　┣ runtime.txt
  ┣ Aptfile
  ┗ requirements.txt
```
srcにはbotのためのプログラムが格納されていて、imgには栗饅頭の画像が保管されています。
それぞれのテキストファイルですがpythonをherokuを扱う際には必要なファイルとなっています。(Aptfileは必要な人だけ)それぞれの役割ですが
runtime.txt : pythonのバージョンを記述
requirements.txt :　pythonで使用するモジュールを記述

これらは必要になってくるのでherokuを扱いたい場合は注意してください！

# tweepyを使って画像を投稿する

現在、(2022/04/04)
``` python
api.update_with_media(filename = "hogehoge.jpg") 
```
では投稿できません。
※apiはtweepy.api()で生成されたオブジェクトです！
投稿するためには以下の手順を踏む必要があります。

``` python
ret = api.media_upload("hogehoge.jpg")
api.update_status(media_ids=[ret.media_id_string])
```
一度、投稿したい画像をupdate_uploadでかましてから動かすとうまくいきました。

# heroku上でopencvを使う
 heroku上でpythonのプログラムを走らせるためには使用するモジュール（
もとからpythonに入っているモジュールは除く）をrequirements.txtに記しておく必要があります！

opencvを扱う場合ももちろんrequirements.txtを下記のようにフォルダ内に残しておく必要があります。
```
opencv-python==4.5.4.58
(モジュール名==バージョン）
```

しかし、opencvをheroku上で扱うためにはこれだけではNGです！！
requirements.txt以外にもAptfile(拡張子なし）を作成しなければなりません！

今回自分の場合は、opencvを利用するためにAptfileには以下のような内容を書き込みフォルダに残すとうまく機能しました。

``` 
libsm6
libxrender1
libfontconfig1
libice6
libgl1
```
# herokuで一時的にファイルを保存する場合

自分の場合、一番困ったのがこの部分で栗饅頭を2倍に増やした後にその画像をツイートするため一時的に保存しておく必要があったのですが、何も考えずに適当な場所に保存するだけではその画像は保存されません！！！

これを解決するためには一度、プログラムを動かしている中でtmpディレクトリを生成したのちにその場所に保存する必要があります。
※もとからtmpディレクトリを作成するのではないことに注意！

つまり、pythonを扱う場合では、
``` python
#osの操作をするためにインポート
import os

#メディアを保存するために一度、tmpディレクトリを作成
os.system("mkdir tmp")

#その後、tmpファイル内にプログラム実行中に作成したメディアを保存する
#save("hogehoge.jpg")
```

という操作を行う必要があります。

参考にしたサイト
https://stackoverflow.com/questions/19253031/heroku-how-to-write-into-tmp-directory

# herokuのタイムスケジューラをpythonで扱うとき

＄マークっぽいところにコマンドを入力して定期実行することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261324/867081bb-c2ba-4f80-5656-81da7d6a2c94.png)

このときにpythonのプログラムを実行する場合は、
```
py something.py
```
ではpythonが実行できないため、
```
python something.py
```
と記述してプログラムを実行しましょう！

# 最後に

初めてのbot作りでAPIの申請やなんやかんやで大変だったので備忘録を残しました。
自分を振り返れば公式ドキュメントを不自由なく読めれるようになればもっと解決がスマートにいったと思います。なのでもっと英語の勉強も頑張りたいと思います！

いまだQiitaでの記事作成に慣れておらず見づらい箇所などがあるかと思いますので是非修正などがありましたらご指摘お願いします！
【勉強メモ】Laravelのqueueとjobについて

実務でqueueとjobについて理解がたりなくて、仕事に時間がかかったため記録としてまとめてました。
間違いがあればご指摘いただけますと幸いです。

# queue(キュー)とjob(ジョブ)とは
非同期処理を行う仕組み
実務でよく見るのは、メール送信やcsv解析など時間がかかる処理はjobクラスで行う印象が強い
※私が実務で読んだコードもcsv解析で使用されていました

# 基本的なキューの設定について
キューの設定は以下の２つのファイルで行われる
.env
config/queue.php

ちなみにconfig/queue.phpにはデフォルトでsyncと設定されています。
これはsynchronizeという同期という意味です。つまり同期処理なので、テストや開発環境で使われ本番環境では使われません。

sync以外には、database, veanstalkd, sqs , redisがあります。

# 実務で使ったdatabaseでジョブを管理する方法について
ジョブをdatabaseに保存するということをまとめます。


## ①.envに以下の設定
```
QUEUE_CONNECTION = database
```
## ②config/queue.php
defaultにdatabaseを設定する

## ③jobのテーブルを追加
```
php artisan queue:table
php artisan migrate
```

## ④ジョブの作成
```
php artisan make:job SendPDFMail
```

## ⑤jobファイルの処理を記述。jobファイルを発火させる処理を書く
省きます。

## ⑥ワーカを実行する
キューの中にあるジョブは自動で実行されるわけではなく、別のプロセスであるWorker(ワーカ)が必要となる
```
php artisan queue:work
```


### キューワーカの実行について
queue:workは手動で閉じるか、ターミナルを閉じるまで処理が続くようになる
上記コマンドはqueue:workコマンド中にコードを変更しても気づかないようになっている
そのため再起動が必要となる。

更新されたコードをリロードする必要も、アプリケーションの状態をリセットしたりするときも再起動する必要がない。ただし、queue:workコマンドよりも大幅に効率が低くなります。
```
php artisan queue:listen
```

### 本番環境でもqueue:workを再起動やらをやらないといけないの？
本番環境では、queue:workプロセスを実行し続ける手段が必要。
queue:workプロセスが終了したことを検出し、自動的に再起動できるプロセスモニタである、Supervisorを設定することができます。
deleted by themを追加したい時の魔法

メモ代わりに残します。

A to B でマージする場合に `deleted by them` が発生したけど追加したい場合、
一度 `rm --cached` して `add` してあげれば良い。
```
git checkout B
git merge A
#=> deleted by theme: hoge_file
git rm --cached hoge_file
git add hoge_file
#=> new file: hoge_file
```
RockyLinuxにRStudioServerをインストールする

# はじめに
RockyLinux（RHEL8のクローンOS）にRStudioServerを構築した際のメモ。
なお、Hyper-V上にRockyLinuxのサーバを立ち上げてインストールしました。
この仮想マシンの構築方法や基本的なネットワーク設定までは書きません。

# 手順
## Rのインストール
epel-releaseのレポジトリを入れてからdnfでインストールでOK。
ちなみに執筆時にはRは4.1.3(2022-03-10)がインストールされました。
※さらにちなみにですが、CentOS7だとepel-releaseのレポジトリ経由でもyumインストールするとR3.6.0が入るので、これより新しいRを入れる場合、ソースインストールが必要です。なので、CentOS7を使い続けてた方は、素直に適当なOSに移行した方が楽なのかなと思います。

```sh
$ sudo dnf install epel-release 
$ sudo dnf install R
$ R --version
R version 4.1.3 (2022-03-10) -- "One Push-Up"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-redhat-linux-gnu (64-bit)
```

## RStudioのインストール
公式ページのやり方が書いてあります。Install for Fedora 28 / Red Hat 8を参考にすればOK。wgetがなければdnfで追加でインストールしてください。

https://www.rstudio.com/products/rstudio/download-server/redhat-centos/

```sh
$ sudo wget https://download2.rstudio.org/server/rhel8/x86_64/rstudio-server-rhel-2022.02.1-461-x86_64.rpm
$ sudo dnf install rstudio-server-rhel-2022.02.1-461-x86_64.rpm
```

## 8787ポートをあける
8787ポートがRStudio用のポートなので、firewall-cmdで空けておきます。

```sh
$ sudo firewall-cmd --add-port=8787/tcp --zone=public --permanent
$ sudo firewall-cmd --reload
$ sudo firewall-cmd --list-all
（ports: 8787/tcpの記載があることを確認）
```

## SELinuxをdisabledにする
SELinuxであまりいい思いをしないので、disabledにしてしまいます。（デフォルト設定だと、httpでアクセスした際にエラーウィンドウが出ます。本当はちゃんと設定すれば良いのかもしれませんが、面倒なので。。）

```sh
$ sudo vi /etc/selinux/config
(７行目を次に書き換えて、:wq)
SELINUX=disabled
$ reboot
```

## リブート後に一応RStudioServerが生きていることを確認
「Active: active (running)」が確認できれば良い。何もせずとも再起動時にサービスが自動で立ち上がるはず。
```sh
$ sudo systemctl status rstudio-server
● rstudio-server.service - RStudio Server
   Loaded: loaded (/usr/lib/systemd/system/rstudio-server.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2022-04-04 10:12:50 EDT; 25min ago
```

## ブラウザでアクセスする

http://${サーバのIP}:8787でアクセスする。認証画面が出て、linux上のユーザ名とパスワードで入れるはず。


# 最後に

RockyLinuxでも、何の問題も無く、RStudioServerを構築できました。以上。

# 環境

- ホストのハードウェア: Minisforum EliteMini HX90
- ホストのOS: Windows 11 Pro 21H2
- 仮想化のソフト: Hyper-V マネージャー バージョン:10.0.22000.1
- 仮想マシンのOS: Rocky Linux release 8.5 (Green Obsidian)
- R version 4.1.3 (2022-03-10) -- "One Push-Up"
- RStudio 2022.02.1+461 "Prairie Trillium" for RHEL 8
pipenvで"Error: the command get_cpu.py could not be found ..."


シェルでpipenvを動かそうとしたら……
```
$ pipenv run get_cpu.py
```

こんなエラーが出ちゃった！
```
Error: the command get_cpu.py could not be found within PATH or Pipfile's [scripts].
```

解決方法→
単に'python3'をつけて実行指示出すの忘れてただけでした（下正解）。

```
$ pipenv run python3 get_cpu.py
```

# あとがき

こんなエラー五秒で直してやったぜ！
SIPを調べた際のメモ

# **SIP**

- [RFC 3261](https://tools.ietf.org/html/rfc3261)
- [RFC 3261 和訳](http://www.softfront.co.jp/tech/ietfdoc/trans/rfc3261j.txt)
- [Wikipedia](https://ja.wikipedia.org/wiki/Session_Initiation_Protocol)

## SIP Request Messages.
![Untitled (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/d74fbba6-6d29-d8dc-4dea-6edb239843f4.png)
![Untitled (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/67a02866-b414-4dc1-0889-ff3222f147a3.png)
* 通話は RTP/UDP

![Untitled (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/e7e18eed-3fdb-33fc-171a-ac749ab2fe94.png)
- 通話の両端の情報（電話番号、IPアドレス) が取れる。
- Call ID を 通話の識別情報に用いれる。

![Untitled (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169589/eac66ad8-fdb2-8c25-02d8-ac559b0195c2.png)

## SIP 応答番号と意味
### 1xx = 情報応答
|値| 意味|
|---|---|
|100 |試行中 |
|180 |呼び出し中 |
|181 |転送中 |
|182 |順番待ち |
|183 |セッション進行中 |


### 2xx = 成功応答
|値| 意味|
|---|---|
|200 |OK |
|202 |受諾：照会に使用 |


### 3xx = リダイレクト応答
|値| 意味|
|---|---|
|300 |複数の転送先 |
|301 |永久的に移動 |
|302 |一時的に移動 |
|305|プロキシ使用 |
|380 |ほかのサービス |


### 4xx = リクエスト エラー
|値| 意味|
|---|---|
|400 |Bad Request |
|401 |認証が必要：レジストラのみ利用可。プロキシは「プロキシ認証 407」が必要 |
|402 |支払いが必要（将来使われる可能性あり） |
|403 |禁止 |
|404 |見つかりません：ユーザが見つかりません |
|405 |メソッド利用不可 |
|406 |容認不可 |
|407 |プロキシ認証が必要 |
|408 |リクエスト タイムアウト：時間内にユーザが見つかりませんでした |
|410 |不在：ユーザは過去に存在しましたが、もうここにはいません |
|413 |リクエスト本体が大きすぎます |
|414 |リクエストURIが大きすぎます |
|415 |非対応メディア |
|416 |非対応URIスキーム|
|420 |不正な拡張：ＳＩＰプロトコル拡張がサーバに認識されません |
|421 |拡張が必要 |
|423 |間隔が短すぎます |
|480 |一時的に利用不可 |
|481 |通話 / トランザクションが存在しません |
|482 |ループ検出 |
|483 |最大ホップ数超過 |
|484 |不完全なアドレス|
|485 |あいまい|
|486 |話し中 |
|487 |リクエストが中止 |
|488 |ここでは容認不可 |
|491|リクエスト待機中 |
|493 |解読不可：S/MIME本文を解読できなかった |


### 5xx = サーバー エラー　
|値| 意味|
|---|---|
| 500| サーバー内部エラー |
| 501| 非実装：SIPリクエスト メソッドが実装されていません|
| 502| 不正なゲートウェイ|
| 503|サービス利用不可 |
| 504|サーバタイムアウト |
| 505|バージョン非対応：サーバはこのSIPバージョンに対応していません |
|513 | メッセージが大きすぎます|


### 6xx = グローバル エラー
|値| 意味|
|---|---|
|600 |随所で話中 |
|603 |拒否 |
|604 |どこにも存在しません |
|606 |容認不可 |
ストリームアルゴリズムを用いて確率抽選を行う

ゲームにおけるアイテムのドロップなどにありがちな、
* Aというアイテムは50%で出現する
* Bは30％で出現する
* Cは20％で出現する

という確率に従ってA,B,Cを抽選するという処理を考えます。
様々な実装方法がありますが、ここでは**ストリームアルゴリズム**的な実装方法について記載します。

# ストリームアルゴリズムとは
**ストリームアルゴリズム**とは、forループを用いて逐次的な処理で実現するアルゴリズムを指します。

例えば、配列から最大値を求める時に
```javascript
const arr = [3, 1, 4, 2]
let max = arr[0]
for(let i = 1; i < arr.length; i++){
  if(arr[i] > max) max = arr[i]
}
console.log(max) // 4
```
のような実装をしますが、これがストリームアルゴリズムです。

# ストリームアルゴリズムによる抽選方法
では本題の抽選についてですが、次のように実装します。
```javascript
const arr = [50, 30, 20] // 生起確率（%）
let index = 0
let sum = 0
for(let i = 0; i < arr.length; i++){
  sum += arr[i]
  if(sum * Math.random() < arr[i]){
    index = i
  }
}
```
これを前述したABCの例で説明すると、
1. まずAが選ばれてる状態から開始
2. Aが50%、Bが30%なので、30/80=37.5% の確率でBを選択状態にする
3. Cは20％なので、20/100=20％の確率でCを選択状態にする

と言う流れになります。

試しに以下のようなコードでサンプリングしてみると、
```javascript
function P() {
  const arr = [50, 30, 20]
  let index = 0
  let sum = 0
  for (let i = 0; i < arr.length; i++) {
    sum += arr[i]
    if (sum * Math.random() < arr[i]) {
      index = i
    }
  }
  return index
}
 
const result = [0, 0, 0]
for (let i = 0; i < 10000; i++) {
  result[P()]++;
}
console.log(result)
```
`[4962, 3006, 2032]` という期待通りの出力を得ることができました。

ストリームアルゴリズムは、メモリを節約することができる特徴があり、色々な場所で使えると思います。
Oracle Net Services

- Enterprise Manager Cloud Control
    - WebブラウザベースのGUI管理画面
    - 複数のサーバを一元的に管理できる統合管理ツール
    - 任意のデータベースサーバターゲット上のネットサービス名やリスナー名を一元的に管理できる
- Enterprise Manager Database Express
    - Oracle Net Servicesの設定を行うことはできない
- Oracle Net Manager(NETMGR)
    - Oracle Net Servicesの設定を実行できるGUIツール
    - GUIのツールで、ローカルのデータベース・サーバーのネーミングメソッドを管理できる
    - 「netmgr」コマンドで起動することも可能
- Oracle Net Configuration Assistant(NetCA)
    - リスナー、ネーミングメソッド、ネットサービス名、ディレクトリ使用をGUIにて設定できる
    - GUIのツールでtnsnames.oraファイルの構成などを行える
    - Oracle Net Manager(NETMGR)に比べて設定できる項目が限定されている
    - DBCAやOracle Universal Installerから内部的に実行されることもとある
    - 「netca」コマンドで起動することも可能
- リスナー制御ユーティリティ(lsnrctl)
    - 「lsnrctl」コマンドで、リスナーの起動や停止を行える
- tnsping ユーティリティ
    - 指定した接続識別子によるリスナーへの接続可否を確認するツール
    - 「tnsping」コマンドで、ネットサービス名の名前解決とリスナーへの到達を試行する

## 動的サービス登録
インスタンスが自インスタンスの情報をリスナーに登録するサービス登録方法
起動中のLREGプロセスは、LOCAL_LISTNERの設定したアドレスに動的サービスを行う


## Oracle Net Servicesの識別子
１つの接続識別子で、複数のデータベースインスタンスを参照できる
１つの接続識別子で、複数のリスニングポートを参照できる

## 接続時ロードバランシング
接続先リスナー情報として、複数のアドレスを指定しておき、接続字工事にいずれかのアドレスをランダムに使用することで、接続先アドレスを負荷分散する機能

## 接続時フェイルオーバー
接続先リスナー情報として複数のアドレスを指定しておき、最初に使用したアドレスで接続に失敗した場合、次のアドレスで再度接続を試行する方法
よって、接続する試行回数は、最大背接続記述しに設定した接続先リスナーアドレスと同じ

## 透過的アプリケーションフェイルオーバー
接続確立後で意図せず接続が切断されたとき、接続を再確立し、かつ、実行中のSELECT文をシームレスに継続する機能

## ネーミングメソッド
- 簡易接続ネーミング(EZCONNECT)
    - 以下の書式で、接続識別子に接続先情報（ホスト名、ポート番号、データサービス名）を直接指定する。
        - host[:port][/service_name]
- ローカルネーミング(TNSNAMES)
    - クライアントコンピュータ上の設定ファイルtnsnames.oraに接続識別子と接続先情報の対応関係を記載しておき、ここから接続先情報を得る
- ディレクトリネーミング
    - LDAP準拠のディレクトリサーバーに接続識別子と接続情報の対応関係を記載しておき、ここから接続先情報を得る
- 外部ネーミング(NIS)
    - 外部のネーミングサービスに接続識別子と接続先情報の対応関係を記載しておき、ここらから情報を得る

## 共有サーバー構成
- ユーザープロセスはディスパッチャと通信する
- ディスパッチャはユーザプロセスからの要求をキューに入れる
- ユーザプロセスからの要求は共有サーバープロセスが処理する

## 専用サーバー構成
- ユーザプロセスのセッション確立時、リスナーが専用サーバープロセスを起動する
- ローカル接続の場合、リスナーは不要
- ローカル接続の場合、接続方式は専用サーバーのみが使用可能
【MySQL】INSERT文でテーブルにデータを追加する 

バックエンドの勉強としてFastAPIをいじっているのですが、どうにもDB周りのコマンドで詰まりがちなのでSQL文を最初から学び直しています。
わいCloudFirstやから…とかいう言い訳は効きそうにないので頑張ります。

<!--more-->
### 前回学んだこと
前回はSELECT文について学びました。

https://qiita.com/Terralien/items/274bf2dd7a5bd9cfdb29

## INSERT文とは
テーブルにデータを追加するときに使用するコマンドです。

### 使い方
`INSERT INTO`の後にテーブル名、`VALUES`の後にカラムに挿入するデータを指定してきます。

```sql
INSERT INTO テーブル名 VALUES (データ1, データ2, データ3...);
```
カラム数が変わらない場合VALUEのみで指定することもできます。
値をセットしない場合はnullとします。

```sql
INSERT INTO staff VALUES (1,'ikeda','leader');
INSERT INTO staff VALUES (2,'satou',null);
```

:::note warn
※カラム数に増減があった場合エラーとなります。
:::

以下のようにカラムを指定した方法もあります。

```sql
INSERT INTO staff (id, name) VALUES (2, "山田さん");
```

コード参考：[MySQL INSERTの基本](https://envader.plus/course/2/scenario/1047/)

### 実は省略できるINTO句
INTO句って要るのかな？
実はMySQLでは省略できます。できるのですが他のRDBMSで省略できない場合もあるので記述していたほうが無難かと思います。

同様にVALUES句もVALUEと省略できるのですが、やはり同じ理由で記述しておいたほうが無難かと思います。

### SELECT文を使って別のテーブルからデータを引っ張ってくる

VALUES部分をSELECTとすることで指定できます。

```sql
INSERT INTO table1 (カラム1, カラム2, ...)
SELECT table2.カラム 
FROM table2 WHERE 条件;
```

## SELECT文問題を解いてみる

実際に身についたか仮想環境[Envader](https://envader.plus)で試してみます。


> 問題1　starテーブルに対して新たにidが6でvalueが6のレコードを追加してください。

解答は今回学んだことそのままなので結果だけ

```sql
select * from star;
+----+-------+
| id | value |
+----+-------+
|  1 |     1 |
|  2 |     2 |
|  3 |     3 |
|  4 |     4 |
|  5 |     5 |
|  6 |     6 |
+----+-------+
```

問題のとおり追加できました。

> 問題2　evaluationテーブルに対して新たにuser_idが2,store_idが10,star_idが5のレコードを追加してください。

```sql
| 1249 |      30 |       47 |       2 |
| 1250 |      42 |        6 |       5 |
| 1251 |       2 |       10 |       5 |
+------+---------+----------+---------+
```

追加できました。
とりあえず覚えたということにします。

## 学んだこと
* INSERT文の使い方、カラムとデータの関係について注意すること。

おかしなエラー出さないためにしっかりとテーブルの構造について理解しておくことが大事なんだなーと思いました。

何か間違っていることなどご指摘ありましたらコメントお願いいたします！

## 参考資料
https://envader.plus/course

https://products.sint.co.jp/topsic/blog/sql-insert

https://itsakura.com/sql-insert
ASP.Net Core MVC チェックボックスがチェックされて無くても値を送信

# 概要
「[Qiita - HTML チェックボックスでfalseも判定する](https://qiita.com/miriwo/items/a663fa7eade2ff2b3593)」を見て、
ASP.NET Core MVCでも値を送れるのか試したところ、
下記の並び順では無理でした。

```html
<input type="hidden" name="test" value="0">
<input type="checkbox" name="test" value="1">
```

# 軽く説明
asp-for="Test"は、HTMLの属性id="Test"とname="Test"として
展開され、submitした際にname="Test"が捕捉され、
サーバへデータが飛びます。

Microsoftは捻くれており、nameが重複して存在した場合、
最初に現れたnameのみをサーバに送ってくれるので
`<input type="hidden" name="test" value="0">`
が先にあると後ろのチェック状態がどうであろうと
type="hidden"のvalue="0"しか送られなくなります。

# 解決方法

#### チェックボックスより後ろに書く

```html
<form action="/" method="post">
    <input type="checkbox" asp-for="Test" value="1">
    <input type="hidden" asp-for="Test" value="0"> @*後ろに書く*@
    <button>送信</button>
</form>
```

## まとめ
### これがMicrosoft Quality...
補足すると同名の複数チェックボックスの取得は、ビューモデルの型に
List\<bool>やList\<string>を使うことで可能となっています。

チェックボックスにチェックが無い場合に、0を送りたいという
要件はhiddenの要素をチェックボックスより後ろに書くことで
可能となります。
Javascript を書く場所

## はじめに
Javascriptを書く場所について考える
## ゴール
JSを書き込む場所を知ること
## 教科書
https://www.sbcr.jp/product/4815601577/
## 内容
```html:html内に直接記載する
-------------
</footer>
<script>
    'use strict';
    console.log('よく柿食う客だ');
</script>
```

```html:jsを読み込む部分を記述する
</footer>
<script src="script.js"></script>
```

```js:上に読み込むJSファイル「script.js」を作成する
'use strict';
console.log('よく柿食う客だ');
```
Flutter Firebase storageのファイルを削除する方法

# はじめに
Flutterアプリを勉強中（まだまだ奮闘中の身）
画像をタスクの要素として追加するようなアプリを作成中にタスクの削除をした際に画像も削除しないと不要な画像がFirebaseStorageに溜まってしまうことを懸念して、画像URLから画像の削除を試みる

#開発環境
・使用言語：dart(flutter)
・AndroidStudio 4.1.2
・iOS シミュレーター(iOS14.5)

# FirebaseのCloudStorageで定義されているdelete()メソッドを使用
自分が作っているアプリでは画像のURL情報を持っており、CloudStorageのファイル削除の方法として以下公式ドキュメントに記載のdelete()メソッドを使用すれば良いと判明
https://firebase.google.com/docs/storage/web/delete-files?hl=ja#web-version-8

はりきって使用してみるもファイルが見つからないと言われる

```dart
Future<void> _deletePhotoData(TaskData data) async {
   final storageReference = FirebaseStorage.instance.ref();
   await storageReference.child(data.url).delete();
}
```
# 原因
恥ずかしながら公式ドキュメントを良く読むと削除対象ファイルの相対パスを指定しなければならないよう。。。（下記が正しいdelete()メソッドの使い方）
```dart
Future<void> _deletePhotoData(TaskData data) async {
   final storageReference = FirebaseStorage.instance.ref();
   await storageReference.child('images/desert.jpg').delete();
}
```
ところが相対パス情報はTaskData内では持っておらずURLからどうにかして相対パス情報を得たいところ。ということで色々調査したところ以下のやり方を見つけたがかなり脳筋。。。

https://jpcodeqa.com/q/4e8c24203b077566adf08b12eb6b8380

```dart
Future<void> _deletePhotoData(TaskData data) async {
   String filePath = data.url.replaceAll(RegExp(r'https://firebasestorage.googleapis.com:443/v0/b/"アプリ名".appspot.com/o/'), '');
   filePath = filePath.replaceAll(RegExp(r'%2F'), '/');
   filePath = filePath.replaceAll(RegExp(r'(\?alt).*'), '');
   final storageReference = FirebaseStorage.instance.child(filePath);
   await storageReference.delete();
}
```
確かに削除はできるがもう少しいいやり方がありそう。。。

# 解決方針

下記refFromURL()メソッドを使用するとURLからFirebase Storageの相対パスを取得できる！
https://firebase.google.com/docs/reference/node/firebase.storage.Storage#reffromurl

```dart
Future<void> _deletePhotoData(TaskData data) async {
   final storageReference = FirebaseStorage.instance.refFromURL(data.url);
   await storageReference.delete();
}
```
めっちゃスッキリ解決しました！！！
PPAPを拒否するMilterを作ってみました

# PPAPを拒否するMilterを作ってみました

## はじめに

PPAPなメール、つまり、暗号化されたパスワード付きzipが添付ファイルに含まれているメールを拒否するMilterを作ってみました。

https://github.com/hirachan/no-ppap-milter

今回は、使い方を簡単に説明します。
環境は、手元にあったCentOS7ですが、どの環境でも大して変わらないと思います。

## 事前準備

使用しているライブラリ`pymilter`がCのmilterとリンクしますので、gccとpython, sendmailそれぞれの開発用ライブラリが必要です。

```console
yum install -y python3-devel gcc sendmail-devel
```

Ubuntuの場合は、

```
apt-get install -y gcc python3-dev python3-pip libmilter-dev
```
です。

## No-PPAP-Milterのインストール

```console
pip3 install no-ppap-milter
```

`no-ppap-milter` というコマンドがインストールされます。

## Postfixの設定

main.cfに以下のように追加します。

```:main.cf
milter_protocol=6
milter_default_action=accept
smtpd_milters=inet:localhost:9201
```

unix domain socketを使う場合は、smtpd_miltersのところを

```:main.cf
smtpd_milters=unix:/var/run/milter.sock
```
のようにします。

## No-PPAP-Milterの起動

`no-ppap-milter`コマンドを実行します。

```console
no-ppap-milter
```

unix domain socketを使う場合は、`--socket-name`オプションで指定できます。
postfixユーザーが読み込めるようにpostfixユーザーで実行するのがいいでしょう。

```console
sudo -u postfix /usr/local/bin/no-ppap-milter --socket-name unix:/tmp/milter.sock
```


## 確認

### 普通の添付ファイルのあるメールの場合

```console
# telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 example.com ESMTP Postfix
HELO localhost
250 example.com
MAIL FROM: hirano@example.com
250 2.1.0 Ok
RCPT TO: hirano@example.com
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
MIME-Version: 1.0
... 省略 ...

--00000000000075672405db1ef6ff--
.
250 2.0.0 Ok: queued as 321E421CBB
```

ちゃんと届いたようです。
では、PPAPなパスワード付きZIPファイルの添付されたメールではどうでしょうか。

### パスワード付きZIPな添付ファイルのあるメールの場合

```console
... 省略 ...
DATA
354 End data with <CR><LF>.<CR><LF>
... 省略 ...
.
550 5.7.1 We do not accpet encrypted zip.
```

いい感じですね。拒否されました。
リスナー経由接続時のシステムコールを見る（Oracle Database 19c)

# Oracle Databaseへの接続
Oracle Databaseインスタンスにネットワーク経由で接続するためにはリスナーが必要です。リスナーは指定されたプロトコルとポート番号でクライアントからの接続を待ちます。クライアントが接続すると認証を行い、インスタンスと接続します。デフォルトでは「専用サーバー」と呼ばれるクライアントと１対１に対応するプロセスが起動し、クライアントからの SQL 文を処理します。本記事では Linux 版の Oracle Database 19c でクライアント接続時に発行されるシステムコールをトレースし、専用サーバープロセスが何を行っているかを確認します。

# システムコールのトレース
Linux でシステムコールのトレースを取得するには strace コマンドを実行します。プロセスとしてリスナーを指定します。また子プロセスもトレースするために -f オプションも指定します。

```SHELL:
$ ps -ef|grep tns | grep -v grep
root         29      2  0 Apr02 ?        00:00:00 [netns]
oracle     4828      1  0 Apr02 ?        00:00:01 /u01/app/oracle/product/19.0.0/dbhome_1/bin/tnslsnr LISTENER -inherit
$
$ strace -f -p 4828 -o trace.out
strace: Process 4828 attached with 2 threads
strace: Process 42229 attached
strace: Process 42230 attached
```

# トレース結果

## プロセス起動
プロセスID 4848 のリスナーはクライアントの接続を受け付けます。
```
   4828  accept(11, {sa_family=AF_INET6, sin6_port=htons(59880), inet_pton(AF_INET6, "fe80::5ad2:2131:8c7:892d", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=if_nametoindex("ens33")}, [128->28]) = 19
```

次に子プロセスを生成します。プロセスIDは42229です。リスナー・プロセスは子プロセスの終了を待ちます。
```
   4828  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fcf3d9b7cd0) = 42229
   4828  wait4(42229,  <unfinished ...>
```

子プロセス42229は更に子プロセスを生成します。その後すぐに終了します。
```
  42229 <... clone resumed>child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fcf3d9b7cd0) = 42230
  42229 exit_group(0 <unfinished ...>
```

孫プロセス 42230 は $ORACLE_HOME/bin/oracle を実行します。これが専用サーバーになります。

```
  42230 execve("/u01/app/oracle/product/19.0.0/dbhome_1/bin/oracle", ["oracleO19A", "(LOCAL=NO)"], 0x172f2f0 /* 32 vars */ <unfinished ...>
```

専用サーバープロセスはmmapシステムコールでSGAに接続します。
```
  42230 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f920678c000
  42230 mmap(NULL, 2105552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f9206369000
  42230 mprotect(0x7f920636b000, 2093056, PROT_NONE) = 0
  42230 mmap(0x7f920656a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0x7f920656a000
```

上記のように専用サーバーを起動するためには２つの子プロセスを生成する必要があります。最初の子プロセスがすぐに停止することで、専用サーバー・プロセスが親プロセスがいない独立したプロセスとして起動することができます。Oracle Database の専用サーバー構成は初期接続の負荷が高いため共有サーバー構成やコネクション・プーリング等のテクノロジーを使って負荷を軽減する対策が行われます。

## 設定ファイルの読み込み
専用サーバーは認証を行いますが、その際にいくつかの設定ファイルを読み込みます。以下のファイルの確認や読み込みを行っていることがわかります。

|ファイル名|説明|備考|
|:---|:---|:---|
|${ORACLE_HOME}/env.ora|環境変数の設定？||
|/etc/orabasetab|読み取り専用Oracle-Home関連||
|${ORACLE_HOME}/install/orabasetab|読み取り専用Oracle-Home関連||
|${ORACLE_HOME}/network/admin/sqlnet.ora|SQL*Net設定||
|${ORACLE_HOME}/network/admin/intchg.ora|CMAN関連||
|${ORACLE_HOME}/network/admin/tnsnav.ora|CMAN関連||
|${ORACLE_HOME}/opmn/conf/ons.config.{hostname}|Oracle Notification System設定||
|${ORACLE_HOME}/opmn/conf/ons.config|Oracle Notification System設定||

上記以外に共有ライブラリの読み込み、ログ・ファイルの出力、メッセージ・カタログ（msb）の読み込み等が行われます。