OmniAICreator/Qiita-1.07M huggingface dataset:
Herokuでpg:psqlを実行しようとしたらThe local psql command could not be located

初歩中の初歩で引っかかったのでメモ。
意外とこんなところで引っかかる人もいるのかも…ということで。
※ローカル環境はWindows8.1を使ってます。

HerokuのアプリにHeroku Postgresを導入し、いざ`heroku pg:psql -a [appname]`を打ったところ、こんなメッセージが。

```:command
$ heroku pg:psql -a [herokuのアプリ名]
--> Connecting to postgresql-adjacent-61496
 !    The local psql command could not be located. For help installing psql, see https://devcenter.heroku.com/articles/heroku-postgresql#local-setup
```

<h2>PostgreSQLをローカルにインストール</h2>
CLIで実行するにあたって、ローカルにPostgreSQLがインストールされている必要があるので、インストールします。

Heroku上のバージョンとローカルのバージョンを合わせる必要があるらしいので、まずは確認。

```:command
$ heroku pg -a [herokuのアプリ名]
=== DATABASE_URL
Plan:                  Hobby-dev
Status:                Available
Connections:           0/20
PG Version:            11.6
Created:               2020-02-01 02:31 UTC
Data Size:             7.9 MB
Tables:                1
Rows:                  2/10000 (In compliance)
Fork/Follow:           Unsupported
Rollback:              Unsupported
Continuous Protection: Off
Add-on:                postgresql-adjacent-61496
```

11.6だったので、postgresqlのダウンロードページから、同じバージョンをダウンロードしてインストールします。

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

よし、というわけでもう一度打ってみましょう。

```:command
$ heroku pg:psql -a [herokuのアプリ名]
--> Connecting to postgresql-adjacent-61496
 !    The local psql command could not be located. For help installing psql, see https://devcenter.heroku.com/articles/heroku-postgresql#local-setup
```


<b>……は？</b>



<h2>Pathを設定する</h2>
なんでやねんと思いつつ、提示されているURLをチェックしてみたら、こんな記載がありました。（Windows Set Upのところを参照しましょう）

>Remember to update your PATH environment variable to add the `bin` directory of your Postgres installation. The directory will be similar to this: `C:\Program Files\PostgreSQL\<VERSION>\bin`. If you forget to update your PATH, commands like `heroku pg:psql` won’t work.

引用元：https://devcenter.heroku.com/articles/heroku-postgresql#set-up-postgres-on-windows

「ちゃんとPathを通さないとコマンド機能しないから忘れんなよ。」ってことみたいです。というわけで、Pathを設定しましょう。

<b>「コントロールパネル」
　　＞「システムとセキュリティ」
　　　＞「システム」
　　　　＞「システムの詳細設定」
　　　　　＞「詳細設定」のタブから「環境変数（N）」を選択</b>


ポップアップウインドウが表示されるので、「システム環境変数」から"Path"を探します。そこで「編集」を選択し、binファイルの置かれているパス(今回であれば`C:\Program Files\PostgreSQL\11\bin`)をコピペします。

ちなみに入力されているデータを消さないように、先頭に区切り文字の`;`を付与してペーストします。私は何も知らずにそのまま上書きしてしまい、ひどい目に遭いました。Windows10ではそのような心配は無いようですが、Windoqs8.1の方はくれぐれも注意です。


そして改めて実行すると…。今度はちゃんと通ったようです。

```:command
$ heroku pg:psql -a [herokuのアプリ名]
--> Connecting to postgresql-adjacent-61496
psql (11.6)
SSL 接続 (プロトコル: TLSv1.2、暗号化方式: ECDHE-RSA-AES256-GCM-SHA384、ビット長: 256、圧縮: オフ)
"help" でヘルプを表示します。
herokuのアプリ名::DATABASE=>
```
Windows起動・終了まわりのメモ



## 時間指定で自動で起動する

BIOS設定を参照
自動起動できないタイプも存在する？

## スタートアップ
1. 隠しファイルを表示する

		reg add "HKCU¥Software¥Microsoft¥Windows¥CurrentVersion¥Explorer¥Advanced" /v Hidden /t REG_DWORD /d 1 /f
	
2. 下記のフォルダにアプリケーションを配置する

**特定のユーザがログオンした時のみに実行する場合**
	
	C:\Users\[ユーザー名]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

**全てのユーザがログオンした時に実行する場合**
		
	C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp


Winキーを押しながらRキーを押して「ファイル名を指定して実行」に以下を入力するとStartUpフォルダ開くことができる

	// 特定のユーザ
	shell:startup
	
	// 共通ユーザ
	shell:common startup



## jscript アプリケーションを起動

ウインドウスタイルを指定して起動する

```start.js

// ウインドウスタイル
var WS_NOTVISIVLE   = 0;    //ウインドウは非表示
var WS_ACT_NOMAL    = 1;    //ウインドウはアクティブ、サイズは通常(規定値)
var WS_ACT_MIN      = 2;    //ウインドウはアクティブ、サイズは最小
var WS_ACT_MAX      = 3;    //ウインドウはアクティブ、サイズは最大
var WS_NOTACT_NOMAL = 4;    //ウインドウは非アクティブ、サイズは通常
var WS_ACT_DEF      = 5;    //ウインドウはアクティブ、サイズは前回終了時と同じ(アプリによって動作は異なる)
var WS_NOTACT_MIN   = 7;    //ウインドウは非アクティブ、サイズは最小

// Shell関連の操作を提供するオブジェクトを取得
var sh = new ActiveXObject("WScript.Shell");

// 5秒待機
WScript.Sleep(5000);

// カレントディレクトリを設定
sh.CurrentDirectory = "../Desktop/app";
// アプリ起動
sh.Run("Test.exe", WS_ACT_NOMAL);

//  オブジェクトを解放
sh = null;

```

## jscript node-foreverを起動

```start.js

// Shell関連の操作を提供するオブジェクトを取得
var sh = new ActiveXObject("WScript.Shell");

// 5秒待機
WScript.Sleep(5000);

//  カレントディレクトリを設定
sh.CurrentDirectory = "../test";
// PowershellでNode起動(空白を含む引数を渡すには""でくくるが、JScriptで"を渡すには"の前に\をつける)
sh.Run("\"C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe\" \"forever -c 'cmd /c node' start app.js\"", 1);

// 5秒待機
WScript.Sleep(5000);


//  オブジェクトを解放
sh = null;

```

## アプリ起動後にクラッシュを監視したい
https://github.com/Satoshi-Hirazawa/windows-alive-checker/blob/master/aliveChecker.js


## 自動でシャットダウン
1.［タスク スケジューラ］を開く
2.［基本タスクの作成］を選択
3. 時間を入力する
4. [プログラム/スクリプト]に[shutdown]を入力
5. [引数の追加]に[/s /f]を入力

	/s	シャットダウンを実行します。再起動にしたい場合は s ではなく r を指定
	/f	警告せずにアプリを強制終了します。保存していないデータがあっても、強制終了される
	/t 120	プログラムを起動するまでの時間（秒）を設定する


## 参考サイト
http://jscript.zouri.jp/Source/ApplicationCtrl.html
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1112123261
VMware vCenter Server Appliance のアップグレード(6.0->6.7)をした話

# VMware vCenter Server Appliance のアップグレード(6.0->6.7)をした話
はい皆さんこんにちは

結論から言うとこの記事は
vCSAのアップグレードを2通り
6.0U2->6.5U3
6.0U2->6.7U3
した手順と思った事をまとめた話です。

# 詳細

資料が欲しい方はこの辺見てください。
https://docs.vmware.com/jp/VMware-vSphere/6.5/vsphere-esxi-vcenter-server-652-upgrade-guide.pdf
https://docs.vmware.com/jp/VMware-vSphere/6.7/vsphere-vcenter-server-671-upgrade-guide.pdf　
https://kb.vmware.com/s/article/2147929?lang=ja

環境：
ESXi6.0
vCSA6.0U2（小環境）

このvCSAの環境が極小だと、とても重い。
**WebClientが悲しいぐらい重い**
いやでもDISK容量がもったいない・・・
という人はシンディスクモード（使う分だけ拡張していく）を選んでやりましょう。
※極小にしたあと、設定変更でvCPUの数を増やしてもいいです。

注意事項：
ダウングレードする事も考えて事前に旧環境のスナップショットを取得しましょう

##アップグレードステージ１
・ソースアプライアンスに接続

・ソースアプライアンスを管理するESXiかvCenterに接続
　（大体の人はESXiになると思います）

・新規アプライアンスを立てるターゲットESXiかvCenterに接続
　**1つ前の入力とは別に手入力が必要です。ちょっと面倒**

・新規アプライアンスの設定

・デプロイサイズの設定
　**極小はやめておきたい。**

・データストアの選択
　ここでシンディスクモードが選択できます

・ネットワークの設定


##アップグレードステージ２

・ソースのvCenter Server および管理サーバーへの接続

　**えっ！？また入れるの・・？**

・アップグレードで移行するデータの選択

・CEIPへの参加


##アップグレード完了

古いvCSAはシャットダウンされ、新しいvCSAが起動します。

IP、ホスト名、FQDNは引き継がれます。
仮想マシン名も引き継ぎたい場合は、
古い方をリネームしてから新しい方をリネームしてください。

6.7の場合は
・HTML5形式のクライアントになります（結構軽い）
・フラッシュ版も使えます

6.5の場合は
・フラッシュ形式のクライアントになります
・HTML5の機能制限版も使えます

##ダウングレードについて

IPアドレスが引き継がれているので、
新しい方をシャットダウンしてから（vCSAでもESXiでもどちらでもOK）
古い環境をスナップショットからリストアします。
このまま古い環境をパワーオンすると旧環境が使えます。

この状態から古い方をシャットダウンー＞新環境パワーオンすると新環境が使えます。

たったこれだけで新旧の切り替えが可能です。

##感想

フラッシュも2020年末でサポート終了なのでHTML5に移行したいですね。
移行予定の無い企業のvCSAとかどうするんだろな・・・


**ありがとうございました。**
【Android】アプリの権限を許可してもらうために「設定」を開きたい

Androidアプリを作っていると、アプリからデバイスの「設定」に飛ばしたくなることがあります。例えば、アプリ内でカメラを使いたいときに、カメラへのアクセスが許可されていない場合は使えないので、「設定」で許可してもらいたいです。
そこで、アプリの「設定へ」のようなボタンを押すと設定画面を開くようにする方法を、忘れないように記しておきます。

以下の手順では、該当アプリの詳細設定画面に飛ぶようになっています。

アプリの詳細設定画面
![application_details_settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124752/eec418da-c855-7fa9-5224-6b58ad71ea64.png)

# 手順
アプリの詳細設定画面を開くコードを以下に示します。

```kotlin
val settingsIntent = Intent(
    android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, 
    Uri.parse("package:<アプリのパッケージ名>")
)
settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(settingsIntent)
```

まず、Intentを生成します。
action（第一引数）に`Settings.ACTION_APPLICATION_DETAILS_SETTINGS`を渡すことで、特定のアプリの詳細設定画面を表示できます。
data（第二引数）に詳細設定画面を表示したいアプリのURIを渡します。

```kotlin
val settingsIntent = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:<アプリのパッケージ名>"))
```

次に、Intentにフラグを追加します。
`FLAG_ACTIVITY_NEW_TASK`をセットすると、新しいタスクでActivityが開始されるようになります。例えば、設定画面に移動した後、設定が終わって戻るボタンを押したときに、元のアプリに戻ることができます。

```kotlin
settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
```

最後に、Activityを開始します。

```kotlin
startActivity(settingsIntent)
```

これで、詳細設定画面を開けるようになりました。
for (auto 変数:((初期値)...最終値(, 増加量)))

#無限ループバグが必ずできないfor文
こういうループが正直欲しい(他人にソース渡すときにバグができない安心感がある)。
for (auto 変数:((初期値)...最終値(, 増加量)))->初期値(デフォルト:0)と増加量(デフォルト:1)は省略可能

```ex.cpp

for (auto x:(...<100)) 
{
	printf("%d", x);
}
//以下に等しい
//for(int x = 0 ;x < 100; x++){
//	printf("%d", x);
//}
for (auto x:(100...>1, -1)) 
{
	printf("%d", x);
}
//以下に等しい
//for(int x = 100 ;x > 1; x--){
//	printf("%d", x);
//}
//こういう書き方も可能(static constexpr auto length = 100が定義済み)
//for(auto i = 0: (...<length))
//auto rng = (...<100)みたいに書くことも可能。

```
ソースコードエディターにfor...で載る->使うとfor(auto i : (...<length))とコードに自動で書かれる

#C/C++の特性として柔軟性の高さが挙げられる。
悪魔に魂を売ると言われる危険なマクロを無くすためにtemplate<>を作った。だからこそ柔軟性の高さからfor (auto 変数:((初期値)...最終値(, 増加量)))も可能なはず。

#この子のメリットはこれだけではない。
このような書き方もできるようになるのである。

```ex.cpp
//template<class T>iEnumerable(T& collection,DefaultRange rng)が定義。
//std::string MyArrey[100]が定義。
for(auto& p :iEnumerable(MyArray,(0...<98,2))){//std::pair<std::string&,int>型が返却
	printf("%s",MyArray[p.second+2] == MyArray[p.second]? p.first.c_str():"Error");
}

```
スレッド基本要点

・スレッド→複数の処理を起動できる
・start()→スレッドの起動
・sleep()→カッコ内に記述した秒数停止
・join()→スレッドの終了を待つ
・threadを使うにはThreadクラスを継承するか、Runnableインターフェイスを実装する

・複数のスレッドが同時に起動しているとき、ある一つのフィールドに同時に複数アクセス
　することで予想の処理と矛盾が生じることがある
↓
・そのため、メソッドに「synchronized」という指定をつけることであるthreadがメソッドを
処理している間はほかのスレッドはこのメソッドを呼べず矛盾を防ぐことができる
grepを使って文字列を検索する方法

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#ソースファイルの中に特定の物を調べたい

grepコマンドを使用したら良い

```linux
$ grep 検索文字列 ファイル名
```

「grep」コマンドはファイルに特定の文字列が存在するか検索するときに使われる便利なコマンド

####[検索方法のオブションなど](https://qiita.com/heroyct/items/fed4d2b0e29292a7a599/)

#参考記事
・[【Linuxコマンド】grepで特定の文字列を抽出する方法](https://www.sejuku.net/blog/48915/)
・[grep -ir - explainshell.com](https://explainshell.com/explain?cmd=grep+-ir/)
・[grepの利用技まとめ](https://qiita.com/heroyct/items/fed4d2b0e29292a7a599/)
rsyslogで取得しているログが logrotate でローテ―ト後に更新されないとき

Samba auditログをrsyslogで取得する機能を実装中、logrotate後にログファイルが更新されず一瞬詰まったので、解決方法を共有させて頂きます。

# 問題
```configuration:/etc/rsyslog.d/sample.conf
local5.* /mnt/system/logs/samba/audit.log;RSYSLOG_FileFormat
```

```:/etc/logrotate.d/sample
/mnt/system/logs/samba/audit.log {
    create 0644 syslog adm
    ifempty
    dateext
    dateformat .%Y-%m-%d
    maxsize 5G
    missingok
    compress
    monthly
    rotate 12
}
```

上記のように、rsyslogでログを取得している場合、logrotateが実行された後にログファイルが更新されなくなってしまいました。

# 解決方法
logrotateが実行された後、```systemctl restart rsyslog``` すると直りました。  
これを以下の通りlogrotateの **postrotate** で自動化して解決しました。

```:/etc/logrotate.d/sample
/mnt/system/logs/samba/audit.log {
    create 0644 syslog adm
    ifempty
    dateext
    dateformat .%Y-%m-%d
    maxsize 5G
    missingok
    compress
    monthly
    rotate 12
+   postrotate
+     /bin/systemctl restart rsyslog
+   endscript
}
```

ちょっと書き方独特ですね。endscriptをお忘れなく。  

以上！
【Rails6】DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must now accept two parameters, the view object and the source for the view object.

Rails6アップデート後、rails起動時に以下のWarningを吐くようになってしまったのを調査・解決したメモです。

```
DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> #<#<Class:0x00007ffbbcf57de0>:0x00007ffbbf219590>.call(template)
To:
  >> #<#<Class:0x00007ffbbcf57de0>:0x00007ffbbf219590>.call(template, source)
```

# TL;DR

```
$ bundle update slim
```
で解決。

# 環境
- Ruby: 2.6.3
- Rails: 5.2.4.1 => 6.0.2.1 へアップデート

# なんだこのWarning :thinking: 
まずはメッセージの内容を見てみます。
`template handler` 周りのインタフェースに変更が入って、 `Single arity template handlers` が非推奨になったようです。なるほど、わからん。
https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/template/handlers.rb#L46-L56

推奨される修正内容が、

```
Change:
  >> #<#<Class:0x00007ffbbcf57de0>:0x00007ffbbf219590>.call(template)
```

ということで、自前のアプリケーションのコードが原因ではなさそう。
どうやら view 周りのGemが怪しそうだぞ、とアタリをつけます。 　　

# slim が怪しい？ :thinking: 
テンプレートエンジンに [slim](https://github.com/slim-template/slim-rails) を使用していたので、 slim の issue を漁ってみます。

https://github.com/slim-template/slim-rails/issues?utf8=%E2%9C%93&q=is%3Aissue+rails+6

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/48b38d50-4b77-35c5-14dd-09ce93ea9e64.png)


それっぽい雰囲気の issue を発見。しかもClose済み。
https://github.com/slim-template/slim-rails/issues/162

中を見てみると、この issue で報告されているエラー内容とは違う模様でした。
しかし、コメントをサーっと流し見していると、

https://github.com/slim-template/slim-rails/issues/162#issuecomment-530944015
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/a2038777-57b5-7e62-14c0-89a3338b53bb.png)

こんな コメントがあったので、 https://github.com/slim-template/slim/issues/827 も見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/ac1cd2a4-b4a7-436d-6b31-8673d60e4135.png)


おーこれこれ。同じWarningだ。
コメントを見ていると、

https://github.com/slim-template/slim/issues/827#issuecomment-478240650
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/16333e96-d858-e6bf-2295-7ad1773c5b02.png)

どうやら、 slim が依存している [temple](https://github.com/judofyr/temple) が怪しそう。

ちなみに使用していた temple のバージョンは 0.8.0 でした。

# temple が怪しい？ :thinking: 

同じように temple の issue も漁ってみるとすぐ見つかりました。
https://github.com/judofyr/temple/issues/122
https://github.com/judofyr/temple/pull/121

修正内容を見てみると、おーなるほどね、という感じ。
https://github.com/judofyr/temple/pull/121/files
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290998/0d8c24ed-398b-7055-a1a4-0a5f004fa7e8.png)

すでに修正版がリリース済みなので、
以下のコマンドを実行して slim ごと temple をアップデート。

```
$ bundle update slim
```

無事、Warningを解消できました。
Windows上でのWebスクレピング環境構築(Selenium)

#1. 本文の目的

Webスクレイピングの技術を勉強して、各種タスクを自動化してみたい。
Windows上でSeleniumを使用したWebスクレイピングの環境構築方法を記載する。

#2. 方法


##2-1 環境

OS : Windows10


##2-2 Jupyter環境の準備

Jyupterをインストールします。インストール手順は[こちら](https://qiita.com/STInverSpinel/items/9801f30c2fd1a378518d)

インストール完了後、適当な場所にworkディレクトリ(例：C:/Users/xxxx/Desktop/work/)を作成する。Jupyterを起動し空のシートをworkingディレクトリに作成する。


##2-3 geckodriverドライバーインストール

geckodriverの取得が必要です。[こちら](https://github.com/mozilla/geckodriver/releases/tag/v0.19.0)からwindows版をダウンロードします。
![17.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/4a8f9d1f-a8de-116b-e833-2c763660fbd2.jpeg)

zipファイルを展開後、「geckodriver.exe」をworkディレクトリ(例：C:/Users/xxxx/Desktop/work/)に配置します。

##2-4 chromedriverドライバーインストール

chromedriverの取得が必要です。まずは、PCにインストールされているchromeのversionを調べます。（ヘルプ → Google Chromeについて)

![16.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/a703f4b5-5af7-2bdd-27e5-d1c8d60b44e7.jpeg)

[こちら](https://sites.google.com/a/chromium.org/chromedriver/downloads)よりお使いのchromeのversionに合致したChromeDriverをダウンロードしてください。ダウンロード後、中身を展開して、「chromedriver.exe」をworkディレクトリ(例：C:/Users/xxxx/Desktop/work/)に配置します。

![18.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/dec822a5-db6b-25d1-af36-ffb64e251b73.jpeg)



#3. 動作チェック

(1)pipをインストールする。

```python:
pip install selenium
```
(2)webブラウザを立ち上げ、yahooJapanのページを開く。

```python:
from selenium import webdriver
browser = webdriver.Chrome(executable_path="C:/Users/Takeshi/Desktop/work/chromedriver.exe")
browser.get('https://www.yahoo.co.jp')
```
実行環境のスクリーンショット
![19.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/16540ac8-ec9d-3875-21c8-1cbcc655f828.jpeg)
【ふくだ学習録】Docker入門 part4【23日目】

# ふくだ学習録とは？
ふくだが学習したことの備忘録。
目に見える形で残すことによってやる気を出す個人的な作戦です。
他人に見せるように書いているわけではないので、すごく読みにくいです。

### 読了した本
[データベースエンジニア養成読本 [DBを自由自在に活用するための知識とノウハウ満載!]](https://www.amazon.co.jp/dp/4774158062/ref=cm_sw_r_tw_dp_U_x_FPphEbQFPPQRM )
[ゼロから作るDeepLearning](https://www.amazon.co.jp/dp/4873117585/ref=cm_sw_r_tw_dp_U_x_y3UiEbF3P6EG7)
[PHPフレームワーク CakePHP 3入門](https://www.amazon.co.jp/dp/4798048577/ref=cm_sw_r_tw_dp_U_x_.YIjEbS1K4JY2)
[SQLアンチパターン](https://www.amazon.co.jp/dp/4873115892/ref=cm_sw_r_tw_dp_U_x_XlokEbJQK2N7P )

### 今読んでいる本

[Docker入門](https://www.amazon.co.jp/dp/480071091X/ref=cm_sw_r_tw_dp_U_x_xVlmEbN8ZTHZK)

# Docker入門

### Docker内でLinuxディストリビューションサービスを動かすには
Linuxディストリビューションがサービス管理に使用するのが「initサーバー」と呼ばれるプログラム。つまりinitサーバーの実態である`/sbin/init`コマンドを用いて、initサーバーをコンテナ内で最初に稼働すれば使用できるようになる。

ただしinitサーバーにsystemdを使用しているディストリビューションの場合、ディストリビューションを動かすために必要な権限やファイルがないことによって動作に制限が生じてしまう。そういったときは、dockerサブコマンドのrunに`--cap-add=SYS_ADMIN`（もしくは`--privileged`）というオプションを指定することで使用できるようになる。

※ホストとコンテナ間の分離度が下がってしまうため、使用には注意する必要がある。

### rmiサブコマンドで依存関係のあるイメージを削除した場合
他のイメージで中間イメージとして使用されているイメージを、rmiサブコマンドで削除した場合、リポジトリ名やタグ名などの情報は消されるが、イメージそのものは残される。

### Linuxコマンドでのオプションの付け方
短縮系は` `で、長い名前での指定時は`=`を使用して値を指定する。
例：`-f 値` `--format=価`

### tarとは？
アーカイブファイルを作るときのコマンド。
.tar拡張子ってのがあるのか、、知らなかった、、

[tar](https://wa3.i-3-i.info/word14224.html)

### buildサブコマンドでブランチ名やディレクトリを指定する方法

```console
$ docker build -t イメージ名 GitリポジトリのURL#ブランチ名orタグ名:ディレクトリ名

例 newbranchというブランチの/dockerというディレクトリのレジストリから、
   myimage:v1.0というイメージを作成する時。
$ docker build -t myimage:v1.0 git://example.com/sample.git#newbranch:docker
```

### loadサブコマンド
tarアーカイブ形式で保存したイメージを元に戻すのに使用するサブコマンド。

### importサブコマンド
tarアーカイブ形式にまとめたファイルシステムデータから、イメージを新たに作成するのに使用するサブコマンド。

### save→load　export→importの違い
saveはイメージを保存、exportはコンテナを保存する。
その上で、saveではイメージのレイヤ情報などが保存されているが、exportではDockerとしての構造やメタ構造は持たずに、ファイルシステムだけが保存される。
基本はsaveコマンドで良さそう。

[Docker save→load　export→import　どっち？](https://qiita.com/leomaro7/items/e5474e67a8e41536f0ff)



# 今日の一言
各コマンドの説明部分入ってきたから、メモることはあんまりなくなってきた！
実際のコマンドとかは、全部覚える必要はなくて、「だいたいこういうことができる」とか「こんなコマンドあるんやー」ぐらい理解するのが効率いい。

ただbuildコマンドの--force-meオプションだけは使い道わからん。謎。
firebase auth で sendEmailVerification() は問題ないのに sendEmailVerification(actionCodeSettings) が 400 のエラーになるとき

getOobConfirmationCode への Post が 400 で帰ってくる

actionCodeSettings の url に指定したドメインが firebase auth の white list に登録されていないのが原因なので登録する

![スクリーンショット 2020-02-03 8.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46544/d920b027-7bb7-2dea-7980-8cd11514abc4.png)


ちなみになんでそれが原因だとわかったのかというと sendEmailVerification() の例外を catch して message を見ると、その旨が親切にかいてあるんですヽ(^o^)丿、親切な message ってホントありがたいですね！
[Shopify] 1月の更新をまとめました

おはようございます、2020年・・もう1ヵ月終わってしまいました。毎日行こうと思ったジムも1日、2日、3日と行き4日目以降一度もいかないまま2月、リアル三日坊主。

さて、1月の更新をまとめました。

# 01月01日API version 2020-01 が一般リリース

すべてにプレビューがリリースされていたので、特にサプライズはないと思われますが、
API Version 2020-01が一般リリースされました。

リリースノートは下記。別途まとめたいと思います。
https://help.shopify.com/en/api/versioning/release-notes/2020-01

# 01月14日 プリディクティブ検索にコレクションが追加されました

日本語でなんて言うんでしょう？あなたが探しているかもしれないよ検索？
プリディクティブ（予測）なので予測検索でいいのかな。

呼び名はどうでもいいとして、APIからプレディクティブされた検索内容の中にコレクションも含まれるようになりました。

イメージは下記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241909/65c4d9a3-8332-ee6c-1adc-f8199f2e61d9.png)

詳細はこちら
https://help.shopify.com/en/themes/development/search/predictive-search

これもまた別途詳記事書きます。

# 01月14日 Shopify Theme Inspector for Chromeの更新

Liquidテンプレートのパフォーマンスなどを確認することができるShopify Theme Inspector for Chrome (Chromeのエクステンション)が更新されました。

Shopify Theme Inspector for Chromeを使いたい方はこちらからダウンロード
https://chrome.google.com/webstore/detail/shopify-theme-inspector-f/fndnankcflemoafdeboboehphmiijkgp

更新内容及びソースはこちらです
https://github.com/Shopify/shopify-theme-inspector

# 01月21日　Storefront GraphQL APIで在庫数を取得できるようになりました。

2020-04版のStorefront GraphQL APIで在庫数を取得できるようになりました。　デフォルトでは表示されません、アプリ設定から“inventory quantity” のチェックボックスをオンしてからAPIを利用してください。

# 01月23日 shopify_app Ruby gem, koa-shopify-auth Node.js が更新されてChrome 80に対応

サードパーティークッキーの取扱いに関して別途まとめようと思いますが、
今回Googleにてサードパーティークッキーの取扱いポリシーの変更に対する対応になります。今回の更新でChrome80以降で第三者（サードパーティーへ）クッキーを発行しないようになります。 

詳細は下記を参照
https://help.shopify.com/en/api/guides/samesite-cookies

アプリを開発している方々には重要なアップデートとなります~~ので‥こちらもまた後で（後で書くぞリストがたまってきています）~~

ここにまとめました
https://qiita.com/syantien/items/bd06d81a78db98328788

# 01月23日　ストアーデザインベター版がデベロッパープレビューで公開

こちらはデベロッパープレビューということで、後々改めてまとめたいと思います。

下記にてフォーラム特設されています、興味のあるかたはご参加を
https://community.shopify.com/c/New-Online-Store-Design/bd-p/storedesign

# 01月23日 App snipepets, App sections extentionsの更新をデベロッパープレビューで公開

ストアーデザイン機能の更新に伴いアプリをスニペットにインジェクトする仕組みが強化されたようです。こちらもデベロッパープレビューということで、後々改めてまとめたいと思います。

テーマ開発を行っている方々はプレビュー版からいじり倒して、次のテーマーを開発していただけたらと思います。

# 01月23日　デベロッパープレビューにてTheme/Sectionの新しい構成を試すことができます

これ・・もう、ストアーデザイン系1個の更新ニュースでよくなかったかと思いながらも、

Theme内のSection構成を練り直したとのことです。今回のプレビューで、

- ヘッダー、フッターのデザインを各ページごとに設定できるように
- ページセクションを個別にカスタマイズすることができるように
- ページデザインからSectionを簡単にAdd/Removeすることができるように
- マスターセクションやマルチセクションを使いページを個別または、全体（Global)で編集することができるように
- プレビュー版では商品ページに限定されていますが、いずれすべてのページに反映される

挑戦してみたい人は新しストアーデザインに対応しているDebut Themeを下記でダウンロードしてください、詳細は下記を参照
https://help.shopify.com/en/themes/development/online-store-editor/index

# 01月28日 App secretの長さが延長されました

32文字から38文字に延長されました。　いったん今のApp secretは心配する必要はないようです。これから新しいアプリを開発される方はprefixにshpss_が付きます。 Prefixいれて32から38なので実質今後わかりやすいようにPrefixつきますよ、というお知らせです。
Sigfox+Arduino+phMeter+AmbientでIoT

#概要

- 目標 IBM　Watoson IoT Platformで受信して Node-REDにデータを渡し，MQTTブローカとして稼働させたい
- 2020.02.15 STEP2:Ambientで計測できた!
- 2020.02.03 STEP1:メールで計測した値が届いた!
- 2020.02.02 悩み：Sigfox callbakがわからない＜@ghibiさんからメッセージもらいました
- 2020.02.01 着手：SigfoxのArduinoシールドでPHメータで自動計測した値をIoT計測してみる

#Sigfox

- [MySigfoxDevice管理サイト](https://backend.sigfox.com/device/list)

## Callback の設定

- １つ目の黒線には　Ambientのチャンネル
- ２つ目の黒線には　Ambientの書き込みキー

![callback4sigfox.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237044/3b65bc2c-5540-07da-25f1-a692a850d539.png)



# IBM Cloud

- [My IBM id ](https://myibm.ibm.com/dashboard/)
- [IBM Cloud](https://cloud.ibm.com/)
- [Tutorial: Create a Node-RED starter application](https://developer.ibm.com/tutorials/how-to-create-a-node-red-starter-application/)
- [Sigfox CallbackとIBM Watson IoT連携 (with Node-RED)](https://qiita.com/ghibi/items/6ac04e23e9072dc07b21)

# Ambient

- [AmibientでSigfoxからのデータを受信して表示している公開チャンネル](https://ambidata.io/ch/channel.html?id=18941)

#基にしたサイト
- [Ambient](https://ambidata.io/ch/channel.html?id=18941&private=true)
- [Sigfox portal](https://backend.sigfox.com/welcome/news)
- [Sigfox Platform](https://try.iotagency.sigfox.com/)
- [SigfoxとArudino](https://qiita.com/ghibi/items/d80aa646db7223ff770a)
- [Sigfox Callback　基礎](https://qiita.com/ghibi/items/53259381a30363538a6d) 
- [Callback応用： Custom payload configの詳細](https://qiita.com/ghibi/items/240e8591a7da1e2cbff0)
- [phセンサとArudino](http://chairoirirakuma.cocolog-nifty.com/blog/2018/09/arduinoph-b0d3.html)


# YouTubeチャンネル

- [YouTube:簡単マイコン教室](https://www.youtube.com/channel/UC41qeaw-dXNdl0puKkXiuKA/)
[SQL Developer 接続設定] ADB(ADW/ATP), DBCS

# Autonomous Database (ADW/ATP)

### 接続タイプ：クラウド・ウォレット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/7260f33a-9a47-31c0-20ed-1723580f929f.png)

# DBCS (Database Cloud Service, Oracle Database VM)

### 接続タイプ：基本

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532975/b5aa82bc-9185-4262-6a63-fabc4e64f169.png)


* 「サービス名(E)」は以下で確認可能。

```bash

[oracle@myhost ~]$ cat $ORACLE_HOME/network/admin/tnsnames.ora

DBCS01_NRT12Q =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = myhost)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = DBCS01_nrt12q.subnet.vcn.oraclevcn.com)  <--サービス名(E)
    )
  )
```


### 接続タイプ：カスタムJDBC

```terminal
jdbc:oracle:thin:ユーザ名/パスワード@//public IP アドレス/DB0623_nrt123.prdpublbsubnet0.prdvcn01.oraclevcn.com（サービス名）
```
[Oracle Cloud] Platform Services のリージョン追加

# はじめに

Oracle Cloud の Region は、以下の二種類のものがあります

- Infrastructure Regions : OCI の画面で提供されているサービスのリージョン
- Platform Services Regions : OCI-Classic のダッシュボード画面で提供されている PaaS サービスのリージョン



Platform Services Regions でリージョンを追加する方法を毎回忘れてしまうので、備忘録として記載します。



# Region 追加

Manage Regions を選択

![1577008137940.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/22cab54c-84fc-9d20-d5f4-0c6e04adfb19.png)



Platform Services Regions を選択

![1577008174512.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/9c85c19f-0ec9-9590-b1f7-dca697db5b70.png)



North America の Subscribe を選択

![1577008217688.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/7555f263-c598-3650-19c0-d7b8ed9d8d82.png)



Subscribe (エラーになった場合は、クラウド管理者側のアカウントで Region 追加を依頼する必要があります)

![1577008247336.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/c511580e-2943-795c-fa61-7f55e259984f.png)



Close

![1577008259509.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/df15fc30-2431-c1bc-466e-1ba7328be9e6.png)



くるくる回りますが、このまま待ち続けても画面は反映されません

![1577008482485.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/ee22be0e-6bad-926f-acca-9b646c8fdb55.png)



数分後にブラウザを更新すると、緑色になります

![1577008506189.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104247/9f71f9b8-f9de-d0de-218c-e24fb13d1ef6.png)
初心者がテーブル定義を視覚的に理解する方法

railsを学習していると魔法のコマンドで自動的にテーブルやカラムが作成され、
なぜ、どうしてそのように作られるのか？どうなっているのか？
が見えてこなかったので一度整理して理解を深めます。

今回はscaffoldで作成したusersテーブルで作成します。
（1つの簡単なテーブル説明なので、ここから派生していければと思います。）

---

DBやテーブルの確認がわからない方はこちらで↓

https://qiita.com/new_engineer/items/7d49b64c4eeb676dabfb

---

今回はdraw.ioを使ってテーブルを視覚的にしていこうと思います。
いろんな使い方ができるのですが、今回は既存のテーブルを作成していこうと思います。

https://www.draw.io/

draw.ioの説明や基本的な操作はこちらの動画を参考にしました。
全て英語で説明されていますが、動画だけでも操作方法を知ることができます。
不安な方は、字幕をつけるとより理解が深まると思います。

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

---

簡単ですが、draw.ioでusersテーブルを作成しました。

<img width="346" alt="スクリーンショット 2020-02-03 7.58.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381043/a42880a7-8c03-72c5-00d1-e48bb095eb5d.png">
LineageOS 16.0（Android 9）

<img src="https://www.raspberrypi.org/forums/download/file.php?id=33832" width=80%>

## 【LineageOS 16.0 (Android 9)】
RPi3B+ のスペックは [Nexus 7 (2012)](https://ja.wikipedia.org/wiki/Nexus_7_(2012) "Nexus 7 (2012) - Wikipedia") 相当（という認識）だったけど、RPi4B はどうなんだろう。
最近のタブレットには疎いからよく分からないけど、やはり数世代前の物と同程度だと思われ。
で、LineageOS。試しに入れてみたけど、流石に動作はもっさり。RPi4B とはいえ比較的新しめの Android を動かすには厳しいよな。
しかし、こうしたビルドを公開している人は凄いよ。
RPi ならイメージ焼きでガチャポンで起動できるし。興味のある方は以下参照。

[LineageOS 16.0 (Android 9) for Raspberry Pi 4](https://konstakang.com/devices/rpi4/LineageOS16.0/ "LineageOS 16.0 (Android 9) for Raspberry Pi 4")
[[DEV] LineageOS 16.0 (Android 9) for Raspberry Pi 4 B](https://www.raspberrypi.org/forums/viewtopic.php?f=73&t=261228&sid=f6a14bad02f5522fdfaccfe3307c46b5 "[DEV] LineageOS 16.0 (Android 9) for Raspberry Pi 4 B - Raspberry Pi Forums")

## 【自作タブレット】
ついでに。最近公式フォーラムで自作タブレットを公開している方を見かけた。こちらも凄いね。
[Raspberry Pi Tablet OS](https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=257991&p=1598329&hilit=tablet#p1581265 "Raspberry Pi Tablet OS - Page 2 - Raspberry Pi Forums")
<img src="https://uc21053b6f27a0e9bd54e5269571.dl.dropboxusercontent.com/cd/0/inline/AxW1xcROcBHM5Mh_-fqeHQNNdJ7kL9o-ITwMmnHMGO4dBvoePi8xKcAbcATq4slFsoQtOQI_suosPVDk_Ys46yfRkAHRNXYz8o0Ms-Vg1e6dJVLni5RBqUjzA9OUodN3wHM/file#" width=80%>
TLEの国際衛星識別符号の文字列化

たまに必要になって都度苦労するのでメモ。

```c++
const char *international_designator_to_string(char (&str)[9],
                                               const int8_t year,
                                               const int16_t launch,
                                               const int16_t piece)
{
    str[0] = '0' + year / 10 % 10;
    str[1] = '0' + year / 1 % 10;
    str[2] = '0' + launch / 100 % 10;
    str[3] = '0' + launch / 10 % 10;
    str[4] = '0' + launch / 1 % 10;

    str[5] = str[6] = str[7] = ' ';
    str[8] = '\0';

    int16_t a = piece - 1;
    switch (piece <= 26 ? 2 : piece <= 702 ? 1 : 0)
    {
    case 0:
        str[7] = 'A' + a % 26;
        a = a / 26 - 1;
    case 1:
        str[6] = 'A' + a % 26;
        a = a / 26 - 1;
    case 2:
        str[5] = 'A' + a % 26;
        a = a / 26 - 1;
    }

    return (str);
}

```

***

こんなかんじ

```c
char buff[9] = {};

printf("\"%s\"\n", international_designator_to_string(buff, 1, 2, 1));
printf("\"%s\"\n", international_designator_to_string(buff, 3, 4, 27));
printf("\"%s\"\n", international_designator_to_string(buff, 5, 6, 703));

printf("\"%s\"\n", international_designator_to_string(buff, 12, 3, 2));
printf("\"%s\"\n", international_designator_to_string(buff, 23, 45, 82));
printf("\"%s\"\n", international_designator_to_string(buff, 34, 567, 3543));

printf("\"%s\"\n", international_designator_to_string(buff, 99, 999, 18278));

printf("\"%s\"\n", international_designator_to_string(buff, -1, -1, -1));
printf("\"%s\"\n", international_designator_to_string(buff, 123, 4567, 18279));
```

に使うと、こんなかんじ

```
"01002A  "
"03004AA "
"05006AAA"
"12003B  "
"23045CD "
"34567EFG"
"99999ZZZ"
"0/00/?  "
"23567AAA"
```

の結果になる。

範囲チェックを行っていないので、範囲外を入れると意図しない挙動になる。特に負数がヤバイ。uint使うべきかも。

`str[5] = str[6] = str[7] = ' ';`の`' '`を`'\0'`にすれば空白埋めじゃなくて終端にもできる。

***

yearとlaunchはただのゼロ埋め10進なので楽だけど、pieceが面倒。「基数26になるだけだろ～？」とかナメてかかると反撃食らう。なんでゼロ埋め32進数とかにしなかったんや……

***

普段はフォールスルーは使わないけど、たまに使うと便利すぎてやばい。
PythonでTwitterBotを作ろう！

## TwitterBotとは
BotとはRobotが語源になっていて、自動でなんらかの処理をするもののことを指します。Twitterにおいて

- 自動ツイートBot
- 自動いいねBot
- 自動フォローBot

など多岐にわたるBotが存在します。

## Botのメリットは？
自動ツイートは通知のような役割を果たします。例えば、「好きなアーティストのライブ情報が更新された場合に自動でツイートする」といったものが挙げられます。
自動いいね、自動フォローは不特定多数の人に自分のアカウントを知ってもらうためのツールとしての働きがあります。これは例えば、自分のTwitterアカウントのPR活動などに使われます。

## Botの作成手順
Botの作成手順は主に以下の3ステップです。

1. Twitter Developer登録
2. プログラム作成(Python)
3. 定期実行登録(Cron)

## 実装
今回は定期的に現在時刻をツイートするBotを作成します。
詳細は以下の動画で紹介しています。

https://youtu.be/Ab6TU9sFBM4

英語版
https://youtu.be/mmKXdLUhG_k

## ソースコード

```python:credential.py
CONSUMER_KEY        = '********'
CONSUMER_SECRET     = '********'
ACCESS_TOKEN_KEY    = '********'
ACCESS_TOKEN_SECRET = '********'


```

```python:twitter_bot.py
from credential import CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET
from requests_oauthlib import OAuth1Session
from http import HTTPStatus
from datetime import datetime

def post_tweet(body):
    # 認証処理
    twitter = OAuth1Session(
        CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET
    )
    # ツイート処理
    res = twitter.post("https://api.twitter.com/1.1/statuses/update.json", params={"status": body})
    print(res)

    # エラー処理
    if res.status_code == HTTPStatus.OK:
        print("Successfuly posted")
    else:
        print(f"Failed: {res.status_code}")

def main():
    # body = "テスト投稿2"
    now = datetime.now()
    post_tweet(now)


if __name__ == '__main__':
    main()

```
[初心者向け]PythonでOpenCVを使う際にPATHで苦労した

#はじめに
C++で画像処理をやっているとグラフ化したいときにMatplotlibを利用できたら便利なのではと思い、Python環境でOpenCVを使ってみようと思い立ったのがきっかけです、しかし手順や参考にしたサイトが多すぎることからセットアップが完了し、実際の画像処理を行うまでにかなりの時間を要してしまったのでメモ代わりに残しておきます。

#まず開発環境の設定に戸惑ってしまった
Python自体は全く触れてこなかったので、そもそもAnacondaなりVSCodeなりのインストールや起動を試しても全くうまく行かない！となりてんやわんや。
最終自分の環境ではVSCodeもJupyter Notebookも使わずシンプルにPython3.7、Anaconda、OpenCV4.2.0のみを使うという結論に至った。
#基本的なセットアップ
様々な方法を試しましたが、最終的にこちらの記事の方のやり方を参考にすることで自分は動きました。
https://qiita.com/FukuharaYohei/items/5d49938ffd33d198f0c0
#具体的な困ったポイント

**PATHは合っているはずなのに画像処理を行ってくれない**
　これが一番時間がかかったところで、下記のコードのように画像処理を行おうと実行するも結果は「NONE」が帰ってくる。
対象画像の名前がfruits.jpgです。

```python:test.py
import cv2

path = "fruits.jpg"

img = cv2.imread(path)

print(img)
```

他の方やサイトを参考にするも"test.py"と同一のディレクトリに入れているはずなのにこの書き方では画像を処理してくれません。

#解決策
どう考えてもPATHが間違っていると確信していたので最新のPython-OpenCVでは書き方が違うのかもしれないと思い、試行錯誤した結果、以下の書き方で無事画像処理は完了しました。

```python:test.py
import cv2
#PATHの先頭に ./ をつけただけ
path = "./fruits.jpg"

img = cv2.imread(path)

print(img)
```
これ、意外と載ってるサイトが無くて、かなり解決するのに時間がかかりました。
正直OpenCVの公式サイトにもしかしたら載っているのかもしれませんがそこを調べるというのは骨が折れそうだったので全く見ていません。
C++のときは先程の文法で行けていたのでおそらく原因はPythonの記述方法の問題かなと思ったり（正直わからないのでわかる方いたらコメントお願いします。）

#なぜこんな記事を残したの？
自分みたいな全くの初心者の方が最初から失敗しないために参考にしてもらいたいと考えたからです。
載せているURLを参考にしながら、この記述方法に気をつけていればうまくいくはずです！
Pythonで「ケツマイモ」と標準出力する方法

* Python3系

```{python3}
print('ケツマイモ')
```

Python3ではデフォルトでUTF-8をサポートしているのでそのまま「ケツマイモ」を出力します。


* Python2系

```{python}
print u'ケツマイモ'
```

```{python}
print 'ケツマイモ'.encode('utf-8')
```

```{python}
# -*- coding: utf-8 -*-
print 'ケツマイモ'
```



Python2系では文字列にバイト文字列とユニコード文字列の二種類があり、デフォルトでASCIIをサポートするため、バイト文字列が出力されてしまいます。
「ケツマイモ」のようなマルチバイトなユニコード文字列を表示するためには、バイト文字列をユニコード文字列に変換する必要があります。
【Python】二通りのtype()の使い方

## はじめに
業務でDjangoのManager周りのコードを読んでいると
見慣れない`type()`の使い方を見つけました。

GitHubのリンクは[こちら](https://github.com/django/django/blob/master/django/db/models/manager.py#L100-L108)

```python

@classmethod
def from_queryset(cls, queryset_class, class_name=None):
    if class_name is None:
        class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
    return type(class_name, (cls,), {
        '_queryset_class': queryset_class,
        **cls._get_queryset_methods(queryset_class),
    })
```

typeに引数が三つ渡されている...???
なんだこれ？

調べてみた所、ちゃんとPython標準ライブラリの[ドキュメント](https://docs.python.org/ja/3/library/functions.html#type)に書いてありました。
(そりゃそう)

ほとんど引用に近い形にはなりますが、軽くまとめてみることにします。

## 結論
__type()は引数の数によって挙動が変わる。__

---
### 1.(恐らく)よくある使い方
> 引数が1つだけの場合、object の型を返します。返り値は型オブジェクトで、一般に object.__class__ によって返されるのと同じオブジェクトです。(Pythonドキュメントより引用)


```python

>>> class Bar:
...     pass

>>> class Foo(Bar):
...     pass
```

`class Bar`とこれを継承した`class Foo`を用意します。

この時type()の挙動は以下のようになります。

```python
>>> foo = Foo()
>>> type(foo)
<class '__main__.Foo'>

>>> type(foo) is Foo
True

>>> type(foo) is Bar
False
```

場合によって`isinstance()`と使い分けましょう。

というのが自分の知っている話でした。


### 2.知らなかった使い方
`class type(name, bases, dict)`
>引数が 3 つの場合、新しい型オブジェクトを返します。本質的には class 文の動的な形式です。
(Pythonドキュメントより引用)

ドキュメントでは以下の二つの文は同じtypeオブジェクトを作ると書かれています。

```python

>>> class X:
...     a = 1

>>> X = type('X', (object,), dict(a=1))
```

第一引数: 生成するクラス名
第二引数: 継承するクラス
第三引数: オブジェクトの属性

となっています。

実際に試してみます。

```python

>>> class Bar:
...     a=1
...
...     def print_hogefuga(self):
...         print('hogefuga')
...

>>> Foo = type('Foo', (Bar,), dict(b=2))

>>> foo = Foo()
>>> foo.print_hogefuga()
hogefuga
>>> foo.a
1
>>> foo.b
2
```

このようにBarClassを継承するFooClassを作ることが出来ました。


## まとめ
以上、自分が知らなかった`type()`の使い方についてでした。

`type()`以外にも驚きの使い方のものはたくさんありそうですね。


## 参考・引用
- [Pythonで型を取得・判定するtype関数, isinstance関数
](https://note.nkmk.me/python-type-isinstance/)
    - よく使われる`type()`, `isinstance()`の解説がされています。
- [Python組み込み関数ドキュメント/#type](https://docs.python.org/ja/3/library/functions.html#type)
    - 個人的には使ったことがないものもたくさんあって面白かったです。いい機会なので見直します。
Python3.7 + Django + Eclipse ローカル構築手順

##前置き
自宅環境にて行った作業記録メモです。
仕事にて使用した事の無い言語やバージョンでの開発し、メモを残す事を目的として作成しております。
今更な事や非効率な事をやっている可能性もありますがご容赦下さい。
##環境
Windows10
Python 3.7.4
Django 3.0.2
Eclipse 2019-12 Ultimate Full Version
##Eclipseダウンロード、展開
####ダウンロードして7zipでローカル直下に解凍、以上!!
※Eclipseに備わっているpython3を環境変数に設定します。
python
`C:\pleiades\python\3`
pip
`C:\pleiades\python\3\Scripts`
pipのアップグレードついでに疎通確認を行います。
`PS python -m pip install --upgrade pip`
##Djangoデバッグ環境構築
###Djangoをインストールする
インストールを行い
`PS python -m pip install django`
インストール&バージョン確認
`PS python -m pip freeze`

```
asgiref==3.2.3
Django==3.0.2
pytz==2019.3
sqlparse==0.3.0
```
Eclipse側でも確認をしておきましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490768/260950c1-a77e-da9f-1cea-b05241118576.png" width="750">
###Django開発環境作成
[ファイル]→[新規]→[プロジェクト]より、新規プロジェクトウィンドウを開き、
[PyDev]→[PyDev Django プロジェクト]を選択します。

適当なプロジェクト名を入力し、文法バージョンを3.7、インタープリターをPython3、
『`src`フォルダーを作成してPYTHONパスに追加する』にチェックを入れ、『次へ』を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490768/5407a7d5-256b-322d-49df-1cf1716ea933.png" width="750">
参照するプロジェクトは無い場合は『次へ』を選択します。
使用するDBを選択し、ユーザ名、パスワードを入力し、『完了』を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490768/a17a7289-0e1a-6135-8673-4f9c3ca5c2fa.png" width="750">
プロジェクトを右クリックし、『実行』→『PyDev Django』を選択し、実行出来たら完成です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490768/d88e6d8d-669d-0689-cb65-c12e6ed073bb.png" width="750">
表示されたURLにアクセスして下記画面が無事表示出来る事を確認しましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490768/f4854514-c67a-e2d6-2bd8-629a1a1d2b1a.png" width="750">
【Golang】zapを用いたロギング

# 概要

Golangのロギングのライブラリであるzapのロギング例を示す。本記事では、以下のようなJSON形式のログを想定している。内容は、ログレベル、時刻、呼ばれた場所、メッセージである。

```bash
{"level":"debug","time":"2020-02-02T23:24:13.185+0900","caller":"logger/utils_test.go:31","msg":"test msg"}
{"level":"info","time":"2020-02-02T23:24:13.186+0900","caller":"logger/utils_test.go:32","msg":"test msg"}
{"level":"error","time":"2020-02-02T23:24:13.186+0900","caller":"logger/utils_test.go:34","msg":"test error"}
```

zapライブラリは、[Readmeのパフォーマンス表](https://github.com/uber-go/zap#performance)では、Golangのロギングライブラリとして有名なlogrusより高速らしいです。

logrusは、[Golang logrusによるロギング](https://qiita.com/kwashi/items/8547ff5800811263f576)にて、記事にしましたが、zapの方が高速ということで、今回記事にしました。

# プログラム

以下に、初期化のプログラムを示します。基本的には、出力方法やログレベルを環境変数から読み込み、それに合わせて初期化しているだけです。呼び出し時に初期化され、logger.Log.Info()などで使用できる。

```go

package logger

import (
	"fmt"

	"go.uber.org/zap/zapcore"

	"go.uber.org/zap"
)

/*zap
https://github.com/uber-go/zap#performance
*/

var (
	Log *zap.Logger
)

func init() {
	envVals, err := getEnv()
	if err != nil {
		fmt.Println(err)
		panic(err)
	}
	outputPaths := []string{}
	if envVals.filePath != "" {
		outputPaths = append(outputPaths, envVals.filePath)
	}

	if envVals.stdout {
		outputPaths = append(outputPaths, "stdout")
	}

	logConfig := zap.Config{
		OutputPaths: outputPaths,
		Level:       zap.NewAtomicLevelAt(envVals.level),
		Encoding:    "json",
		EncoderConfig: zapcore.EncoderConfig{
			LevelKey:     "level",
			TimeKey:      "time",
			MessageKey:   "msg",
			CallerKey:    "caller",
			EncodeTime:   zapcore.ISO8601TimeEncoder,
			EncodeLevel:  zapcore.LowercaseLevelEncoder,
			EncodeCaller: zapcore.ShortCallerEncoder,
		},
	}

	if Log, err = logConfig.Build(); err != nil {
		panic(err)
	}
}
```

以下プログラムに使用する環境変数取得など、、、

```go

package logger

import (
	"os"
	"strconv"
	"strings"

	"go.uber.org/zap/zapcore"
)

type envVals struct {
	filePath string
	stdout   bool
	level    zapcore.Level
}

//getEnv ログに関する環境変数を設定
func getEnv() (*envVals, error) {
	res := envVals{}
	res.filePath = os.Getenv("LOGGER_FILE_PATH")

	var err error
	res.stdout, err = strconv.ParseBool(os.Getenv("LOGGER_STDOUT"))
	if err != nil {
		res.stdout = true
	}

	level := os.Getenv("LOGGER_LEVEL")
	switch level {
	case "debug":
		res.level = zapcore.DebugLevel
	case "error":
		res.level = zapcore.ErrorLevel
	default:
		res.level = zapcore.InfoLevel
	}

	return &res, nil
}
```
どこかで見たことのあるpython3の内包表記（List、辞書）

# はじめに

pythonのお勉強がてらの自分メモです
サンプルソースの動作確認は「Google Colaboratory」でやってます。


## Listの内包表記
### for文でリスト作成

```python3:test.py
list = [] 

for i in range(5):
    list.append(x)
print(list)

# => [0, 1, 2, 3, 4]
```

### 内包表記でリスト作成

```python3:test.py
list = [i for i in range(5)] 
print(list)

# => [0, 1, 2, 3, 4]
```

### なんとifも使える
ifをつけることによりList内の要素が減ります
**補足**　内包表記内のifはif節と呼びます

```python3:test.py
# 【for文】偶数だけListに入れる
list = [] 
for i in range(10):
    if i % 2 == 0:
        list.append(i)
print(list)
# => [0, 2, 4, 6, 8]

# 【内包表記】偶数だけListに入れる
list = [i for i in range(10) if i % 2 == 0] 
print(list)

# => [0, 2, 4, 6, 8]
```

### さらにif-elseも使える・・・ただし可読性がいいかは謎。。。
**補足**　内包表記内のif-elseは条件式と呼びます

```python3:test.py
# 【for文】「偶数」「奇数」と入れる
list = [] 
for i in range(10):
    if i % 2 == 0:
        list.append("偶数")
    else:
        list.append("奇数")
print(list)
# => ['偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数']

# 【内包表記】「偶数」「奇数」と入れる
list = ["偶数" if i % 2 == 0 else "奇数" for i in range(10)] 
print(list)

# => ['偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数', '偶数', '奇数']
```

## 辞書の内包表記
### for文で辞書作成
```python3:test.py
dict = {}
key_list = [1, 2, 3]
value_list = ["abc", "def", "xyz"]

for i in range(len(key_list)):
    key = key_list[i]
    value = value_list[i]
    dict[key] = value
print(dict) 
# => {1: 'abc', 2: 'def', 3: 'xyz'}
```
### 内包表記で辞書作成
```python3:test.py
key_list = [1, 2, 3]
value_list = ["abc", "def", "xyz"]

dict = {key : value for key, value in zip(key_list, value_list)}
print(dict)
# => {1: 'abc', 2: 'def', 3: 'xyz'}
```



# 終わりに
内包表記で書くとだいぶ短くなるますね、慣れるまではちょっと読みづらいけど・・・。

これ書いてる時、
昔SI屋の下請けでjava書いてた頃「三項演算子」とか読めねーし、短くなるから使うな（怒）
と元請け社員様に言われたことを何故か思い出しましたｗ

※**短くなる**　⇒　最近の子は知らんだろうけど、昔はステップ単価という見積もりが・・(ry

# 謝辞
コメントを頂いたshiracamusさんありがとうございます
[Unity]カメラ前平面における画面内サイズを表示する

![スクリーンショット-2020-02-03-2.05.15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/9eb54f5f-f3c3-0a93-d994-df65490e3eef.gif)

画面のすぐ外から敵を登場させたり、カメラ前数mの表示範囲を知りたい時など、カメラの視錐台表示では大きすぎて位置関係がよくわからないことがあります。

そんなときに便利な、カメラ前平面における表示範囲をRectで返してくれる関数です。

```
public static Rect GetViewRectOnPlane(Camera _cam, float _dist){
    float w=0f,h=0f;
    if(!_cam.orthographic){
        Vector3[] frustumCorners = new Vector3[4];
        _cam.CalculateFrustumCorners(new Rect(0, 0, 1, 1), -_dist, Camera.MonoOrStereoscopicEye.Mono, frustumCorners);
        h = (frustumCorners[1]-frustumCorners[0]).magnitude*0.5f;
        w = (frustumCorners[2]-frustumCorners[1]).magnitude*0.5f;
    }else{
        h = _cam.orthographicSize;
        w = h*((float)Screen.width/(float)Screen.height);
    }
    return new Rect(0f,0f,w,h);
}
```

これを使って、OnDrawGizmos()内でカメラ前にRectをデバッグ表示するとわかりやすいかと思います。

```
float fwd=4f;
Rect rect = GetViewRectOnPlane(camera,fwd);
Vector3 camPos = camera.transform.position;
Vector3 fwdPos = Vector3.forward*fwd;
Vector3 pLT = new Vector3(-rect.size.x,rect.size.y,0f);
Vector3 pRT = new Vector3(rect.size.x,rect.size.y,0f);
Vector3 pLB = new Vector3(-rect.size.x,-rect.size.y,0f);
Vector3 pRB = new Vector3(rect.size.x,-rect.size.y,0f);
fwdPos = camera.transform.rotation * fwdPos;
pLT = camera.transform.rotation * pLT;
pRT = camera.transform.rotation * pRT;
pLB = camera.transform.rotation * pLB;
pRB = camera.transform.rotation * pRB;
Gizmos.DrawLine(camPos+fwdPos+pLT,camPos+fwdPos+pRT);
Gizmos.DrawLine(camPos+fwdPos+pLB,camPos+fwdPos+pRB);
Gizmos.DrawLine(camPos+fwdPos+pLT,camPos+fwdPos+pLB);
Gizmos.DrawLine(camPos+fwdPos+pRT,camPos+fwdPos+pRB);
```
docker-composeで立ち上げたコンテナがすぐに落ちる時の対処法メモ

### 概要
docker-composeを使っている時にコンテナが落ちまくって困ったのでメモ。
このコマンドでコンテナ側に何が起きていたかがわかる。

```bash
docker-compose logs
```

このあたりのオプションをつけるとさらに使えそう。

* t:タイムスタンプをつける
* f:監視モード(tailと同じ)

### こんな時に使えそう
* いつの間にかコンテナが落ちてる
* コンテナ内にsshで入ってい他のに急に追い出される

### 参考
* [公式ドキュメント](https://docs.docker.com/compose/reference/logs/)
package.jsonで環境変数(NODE_ENV)を設定するとき、WindowsでもLinux,Macでも動くようにする

# 概要
**npm start**したいときpackage.jsonで環境変数(たとえばNODE_ENV)をセットしつつ起動したいとき[**cross-env**](https://www.npmjs.com/package/cross-env)をつかうと実行環境がWindowsなのかLinux、Macなのか、といったプラットフォームを意識しなくて良いようにする

## 使用前→Linux用とWindows用で書き換える必要あり

スクリプトは以下のようになる

**Linux,Macなら**

```json:package.json(使用前)
"scripts": {
    "test":"NODE_ENV=test jest"
}
```

**Windowsなら**

```json:package.json
"scripts": {
    "test":"set NODE_ENV=test&&jest"
}
```

このようにプラットフォームを意識して書きわける必要があった

## 使用後→"**cross-env**"で解決

[**cross-env**](https://www.npmjs.com/package/cross-env)をインストールする

```
npm install --save-dev cross-env
```

**Linux,MacもWindowsも**以下でOK


```json:package.json(使用後)
"scripts": {
    "test":"cross-env NODE_ENV=test jest"
}
```

これで、プラットフォームを意識せずに、以下のように実行することができる

```
npm test
```
【Golang】ユニークなID作成

# 概要

Golangで、以下のような文字列であるユニークなIDの作成方法を示す。ユーザーIDの作成などに、使用する目的でプログラムを作成した。
作成には、[oklog/ulid](https://github.com/oklog/ulid)というgolangのライブラリを使用した。

```bash
0000XSNJG0MQJHBF4R33AHWHGX
```
Git: [k-washi/bss-utils/uniquegenerator](https://github.com/k-washi/bss-utils/tree/master/uniquegenerator)

# プログラム

以下のプログラムのように時間に依存したユニークなIDを作成している。また、Validationも作成している。

```golang
package uniquegenerator

import (
	"errors"
	"math/rand"

	"github.com/oklog/ulid/v2"

	"time"
)

var (
	t       = time.Unix(1000000, 0)
	entropy = ulid.Monotonic(rand.New(rand.NewSource(t.UnixNano())), 0)
)

//generateUlid ex. output: 0000XSNJG0MQJHBF4QX1EFD6Y3
func generateUlid() ulid.ULID {
	return ulid.MustNew(ulid.Timestamp(t), entropy)
}

//Get ex. output: 0000XSNJG0MQJHBF4QX1EFD6Y3
func Get() string {
	return generateUlid().String()
}

//Validation ulid string check size
func Validation(id string) error {
	if len(id) != ulid.EncodedSize {
		return errors.New("Unique ID generator validation error: length is not match")
	}
	return nil
}
```
シェルスクリプトとは？

相変わらず、IT業界になれない筆者です(-_-)
先週、やっとjavaのコードが少しかけるようになったので、改修を任され（期限メッチャギリギリ）
その作業がやっと終わり、ひと段落ついて余裕な雰囲気を出していたのですが、
無茶ぶりは突然！！
上司「C言語とかバッチわかる？」
自分「全然しらないです！！」
上司「マジか～。まぁやるしかないけどね！！」
自分「(；ﾟДﾟ)」
上司「書いてあるコードはSQLベースだから君なら読めるよ！余裕余裕！！」
自分「イラ！根拠のない事言わないでちゃんと作業内容と目的を教えてください！」
上司「そんなの、自分で調べながらやるんだよ！！自分も知らないながら、ここまで覚えたんだよ！！」
自分「心の声（しるか！！(；一_一)　）
自分「はぁ、でなにをやるんですか？」
上司「取り合えず設計書よんで、ジョブをテストするシェルスクリプト組んでみて！」
自分「シェルスクリプト？？」
自分「殻の台本ですか？（おバカ）」
上司「はぁ、お前は何も知らんやつだな！」
上司「とりあえず、ggrks」
と、いう事で毎度前置きがながくてすいません(>_<)
シェルスクリプトについて調べたのでサクッと書いておきます。
##シェルスクリプトとは？
ユーザがPCにあれやこれや頼むための命令文と認識しています。
■「ユーザ」→「命令文」→「PC」
要はユーザ（自分）から、PCに命令文を送る際の__<font color="IndianRed">「命令文」</font>__が
__<font color="IndianRed">シェルスクリプト</font>__です！
まぁもっとざっくり言うとパソコンの中の人と対話する台本って感じかなと。
##シェルとカーネルの関係
では、実際にどうのような感じで動いているのかざっくり説明していきます。
登場人物
①__<font color="IndianRed">カーネル</font>__（ケン〇のおじさんではないようです！）
PCの中で自分たちの命令を実行してくれる偉い人！
②__<font color="IndianRed">シェル</font>__
カーネルに自分たちの命令を伝えてくれる仲介人的な？人
③__<font color="IndianRed">ユーザ</font>__
自分たちユーザですね。
図で表すとこんな感じです。
![asd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518234/3b71ec3a-3276-61c1-23fe-9c90313e5aee.png)
この図に書いてあるユーザからのコマンドをテキストファイルに書いたものを
__<font color="IndianRed">シェルスクリプト</font>__と呼びます。

結果！！
__シェルスクリプトとは、ユーザがカーネルさんに、命令するための
文章を書いたファイルのなのだと理解！__
MySQLのNOT INでNULLが含まれていると常にFALSEの結果となるらしい

参考：https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_NOT_IN
※ PostgreSQLの参考ですが、MySQLで試してみても同じだったので投稿させていただきました:bow:

https://www.db-fiddle.com/f/xphPFvA6EnHq1n49ZronD3/2

```sql
-- nullが入ってない場合はtrue/false問題なし
select 
	1 in (1, 2, 3) -- true
   ,5 in (1, 2, 3) -- false
   ,1 not in (1, 2, 3) -- false
   ,5 not in (1, 2, 3); -- true

-- nullが入ってた場合は一致するのがない場合はnullになってしまう
select 
	1 in (1, 2, null) -- true
   ,5 in (1, 2, null) -- null！！！
   ,1 not in (1, 2, null) -- false
   ,5 not in (1, 2, null); -- null！！！
```

nullはfalseっぽい値なので、not inでnullがあるとtrueと返すのが不可能になってしまう！

```sql
select 'hoge' where 1 not in (1, null); -- 空の結果が変える
select 'hoge' where 5 not in (1, null); -- 空の結果が変える
```

---

例えば`NOT IN`のサブクエリでnullが含まれてしまっても思った通りに動きません

https://www.db-fiddle.com/f/6Nj26AmL9PwBrw75U54xz7/0

```sql
create table hoge(n int);
insert into hoge
values (1),(2),(3),(4),(5),(6),(7);

create table fuga(i int);
insert into fuga
values (5),(null),(7);
```

```sql
-- inの場合は問題なく、fugaの5,7が一致する2レコードの結果になる
mysql> select *
    -> from hoge
    -> where n in (select * from fuga);
+------+
| n    |
+------+
|    5 |
|    7 |
+------+
2 rows in set (0.01 sec)

-- not inの場合はnullが含まれてしまうとtrueと返すことがないので、
-- 空の結果になってしまう
mysql> select *
    -> from hoge
    -> where n not in (select * from fuga);
Empty set (0.01 sec)
```

やり方はいろいろあると思いますが、例えば NOT EXISTSなどを使うなどすると良いと思いました

```sql
mysql> select *
    -> from hoge
    -> where not exists (select * from fuga where n = i);
+------+
| n    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    6 |
+------+
5 rows in set (0.00 sec)
```

以上です。見ていただいてありがとうございました。m(_ _)m
CentOS8にPrometheusをインストールする

# はじめに
Prometheusを触ってみたかったので動かしてみます。
Prometheusは複数のコンポーネントで構成され、今回説明するのは Prometheus 本体です。
それ以外にも「exporter（監視エージェント）」や「alertmanager（通知の実行）」などが存在します。

# 環境
インストールの前提となる環境は以下のとおりです。

- OS：CentOS8
- selinux：無効
- firewalld：無効
- Prometheusはバイナリを使用（Dockerは使用しない）
- インストールディレクトリ： /usr/prometheus
- Prometheusバージョン：2.15.2

# インストール
それではインストールを行います。
作業に必要なパッケージとPrometheusインストールします。

```
yum install -y  wget  tar
mkdir /usr/prometheus

cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.15.2/prometheus-2.15.2.linux-amd64.tar.gz
tar zxvf prometheus-2.15.2.linux-amd64.tar.gz

mv ./prometheus-2.15.2.linux-amd64/* /usr/prometheus/
rm prometheus-2.15.2.linux-amd64.tar.gz
rmdir prometheus-2.15.2.linux-amd64
cd /usr/prometheus
chown root:root -R /usr/prometheus
```
※ /tmp は作業用のディレクトリです

## systemd ユニットファイルの作成
ダウンロードしたバイナリを実行すれば起動しますが、ユニットファイルを作成していきましょう。

``` /usr/lib/systemd/system/prometheus.service
[Unit]
Description=Prometheus
Documentation=https://prometheus.io/docs/introduction/overview/
After=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Type=simple
ExecStart=/usr/prometheus/prometheus \
--config.file=/usr/prometheus/prometheus.yml
ExecReload=/bin/kill -HUP $MAINPID
Restart=no
```
作成したユニットファイルを読み込み、Prometheusを起動します。

```
systemctl daemon-reload
systemctl enable prometheus
systemctl start prometheus
```

### 起動確認
ブラウザで http://＜IPアドレス＞:9090/ にアクセスできるか確認しましょう。

### 気になるオプション
細かい動作の検証ができていませんがこのあたりのオプションを変更する事がありそうです。
ユニットファイルのExecStartの項目に付け足していきます。


|オプション|内容|
|:-----------|:------------:|
|--web.listen-address=localhost:9090|localhostからのみに変更 [^1]|
|--storage.tsdb.retention.time|データ保持期間|
|--storage.tsdb.retention.size|データ保存サイズ|
|--storage.tsdb.wal-compression|WALを圧縮|
|--storage.tsdb.path|データ保存するパスを指定（デフォルトのままだと /data/ に保存される）|
必要に応じて /usr/lib/systemd/system/prometheus.service を書き換えます。
※/usr/lib/systemd/system/prometheus.service を修正した場合は 「systemctl daemon-reload && systemctl restart prometheus」を都度実行しましょう。
[参考：「RedHat」SYSTEMD のユニットファイルの作成および変更](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files)

[^1]: アカウントやIPアドレスによるアクセス制限ができないので、Apacheなどをかませて使用すると良さそう

それ以外のオプションはヘルプで確認できます。

```
/usr/prometheus/prometheus --help
```

### コンフィグの場所がわかりにくい
/etc/ 配下をとりあえず探してしまう方のためにひと工夫しておきましょう。

コンフィグファイル自体は /usr/prometheus にあるのでシンボリックリンクを設定します。
（コンフィグファイル自体を動かして ExecStartの「--config.file」を修正しても良いでしょう）

```
ln -s /usr/prometheus/prometheus.yml /etc/prometheus.yml
```

# 終わりに
本体をインストールしただけなので、まだ監視ができていません。
次はexporterを動かして監視する記事がかけたら良いですね。

## 更新履歴
2020/03/08
気になるオプションにstorage.tsdb.pathを追加しました。