OmniAICreator/Qiita-1.07M huggingface dataset:
ゲームやるとき説明書を読まないタイプのひとって Rust やるときスタックとかヒープのところスルーすると思うんですけどちゃんとやっておくと具合がいいですよ

# はじめに

スタックとかヒープとかについてうろおぼえだったので軽くスルーしながら Rust を勉強していったんですけど、ちゃんと理解しておくといろいろわかりやすくなっていくのでちゃんとやったほうがいいなーと思ったのでちょっとまとめてみました。
自分も勉強中なのでつっこみ有れば歓迎です。

# スタックとは

プロセス起動時に割り当てられたメモリ領域です。
プロセスから見ると起動時からアドレスを知っているのでアクセスは速いのですが、容量はあまり大きくないです。
データの保存・取得方法に癖があり、スタックを配列と見立てると、保存時には push しかできず、取得時には pop しかできません。
不便ではありますが、末尾のアドレスさえ知っていればすぐに読み書きできるので、その構造からもアクセス速度は速くなります。

# ヒープとは

必要に応じてプロセスに割り当てられるメモリ領域です。
割り当てにあたって OS にメモリー割り当ての要求をする必要があるので、はじめから割り当てられているスタックに比べるとアクセスが遅くなりますが、利用できる容量はスタックよりも大きくなります。
データの保存・取得は任意のアドレスへ行うことができます。

# 関数とスタック

Rust では関数を実行する際に利用する引数や変数などのデータをスタックに保存し、関数終了時にスタックから取り除きます。
実行中の関数から関数を呼び出した場合には、実行中の関数のデータの後ろに新しい関数のデータが push されます。

スタックは末尾のデータにしかアクセスできないという制約を持ちながらも高速でアクセスできるという利点があると説明しましたが、
このように利用すると実行中の関数からは常に必要なデータには高速にアクセスでき、関数が終了してデータを pop すると関数呼び出し前の状態に容易に復帰できるので都合が良いのです。

# 所有権システムとスタック

関数とスタックの関係を知っていると、所有権システムについて理解がしやすくなります。
所有権とは「値が変数に束縛され、変数の宣言されたスコープが無効になると値が破棄される」というルールのことですが、これは関数呼び出し終了でスタックからデータが破棄されるという挙動をそのまま抽象化したものであると気がつきます。

# スタックとヒープと変数

前々節で変数のデータはスタックに保存されると説明しましたが、一部のデータはヒープに保存されます。

ヒープの特徴はアクセスが低速な代わりに任意の容量を割り当てることができると説明しましたが、その特徴の通り可変長のデータや容量の大きいデータはヒープに保存され、実データへのポインタやデータ長などのメタデータのみスタックに保存されます。
こうしてデータをヒープに置きポインタだけスタックに置くことで、大きなデータも柔軟に扱いつつスタックの解放のタイミングで関連するヒープのデータも安全に解放することができます。

具体的にヒープに保存されるデータは String や Box、Vec などの型のもので、ヒープとスタックの特徴について理解しておくとこれらの型をうまく使えるようになるのではないでしょうか。
Espressoで複数のRuleを指定する

#これは何？
Espressoを使ってUIテストを行う時にデバイス利用のPermissionを自動で許可する方法はいくつかあるけど、Rulesが複数個になってしまう、、、というのを解決します。
言語はKotlinです。

# では、サクッと
例えば、StartのActivityをHogeActivityと指定しているけど、GPSのPermissionも自動で許可させたい場合を想定するとはこう書きます。

```kotlin:MyHogeActivityTest.kt
@Rule @JvmField
var mActivityTestRule = ActivityTestRule(HogeActivity::class.java)

@Rule @JvmField
var mGrantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION)
```

`import`とかはこれが必須になります。
```kotlin:MyHogeActivityTest.kt
import android.support.test.rule.ActivityTestRule
import android.support.test.rule.GrantPermissionRule
```

```kotlin:app/build.gradle
...
dependencies {
...
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-intents:3.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'junit:junit:4.12'
...
}
```

以上！
【Rails】pathヘルパーでURLが/:idではなく.idになってしまった時に確認すること

##状況
```
<td><%= link_to '詳細', inquiries_path(inquiry) %></td>
```

上記のようにlink_toメソッドでURLを生成すると想定とは異なるURLが出来てしまった

```
http://xxx.com/inquiries.id
```
本当は下記のようにしたい。

```
http://xxx.com/inquiries/:id
```

##確認すること
そんなとき、まずはpathヘルパーが単数形になっているか確認しよう。
もし複数形になっていたら単数形に直そう。これで解消するはず。

```
<td><%= link_to '詳細', inquiry_path(inquiry) %></td>
```

##それでも解消しなかったら
今回がそうだった。変更したら今度は

```
undefined method
```

とエラーが出てきた。

次はルーティングを確認。

```
  get '/inquiries', to: "inquiries#index"
  get '/inquiries/:id', to: "inquiries#show"
```

これを変更。

```
resources :inquiries, only: [:index, :show]
```

これで無事治った！

おそらく単数形リソースと複数形リソースの違いでpathヘルパーにも影響が出たのではないか。

やはりそのようでした！詳しくは下記をご覧いただくと良いと思います

[Railsのルーティングを極める (後編)](https://techracho.bpsinc.jp/baba/2014_03_03/15619)

以上です。
プログラミング学習　記録

#なぜQiitaで記録を取るのか

- 面接で有利になるから
- 提示を要求されるから

###以上を踏まえて記録を残すこととする。

##学習内容
*Railsチュートリアル2周*

**<a href="https://www.amazon.co.jp/dp/4774193976/ref=cm_sw_r_tw_dp_U_x_lRpHCb3C7H62T">プロを目指す人の為のRuby入門</a>**

**<a href="https://www.amazon.co.jp/dp/4839962227/ref=cm_sw_r_tw_dp_U_x_MSpHCb822RJN5">現場で使える ruby on rails 5速習実践ガイド</a>**
TCP Flagの１６進数表記

wiresharkでパケット解析する分にはGUIならすぐわかるが
CUIでしか解析できない場合にtsharkを使用しなかればならない場合がある。（ほとんどないかも。。。）

tsharkのオプション　-e で `tcp.flags`を指定している時に
TCP Flagが１６進数で調べるに手間取ったのでまとめ。

```
0x00 NULL
0x01 FIN
0x02 SYN
0x04 RST
0x10 ACK
0x20 URG
```

各パケットの詳しい中身は以下のサイトが参考になりました。
https://www.wdic.org/d/COMM/PROT/LAYER/34/TCPIP/TCP
DynamoDBについてまとめてみた

# DynamoDB
DynamoDBはマネージド型のNoSQLデータベースです。  
NoSQLデータベースの特徴としてリレーショナルデータベースでは難しい拡張性が挙げられます。  

## DynamoDBの特徴
* ストレージ容量が必要に応じて自動的に拡張  
ストレージについては事前の容量を指定する必要がなく、利用者がテーブルにデータを書き込んでいけば、必要に応じてストレージ容量が自動的に拡張します。  
※課金形態は従量課金制  
* 秒間あたりのI/O性能(スループット)を指定できる  
テーブル毎に秒間あたりの読み書きスループットが指定でき、この値はデータベース使用中に変更することも可能です。  
* データを3つのデータセンタに複製することで高可用性と高耐久性を提供  
データを地理的に離れた3つのデータセンタに複製するため、利用者側で冗長性を考慮する必要がありません。  
※一つのデータセンタで障害が発生してもデータの破損や消失が発生しない  
* 読み込み生合成の強弱を指定することで性能と生合成のバランスを選択可能  
DynamoDBの生合成は結果整合性となります。  
つまりあるデータを書き込み、直後に読み込んだ場合に、最新の結果が反映されない場合があります。  
DynamoDBではそのような整合性をオプションとして指定することができ、強い整合性を指定することも可能です。  
※ただし強い整合性オプションを指定することで読み込みスループットが半減してしまうデメリットも存在するため、デフォルトの整合性で要件を満たすよう設計することが重要  

## アクセス制御に関して
DynamoDBはリージョンサービスであるため、プライベートサブネットからデータの読み書きを行うにはNATインスタンスが必要となります。  
※パブリックサブネットに立てたNATインスタンスからアクセスする必要があり、DBアクセスの際に毎回インターネットアクセスが必要となる  
DynamoDBに対する操作は、IAMによりテーブルや項目レベルのアクセス管理を行います。  
DynamoDBにアクセスするアプリケーションがEC2インスタンス場で動作する場合は、そのインスタンスに対しDynamoDBへのアクセスが許可されたポリシーが設定されたIAMロールを割り付ける必要があります。
golangのflycheck

# flycheckが遅い・・・
 いつからかはわからないが、cgoが入ると極端にコンパイル時間が長くなり非常に使いづらくなっていた。
gometalinterやgolangci-lintに切り替えても同じ現象でした。

# checkerをdisableに
 flycheckには、golang用のcheckerが複数ありgometalinterなどに変更しても、これらがdisableになっていなかった。
特にerrcheck/unconvert/megacheckが遅かったのでこの3つをdisableにすれば短時間のチェックができそうです。
注意点としてはsetqではなく、setq-defaultでないとdisableに出来ませんでした。


```elisp

  (setq-default flycheck-disabled-checkers '(
                                     ;; go-gofmt
                                     ;; go-golint
                                     ;; go-vet
                                     ;; go-build
                                     ;; go-test
                                     go-errcheck
                                     go-unconvert
                                     go-megacheck
                                     ))
```

普段はgolangci-lintを使うようにしてこれらは全てdisableにしています。
ログイン不要で縦書きツイートができるサービスを作成した

# はじめに
ローンチしたサービス：[縦ったー](https://tatetter.netlify.com)
ソースコード：[GitHub](https://github.com/iwatos/tatetter)

ログイン不要で縦書きツイートができるサービスを作成しました！いえーい！
![スクリーンショット 2019-03-28 22.55.01.png](https://qiita-image-store.s3.amazonaws.com/0/230281/7e7abd28-dd8b-7cbe-1a67-0d52d2af3cca.png)

...と思ったらn番煎じでした。
そのままにしておくのも悔しいのでどうやって作成したかを書いていきます。

### 縦書きツイートサービスの先人たち
* [ツイッター縦書きヘルパー](https://tategaki.yanoshin.jp)
* [縦つい。](https://yubais.net/tools/tatetwi/)
* [縦書きったー](https://tategakitter.netlify.com)

### 先人に比べた本サービスの強み
* 入力文字が即座に縦書きに変換されて表示される。
* 半角文字を入れても形が崩れない

# 開発環境
Vue.js + Netlify
サーバレスです。DBもAPIも使わないからね。

# 利用の流れと仕組み
1. テキストボックスにツイートしたい内容を入力
2. 1の文章を縦書きに変換
3. 2の結果をもう一つのテキストボックスに出力
4. つぶやくボタンを押下
5. 3の結果が記入されたtwitterのツイートするページが開く
6. 内容を確認後ツイート。

# 解説
## 縦書きの変換
以下の流れで変換しました
1. 半角文字を全角文字に変換
2. 入力テキストを一文字ごとの二次元配列に変換
3. 二次元配列を右90度回転
4. 3結果の二次元配列を改行を足しながらつなげて文字列に戻す。

コードは要点のみ記載するので詳しい部分はgithubの
src/components/Content.vue を参照ください。

### 半角文字を全角文字に変換
半角文字と全角文字が混ざると縦書きにした時に形が崩れるので、
半角文字を全て全角文字に変換します。

```js
       let fullText = halfText.replace(/[!-~]/g, function(s) {return String.fromCharCode(s.charCodeAt(0) + 65248)})
       fullText = fullText.replace(/ /g,"　")
```

半角文字（英数字記号）は正規表現で/[!-~]/g(文字コードが!から~までの文字を指定)で表現できます。
半角文字の文字コード値に65248を足すと対応した全角文字になるので、それらに置換します。
また、半角スペースは上記では全角スペースにならないので、半角スペースを全角スペースに置換する処理も記述します。

### 文字列を一文字ごとの二次元配列に変換
文字列の高さ×幅の長方形の二次元配列に文字列を一文字ずつ入れていきます。
改行があった場合は配列の次の行に格納します。

```js
       //一字ずつ二次元配列に格納  
       str.split("\n").forEach(function(e, i){
         e.split("").forEach(function(f, j){
           matrix[i][j] = e[j]
```

### 二次元配列を右90度回転
先ほど作成した二次元配列を右90度分回転させます。
これで縦書きの配置になります。

```js
for (let i = 0; i < height; i++) {
            for (let j = 0; j < width; j++) {                
                rotatedMatrix[j][i] = matrix[height-i-1][j];
            }
        }
```

### 二次元配列を結合して文字列にする
各行ごとに文字を結合し、
行と行は、間に改行を入れて繋げます。

```js
 matrix.forEach(function (e,i,v) {
        v[i] = e.join("")
      })
      let str = matrix.join("\n")
```

以上で縦書きに変換されました。

## つぶやくボタンの設置
単純に呟けるページを開くだけなら

```html
<a href="https://twitter.com/share">Tweet</a>
```
でも可

今回はツイートページを開く時に末尾に「【縦書き本文】(縦ったーURL) #縦ったー」と表示させたかったので以下のように記述

```html
<a href="https://twitter.com/share" 
data-url="https://tatetter.netlify.com" 
data-text="【縦書き本文】"
data-hashtags="縦ったー"
>つぶやく</a> 
```
【縦書き本文】については改行をURLエンコードに変換させる必要があるため以下を記述

```js

let text = this.verticalText.replace(/\n/g, "%0A")
```
## 補足
twitterは文字列の先頭が空白でつぶやくと、空白がトリミングされるので
先頭文字が空白の場合"."に変換するようにします。

```js
let s = str.slice(0, 1)
      if(s == "　"){
        return "．" + str.slice(1) 
      }
      return str
```

#公開
1. GitHubにコミット
2. Netlifyで公開！

とても簡単
Netlifyの使い方は以下
[基礎から学ぶVue.js：Vue.js + Netlifyで自動デプロイ](https://cr-vue.mio3io.com/tutorials/netlify.html#ビルド設定)

#感想
DBがいらないものならVue.js + Netlifyでかなり簡単にこんなページが作れて楽しい！
ただアイデアはなかなか出なかったり、今回みたいに先人がいたりするので厳しい。

# 参考
[JavaScriptで英数を全角/半角に変換する方法](https://qiita.com/yamikoo@github/items/5dbcc77b267a549bdbae)
[Twitterシェアボタンの設置](https://qiita.com/dora_____emon/items/4230d28086c5913622bd)
Raspberry Pi 導入（カメラ付き）

##モチベーション
AWS IoT ボタン買ってAWS繋いでみたが、要はON信号送るだけで面白い用途が思いつかなかったので、IoTといえばラズパイでしょ！っということで、導入。
##購入品
ラズパイ本体は理由なく一番ハイスペックなものを選択。
カメラは動けばいいので安価なものを選択。
amazonでポチって、２日で届く。
- ABOX Raspberry Pi 3 Model b+ ラズベリーパイ 3 b＋ ￥ 9,999 
- HiLetgo OV5647 5MP Raspberry Pi 3 カメラ OV5647 HDカメラモジュール ￥ 1,200 
##導入手順
- HDMIに液晶、USBマウス、USBキーボードを接続し、電源ON
- 言語、キーボード、WiFiの設定後
- RaspbianをInstall.
- 途中でOSをupdate
- 再起動

以上でRaspbian立ち上がる
OSの素性をメモっとく

```
$ uname -a
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.8 (stretch)
Release:	9.8
Codename:	stretch

```

USB接続情報取得

```
$ lsusb
Bus 001 Device 005:Jing-Mold Enterprise Co., Ltd
Bus 001 Device 004:Logitech, Inc. Marble Mouse(4-button)
Bus 001 Device 006:Standard Microsystems Corp.
Bus 001 Device 003:Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002:Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001:Linux Foundation 2.0 root hub
```

一旦SHUTDOWNし、電源外し、カメラ接続、電源ON。
raspi-configからカメラを有効にする。

```
# sudo raspi-config
```

- 「Interfacing Options」選択
- 「P1 Camera」選択
- 「Would you like the camera interface to be enabled?」→「はい」
- 「了解」
- 「Finish」
- 「Would you like to reboot now」→「はい」

再起動したらお試しで静止画撮影

```
$ raspistill -o test.jpg
$ raspivid -o test.h264
```
##終わりに
ひとまず導入完了。
次何しよう。

- 他のセンサー繋ぐ
- AWSにデータ上げる
- アクチュエータ動かす（カメラをパーンさせたい）
- 画像認識させる
GitFlowについて、軽くまとめる？

#まえがき
利用・勉強していての個人的な感想を書いている内容になります。
間違い・不足がある可能性がありますので、何かありましたら「コメント」や「編集リクエスト」頂けると助かります。

# GitFlowとは？
Gitを使う上での、ブランチの使い方（ルール・方針）というのでしょうか。
GitFlowというルールを決めて、それに沿うように手伝ってくれる便利なツール（プラグイン）とでも言えば良いでしょうか。

# イメージ
GitFlowの有名な図をちょっと拝借
![git-flow-nvie.png](https://qiita-image-store.s3.amazonaws.com/0/118481/ba229e06-609c-ad7e-440f-705e42956ed4.png)
参考：https://leanpub.com/site_images/git-flow/git-flow-nvie.png

# ブランチの種類
## master
リリースできる状態をキープするブランチ。
ここに開発者が修正ソースを適用（push）する事はありません。
常にクリーンな状態がキープされています。

## develop
現在開発中の最新状態となっているブランチ。
ここも開発者が直接修正（push）する事はありませんが、各開発者が修正完了したソースがここに集まります。

## feature
各開発者が自由に作成し、修正をするブランチ。
基本はローカルにのみ存在し、リモートには存在するのは、developにマージ待ちのものか、保留になったものといったところでしょうか。

ブランチ名は、修正内容がわかりやすい内容にするか、Redmine等でチケット駆動開発している場合はチケット番号にしておくと便利です。

## release
リリースする際に作成されるブランチ。
developから作成され、リリースに関する修正があれば、このブランチで実施します。

releaseブランチ以降のブランチ名は、リリース番号（V1.0.0等）にすると便利です。

## hotfix
リリース後に見つかったバグなど、developの開発が先に進んでしまっているなどして、
次のリリースを待てない！となった場合に利用されます。

# 開発の手順（develop→feature→develop）
1. 各開発者が自分のfeatureを作って、修正
    
    ```terminal
    git flow feature start {ブランチ名}
    ```
1. 修正が完了したら、リモートにpush（publish）

    ```terminal
    git flow feature publish {ブランチ名}
    ```
1. マージリクエスト（プルリクエスト）にて、developにマージ（コードレビューする）
GitLabやGitHubにて、developにマージします。
※ここでの手順は省略します。
個人開発など、コードレビューを省略する場合は、featureのfinishでしょうか

    ```terminal
    git flow feature finish {ブランチ名}
    ```

# リリースの手順（develop→release→master）
1. リリース準備に、releaseブランチの作成

    ```terminal
    git flow release start {ブランチ名}
    ``` 

1. リリース用の修正があれば修正してコミットし、push(publish)

    ```terminal
    git flow release publish {ブランチ名}
    ``` 
1. 作業が完了したら、リリースブランチの終了＆マージ

    ```terminal
    git flow release finish {ブランチ名}
    ``` 
この時に、タグが作成されます。

# バグ対応の手順（master→hotfix→master/develop）
1. バグフィックス用にhotfixブランチの作成

    ```terminal
    git flow hotfix start {ブランチ名}
    ``` 
1. バグ修正してコミットし、push(publish)

    ```terminal
    git flow hotfix publish {ブランチ名}
    ``` 
1. 修正完了したので、hotfixブランチをマージ

    ```terminal
    git flow hotfix finish {ブランチ名}
    ``` 
※masterとdevelopの両方にマージされます


#まとめ
色々なブランチが登場してきますが、基本は、
1. 開始（start）
2. 修正
3. 公開・共有（publish）
4. 終了（finish)
と言う感じですね。
dockerで苦戦したところの備忘録

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているryota_miraidenshiです。
今回、dockerの基本について勉強しましたが、その中で自分が苦戦したところについて自分と同じような境遇の人を助けることができたらと思い、記録しておきます。

#Error unpacking rpm package httpd ~ centos

これはubuntuでdocker buildするときに発生したエラーで、自分はhttpd-2.4.6-88.el7.centos.x86_64をインストールするときに発生しました。
これの改善として

```
$docker info
~
Storage Driver: aufs
~
```

とはじめになっていたので/etc/default/docker にDOCKER_OPTS="--storage-driver=devicemapper"を設定したのち、

```
$restart docker
```

でリスタートさせます。（imageなど消えますので必要ならばバックアップを取っておきましょう）

もう一度確認して

```
$docker info
~
Storage Driver: devicemapper
~
```

となっていれば成功です。
この後もう一度buildすれば成功しました。

#Error pushing to registry: Authentication is required.

```
docker push image名
```
をしたときに出たエラーですが、これはできるとそれだけかと思うことですが知らないとハマってしまいます。
このpush時のimage名ですが、Docker Hubのアカウント名/image名とする必要があります。
つまり自分のDocker Hubのアカウント名がryota8976なのでimage名をryota8976/httpdとする必要がありました。

#終わりに
プログラム初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正しますのでどんどん指摘してください。
Datadog muti-orgのusage summary APIのレスポンス解説


Datadogで複数organizationからDatadog自体の利用量を取得したいことがあります。
`https://api.datadoghq.com/api/v1/usage/summary`を使えば
[複数organizationの利用量](https://docs.datadoghq.com/api/?lang=ruby#get-usage-across-your-multi-org-account)が取得できます。
ただレスポンス仕様が2019年3月の段階でまだ白紙なので、yaml形式でのサンプルを紹介します。

##一部省略したサンプル
```yaml
- 200 # http status
# ここからは実際に使うデータ
# まずは期間内の合計データから。
- infra_host_top99p_sum: 500 # 期間分のinfrastructure利用量合計。期間もorganizationもすべて合算
  apm_host_top99p_sum: 500   # 期間分のAPM利用量合計。期間もorganizationもすべて合算
  container_hwm_sum: 500     # 期間分のcontainer利用量合計。期間もorganizationもすべて合算
  # usageは期間分の配列で月ごとの情報をハッシュで保有している。
  # 2ヶ月なら配列サイズが2。並び順は最新のものが一番最後
  usage:
    - 略 # ここは最新の月より前の月の情報。
    - infra_host_top99p: 250 # 最新の月のinfrastructure利用量合計。key名にsumがない。
      date: 2019-03 # その月。この例は最新の月
      orgs: # orgs配下は1ヶ月分のorganization単位での情報を配列で保有している
        - name: your_org_name_1 # あるorganization名
          infra_host_top99p: 50 
        - name: your_org_name_2 # あるorganization名
          infra_host_top99p: 50
```

##Ruby Clientの拡張
以下を追加するときれいに拡張できます。

v1配下に`usage.rb`ファイルを追加
https://github.com/DataDog/dogapi-rb/tree/master/lib/dogapi/v1

facadeのinitializeメソッド内で他サービス同様にインスタンス変数追加し、さらにAPI用メソッド追加
https://github.com/DataDog/dogapi-rb/blob/master/lib/dogapi/facade.rb
誰か教えてGCP(1) GAEのサンプルアプリケーションを作った

# GCPを触り始めたがいろいろとわからない
AWSはそれなりに触ったことがあるのですが、GCPもお試しできる環境にあるので、いろいろと触ってみているところです。
その中でいろいろと分からないところを、ぜひWeb上のスーパーマンの皆様に教えていただきたいです。
（AWSに比べてGCPは情報量が少ない）
自分で解決したら、追記いたします。

# Summary
## GAEのサンプルを動かした結果、分からないこと
* GAEのdefaultに作ったサービスは消せないのか
* GAEのファイアウォールルールについて

# 以下、作業
## GAEのサンプルアプリケーションのTutorial
https://cloud.google.com/appengine/docs/standard/python3/quickstart?hl=ja
を参考に、flaskアプリケーションが簡単に立ち上がることを確認。

A/Bテストも、
**複数バージョンをデプロイし、「バージョン」→「トラフィックを分割」**
より、トラフィックの設定をランダムに設定することで簡単にできました。

「おおーすごいな、じゃあサンプルを消そう」とした時に、**defaultサービスのリソースが消せない**

defaultにひもづくバージョンを１つまでには落とせたのですが、その後のバージョンが消せないという状況になりました。

https://cloud.google.com/go/getting-started/delete-tutorial-resources?hl=ja
を参考にすると、defaultは停止はできても、削除するならprojectを消さないといけないということ。
Tutorialではdefaultで作るのに、それが消せないという罠。

停止すると他のサービスも使えなくなってしまうので、困った状況です。
サンプルとはいえ、課金が続いてしまうのも良くないので、いい方法あれば教えてください。

## GAEのファイアウォールルール
GAEではファイアウォールルールの設定ができるので、https://cloud.google.com/appengine/docs/standard/python/creating-firewalls?hl=ja&_ga=2.96422555.-662880421.1524103351
を参考に試してみることに。

| IP Range | Rule | Priority |
|:-----------|------------:|:------------:|
| XXX.XXX.XXX.XXX | Allow | 100 |
| * | Deny | default |

と設定し、自端末のIPであるXXX.XXX.XXX.XXXから接続しようとすると、**403エラー**に。

defaultをAllowにすると、繋がる。
思い切って、XXX.XXX.XXX.XXX→0.0.0.0/0にしても変わらず。

Cloud Consoleだと上記設定でIP制限がかけられるのですが、外部からのアクセスがうまくいかないという状況です。なぜだ。
知見ある人は是非教えてください。
（別のサービスをFrontとして運用する、まずやり方が間違っているなど）

# 次回
GAEをもう少し掘り下げたい。負荷試験のスケーリングとか。
GKEもやりたいですね。
Powerapps:flowで値をreturnする方法

自分メモ
以下サンプル

flowで以下のように作成
フロー名は"検証フォーム"で
変数cに"こんにちわ"が入る

<img width="596" alt="flow.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/372905/73a10ec0-f0b6-eeb0-44e1-02dec496bbc7.jpeg">

powerapps側でflow実行用のボタンと受け取りボックスを作成。

通常の指定だと
'検証フォーム：返答'.Run()だけど

返り値を受けるために以下のように変更。
UpdateContext({result:'検証フォーム：返答'.Run()})

<img width="419" alt="powerapps.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/372905/5cec350c-b049-9489-190b-af67daf906fe.jpeg">

ボタンをクリックすると、returnでボックスに値が表示されるようになる。
Visual Studio Code インストール・日本語化・レポート自動送信停止

# ダウンロードしてインストール

Visual Studio Code - Code Editing. Redefined
https://code.visualstudio.com/

# 日本語化
左端の拡張機能から「Japanese Language Pack for Visual Studio Code」を検索してインストール
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13267/b417135f-a376-b2a0-9d9a-3922c3f5e6bc.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13267/cf3e771e-cd1f-d58d-7a0b-2cbe9130a25c.png)

# 自動ログ送信の停止
設定を開き、「telemetry」もしくは「テレメトリ」で検索。デフォルトONになっている2個のチェックを外す。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13267/418a50ce-5129-9c52-5d0b-ef3c1cf2c695.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13267/3f85ebeb-4a5e-65d5-85ec-d42eab4f62ba.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/13267/7cac1437-5421-ac68-1bb4-a9d19c89f8ea.png)
【Go1.12 】dep からModulesに移行してGOPATH配下から脱出する 

# はじめに

Go1.12からModulesが標準でサポートされ、
いよいよ言語標準機能で依存関係管理とバージョニングが可能となりました。

これにより、

- GOPATH配下にソースレポジトリがなくても良くなった
- vendoringしなくても良くなった

という利点が生まれます。

というわけで、depで依存管理していたレポジトリを、Modulesによる依存管理に移行してみました。

# 手順

今回は、github.com/n-someya/lambda-gittrendというレポジトリを脱depさせ、Modules対応させてみました。
lambda-gittrendの直下には、`Gopkg.lock`がある状態です

## 1. GOPATHからの脱出

まずは、$GOPATH以外のパスにレポジトリを移動します。

```sh
cd $GOPATH
cp -r src/github.com/n-someya/lambda-gittrend ~/lambda-gittrend
```

## 2. Modulesへの移行

```sh
cd ~/lambda-gittrend
go mod init
```

以下のような出力がされて、コマンドが完了します。

```
go: creating new go.mod: module github.com/n-someya/lambda-gittrend
go: copying requirements from Gopkg.lock
```

え、これだけ？と思いましたが、dep対応のレポジトリなら`Gopkg.lock`を読みこんで勝手に移行してくれます。
コマンドが完了すると、`go.mod`というファイルができています。



ちなみに、1からレポジトリ作る時は、
`go mod init`の後にレポジトリパスを書きます。 `go mod init github.com/n-someya/foo`みたいな感じです。

### 3. dep関連ファイルとディレクトリの削除

今までありがとう、、、

```sh
rm Gopkg.lock Gopkg.toml
rm -r vendor
```

これだけで `go build` 出来るようになりました。
Gitのレポジトリから、大量のvendorディレクトリも消えて満足です！

# Modulesのコマンド達

移行終了時にはビルド出来る状態になっていると思いますが、
実際のリリース時には以下のようなコマンドで、レポジトリの状態をチェックするのが良いみたいです。

## 依存関係の整理

依存モジュールを整理し、不必要なものはpruneされます。
また、全てのビルドタグ、OSの組み合わせでビルド可能か？などが精査されます。

```sh
go mod tidy
```

## 依存パッケージを含んだ全てのテスト

タイトルの通りです。
依存パッケージ含めて、全てのテストをします。

```sh
go test all
```

※私のレポジトリでは残念なことに通らず。。。aws lambdaのSDKとかテストこけてるんだがどういうこと


## 依存パッケージのVerify

ダウンロードされている依存パッケージが、本当に正しいかを検証します。

```sh
go mod verify
```
# 終わりに

思ったより簡単でした。
なお、ビルド環境とかで、どうしてもGOPATH配下でModulesを使わなければいけない場合は
`GO111MODULE`環境変数を`on`に設定しておくとModulesが使えるはずです。
【AWS】lambda のめんどくさい棚卸しを楽にするワンライナー

lamdaってお手軽にガンガン作れるので、気がつくとめっちゃ数が増えてませんか？

そうするとだんだんと管理がめんどくさくなって、いざ棚卸しってタイミングでGUIからポチポチ一覧を出すのはしんどいですよね。

なので、もしそんな状況になったら、このワンライナーで幸せになれるかも知れません。

`aws cli` と `jq` で実現しています。手元のMacBookで検証しました。

今回は、"関数名, ランタイム, 最終更新日時, 説明" を抜いて表示していますが、お好みで修正して欲しい情報だけ出力していただければと思います。

```terminal:ワンライナー
# CSV形式で標準出力するパターン
$ aws lambda list-functions --region ap-northeast-1 | jq '.Functions[] |  { "関数名": .FunctionName , "ランタイム": .Runtime, "最終更新日時": .LastModified, "説明": .Description }' | jq -rs '(.[0]|keys_unsorted),map([.[]])[]|@csv'
"関数名","ランタイム","最終更新日時","説明"
"MyFunction-110M4HMNJGFGE","nodejs8.10","2018-11-21T11:22:37.400+0000","This is lambda function"
"AwesomeFunction-XWRELL62AGVT","nodejs8.10","2017-11-17T06:26:50.152+0000","This is awesome function"
：

# TSV形式でクリップボードに出力するパターン
$ aws lambda list-functions --region ap-northeast-1 | jq '.Functions[] | { "関数名": .FunctionName , "ランタイム": .Runtime, "最終更新日時": .LastModified, "説明": .Description }' | jq -rs '(.[0]|keys_unsorted),map([.[]])[]|@tsv' | pbcopy

```

あとはファイルにリダイレクトしたり、Google Spread Sheetにコピペするだけで、**簡単に一覧表**にできます。

補足として上記では`jq`コマンドで表示項目を絞ってますが、`aws cli`のqueryオプションを使っても同様のことができます。必要最低限の情報でよいのであれば、こちらのほうがおすすめです。

```terminal:queryパラメータを使ったワンライナー
$ aws lambda list-functions --query 'Functions[].[ FunctionName, Runtime, LastModified, Description ]' --region ap-northeast-1 --output table > lambda-list.txt
```

応用すればEC2などの棚卸し用の資料も簡単に作れるので、ぜひご活用ください:smiley:
Tweepyで出来ることをまとめていく

##自分のフォロワーをカウント


```python
#AUTHの説明は割愛
import time
import tweepy

auth = tweepy.OAuthHandler(
        consumer_key='xxxxxxx',
        consumer_secret='xxxxxxx')
auth.set_access_token(
        'xxxxxxx',
        'xxxxxxx')

api = tweepy.API(auth)


ids = []
for page in tweepy.Cursor(api.followers_ids, screen_name="アカウント名").pages():
    ids.extend(page)
    time.sleep(60)

print (len(ids))
```
SFTPで大きいファイルをダウンロードする (Perl/Ruby/Python)

| |URL|
|:--|:--|
|基本|https://qiita.com/cielavenir/items/9d068c49186060a47650|
|Pythonの.ssh/config読み出し|https://qiita.com/cielavenir/items/6aa9e6dc1166ae947c6f|
|大きいファイルの取得|https://qiita.com/cielavenir/items/f38223c156e4aaab58ad|

そこそこ大きい100MBほどの、リモートのテキストファイルを処理したいことはあると思います。
このような場合、逐次読み出しだと遅くなるので、一気に読み出してオンメモリで処理する必要があります。

## Perl

Perlはバッファまわりが賢いようなので`local $/`でも行けますし、string ioのようなことをしても良いです。

```pl
#!/usr/bin/perl
use strict;
use Net::SFTP::Foreign;
my $sftp = Net::SFTP::Foreign->new('host');
my $file_content;
if(0){
	open(my $fh,'>',\$file_content);
	$sftp->get('/foo/bar',$fh);
	$fh->close;
}else{
	my $fh = $sftp->open('/foo/bar',Net::SFTP::Foreign::Constants::SSH2_FXF_READ);
	$file_content = do { local $/; <$fh> };
	$fh->close;
}
print length($file_content);
$sftp->disconnect;
```

## Ruby

https://qiita.com/yohm/items/c469671d866ca32643f9 で触れられているように、sftp.download!は遅いです。後述するPythonと異なり、(バッファの設定とか調べましたが)SFTPの範囲ではどうしようもないようです。
身も蓋もないですが、`sftp.session.scp.download!`を使います。もちろん(Net::SSHのインスタンスをsshとしたとき)`ssh.scp.download!`でもOKです。

```rb
require 'net/sftp'
require 'net/scp'
Net::SFTP.start('host',nil){|sftp|
	io = StringIO.new
	sftp.session.scp.download!('/foo/bar',io)
	p io.string.size
}
```

## Python

Python2では以下のようにprefetchで良いようです。

```py
with sftp.file('/foo/bar','r') as f:
	f.prefetch()
	f.read()
```

ただ、Python3やPyPyではあまり高速になりませんでした。getfoを使えば良いようです。
Python2/3対応にするには以下のようなことをすれば良いです。

```py
if sys.version_info[0]>=3:
	from io import StringIO, BytesIO
	def getTextString(sftp, path):
		io=BytesIO()
		sftp.getfo(path,io)
		return io.getvalue().decode('utf-8')
	def getTextIO(sftp, path):
		return StringIO(getTextString(sftp, path))
else:
	from StringIO import StringIO
	def getTextString(sftp, path):
		return getTextIO(sftp, path).getvalue()
	def getTextIO(sftp, path):
		io=StringIO()
		sftp.getfo(path,io)
		io.seek(0)
		return io
```
Qiita記事作成　使えそうな文字色

HTMLタグで設定します。
個人的に使うかもしれない色だけ抜粋。
時短の為、マークダウンの強調も入れておく（大体色を付けた上で太字にしたいので）

---

- <font color="red">**赤**</font><br>`<font color="red">****</font>`
- <font color="blue">**青**</font><br>`<font color="blue">****</font>`
- <font color="green">**緑**</font><br>`<font color="green">****</font>`
- <font color="deepskyblue">**水色**</font><br>`<font color="deepskyblue">****</font>`
- <font color="purple">**紫**</font><br>`<font color="purple">****</font>`
- <font color="orange">**橙**</font><br>`<font color="orange">****</font>`

---
Django REST Frameworkの中身を少し調べた。（serializers.CharField）

# serializerでデータを更新できない!!

serializerを使ってデータを操作しようとしたところエラーになってしまい挙動がわからないことがあったので内部のコード眺めてみました。

## サンプルのシリアライザ定義

以下、例です（変数名とか雰囲気で読んでください）

```python:cat_serializers.py
class CatSerializer(serializers.ModelSerializer):
    name = serializers.CharField()
    birthday = serializers.DateField(
        format="%Y-%m-%d",
        required=False,
        input_formats=["%Y-%m-%d"])
    gendar_code = serializers.IntegerField(required=False)

    class Meta:
        model = Cats
        fields = (
            'name',
            'birthday',
            'gendar_code'
        )
```

## 実行コード

以下、事象発生させるコード。

```Python:sample
>>> serializer = CatSerializer(instance, data=params, partial=True)
>>> serializer.is_valid(raise_exception=True) # ここでエラー
>>> serializer.save()
```

詳しいエラー文言忘れてしまいましたが、`Invalid data. String not valid.`みたいなこと言われました。

## Django REST Frameworkの中を見てみる

「あー…はいはい」と適当に見当つけながらいくつか思いつく方法をためしたのですがだめでした。 
このままでは嵌りそうだったのでエラーになった項目のフィールドの処理を見ることにしました。

[GitHub](https://github.com/encode/django-rest-framework/blob/master/rest_framework/fields.py)でSerializerのFieldタイプごとの処理を確認。
CharFieldの項目でエラーになっていたので確認。
753行目移行がCharFieldの処理。その中に以下のような場所が

```python:fields.py(L795)
    def to_internal_value(self, data):
        # We're lenient with allowing basic numerics to be coerced into strings,
        # but other types should fail. Eg. unclear if booleans should represent as `true` or `True`,
        # and composites such as lists are likely user error.
        if isinstance(data, bool) or not isinstance(data, six.string_types + six.integer_types + (float,)):
            self.fail('invalid')
        value = six.text_type(data)
        return value.strip() if self.trim_whitespace else value

```

`isinstance`でdataのデータ型見てたみたいですね。
sixってなんだ?とも思った場合は[こちら](https://docs.djangoproject.com/ja/2.1/_modules/django/utils/six/)。DjangoのUtilityモジュールでした。

## 内部処理わかったところで原因を見つける

その上で改めて実行していたコードのdata(上記sampleでいうところのprams)を見てみました。
そうすると以下のような感じに。

```python:sample2
>>> print(dir(params))
{name: b'適当な文字列', birthday: '2019-03-06', gendar_code: 1}
```

「name（実際は違う変数だけど）がバイト列じゃん!こいつか!!」
ということで、このデータに対応するように修正したら動作しました。
onlineTool > Table Convert Online > 様々な形式からのimport, 様々な形式へのexport | UI > 項目の連続入力

### 関連

- [Markdown > Link > csvからの変換ツール](https://qiita.com/7of9/items/b2fa693ec8e88256144a#comment-b16c81d2a7bdcba95fdc)

上記の記事のコメントにて @Ayayoli さんにツールを紹介いただいた。

有用そうなツールではありますが、Qiitaではコメントでは検索できない（2019年3月現在）ため、かつ、タイトル検索を考慮して、別記事とします。

## Table Convert Online

https://tableconvert.com/

### Import

- Excel
- URL
- HTML
- Markdown
- CSV
- JSON (2019-05-09追記)

### Export (2019-05-09更新)

- Markdown
- IDEA
- CSV/TSV
- JSON
- XML
- YAML
- SQL
- HTML
- Excel
- LaTeX
- TEXT

### 感想 (2019-03-06)

まだ本格的に使っていない2019年3月6日の感想です。

- 対応形式が豊富でいいですね
- セルの操作が便利そうです
    - 行挿入
    - 行削除
    - 列挿入
    - 列削除
    - コピーペースト


### UI > 項目の連続入力 > Tabキーを使う (古い情報)
(追記: 2019-03-11)

下記の記載は「古い情報」です。

~~複数のセルに入力する場合は、<kbd>Tab</kbd>キーを使うようにすると連続入力が便利です。~~

~~1. セルに値を入力~~
~~2. Tabキーを押す~~
~~3. 次のセルに対して手順1から繰返す~~

### UI > 項目の連続入力
(追記: 2019-03-11)

複数のセルに入力する場合

1. セルに値を入力
2. 下カーソルキーか右カーソルキーで移動
3. 繰返す

使いやすくなりましたね。
Windows 10で therecipe/qt を使うまで

# 1. 前提条件
- https://github.com/therecipe/qt でGUIなアプリを作るための下準備をする。
- （Fast track版ではなく）Official版をインストールする。

## 1-1. PC環境
- Windows 10 Pro （バージョン1803）
- Intel Core i5-8250U @ 1.60GHz
- 8GBメモリ
- PowerShellを使っていますが、コマンドプロンプトでも同じ
- HTTP(S)のプロキシサーバーに接続する場合、環境変数 http_proxy, https_proxyを設定しておく。

# 2. Goのインストール
https://dl.google.com/go/go1.12.windows-amd64.msi
をダウンロード、インストール

- コントロールパネルの(システム)環境変数で、以下の設定を確認しておく。

| 変数     | 値                                   |
|----------|-------------------------------------|
| GOPATH   | C:\Users\\*your-name*\go            |
| PATH     | C:\Go\bin と C:\Users\\*your-name*\go\bin を追加  |
| GOCACHE  | on                                  | 
| GOROOT   | C:\Go\                              |

- Go 1.12 (Windows) では、 GOCACHE が on でないと何かとうまくいかないので注意。
- Go 1.13 (Windows) では、GOCACHE が C:\Users\\*your-name*\AppData\Local\go-build などとしておく。

# 3. Qtのインストール
https://download.qt.io/archive/qt/5.12/5.12.0/qt-opensource-windows-x86-5.12.0.exe.mirrorlist
より、5.12.0 版のオフラインインストーラーを入手、インストール。コンポーネントの選択はは以下の通り。Qt ChartsからQt Scriptまではお好みで。(※1)

![qtinstaller.PNG](https://qiita-image-store.s3.amazonaws.com/0/173885/1ad065e5-a7ea-7f51-8a81-f1d83a704a41.png)

- Qtのバージョンは、 https://github.com/therecipe/qt/wiki/Installation のバージョンに合わせておくのが無難

※1: お好みでと書いておきながら、ビルド時にいちいちLoadModuleできないぞと怒られる（使っていなければ実害はないが）ので、容量に余裕があればQt Charts から Qt Scriptまでを入れておくのが吉のようだ。

# 4. therecipe/qt のインストールとテスト実行
コマンド プロンプトで、

```bat
set GO111MODULE=off
go get -v github.com/therecipe/qt/cmd/... && for /f %v in ('go env GOPATH') do %v\bin\qtsetup test && %v\bin\qtsetup -test=false
```

を実行。インストールしていないモジュールについては、

```bat
time="2019-03-06T18:24:47+09:00" level=error msg="failed to load C:\\Qt\\Qt5.12.0\\Docs\\Qt-5.12.0\\qtscript\\qtscript.index" error="open C:\\Qt\\Qt5.12.0\\Docs\\Qt-5.12.0\\qtscript\\qtscript.index: The system cannot find the path specified."time="2019-03-06T18:24:47+09:00" level=warning msg=parser.LoadModule error=EOF module=Script
```

のようなエラーが出るが、気にしない。

環境によりますが、私の環境だと40分ほど待ったのちに、

![qtexample.PNG](https://qiita-image-store.s3.amazonaws.com/0/173885/6b067d43-f82e-ddc6-08c7-26124ed0a70f.png)

のような、7つのサンプルアプリのテストビルドが成功して完了する。ここまでくれば、とりあえず安心。

- Qt 5.13ではDeprecatedとなっているQt Scriptもインストールしておいかないと、テスト実行時にエラーとなる。うーむ…。

# 5. 最終確認
インストールがうまく行っている場合、以下のコマンドでビルドできる。

```bat
qtdeploy.exe build windows
```

--- 

# その他
- Windows 10 (1903) / Go 1.13.4 / Qt 5.13 MinGW 版（[スタンドアローンインストーラはこちら](https://download.qt.io/official_releases/qt/5.13/5.13.0/qt-opensource-windows-x86-5.13.0.exe)）の組み合わせでも確認。
- Qtをバージョンアップしたら、`C:\Qt\Qt5.13.0\Tools\mingw730_64` などにPATHを通しておかないとエラーになる。
- Go 1.12 にアップデートしたら、色々と動かなくなって焦ったので再インストールしてみた次第。ついでに、ハマリどころがあれこれあったのでメモ。
- コマンドがどこにあるか調べるのに、コマンドプロンプトでは `where` だが、 PowerShell だと `Get-Command`（または`gcm`）なのでややこしい。
- インストールがはじまって、qt/sql のところで10分くらい待たされた。qt/purchasingも少し待つ。気長に待つべし。
- `qtdeploy` するときに、3 でインストールしなかったモジュールについてはエラーが出る。
- ビルドするときにはsysoファイルのアーキテクチャも揃えておかないといけない。Qtと同時インストールしたMinGWに含まれる`windres.exe`で生成できる。このツールは`C:\Qt\Qt5.12.0\Tools\mingw730_64\bin`にあるのでパスを通しておくと良い。 使い方は、https://qiita.com/zetamatta/items/dd63a2ff4d01fdb6709a に詳しい。
Mockeryのパーシャルモックが便利

# 概要

モックを使わなくてもテストができればそれに越したことはありません。
最近のMVCフレームワークはユニットテストを考慮された作りになっていることが多いので、あまり苦労することはないかもしれませんが、筆者の環境ではフレームワークのコアの処理や、コアの処理に誰かが加えた変更がユニットテストの実行を阻害するケースがあったので、Mockeryというモッキングフレームワークが役に立ちました。
今回はパーシャルモックという機能について、共有と備忘録の目的で投稿します。


**環境**

 - PHP 5.3
 - Zend Framework 1.11
 - PHPUnit 3.7
 - mockery 0.9.8

**インストール**

```
composer require mockery/mockery --dev
```

# 基本的な使い方

実際にこういった使い方はあまりしないと思いますが、基本的には以下のようにモックを作成することができます。

```php
class CampaignControllerTest extends PHPUnit_Framework_TestCase
{
  public function test_indexAction()
  {
    // モックを作成
    $fakeItemModel = \Mockery::mock('ItemModel');
    // ItemModel が array('id' => 1) を返すように
    $fakeItemModel->shouldReceive('get')
                  ->andReturn(array('id' => 1));

    var_dump($fakeItemModel->get()); // array('id' => 1)
  }
}
```

# パーシャルモック

例えば、あるメソッドがAPI通信をしている場合など、テスト対象のクラスの一部のメソッドだけ、テスト時には実行したくないという場合があります。
そういった場合にはパーシャルモックを使うと便利です。

**テスト対象クラス**

```php
class CampaignController extends Controller
{
  public function getItem() {
    // ItemModelはAPI通信をしているとする
    $mode = new ItemModel();
    return $model->get();
  }

  public function indexAction() {
    $item = $this->getItem();
    // ここから下をテストしたい
    if (is_null($item['id'])) {
      echo 'error page!';
    }
    ...
  }
}
```

**テストコード**

```php
class CampaignControllerTest extends PHPUnit_Framework_TestCase
{
  public function test_indexAction()
  {
    $mock = \Mockery::mock('CampaignController')->makePartial();
    $mock->shouldReceive('getItem')
         ->andReturn(array('id' => null));

    $mock->indexAction(); // 'error page!'
  }
}
```

一見するとテストが難しいケースも、こういったライブラリの助けを得ることでテストが可能になります。
ユニットテストを有効活用して、保守性の高いコードを目指したいと思います。
みなさんもぜひチャレンジしてみてください。
MacでVPN(L2TP over IPSec)が繋がらない時に疑うこと

# 設定方法は正しい？

- システム環境設定 > ネットワーク > 左下の「＋」ボタン > VPN
- サーバアドレス、アカウント名

VPNサーバ次第で下記も確認

- 認証設定（ユーザ認証:パスワード+コンピュータ認証:共有シークレット、など）
- `/etc/ppp/ip-up`の権限(chmod/chown)やスクリプト（ルーティングなどしてるはず）に問題ないか？
  - rootユーザーで実行されるが、OSXのバージョンによってはPATHが足りないため、自分は`PATH=$PATH:/usr/sbin:/sbin`などを付けてる

# 接続してログ確認

```sh:/var/log/ppp.log
Wed Mar  6 16:05:06 2019 : publish_entry SCDSet() failed: Success!
Wed Mar  6 16:05:06 2019 : publish_entry SCDSet() failed: Success!
Wed Mar  6 16:05:06 2019 : l2tp_get_router_address
Wed Mar  6 16:05:06 2019 : l2tp_get_router_address <あなたのルーターのアドレス> from dict 1
Wed Mar  6 16:05:06 2019 : L2TP connecting to server '<サーバアドレス>'
Wed Mar  6 16:05:06 2019 : IPSec connection started
Wed Mar  6 16:05:07 2019 : IPSec phase 1 client started
Wed Mar  6 16:05:17 2019 : IPSec connection failed
```

- 上記の場合ユーザ認証までいっておらず、ルータとサーバ間の接続に問題があることがわかる
  - 成功時は下記の流れ
  - `IPSec connection established`
  - `L2TP connection established`
  - `Connect: ppp <--> socket`
    - この辺りで`/etc/ppp/ip-up`などが発火
  - 共通鍵認証/ユーザ認証など

# ルータの設定を確認

- 例えばテザリング経由の4G回線でVPN接続が成功するなら、無線ルータなどに問題がある可能性大
- ルーターの設定画面にアクセス
  - システム環境設定 > ネットワーク > Wi-Fi > 詳細 > TCP/IP からルーターのアドレスをブラウザで開けば、大手のルーターなら設定画面が開くはず
- ルーターの設定を直す
  - 各社のサイトなどをググる
  - 自分がIO-DATAのルーターでハマった時は、セキュリティ設定で「IPSecパススルー」が無効で、これを有効にしたら解決した
  - https://www.iodata.jp/support/qanda/answer/s18113.htm
  - （デフォルトで無効なのハマるよ......）
IBMi Node.js Ver10導入備忘録

以前[IBMi node.jsのNative Addonモジュールをビルドする環境を構築してみた（Node Ver8編）](https://qiita.com/yamurata/items/befe28489cccdf0c4339)を書きましたが、Nodo.js Version10.5を導入して少しはまりましたので備忘録として残しておきます。

### 1)おもむろにコマンドを打ったのが失敗のもと

```
yum install nodejs10.ppc64
```
インストール自体は上手く行きます。
nodeのバージョンを変えるため

```
nodever 10
```
を実行すると、

```
Could not load program node:
rtld: 0712-001 Symbol _ZNSt15_Sp_counted_ptrIDnLN9__gnu_cxx12_Lock_policyE2EE10_M_disposeEv was referenced
      from module node(), but a runtime definition of the symbol was not found.
rtld: 0712-001 Symbol _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_destroyEv was referenced
      from module node(), but a runtime definition of the symbol was not found.
rtld: 0712-001 Symbol _ZNSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE10_M_releaseEv was referenced
      from module node(), but a runtime definition of the symbol was not found.
rtld: 0712-002 fatal error: exiting.
```
とか出力され、バージョンが変わりません。
それどころか、今まで動いていたNode Version8も動かなくなってしまいました・・・。

### 2)とりあえず復旧します。
結論から言えば、動いていた時と同じバージョン（8.10.0）を再導入すれば復旧します。

```
yum remove nodever.noarch
yum --showduplicates search node
yum install nodejs8-8.10.0-0.ppc64
```
nodeverをアンインストールすると、node.jsもアンインストールされます。
オプションに --howduplicatesをつけると、公開されているバージョン全てが表示されるので、
後はバージョン指定で再導入します。

### 3)まずnode.js ver8をアップデートします。
依存関係にあるパッケージが古いのが原因？
また、いきなりVer10を導入するのでは無くnode ver8をアップデートして稼働するか確認することにしました。

```
yum info libgcc-aix
yum info libstdcplusplus6
yum info nodever
yum info nodejs8.ppc64

yum update libgcc-aix
yum update libstdcplusplus6
yum update nodever
yum update nodejs8.ppc64
```
infoでAvailable Packagesの表示があれば、新しいバージョンが出ています。
私の環境では、全て新しいバージョンが出ていたので、updateでそれぞれ最新化しました。

この状態で

```
node -v
 v8.15.0
```
と返ってきました。

### 4)node10を導入します。
```
yum install nodejs10.ppc64
nodever 10
node -v
 v10.15.0
```
無事、動きました・・・。

（現在、本番環境で元気に動いております。）
リバースプロキシサーバとして使ってるNginxでBasic認証をかける(サブドメイン対応)

VPSを借りてWEBサービスを個人開発しているが、開発用のサブドメインを用意したりするときに、Basic認証を掛けたいと思ったのでその時のメモ。

今回はASP.NET Coreで作ったアプリに対するリバースプロキシとしてNginxを使っている。

OSはUbuntuの16.04か18.04（忘れた）

## htpasswdインストール

```bash
sudo apt-get install apache2-utils
```



## htpasswdファイルの作成

```bash	
# 認証に使うユーザ名とパスワードを入力する
sudo htpasswd -c /etc/nginx/.htpasswd {username}
 ->New password: {password}
 ->Re-type new password: {password}
```



## nginx設定ファイルに追記

```nginx

server{
    server_name    example.com;

    #（略）

    location / {
        auth_basic "認証時のメッセージ";
        auth_basic_user_file /etc/nginx/.htpasswd; # .htpasswdファイルのパス
        proxy_pass    http://localhost:25000/; #リバースプロキシの先
    }

}

#こちらはサブドメインとしてsub.example.comにも認証をかけたい場合の設定
server{
    server_name    sub.example.com;

    # (略)

    location / {
        auth_basic "認証時のメッセージ";
        auth_basic_user_file /etc/nginx/.htpasswd; # .htpasswdファイルのパス
        proxy_pass    http://localhost:15000/;
    }

}

```

## nginx再起動

```bash
 sudo systemctl restart nginx
```

これでサブドメインごとにbasic認証をかけたりかけなかったりできるので、個人開発等で開発用のサブドメインに認証かけたい時とか便利
Vue.jsのコンポーネント間のシンプルな通信

#概要
Vue.jsのコンポーネント間での通信をまとめました。初心者向けです。
Vuexを使用しない方法と、使用した方法のサンプルを元に説明します。

##Vue.jsのみ

<p class="codepen" data-height="400" data-theme-id="0" data-default-tab="js,result" data-user="ymnk" data-slug-hash="KEaPwz" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="Vue.js Simple Components Communication">
  <span>See the Pen <a href="https://codepen.io/ymnk/pen/KEaPwz/">
  Vue.js Simple Components Communication</a> by T_Y (<a href="https://codepen.io/ymnk">@ymnk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

###説明
親コンポーネントと子コンポーネントとで相互に通信しているサンプルです。
本やブログには、親から子は`props`、子から親は`event`と書いてあることが多いです。
ですが、それだけでは不十分だと感じたので、少し丁寧に説明してみます。

###親から子へ値を渡す
親コンポーネントのボタンを押すと子コンポーネントの値が増える。

1. 子コンポーネント：受け取る値を`props`で設定する。
2. 親コンポーネント：子コンポーネントに渡す値を`data`で設定する。
3. 子コンポーネントのタグ：`v-bindディレクティブ`を設定して1と2を紐づける。


###親から子のメソッドを実行する
親コンポーネントのボタンを押すと、子コンポーネントのデザインが切り替わる。

1. 子コンポーネント：親コンポーネントから実行するメソッドを設定する。
2. 子コンポーネントのタグ：`ref`を設定する。
3. 親コンポーネント：`$refs`を使い、子コンポーネントのメソッドを実行する。


###子から親のメソッドを実行する
子コンポーネントのボタンを押すと、親コンポーネントの値が増える。

1. 親コンポーネント：子コンポーネントから呼び出すメソッドを設定する。
2. 子コンポーネントのタグ：`v-onディレクティブ`を設定し、子コンポーネントから1を実行できるようにする。
3. 子コンポーネント：`$emit`を使って2を実行する。



##Vue.js + Vuex

<p class="codepen" data-height="400" data-theme-id="0" data-default-tab="js,result" data-user="ymnk" data-slug-hash="drNvzz" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="Vue.js  Components Communication With Vuex">
  <span>See the Pen <a href="https://codepen.io/ymnk/pen/drNvzz/">
  Vue.js  Components Communication With Vuex</a> by T_Y (<a href="https://codepen.io/ymnk">@ymnk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

###説明
Vuexは複雑なアプリケーションの状態管理をするためのライブラリです。適切なデータフローを設計するために使います。
値を`store`で一括管理することで、どのコンポーネントからでも使用できるようになります。
サンプルでは、親コンポーネントのボタンから`store`を更新し、子コンポーネントで値を表示しています。

####Storeの説明
|名前|役割|呼び出し方|
|:-----------------|:------------------|:------------------|
|state|値の一覧|store.state.名前|
|getters|値の取得|store.getters('名前')|
|mutations|値の設定|store.comit('名前', 値)|
|actions|値の計算と設定|store.dispatch('名前')|

####注意事項
- 単一コンポーネント使った場合、呼び出しは`store`でなく`this.$store`と書く。
- `state`は`store.state`で直接呼ばず、`getters`に統一するようルール化するとよい。
Ubuntuにtmuxを入れた話

#はじめに
Ubuntuにtmuxをインストールしたので、その際に学んだことを忘備録としてまとめます。
初学者のため、間違いや勘違いがあるかもしれません。
その際はご指摘いただければ修正いたします。

#tmuxとは・・・
端末多重化ソフトです。
UNIX系、LINUX系のOS（自分はUbuntuを使用）が使いやすくなるソフトというイメージで使用しています。
##tmuxを使用するメリット
・1つの**ターミナル**内を分割して使用できる（Windowをpaneに分割できる）
・**セッション**（tmuxが管理するWindow全体を指す）の**デタッチ**（切断）と**アタッチ**（接続）が可能
この他にも多数のメリットがある。[Wikipedia](https://ja.wikipedia.org/w/index.php?title=Tmux&action=edit&section=1)参照

#tmuxの操作方法
コマンドで操作する方法とキーボードで操作する方法がある。
キーボード操作にはPrefixキーを使用する。
Prefixキーのデフォルトは「ctrl+b」
##基本操作
####セッションの作成
```
$ tmux new -s 名前
```
####デタッチ
`prefix`+`d`
####アタッチ
```
$ tmux a -t セッション名 
```
####名前変更
`prefix`+　`$`
####現在のセッション名とWindow数を表示
```
$ tmux ls
```
####セッションの削除
```
$ tmux kill-session -t セッション名
```
####全て終了
```
$ tmux kill-server
```
####コマンドをすべて確認
`prefix`+`?`
ちなみに`esc`を押すと抜けることができる
##ウィンド操作
####ウィンドの切り替え
`prefix`+`ウィンドの下のバーに表示されている数字`
####ウィンドに名前を付ける
`prefix`+`,`
####ウィンドをリスト表示
`prefix`+`w`
####ウィンドの削除
`prefix`+`&`

##ペインの作成
####水平分割
`prefix`+`“`
####縦に分割
`prefix`+`%`
####切り替え
`prefix`+`O`
もしくは
`prefix`+`矢印キー`
####ペインの切り替え
######前
`prefix`+`{`
######次
`prefix`+`}`
####ペインをウィンドとして独立
`prefix`+`!`

##設定ファイルの作成
.tmux.confを作成し、その中に設定を記入することで、ショートカットキーの作成や設定ができる
####ホームディレクトリに.tmux.confをひらく
```
$ vi ~/.tmux.conf
```
####保存して終了
`esc`キーを押したのち

```
:wq
```
保存せずに終了
`escキーを押したのち

```
:　q!
```
####tmuxに反映
```
$ tmux source-file ~/.tmux.conf
```
Vim/viの操作について、詳しくは[こちら](http://www.webhtm.net/vim/preserve.htm)

#まとめ
まだ、tmuxを使いこなせていませんが徐々に慣れていきたいと思います。
後にBufferやSSHについてもまとめたいと思います。
サイドになりますが、初学者の為、間違いや修正があればご指摘いただけると幸いです。
よろしくお願いいたします。
CentOS 7 に WordPress 5.8 をインストール

CentOS 7 にLAMP(Linux/Apache/MariaDB/PHP)環境のインストールを行う手順を以下に記します。


# タイムゾーンの変更

```
sudo su - 
timedatectl set-timezone Asia/Tokyo
```

# Apache のインストール

```
yum -y install httpd
systemctl enable httpd
systemctl start httpd
```

webブラウザで CentOS 7 サーバのIPアドレスにアクセスして Apache のテストページが表示されるか確認します。

<img width="1189" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122952/c1c8b6e6-9fe2-6df9-00c5-fa37941b7580.png">



# PHP のインストール

```
yum -y install epel-release
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum -y install --enablerepo=remi,remi-php74 php php-devel php-mbstring php-pdo php-gd php-mysqlnd
systemctl restart httpd
```

# MariaDB 5.5 のインストール

```
yum -y install mariadb-server mariadb-client
systemctl enable mariadb
systemctl start mariadb
```

2020-07-24 時点では MariaDB 5.5.65 がインストールされました。

```
[root@centos7 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 5.5.65-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>
```

# WordPress のインストール

## WordPress 5.x ダウンロード/展開

最新版 WordPress 5.x をダウンロード、DocumentRoot 配下に展開します。

```
yum -y install wget
cd /var/www/html
wget https://ja.wordpress.org/latest-ja.tar.gz
tar xvf latest-ja.tar.gz
chown -R apache:apache .
```

## WordPress 用データベース作成

文字コードUTF8でデータベース wordpress を作成します。

```sql
[root@centos7 html]# mysql

MariaDB [(none)]> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;
Query OK, 1 row affected (0.00 sec)
```

## WordPress 用 MariaDB ユーザの作成

さきほど作成したデータベースのみ全権限を持つ wordpress ユーザを作成します(ユーザ名/パスワードは適宜変更してください)。

```
GRANT ALL ON wordpress.* TO wordpress@localhost IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
```

## WordPress 初期設定

webブラウザで xx.xx.xx.xx/wordpress にアクセスし、WordPressの初期設定を行います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122952/e2a57068-9ca9-de5a-9db6-273de5a97770.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/122952/f44caded-dc3b-7ee1-199f-b4fab2d5ba9e.png)

正常にインストールが完了すると、指定したユーザ、パスワードでダッシュボードにログインできます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122952/65d2dab7-7c3b-f5df-1b96-401c290d5e53.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/122952/a47cb122-2d9c-c695-b79c-7f07620a4728.png)
Python asyncio


[Tasks and coroutines](https://docs.python.org/3.6/library/asyncio-task.html) のメモです。
Python で websockets を扱おうとしたらなぜか asyncio という物が必要になったので調べている。

## Coroutine

コルーチンとは、javascript の async await のように、シングルスレッドで並行処理を行う物。

早速コルーチンを使ったカウンタを書いてみる。コルーチンを定義するには `def` の代わりに `async def` と書く。コルーチン関数を呼ぶと、コルーチン関数の内容はすぐ実行されず、コルーチンオブジェクトが返る。コルーチン関数の内容を実行するには、await を使って他のコルーチンから呼ぶか、イベントループに渡す必要がある。

```python
import asyncio

# 1 から max までの数を数えるカウンターのコルーチン版
async def counter_coroutine(max):
    count = 0
    while count < max:
        count += 1
        print(count)
        await asyncio.sleep(1) # asyncio.sleep は coroutine。await で完了を待つ。
    return '数え終わりました'

counter = counter_coroutine(3) # コルーチン関数の返り値はコルーチンオブジェクト
print(f'counter is {counter}')
loop = asyncio.get_event_loop()
result = loop.run_until_complete(counter) # コルーチン関数の return で返した物は loop.run_until_complete の返り値になる。
print(result)
loop.close()
```

実行結果

```shell
counter is <coroutine object counter_coroutine at 0x1032f78e0>
1
2
3
数え終わりました
```

## Future

コルーチンは上のように run_until_complete() に直接渡しても実行出来るが、実は run_until_complete() の内部的ではコルーチンから future を作って実行しているらしい。future を直接使えば多少冗長だがこのようになる。

```python
import asyncio

# 1 から max までの数を数えて Future で結果を返す
async def counter_coroutine(max, future):
    count = 0
    while count < max:
        count += 1
        print(count)
        await asyncio.sleep(1) # asyncio.sleep は coroutine。await で完了を待つ。
    future.set_result('数え終わりました')

future = asyncio.Future() # future というのは非同期処理の結果を受け取る入れ物。
counter = counter_coroutine(3, future)

loop = asyncio.get_event_loop()
task = asyncio.ensure_future(counter) # counter の実行を登録して task 生成(ここでは使わない)
print(f'task is {task}')

loop.run_until_complete(future)
print(future.result()) # set_result() の内容を result() で取り出せる。
loop.close()
```

実行結果

```shell
task is <Task pending coro=<counter_coroutine() running at future.py:4>>
1
2
3
数え終わりました
```

## Task

上の例では、ensure_future によって counter の実行を登録した task という物を作りました。task はいわばスレッドのような物らしいです。task を何に使うかと言うと、このドキュメントを見た限り良くわかりませんでした。

## 複数の coroutine を並行に実行

asyncio.gather() を使うと、複数のコルーチンを並行に動かす事が出来る。

```python
import asyncio

# 1 から max までの数をコルーチンで数える。名前付き。
async def counter_coroutine(name, max):
    count = 0
    while count < max:
        count += 1
        print(f'{name}: {count}')
        await asyncio.sleep(1) # asyncio.sleep は coroutine。await で完了を待つ。
    return f'{name} 数え終わりました'

# カウンターを3つ同時にスケジュール。
counters = asyncio.gather(
    counter_coroutine('A', 1),
    counter_coroutine('B', 2),
    counter_coroutine('C', 3),
)
print(f'counters is {counters}') # asynio.gather の返り値は future

loop = asyncio.get_event_loop()
result = loop.run_until_complete(counters) # コルーチン関数の return で返した物は loop.run_until_complete の返り値になる。
print(result)
loop.close()
```

実行結果

```shell
counters is <_GatheringFuture pending>
C: 1
B: 1
A: 1
C: 2
B: 2
C: 3
['A 数え終わりました', 'B 数え終わりました', 'C 数え終わりました']
```

## 良くわからない事。

asyncio.ensure_future も asyncio.gather も同じようにコルーチンを受け取って実行を登録する関数だが、asyncio.ensure_future の返り値が task で asyncio.gather が future なのが謎。あと、全体的に複雑過ぎるような気がする。
Dark Readerを利用してWebサイトをとことんダークモードにする

macOS Mojaveからダークモードが搭載され、標準アプリや対応アプリが増えて、だいぶといい感じになってきたのですが、それ故にすべてをダークモードで揃えたくなる衝動が抑えられなくなってきたので、衝動を抑えずにやってみました。

<img width="1224" alt="スクリーンショット 2019-03-05 15.24.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/0b5e631e-44a1-0cc1-c61e-e381568d3743.png">

## Dark Reader最高

以前にGIGAZINEさんで紹介されていたDark Readerを利用してWebサイトをダークモードにしてみました。Google Chrome、Firefox、Safariに対応していますが、SafariはMac App Storeで有償($4.99)となっています。(2019/03/05時点)


Chrome・Firefox・Safariを簡単に「ダークモード」にできる拡張機能「Dark Reader」を使ってみた - GIGAZINE
https://gigazine.net/news/20181205-dark-reader/

Dark Reader
https://darkreader.org/

Dark Reader - Chrome ウェブストア
https://chrome.google.com/webstore/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieeh?hl=ja
>すべてのウェブサイトにダークテーマを適用します。夜間や毎日のブラウジングにDark Readerを使用し、あなたの目を気遣います。
このアイ・ケアの拡張機能は、オンザフライでウェブサイトのためのダークテーマを作成し、ナイトモードを有効にします。 Dark Readerは鮮やかな色を反転させてコントラストを高め、夜間に読みやすくします。

目を気遣うとか、バッテリーの持ちが、とかそんなのはどうでも良いのです。見た目をダークモードで揃えたいのです。

詳しい利用方法はGIGAZINEさんの記事をご参考ください。

Qiitaのホームです。いい感じですねー。<img width="1238" alt="スクリーンショット 2019-03-05 15.20.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/378ecf8c-69b2-d4b1-5b0b-028dcfde3a3e.png">


これまでにも、Webサイトをダークモードにする拡張機能はありましたが、画像の色彩まで反転されてしまって敬遠してたのですが、Dark Readerは画像はそのままにしてくれます。サイト毎に設定を変更することができ、フィルタ設定で細かな調整もできます。
<img width="270" alt="スクリーンショット 2019-03-05 15.22.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/2cf369b7-6618-6366-7b77-f633ff9039ce.png">

フィルタ設定を弄らずとも拡張機能のメニュー「その他」にあるテーマエンジンの指定でだいたいのWebサイトで適切な設定をみつけることができます。
<img width="269" alt="スクリーンショット 2019-03-05 15.23.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/937385c2-527e-6453-630b-ae80b55aaab6.png">

- テーマエンジン: フィルタ
<img width="1224" alt="スクリーンショット 2019-03-05 15.24.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/0b5e631e-44a1-0cc1-c61e-e381568d3743.png">
- テーマエンジン: フィルタ＋
<img width="1227" alt="スクリーンショット 2019-03-05 15.24.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/59da46fd-dde0-16e9-c826-00c47f34536e.png">
- テーマエンジン: 静的
<img width="1236" alt="スクリーンショット 2019-03-05 15.24.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/ad01c45a-99ed-8c03-c5d4-49601d21e1a5.png">
- テーマエンジン: 動的
<img width="1239" alt="スクリーンショット 2019-03-05 15.34.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/48549/06147130-bf84-0c79-a512-bf9bf3deee29.png">

しばらく利用していますが、ブラウザが極端に重くなったりすることはなく今のところは快適に利用できています。


## 参考

Chrome・Firefox・Safariを簡単に「ダークモード」にできる拡張機能「Dark Reader」を使ってみた - GIGAZINE
https://gigazine.net/news/20181205-dark-reader/

Dark Reader
https://darkreader.org/

Dark Reader - Chrome ウェブストア
https://chrome.google.com/webstore/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieeh?hl=ja