OmniAICreator/Qiita-1.07M huggingface dataset:
【Error】本番環境でアプリが表示されない

# 概要
手順通り、デプロイ作業を行なったのに、本番環境で表示されない:sob:
という事象に陥って1時間近く試行錯誤した結果、単純な回答だったため自分の戒めのため備忘録として残します:bow_tone1:

# 事象
ブラウザで **http://＜サーバに紐付けたElastic IP＞:3000/**を入力しても表示されない:sob:
<img width="436" alt="スクリーンショット 2020-06-04 16.08.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634091/1bd9f62e-f8ef-ffc7-9038-406250740473.png">

何かの間違い？？と思い、リロードしてもロードが続いた結果、変わらず。。

# 検証
##①ターミナル（ECサーバ）でエラーを確認

```terminal:リポジトリ名(ECサーバ)
$ less log/unicorn.stderr.log
```
上記コマンドを入力した結果表示されたのが以下のエラーです
<img width="1319" alt="スクリーンショット 2020-06-04 16.14.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634091/1a649c0d-2f33-edaa-8303-76c3ff85a5ce.png">

確認すべきは、3行目の**(Mysql2::Error::ConnectionError)**です。
Mysqlは起動してるってこと？？

##②Mysqlの状態を確認

```terminal:リポジトリ名(ECサーバ)
$ sudo service mysqld status

#コマンド入力後、下記の表示されたら起動中
mysqld (pid  8621) is running...

```
よし！問題なし。。ではなぜ？？

##③AWSでポートの確認
<img width="1421" alt="スクリーンショット 2020-06-04 16.28.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634091/36886347-f288-cf20-4824-3f225ee480b3.png">


ポート範囲の入力漏れ:tired_face:

# 原因
AWSにあるセキュリティグループのポート設定時に入力漏れがありました。
インバウンドルール追加時に下記の内容を入力する必要があります。

**【タイプ】**カスタムTCPルール
**【プロトコル】**TCP
**【ポート範囲】**３０００　　←私、忘れました:expressionless:
**【ソース】**カスタム　0.0.0.0/0

無事、ブラウザに画面が表示されました:sparkles:
※最初はCSSが反映されていないため、ビュー崩れが起こっていると思います！

# 参考
本番環境デプロイ時のコマンド集
https://qiita.com/15grmr/items/7ad36caa82a0fa27c4bd

デプロイ時に対峙したエラーとその対応
https://qiita.com/sho012b/items/54fcd932ff8c76cdcd05
個人開発時に作業が捗るショートカットキー8選（完全に個人的な主観）

***
個人開発を進めていて、役立つなと思ったショートカットをまとめてみました。

***
###①スーパーリロード
####command + R(Chrome,Safari,Opera)
####command + Shift + R (Firefox)

リロードしたいときのショートカットです。
変更をして、動作確認などをブラウザで確認したいときに役立ちます。

***

###③現在のタブを閉じる

####command + W

ググって調べ物をした際に、必要なくなったらこのショートカットで現在のタブを閉じることができます。

***
###③キャッシュのクリア

####control + Shift + Delete

キャッシュクリアを1秒で出来るめちゃくちゃ便利。動作が一気に軽くなる。
神。

***

###④アプリケーションの終了

####command + Q

タブが溜まりすぎて、いちいち一つ一つ消すのがめんどくさい場合に有効です。
このショートカットを押すだけで、アプリケーションが終了するので全消しできます。
（保存していないものについては注意が必要ですが..）

***

###⑤シークレットウィンドウを開く
####command + Shift + N

新しくウィンドウを開くのは、**command + N**ですが、自身はこちらを使っています。
というのも、Googleの拡張機能などを無効にしてくれるので、フラットな状態で動作確認ができます。

***

###⑥範囲を指定して、スクリーンショット

####command + Shift + 4

自身が、必要なところだけスクリーンショットが取れるので、メモに何か残したい時に多用しています。
ちなみに
**画面全体のスクリーンショット**
command + Shift + 3
**動画撮影**
command + Shift + ５

***

###⑦カーソルを行頭/行末に持ってくる

####control + A(行頭)
####control + E(行末)

この二つは、エディタとターミナルでよく使っています。
移動にイライラしなくなります。

***

###⑧直前の操作のやり直し
####command + Z

エディタで、間違えてコードを消してしまった時に、このショートカットで死者蘇生してますね。
携帯だと死者蘇生できないので、改めてこのショートカットのありがたみを感じます。



***

終わり。おすすめのショートカットあったら教えてください。。。
VM Import/Export

#VM Import/Export
> VM Import/Export を使用すると、仮想マシン (VM) イメージを既存の仮想化環境から Amazon EC2 にインポートし、それを元の環境にエクスポートすることができます。この方法を使うと、アプリケーションおよびワークロードを Amazon EC2 へ移行したり、VM イメージカタログを Amazon EC2 にコピーしたり、バックアップと災害対策のために VM イメージのリポジトリを作成することができます。

ほとんどの VM Import ニーズには、AWS Server Migration Service の使用をお勧めします。AWS SMS はインポートプロセスを自動化し (大きな VM インフラストラクチャの移行ワークロードを軽減)、変化する VM の増分更新のサポートを追加して、インポートされた VM をすぐに使用できる Amazon マシンイメージ (AMI) に変換します。

##VM Import/Export の機能
> 仮想化環境から Amazon EC2 に VM を Amazon Machine Image (AMI) としてインポートする機能。AMI から EC2 インスタンスをいつでも起動できます。

仮想化環境から Amazon EC2 に VM を EC2 インスタンスとしてインポートする機能。インスタンスの最初の状態は stopped です。インスタンスから AMI を作成できます。

仮想化環境から以前にインポートした VM をエクスポートする機能。

ディスクを Amazon EBS スナップショットとしてインポートする機能。

VM Import は Linux 用 ENA ドライバをサポートしています。ENA のサポートは、元の VM に ENA ドライバまたは NVMe ドライバ、あるいはその両方がインストールされている場合にのみ有効になります。最新のドライバをインストールすることをお勧めします。

##VM Import/Export の使用を開始する方法
> 最初に、VM を AMI としてインポートするか、またはインスタンスとしてインポートするかを決定する必要があります。

##VM Import/Export の仕組み
> Amazon EC2 で VM を使用するには、最初に仮想化環境からエクスポートしてから、Amazon Machine Image (AMI) またはインスタンスとして、Amazon EC2 にインポートする必要があります。

##イメージのインポートとインスタンスのインポートの違い
<img width="816" alt="スクリーンショット 2020-06-04 16.16.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/efb63bac-ef5e-7218-c14e-85708fa94169.png">

##イメージのインポート
> まず、エクスポート用に仮想マシンを準備して、サポートされているイメージ形式の 1 つを使用してエクスポートします。次に、VM イメージを Amazon S3 にアップロードし、イメージのインポートタスクを開始します。インポートタスクが完了したら、AMI からインスタンスを起動することができます。他のリージョンに AMI をコピーすると、それらのリージョンでインスタンスを起動できます。

<img width="703" alt="スクリーンショット 2020-06-04 16.17.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/18e09f1a-a6e8-405d-5351-d2084b92cbe5.png">

##インスタンスのインポート
> まず、エクスポート用に仮想マシンを準備して、サポートされているイメージ形式の 1 つを使用してエクスポートします。次に、VM イメージを Amazon S3 にアップロードし、インスタンスのインポートタスクを開始します。インポートタスクが完了したら、停止したインスタンスから AMI を作成できます。他のリージョンに AMI をコピーすると、それらのリージョンでインスタンスを起動できます。以前インポートしたインスタンスを仮想化環境にエクスポートすることもできます。

<img width="768" alt="スクリーンショット 2020-06-04 16.18.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321923/4066d3c4-76a4-a52b-e4cf-eba778a6b0ec.png">

##VM Import/Export を使用して VM としてインスタンスをエクスポート
> VM としてのエクスポートは、Amazon EC2 インスタンスのコピーをオンサイト仮想化環境にデプロイする場合に便利です。ほとんどの EC2 インスタンスは、Citrix Xen、Microsoft Hyper-V、および VMware vSphere にエクスポートできます。

##Amazon Machine Image (AMI) から VM を直接エクスポートする
> Amazon Machine Image (AMI) に基づく VM ファイルのエクスポートは、標準化された新しいインスタンスをオンサイトの仮想化環境にデプロイする場合に役立ちます。通常 AMI は、Citrix Xen、Microsoft Hyper-V、および VMware vSphere にエクスポートできます。
Zabbix Agent-active ログ監視permission設定

LinuxのOSログといえば/var/log/messagesとなるが、このログファイルはroot権限がないと読み込みができないログファイルとなっている。

```
# ls -l /var/log/messages
```

```
-rw------- 1 root root 134324  3月 16 12:50 /var/log/messages
```

通常、Zabbix Agentのプロセスはzabbixユーザーの権限で動作するため、このログファイルが監視できず困る場面がある。回避策としては、Zabbix Agentをroot権限で動作させるようにすることが考えられる。Zabbix Agentをroot権限で動作させるためには、zabbix_agentd.confに以下の設定を加えればよい。

```
# vi /etc/zabbix/zabbix_agentd.conf
```

```
### Option: AllowRoot
AllowRoot=1 **=0から変更　
```
しかし、上記方法は、Zabbix Agentがroot権限で動くことになり、セキュリティ面で推奨されない設定となる。そこで、今回はAllowRoot=1せずにログ監視できる方法を考えてみた。

#SELinuxをどうしても利用したくない場合

どうしてもSELinuxを有効にしたくないのであれば、ファイルのパーミッションでzabbixユーザでも読めるようにすることでsyslogのファイルを監視できるようになります。

デフォルトの設定のファイルのパーミッションを確認する

```
# ls -l /var/log/messages

-rw------- 1 root root 223408  6月  4 15:10 /var/log/messages

```
このファイルのオーナーとパーミッションを以下のように変更します。

```
# chown root:zabbix /var/log/messages
```

```
# chmod 640 /var/log/messages
```
再度確認してみます。

```
# ls -l /var/log/messages
```

```
-rw-r----- 1 root zabbix 285204  6月  4 16:00 /var/log/messages
```
これで、Zabbixエージェントから/var/log/messagesにアクセスできるようになります。

logrotateの設定も忘れずに。

設定しておかないと、ログファイルのローテーション時に、ログファイルのオーナーとパーミッションをデフォルトの状態に戻されてしまいます。

logrotateの設定

```:/etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    missingok
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
    create 0640 root zabbix ---追記する
}
```
「create 0640 root zabbix」を追加しておくことで、ログローテーションを実行する際、新しいファイルのパーミッションとオーナーを明示的に指定しておくわけです。
高位合成言語Polyphony (windowsでiverilog その12）


#概要

windowsでiverilogやってみた。
polyphony、やってみた。
alu書いてみた。

#サンプルコード


```
import polyphony
from polyphony import testbench, module
from polyphony.io import Port
from polyphony.typing import uint3, uint4, uint16
from polyphony.timing import clksleep, clkfence, wait_rising, wait_falling

@module
class alu:
	def __init__(self):
		self.a = Port(uint16, 'in', protocol='valid')
		self.b = Port(uint16, 'in', protocol='valid')
		self.com = Port(uint3, 'in', protocol='valid')
		self.y = Port(uint16, 'out', protocol='valid')
		self.append_worker(self._worker)
	def _worker(self):
		while polyphony.is_worker_running():
			aa:uint16 = self.a.rd()
			bb:uint16 = self.b.rd()
			co:uint3 = self.com.rd()
			yy:uint16 = 0
			if (co == 0):
				yy = aa
			if (co == 1):
				yy = bb
			if (co == 2):
				yy = aa & bb
			if (co == 3):
				yy = aa | bb
			if (co == 4):
				yy = aa << 1
			if (co == 5):
				yy = aa >> 1
			if (co == 6):
				yy = aa + bb
			if (co == 7):
				yy = aa - bb
			self.y(yy)

m = alu()

@testbench
def test(m):
	m.a.wr(3)
	m.b.wr(6)
	m.com.wr(6)
	yy = m.y.rd()
	print("3 + 6 = ", yy)
	m.a.wr(3)
	m.b.wr(6)
	m.com.wr(2)
	yy = m.y.rd()
	print("3 & 6 = ", yy)

test(m)



```

#python実行結果


```
3 + 6 =  9
3 & 6 =  2

```

#iverilog実行結果


```


3 + 6 =  9
3 & 6 =  2
  290:finish


```

以上。
mac 初期設定

# mac
- スクロールの向き変更
- キー入力の速度変更
- バッテリー表示を%に変更
- spot 無効
- デュアルディスプレイの同時に動作するのを解除

<img width="657" alt="スクリーンショット 2020-06-04 16.44.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/32c36a57-6675-d87d-3add-e247369eb3d6.png">

![Screenshot 2020-06-11 6.02.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/3bc1fd06-22e1-fda7-8b19-9b2a2e8fbdd2.png)


# chrome
パスワードはアプリから呼び出す

# karabiner-Elements
 (https://karabiner-elements.pqrs.org/)
https://qiita.com/daichi87gi/items/ded35e9d9a54c8fcb9d6

<img width="654" alt="スクリーンショット 2020-06-04 16.46.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/d9e240d3-483d-9076-c98d-f6880fc0618e.png">


# google 日本語入力
- 全部半角に変更

# norton

# dropbox

# evernote

# finder

https://ushigyu.net/2015/05/18/mac-finder-configuration/

# spark

# slack

# illustrator

# webstorm
公式に日本語化のプラグインができるた

# appcleaner
http://freemacsoft.net/appcleaner/

# ターミナル

https://qiita.com/YukiLulu0229/items/11554dcf46a3822ee10d

# brew

```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

brew update

brew install git
brew install tig

```

# ricky font

参考: https://qiita.com/segur/items/50ae2697212a7bdb7c7f

@segur 

```
# sanemat様のリポジトリにタップします
brew tap sanemat/font

# rictyをインストールします
brew install ricty

## またはこっち
brew install brew-cask

brew tap homebrew/cask-fonts
brew cask install font-ricty-diminished
```

# alfred
https://webrandum.net/alfred-syncing/

# dash

# iterm
## profile
###General
working dirを pwaのパスに変更
### colors
https://draculatheme.com/itermをダウンロードしてセット, ForegroundをBlueをドラッグアンドドロップ
### text
fontをrickyに変えて fzを24にする, cursorを Virtical bar
### window
transparencyを30にする
### keys
ショートカットを入力



# そのた
https://qiita.com/jonghyo/items/733e0aeb5d6cd58e4855
【array-foreach-async】forEach()でasync/awaitを使おうとして失敗した皆へ

AWS Lambda関数でNode.jsを使用し、forEach()でasync/awaitしたい状況に陥ったのですが、コードを書いて実行してもawaitの文が実行されていませんでした。色々調べたところ、Node.jsの**`array-foreach-async`**というライブラリを利用することで簡単に解決することができたので、まとめていきます。

# 環境
- AWS Lambda
- Node.js 12

# 修正前の実行コード
今回の説明において不要なコードは省略しています。

```javascript
const env = process.env
const requestPromise = require('request-promise');
const AWS = require('aws-sdk');
const DB = new AWS.DynamoDB.DocumentClient();

exports.handler = async(event, context) => {
    
    // （省略）
    
    event.Records.forEach(async(record) => { // ここでasync  

        // （省略）
            
        const data = await DB.put(dbParams).promise(); // 1つ目のawait
        console.log(data);

        // （省略）

        const req = await requestPromise.post(options); // 2つ目のawait
        console.log(req);
    });
    return "success!"
};
```

実行すると、出力には`success!`のみが表示され、console.logは無視されます。forEach()がawaitの処理完了を待たずに終了し、Lambda関数が閉じてしまったためです。どちらか一方のawaitをコメントアウトしても結果は変わらず。forEach()ではasync/awaitが効いていないことが分かります。
そもそも`Array.prototype.forEach()`自体がasync関数ではないため、引数のcallback関数にasync/awaitを付けたところで無意味ということです。


# 修正後の実行コード
Node.jsの**`array-foreach-async`**というライブラリをインストールすることで、forEach()をasync関数にした`forEachAsync()`を使用できるようになります。
これを使えば、forEach()と同じ動作でasync/awaitを実現できます（参考：[array-foreach-async - npm](https://www.npmjs.com/package/array-foreach-async)）。

まずはライブラリをインストールします。

```
npm install array-foreach-async
```

ソースコードは次のようになります。

```javascript
const env = process.env
const requestPromise = require('request-promise');
const AWS = require('aws-sdk');
const DB = new AWS.DynamoDB.DocumentClient();
require('array-foreach-async'); // ライブラリの読み込み

exports.handler = async(event, context) => {
    
    // （省略）

    await event.Records.forEachAsync(async(record) => { // 変更箇所
                      
        // （省略）

        const data = await DB.put(dbParams).promise(); 
        console.log(data);

        // （省略）
          
        const req = await requestPromise.post(options);
        console.log(req);

    });
    return "success!"
};
```

`forEach`を**`forEachAsync`**に変更し、**文の先頭にawait**を付けます。
実行すると、awaitの文が両方ともきちんと実行され、ログの出力を確認できました。

# 補足
ずっとforEach()を使うことしか考えていなかったため後から気が付いたのですが、そもそもforEach()の代わりに`for〜of`を使用すれば解決できました。JavaScriptに慣れていなさすぎる...
修正前の実行コードを次のように変更すればOKです。

```javascript
const env = process.env
const requestPromise = require('request-promise');
const AWS = require('aws-sdk');
const DB = new AWS.DynamoDB.DocumentClient();

exports.handler = async(event, context) => {
    
    // （省略）
    
    for(const record of event.Records) {

        // （省略）
            
        const data = await DB.put(dbParams).promise(); // 1つ目のawait
        console.log(data);

        // （省略）

        const req = await requestPromise.post(options); // 2つ目のawait
        console.log(req);
    }
    return "success!"
};
```

コードも簡潔であり、わざわざ**`array-foreach-async`**をインストールする必要がないので、**どうしてもforEach()を使わなければならない状況**以外では、素直に`for〜of`を使う方が良いかもしれませんね。

ご参考までに。
Ubuntu18.04でPHP5.6とPHP7.4を使いたかった時のメモ

# やりたいこと
* Ubuntu18.04にphp5.6とphp7.4が動く環境を用意したい
* phpenvやらphpbrew使えばなんとかなるっしょ！
* Dockerは使わないものとする

# phpenvで試してみる。
anyenvでインストールされたphpenvで試した。

```
# phpenv install 5.6.40
```

記録を取っていないが色々コケる。

# 先人達の歴史を調査
お、ちょうど良い記事見つけた。
[ [php][ubuntu]php7とphp5とphpenv - 釣り。IT屋。毎日爆釣。(2019-07-29)](https://peixe.biz/diary/20190729.html)
> 結論：phpenvなんてものはなかった。 ローカルでPHP7を使っててPHP5.xも切り替えて使いたいとかいう場合はdockerでカレントをマウントして使え。

ワロタ。

# phpbrew を使ってみる
参考になる資料
https://gist.github.com/marulitua/f8932064ec5bfe6a5be9fadac7c5a141

# それでも色々コケる
[phpbrewでPHP 7.4を入れるのにいろいろつまづいた](https://gayou.hateblo.jp/entry/2019/11/30/191642)

私の環境は

```
$ brew install openssl
$ brew install libxml2
```

以外にも

```
$ brew install curl
$ brew install libxslt
$ brew install libzip
```
が必要だった。

```
$ brew ls <パッケージ名>
```
でbrew installのインストール先を調べられるので
各位、PATHは変えて下さい。

```
$ export PATH="/home/linuxbrew/.linuxbrew/Cellar/openssl@1.1/1.1.1g/bin:$PATH"
$ export PATH="/home/linuxbrew/.linuxbrew/Cellar/libxml2/2.9.10_1/bin:$PATH"
$ export PATH="/home/linuxbrew/.linuxbrew/Cellar/curl/7.70.0/bin:$PATH"
$ export PATH="/home/linuxbrew/.linuxbrew/Cellar/libxslt/1.1.34_1/bin:$PATH"
$ export PATH="/home/linuxbrew/.linuxbrew/Cellar/libzip/1.6.1_1/bin:$PATH"

$ export PKG_CONFIG_PATH="/home/linuxbrew/.linuxbrew/Cellar/openssl@1.1/lib/pkgconfig"
$ export LDFLAGS="-L/home/linuxbrew/.linuxbrew/Cellar/openssl@1.1/lib"
$ export CPPFLAGS="-I/home/linuxbrew/.linuxbrew/Cellar/openssl@1.1/include"
$ export PHP_BUILD_CONFIGURE_OPTS="--with-openssl=$(brew --prefix openssl) --with-libxml-dir=$(brew --prefix libxml2) --with-curl=$(brew --prefix curl) --with-libxslt-config=$(brew --prefix libxslt) --with-libzip=$(brew --prefix libzip)"
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290072/dbe9fc4f-3bb4-1319-5288-01c808eaee04.png" width="50%">

```
Enjoy!
```
よし！

# PHP5.6とPHP7.4が同居できているのかチェック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290072/4060097e-f4f5-b9a9-8017-46f8bbc94e5e.png" width="50%">

無事動作完了！
pyenvにて、"zipimport.ZipImportError: can't decompress data; zlib not available" で怒られた時

## タイトル通りpyenvで「zipimport.ZipImportError: can't decompress data; zlib not available」とインストールができないとき BY.macOSCatalina

### 解決した内容から...
とりあえず、最終的な解決方法としては、下記の順番でインストールができた。
あと、コマンド実行時にもセキュリティが上がってるみたいで、自分の場合はアプリケーション自体の許可をした。
詳しくは、`設定>セキュリティ>プライバシー>デベロッパーツール`にある`ターミナルにチェック`を入れた。
その後、ちゃんとインストールができた。

```
% brew reinstall zlib

% export LDFLAGS="-L/usr/local/opt/zlib/lib"
% export CPPFLAGS="-I/usr/local/opt/zlib/include"
% export PKG_CONFIG_PATH="/usr/local/opt/zlib/lib/pkgconfig"

```

他にも色々なサイトをみては、試したけど、あまり効果はなくXcodeやコマンドツールも最新にしたけど、上記を実行するまでは解決するに至らなかった...


#### 試したコマンド一覧

```
# 最初に見つけたコマンド
# そもそも"/Library/Developer/CommandLineTools/"の配下には、もう既に"Packages"のディレクトリが存在していなかったw
sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /

xcode-select --install
brew install zlib
```
AWS Service Catalog

#AWS Service Catalog
> AWS Service Catalog では、AWS での使用が承認された IT サービスのカタログを作成および管理できます。この IT サービスには、仮想マシンイメージ、サーバー、ソフトウェア、データベースから包括的な多層アプリケーションアーキテクチャまで、あらゆるものが含まれます。AWS Service Catalog により、組織は一般的にデプロイされる IT サービスを集中管理でき、一貫性のあるガバナンスを達成し、コンプライアンス要件を満たすうえで役立ちます。エンドユーザーは、組織によって設定された制約に従って、必要な承認済みの IT サービスのみをすばやくデプロイできます。

##ユーザー
* カタログ管理者 (管理者)
    *  製品 (アプリケーションおよびサービス) のカタログを管理し、ポートフォリオに整理してエンドユーザーにアクセス権限を付与します。カタログ管理者は、AWS CloudFormation テンプレートの準備や制約の設定を行い、製品に割り当てられた IAM ロールを管理して、高度なリソース管理を提供
* エンドユーザー
    * IT 部門またはマネージャーから AWS 認証情報を受け取り、AWS マネジメントコンソールを使用して、アクセス権限を付与されている製品を起動します。単純にユーザーと呼ばれることもあるエンドユーザーには、操作要件によって異なるアクセス許可を付与できます。たとえば、ユーザーに (使用する製品によって求められるすべてのリソースを起動および管理できるように) 最大限のアクセス許可レベルを付与することも、特定のサービス機能の使用に対するアクセス許可のみを付与することもできます。

##プロビジョニングされた製品
> AWS CloudFormation スタックにより、製品インスタンスを単一のユニットとしてプロビジョニング、タグ付け、更新、および終了できるので、製品のライフサイクルを管理しやすくなります。AWS CloudFormation スタックには、JSON 形式または YAML 形式で記述された AWS CloudFormation テンプレートとそれに関連するリソースのコレクションが含まれます。プロビジョニングされた製品はスタックです。エンドユーザーが製品を起動すると、AWS Service Catalog によってプロビジョニングされる製品のインスタンスは、製品の実行に必要なリソースを伴うスタックになります。

##ポートフォリオ
> ポートフォリオとは、製品の集合で、設定情報も組み込まれています。ポートフォリオは、特定の製品を使用できるユーザー、そのユーザーに許可される製品の使用方法の管理に役立ちます。AWS Service Catalog では、組織のユーザータイプごとにカスタマイズしたポートフォリオを作成し、適切なポートフォリオへのアクセス権を選択的に付与できます。製品の新しいバージョンをポートフォリオに追加すると、そのバージョンは、現在のすべてのユーザーに対して自動的に利用可能になります。また、自分のポートフォリオを他の AWS アカウントと共有して、そのアカウントの管理者がそのポートフォリオに制約 (ユーザーが作成できる EC2 インスタンスの制限など) を加えて配布できるようにすることができます。ポートフォリオ、アクセス権限、共有、制約を使用することで、組織のニーズおよび標準に合わせて適切に設定された製品をユーザーが起動するよう制御できます。

##バージョニング

> AWS Service Catalog では、カタログで複数のバージョンの製品を管理できます。これにより、ソフトウェアの更新または設定の変更に基づいて新しいバージョンのテンプレートと関連するリソースを追加できます。新しいバージョンの製品を作成すると、その製品にアクセスできるすべてのユーザーに更新が自動的に配信されるので、ユーザーは使用する製品のバージョンを選択できます。ユーザーは、製品の実行中のインスタンスを新しいバージョンにすばやく簡単に更新できます。

##アクセス許可
> ポートフォリオへのアクセス権をユーザーに付与すると、ユーザーはポートフォリオを閲覧して、それに含まれる製品を起動できます。AWS Identity and Access Management (IAM) アクセス許可を適用して、カタログを表示および変更できるユーザーを制御できます。IAM アクセス許可は IAM ユーザー、グループ、およびロールに割り当てることができます。ユーザーが IAM ロールが割り当てられている製品を起動すると、AWS Service Catalog では、そのロールで、AWS CloudFormation を使用して製品のクラウドリソースを起動します。IAM ロールを各製品に割り当てると、承認されていない操作を実行できるアクセス権限がユーザーに割り当てられないようにすることができます。また、ユーザーは、カタログを使用してリソースをプロビジョニングできます。

##制約
> 制約によって、特定の AWS リソースを製品に対してデプロイできる方法を制御します。制約を使用して、製品に制限を適用し、ガバナンスまたはコスト管理を実現できます。AWS Service Catalog の制約にはさまざまなタイプがあります。起動の制約、通知の制約、テンプレートの制約です。

起動の制約では、ポートフォリオ内の製品に対してロールを指定します。このロールは、起動時にリソースをプロビジョニングするときに使用されるので、ユーザーがカタログから製品をプロビジョニングする機能に影響を与えずに、ユーザーのアクセス許可を制限できます。

通知の制約は、Amazon SNS トピックを使用してスタックのイベントに関する通知を受けることができます。

テンプレート制約では、製品を起動したときにユーザーが使用できる設定パラメータ (EC2 インスタンスタイプ、IP アドレス範囲など) を制限します。テンプレート制約では、汎用 AWS CloudFormation テンプレートを製品に再利用して、製品単位またはポートフォリオ単位でテンプレートに制限を適用します。

##AWS Service Catalog でタグを管理する
> AutoTags は、AWS Service Catalog のプロビジョニングされたリソースのオリジンに関する情報を識別するタグであり、AWS Service Catalog によってプロビジョニングされたリソースに自動的に適用されます。

> TagOptions は、AWS Service Catalog で管理されるキーと値のペアであり、AWS タグを作成するためのテンプレートとして機能します。

###AWS Service Catalog AutoTags
#MicrosoftTeams の背景画像追加機能がＧＡされたっぽい！

# あれ？？見慣れぬものが・・・

今日テレビ会議してるときに、見つけてしまった！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/32fe7c99-8fe1-28f0-209a-fdda21205511.png)


おおお！なんと Add New ってのができてるじゃないか！

# 試してみる
開くと・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/5d928eda-254b-e24d-acf7-94b32c17766f.png)

ファイルダイアログが表示される！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/cf68a97d-03f7-2600-5373-9d5677011faf.png)

## 使える拡張子

以下の拡張子に対応しているみたい

* .jpg
* .pjpeg
* .jpeg
* .jfif
* .pjp
* .png

## 追加すると・・・

Backgroundに追加されますね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/e3aa5908-9b43-6a95-bccb-191266543a2c.png)

実態は、例のフォルダにアップロードされるようです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/b012dd22-e833-abe6-db82-0017dfe47de8.png)

これで、いちいちフォルダ開いてコピーする必要がなくなりますね😀

なお、こちらは順次各テナントに展開されると思います＼( 'ω')／

あ、画像入れすぎると、背景画像の選択画面が表示されるのに時間がかかるようになるのでご利用は計画的に(笑)
orgファイルをpdfにする方法

#手順

1.まず以下の様なRakefileを、変換したいorgファイルのある所へコピーする。

-written by Yamamoto Kenta

```
file = Dir.glob("*.org")[0].match(/(.*).org/)[1]

desc "platex"
task :platex do
  lines = File.readlines("#{file}.tex")
  t_file = "thesis_midterm"
  lines = convert_thesis(lines)
  File.open("#{t_file}.tex", "w") do |f|
    lines.each { |line| f.print line }
  end
  #system "platex #{file}"
  commands = ["platex #{t_file}.tex",
              "bibtex #{t_file}.tex",
              "platex #{t_file}.tex",
              "dvipdfmx #{t_file}.dvi",
              "open #{t_file}.pdf"]
  commands.each { |com| system com }
end

def convert_thesis(lines)
  head = <<'EOS'
  \documentclass[a4j,twocolumn]{jsarticle}
  \usepackage[dvipdfmx]{graphicx}
  \usepackage{url}

  \setlength{\textheight}{275mm}
  \headheight 5mm
  \topmargin -30mm
  \textwidth 185mm
  \oddsidemargin -15mm
  \evensidemargin -15mm
  \pagestyle{empty}


  \begin{document} 

  \title{核崩壊と核分裂の違いについて}
  \author{情報科学科 \hspace{5mm} 27017561 \hspace{5mm} 山本 健太}
  \date{}

  \maketitle
EOS
  head2 = <<'EOS'
  {\small\setlength\baselineskip{15pt}	% 参考文献は小さめの文字で行間を詰めてある
  \begin{thebibliography}{9}
  \bibitem{houkai} 「放射性崩壊 wikipedia」,(https://ja.wikipedia.org/wiki/放射性崩壊).
  \bibitem{bunretu} 「核分裂反応 wikipedia」,(https://ja.wikipedia.org/wiki/核分裂反応).
  \bibitem{gakusei} 「原子核崩壊のメカニズムとは？理系学生のライターが詳しく解説！」，(https://study-z.net/100061260)．
  \end{thebibliography}
  }
  \end{document}
EOS
  new_line = [head]
  lines[32..-1].each do |line|
    #    if line.match(/\\tableofcontents\n/)
    #      line = "\\tableofcontents\n\\listoftables\n\\listoffigures\n\\pagebreak\n"
    #      p line
    #    end
    new_line << line
  end

  new_line.each do |line|
    line.gsub!('\end{document}', head2)
    # line.gsub!('\tableofcontents','\begin{document}')
    line.gsub!('\tableofcontents', "")
  end
  return new_line
end

desc "test"
task :test do
  #str = Dir.glob("*.org")[0].match(/(.*).org/)[1]
  str = Dir.glob("*.org")
  p str
end
```

2.emacsでorgファイルを開き、そこで”C-c C-e ll”のコマンドを実行しemacsを閉じる。

3.orgファイルと同じ名前のテキストが表示されているはずなので、terminalで”rake platex”を実行する。

4.pdf化される。

#`注 2番でうまくいかなかった場合`

私も手順2でうまくいかなかった。
terminalで”which ruby”と打つと、/usr/bin/emacs と出てきたため、pathがうまく通っていない事が原因である事がわかった。
pathを通そうとしたが、うまくできなかったので応急処置として、/usr/local/bin/emacs 〇〇.org といった様に直接pathを通す事で解決した。

今後、pathの通し方がわかればここにメモしようと思う。

takagi
AirflowでExternalTaskSensorを使う時に気をつけること

# 2行で
- デフォルト設定では `ExternalTaskSensor` のDAGのschedulerは、 `external_dag_id` のものと全く同じ設定とすること
- `ExternalTaskSensor` のDAGのschedulerを変えたい場合は、 `execution_delta` を設定する

# 背景
Airflowは1.10.6。
ExternalTaskSensorを使って別のDAGの終了を確認してからタスクを実行するようなDAGを作りたい。
適当に設定するとなんかうまく動かなくて苦労したのでメモ。

# 動くサンプル1

```test1.py

import airflow
from datetime import timedelta
from airflow import DAG
from airflow.operators.bash_operator import BashOperator

default_args = {
    "owner": "airflow",
    "depends_on_past": False,
    "start_date": airflow.utils.dates.days_ago(1),
    "execution_timeout": timedelta(minutes=30),
    "retries": 3,
    "retry_delay": timedelta(minutes=5),
}

dag = DAG(
    "external_dag",
    default_args=default_args,
    catchup=False,
    schedule_interval="0 2 * * *",
)

t1 = BashOperator(task_id='task_1', bash_command="echo 'aaa'", dag=dag)
t2 = BashOperator(task_id='task_2', bash_command="echo 'bbb'", dag=dag)

t1 >> t2

```

```test_2.py
import airflow
from datetime import timedelta
from airflow import DAG
from airflow.sensors.external_task_sensor import ExternalTaskSensor

default_args = {
    "owner": "airflow",
    "depends_on_past": False,
    "start_date": airflow.utils.dates.days_ago(1),
    "execution_timeout": timedelta(minutes=30),
    "retries": 3,
    "retry_delay": timedelta(minutes=5),
}

dag = DAG(
    "sensor_dag",
    default_args=default_args,
    catchup=False,
    schedule_interval="0 2 * * *",
)

ExternalTaskSensor(
    task_id='sensor_1',
    external_dag_id='external_dag',
    external_task_id=None,
    dag=dag
)
```
external_dag のschedulerと、ExternalTaskSensor の scheduler の設定が同じになっているので動く。1分でも違うと動かないで注意。

# external_dag と ExternalTaskSensor で異なるschedulerを設定したい場合 
external_dag と ExternalTaskSensor の時間をずらしたい場合も出てくる。その場合は、 ExternalTaskSensor の `execution_delta` 引数を使う。

例えば、external_dagの schedulerが `0 2 * * *` で、 ExternalTaskSensor が `5 2 * * *` にしたい場合。つまり、5分後にTaskSensorを起動したい場合。  

ExternalTaskSensorを以下のように設定する。

```test_2.py
# 略

dag = DAG(
    "test_2",
    default_args=default_args,
    catchup=False,
    schedule_interval="5 2 * * *",
    execution_delta=timedelta(minutes=5),
)

ExternalTaskSensor(
    task_id='task_1',
    external_dag_id='test_1',
    external_task_id=None,
    execution_delta=timedelta(minutes=9),
    dag=dag
)
```

差分の5分の`timedelta(minutes=5)` を引数に渡すと動く。気をつけないといけないのが、ぴったり5分じゃないとダメ。1時間とかでも動くだろと思ったけどダメだった。

# 参考
[公式doc](https://airflow.apache.org/docs/stable/_api/airflow/sensors/external_task_sensor/index.html)
[Airflow で異なる DAG 間の依存関係を設定する方法](https://www.flywheel.jp/blog/airflow-dependency-between-dags/)
mysqldumpで--skip-lock-tablesが効かない

#解決したい問題
mysqldumpを使ってDBをダンプするときに`LOCK TABLE`を無効にしたい
通常なら以下で解決するらしい

```bash
mysqldump --skip-lock-tables -h$HOST -P$PORT -u$USER $DB -p$PW $TABLE > dump.sql
```

自分の環境ではこれが上手くいかずLOCKが残ってしまいました。

#解決法
`--skip-add-locks`を使う

```bash

mysqldump --skip-add-locks -h$HOST -P$PORT -u$USER $DB -p$PW $TABLE > dump.sql

```

#参考文献
調べたところデフォルトでいくつかのオプションが有効になっていてそれを打ち消すには`--`をつけると良いらしい。`LOCK TABLE`に関するオプションが2つあったので試してみたところ上手くいきました。
[参考](http://piyopiyocs.blog115.fc2.com/blog-entry-760.html)
GitHub と Bitbucket 比較 2020/06 時点


会社の開発業務での利用を前提に、調べたメモを残しておきます。
動きの激しい業界なので半年後には変わってるかもしれません。

# 利用想定

* repogitoryはprivate
* 数人規模の少数チーム利用
* できたら無料

# 調査前のざっくりサービスの印象

## GitHub

* gitホスティングサービスといえばここ
* ただしprivateにするには有料

## Bitbucket

* privateでも無料
* 有料プランもGitHubより安い
* ちょっとインフラ弱い

だったので、無料だし（経費削減！）とりあえずBitbucketでprivateしておくかー。

**でした。**

# 調査して分かったこと

ただし、4月にこのGitHubの[pricingに変更](https://jp.techcrunch.com/2020/04/15/2020-04-14-github-is-now-free-for-all-teams/
)があり情勢が大きく変わって

## GitHub

* privateもチーム（組織）利用も無料

になっちゃいました。Microsoftありがとーー。

じゃあ、GitHub１択かな、と思い、無料プランでどこまで使えるのか、制限ないのか調べました。

## private repositoryではできない機能で気になるところ

[pricing](https://github.com/pricing)を参考にpublicじゃないと使えない機能を抜粋

* Protected branches
	* 特定のレビュワーじゃないとマージできない or 特定の人しか特定ブランチ上で作業できないようにできる
* Code owners
	* レビュワーを指定できる（マージをこの人の承認必須とするか否かは選べる）
* Draft pull requests
	* プルリクの下書き
* Pages and wikis
	* シンプルなwebsite、もしくはwikiページ

こうみると上３つは開発の運用ルールでどうにかなりそうですが、最後のwiki使えないの地味に痛いかも。

実際wikiがない様子
![github_wiki.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1533/ade01ae0-ffd9-b698-e12b-b9a976f09ecb.png "github_wiki.png")


wikiだけ別サービスで使えばいいんでしょうけど、repositoryやissueと密にリンクしてたので、上手く代用効くかなーという感じ。

# まとめ

* 会社の案件でもGitHubのFreeプランで充分使える（[利用想定](#利用想定)前提）
* wiki欲しい! or チームがちょっと規模大きくてマージとかブランチとか制限したい、ってなったらTeamプラン ($4 per user/month) 使えば充分。それでも充分安いです。。。Microsoftありがとーー
Rubyの条件分岐。if、条件演算子(三項演算子)、unless、case

## Rubyでの真偽値
Ruby では false または nil だけが偽で、それ以外は 0 や空文字列も含め全て真です。

| 偽 | 真 |
|:---:|:---:|
| false,  nil  | それ以外( true,0 ,空文字列など)  |

## if
条件式に一致した場合に指定の処理を行う。

### 構文

```
if 式 [then]
  式 ...
[elsif 式 [then]
  式 ... ]
...
[else
  式 ... ]
end
```
[ ]は省略可能な部分です。

els **e** ifではなくelsif(eがない)なので、他言語経験者は注意。
最後のels **e**  はeが必要。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538652/d177da91-444d-6dc6-eb1a-49c969d680e6.jpeg)

### 例文
```
score = 90

if score == 100
  puts 'S'
elsif score >= 90
  puts 'A'
elsif score >= 80
  puts 'B'
else
  puts 'C'
end

# thenを使っている例
if score == 100 then
  puts 'S'
end
```

## 条件演算子(三項演算子)
判定条件や処理が短い場合に威力を発揮！見やすくなる。

### 構文
```
式1 ? 式2 : 式3
# 条件 ? ◯の場合 : ×の場合
```

### 例文
```
checked = true
puts checked ? "済" : "未"

# 以下の文と同じ意味。
# puts (if checked then  "済" else "未" end)
```

## unless

if と反対。もし〜でなければ。
unlessで書ける文はifでも書けるのでお好みで。

二重否定になるとわかりにくくなるので注意。
[Rubyにおけるunlessとコードの読みやすさについて｜TechRacho（テックラッチョ）〜エンジニアの「？」を「！」に〜｜BPS株式会社](https://techracho.bpsinc.jp/hachi8833/2016_08_23/25010)
### 構文
elsif はない。
elseは省略可能。

```
unless 式 [then]
  式 ...
[else
  式 ... ]
end
```


### 例文
```
unless baby?
  # 条件式が偽(false)のの場合
  puts "ご飯を食べる"
else
  puts "ミルクを飲む"
end
```


## case
ifとの使い分けの目安として、caseのほうは並列的な条件の場合により適していると思いますが、どうでしょうか。

swich文と同じだと思ってたんですが厳密には違うようです…
[Rubyのcaseを〇〇(言語名)のswitch文だと思っている人たちにぼくから一言ガツンと申し上げたい](https://melborne.github.io/2013/02/25/i-wanna-say-something-about-rubys-case/)

### 構文
```
case [式]
[when 式 [, 式] ...[, `*' 式] [then]
  式..]..
[when `*' 式 [then]
  式..]..
[else
  式..]
end
```



### 例文
```
os = "macOS"

case os
when "Windows"
  # 処理
when "macOS", "Unix"
  # 同じ処理をする条件をまとめて記述できる
when "Linux"
  # 処理
else
  # 処理
end
```


## 参考
[制御構造 (Ruby 2.7.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/2.7.0/doc/spec=2fcontrol.html)
[演算子式 (Ruby 2.7.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/2.7.0/doc/spec=2foperator.html#cond)
【Git】修正したファイル差分の一覧を取得する。

メモとして残します。


#■やり方
```shell
git diff --name-status コミット1revision コミット2revision
```
削除したファイルを除きたい場合は`--diff-filter=d`オプションを付ければOK。
　
#■おまけというより、追記
日本語というより、全角文字はエスケープされた状態で表示されるため、下記のコマンドを実行して、gitの設定を変更しましょう。

```shell
git config --global core.quotepath false
```
WitMotion BW61を使ってみた

#1. はじめに
* 6軸以上のジャイロセンサをBluetoothで飛ばしていろいろやりたい
* できれば電池駆動できる小消費電力なもので
* できればそんなに高くないもの

#2. 使用機器
[WitMotion BWT61](https://www.amazon.co.jp/gp/product/B07RS3CSG1/ref=ppx_yo_dt_b_asin_title_o05_s00?ie=UTF8&psc=1)

* 電源は3.3~5v
* MPU6050を使ってる
* BLEも載ってる
* チュートリアルなど、資料が充実

#3. メーカーの資料サイト
　[https://wiki.wit-motion.com/english](https://wiki.wit-motion.com/english)


#4.試運転

* VCCとGNDにUSBからの電源をつなぐ(余っているArduinoのピンヘッダから拝借)
* 電源が入ったらBluetooth機器の"HC-06"とペアリングする（passwordはデフォルトで"1234"）
* [ここ](http://wiki.wit-motion.com/english/doku.php?id=module)の一覧からWT61をクリックして"WT61.zip"をダウンロードし、適当な場所に展開![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637529/a6b3cfcf-6533-3ade-038a-f8aeb34856f4.png)

* "WT61\PC Software _JY61 For WT61C BWT61 BWT61CL"フォルダ内のMiniIMU.exeを実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637529/3930dffe-42ca-3942-0794-1a120efea4b1.png)
こんな感じだったり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637529/56833900-295b-3ba2-97eb-77aa6884fa21.png)
こんな感じに！
VyOS 1.1系から1.3に移行する際の注意点

# きっかけ
公式のVyOSバージョンがしばらく1.1.8のままで、Kernelバージョンが古かったりセキュリティアップデートもされていないので、最新の1.3.xをクリーンインストールして設定したところ細々とした変更が見られたので、移行する際にハマりやすい変更点を自分用備忘録として。


## 構成
WAN側GW:172.16.1.1
WAN側IP:172.16.1.10
LAN側IP:192.168.1.1


## デフォルトゲートウェイの設定
1.1系まで使えてた「set system gateway-address "Address"」が使えなくなったので、スタティックルートで0.0.0.0の宛先をGWのIPに向けてあげる。

```
# 1.1.x系
set system gateway-address '172.16.1.1'
```

```
# 1.2以降
set protocols static route 0.0.0.0/0 next-hop 172.16.1.1
```


## DNSの設定

基本的に同じだが、1.3からはDNSリフレクション攻撃の対策としてallow-fromでDNSの応答を許可するIPレンジを設定する必要がある。それに伴い「forwarding listen-on "Interface"」もサポート外となり、明示的に許可するLAN側アドレスを指定する仕様に変更された。

```
# 1.1.x系
set service dns forwarding listen-on 'eth1'
```

```
# 1.3以降
set service dns forwarding listen-address '192.168.1.1'
set service dns forwarding allow-from '192.168.1.0/24'
```



## 参考

Default Gateway/Route
https://docs.vyos.io/en/latest/system/default-route.html


DNS Forwarding
https://docs.vyos.io/en/latest/services/dns-forwarding.html
safari でアドレスバーに絶対パスを入力してPC内のHTMLを表示する

単純なことだが、調べるのに時間がかかったのでメモ。

css,js 等で簡単に試したいことがあった時に chrome だと適当にhtmlファイルを作成してアドレスバーに絶対パスを入力すると表示できるが、safariだとそのパスをwebで検索してしまう。
safari でも同じことがしたいときは以下のようにする。
`file:/path/to/hoge.html`
Zabbix x CentOS 7 SNMPTrap ログ出力を変更する

SNMPTrap（snmptrapd）のログ出力に関する設定。

snmptrapdはデフォルトでは/var/log/messagesにログを出力するが、大量に出力する場合には取り回しが悪いことから、別ファイルに出力する設定を行う。

尚、snmptrapdのオプションで直接出力先となるログファイルを指定することも可能だが、再起動するたびにログファイルがリフレッシュされることから、syslog経由でログを出力する。

#snmptrapd 

起動オプションにログ出力先を指定する。（以下の例ではlocal5に出力）

```vim:/etc/sysconfig/snmptrapd
OPTIONS="-Ls5d -Lf /dev/null -p /var/run/snmptrapd.pid"
```
#syslog

syslogのlocal5に送られたログをファイルに出力するための設定を行う。

```:/etc/rsyslog.conf
# snmptrapd.log
local5.*   /var/log/snmpd/snmptrapd.log
```
ログ出力先を作成し、syslogを再起動する。

```
mkdir /var/log/snmpd
```


```
systemctl restart rsyslog
```

#動作確認

snmptrapdを再起動することで出力を確認する。

## snmptrapd再起動

```
systemctl restart snmptrapd 
```
/var/log/snmpd/snmptrapd.logを確認してみる。

```
cat /var/log/snmpd/snmptrapd.log
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635477/8eaca282-e48e-731f-3d2e-35a84ec8de19.png)

無事ログのお引越しが完了しました。
並列処理数を指定できてキャンセルできる Promise.all の実装

# 実装

```ts
import type { AbortSignal } from 'abort-controller'

// Node.js など DOMException がない場合に必要に応じて定義
export const DOMException =
  ('undefined' !== typeof window && window.DOMException) ||
  ('undefined' !== typeof self && self.DOMException) ||
    class DOMException extends Error {
      constructor(message: string, name: string) {
        super(message)
        this.name = name
      }
    }

// キャンセル機能が不要な場合、同時実行数のみを渡せるように
type Options = number | { concurrency: number; signal?: AbortSignal }

export const promiseAllWithConcurrencyLimit =
  async <T>(promises: (() => Promise<T>)[], options: Options) => {
    const opts = 'number' === typeof options ? { concurrency: options } : options
    const { concurrency, signal } = opts
    const results: T[] = []
    let idx = 0
    await Promise.all(Array.from({ length: concurrency }).map(async () => {
      while (true) {
        if (signal?.aborted) 
          return Promise.reject(new DOMException('aborted', 'AbortError'))
        const cur = idx++
        const task = promises[cur]
        if (!task) return
        results[cur] = await task()
      }
    }))
    return results
  }
```

# 記事を書くまでの経緯

以前、[並列処理数を指定できる Promise.all の実装](https://qiita.com/rithmety/items/9bc7111c14033fe491f2)という記事を書きました

長時間かかるタスクの実行中になんらかの要因でやっぱり中止したいと思うかもしれません
fetch の仕様を参考にキャンセルできるようにしたのが上記になります

# 使用例

```ts
const controller = new AbortController()
const onCancelButtonClicked = () => {
  controller.abort()
}
try {
  await promiseAllWithConcurrencyLimit(
    userIds.map(id => async () => fetchUserById(id)),
    { concurrency: 3, signal: controller.signal }
  )
} catch (err) {
  if ('AbortError' !== err?.name) throw err
}
```
Excelマクロ 4.0を利用した攻撃における非表示シートを表示させるツール

2019年ころからExcelのマクロ4.0（化石のようなマクロだが、書けば最新のExcelでも動作してしまう）を利用した攻撃が観測されています。

出始めの攻撃は、マクロを記載したシートを非表示にしてぱっと見見えなくするような手法だった（右クリック「再表示」で表示可能）ようですが、
最近観測されているものではveryHiddenという形式のシートにすることで、右クリックでも再表示させることができなくなっているものがあります。

#veryHiddenを表示させるための方法
##コミュニティ
こちらで方法について議論されています
https://isc.sans.edu/forums/diary/Excel+Maldocs+Hidden+Sheets/25876/

##ツール
githubでいくつか公開されています。
・exe形式
https://github.com/DBHeise/ShowSheets/releases
・Powershell
https://github.com/denk-core/ExcelSheetUnhide

Powershellのほう使ってみたらシンプルで使いやすかったです！

以上。
AWS Blue/Greenデプロイの動作について

# この記事について
CodeDeployを利用すると、ECSへのデプロイでBlue/Greenを簡単に実現できます。
どのような動きをして、実現できているのかを確認したので、記録しておきます。

Blue/Greenの設定などの解説は行いません。

# Blue/Greenデプロイについて
すでにご存知かもしれませんが、一応。
Blue/Greenデプロイとは、デプロイ手法の一つで、本番環境（Blue）に対し、検証環境（Green）を別途立ち上げて、その検証環境をそのまま本番環境として利用することで、デプロイ時のダウンタイムを低減させることを目的としています。

本番環境及び、検証環境の切り替えは、ルーティングを変更することで行う。

# 全体像について
今回の内容は、下図だけでわかると思います。

![無題のプレゼンテーション (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/af7758ad-290c-683d-b505-d4e1828a4d6d.jpeg)

# 動きを確認していきます。
検証環境は、ECSのFarget環境へのデプロイになります。

- group1 → xxx-fargate
- group2 → xxx-fargate-2

とします。

## ①初期状態
ロードバランサーは、443/8080どちらも`xxx-fargate`へルーティングします。
<img width="974" alt="スクリーンショット 2020-06-04 10.11.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/27a8e6e4-0b70-a30f-db6f-3c675a3238da.png">

## ②デプロイの開始
<img width="1137" alt="スクリーンショット 2020-06-04 10.14.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/a3519d84-2dc8-e4ca-6e4c-1aab4a818fc4.png">

- ロードバランサーの状態

変更はありません

<img width="974" alt="スクリーンショット 2020-06-04 10.11.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/27a8e6e4-0b70-a30f-db6f-3c675a3238da.png">

## ③ビルド完了、8080をGreen環境へルーティング
<img width="1142" alt="スクリーンショット 2020-06-04 10.18.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/7b40daa7-8381-f652-c9c4-8acf482cf9dc.png">

- ロードバランサーの状態

8080が、`xxx-fargate-2`へルーティングされるように変更されています。

<img width="974" alt="スクリーンショット 2020-06-04 10.18.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/589b642a-9fde-e261-8c55-720372fae17b.png">

- fargateタスクの状態

タスクはBlue(本番)と、Green（検証）の２つ実行されています。

<img width="1221" alt="スクリーンショット 2020-06-04 10.19.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/e2ebb41a-ecae-b818-33cc-7cef3ba8e763.png">


## ④置き換え&タスクの削除
<img width="1176" alt="スクリーンショット 2020-06-04 10.19.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/f71df5d2-b4e2-dfa2-b7b2-418ce3373d25.png">

- ロードバランサーの状態

443が`xxx-fargate-2`へルーティングされるようになります。

<img width="991" alt="スクリーンショット 2020-06-04 10.20.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/5197ab3c-79c7-129b-a78a-f8a81ce2ca4c.png">

CodeDeployのコンソールで`元のタスクセットを終了`をクリックすると、もとのタスクが削除されます。

<img width="1165" alt="スクリーンショット 2020-06-04 10.20.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/11627e09-ca7e-4c97-5daf-b9cac3f00e6f.png">

- fargateタスクの状態

もとのタスクが削除されています。

<img width="1226" alt="スクリーンショット 2020-06-04 10.20.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330639/d4c538f4-2881-f422-27f9-f80b4a420bae.png">
Node.jsをPHPで書き換えてみた

N予備校のプログラミング入門コース3章で作成した「秘密の匿名掲示板」をPHPで書き換えてみたので，その記録です。

#きっかけ
スラスラわかるPHP（志田 仁美 著　翔泳社 刊）をやってみて，
「この間作った匿名掲示板，書き換えられるのでは？」
と思ったので。
スラスラわかるPHPをやってみた所感は[こちら](
https://note.com/ayareily/n/n56391bc9cb41)

#早速書き換える
##仕様を変更したところ
- 認証の方式  
おそらくN予備校ではBasic認証（alartみたいに上に出てくるやつ）を使っていたと思いますが，
書き換えの際にはスラスラわかるPHPのように，DBを使用する方式としました。  
- TrackingID  
N予備校で作成した際はCookieを利用してTrackingIDを実装していたと思いますが，セッションを利用する方式としました。

その他細かい変更点はあると思うのですが，大きく変更したのはこちら2点です。

##書き換えで苦労したところ
###記事とユーザーの情報をどう関連付けるか
Laravelでは
userテーブル->id = articleテーブル->userid
としておけば情報を結びつけてくれていましたが，
今回はそれができない…ということで，とても苦労しました。
結局，セッションに該当するユーザー情報をもたせることで実現しました。
今回の場合，ユーザーのidとユーザー名が該当しました。

###TrackingIDをどう実現するか
Cookieを使うべきか？それともセッションを使うべきか？…という，なんとも根本的なところから悩みました。
こればかりは一人で解決できず，友人にも意見を求めたところ，セッションで実現でいいのでは？という意見をもらったので，結局セッションを使うということで，決着。
ざっくりとした実装方法は下記の通りです。
>ログイン時にランダムな文字列を予めセッションにセットしておく（仮にsecretidとします）
→書き込み時にpostテーブルに格納
→IDとして表示するのはsecretidの値

#所感
###思ったよりも難しかった気がする
これはただ単に私の実力不足に起因するものだと思いますが，思ったよりも難しかった気がします。

###勉強になった
セッションか？Cookieか？を考えたり，どうやってuserテーブルの情報をpostテーブルに入れるか…？を考えたり。
今まではmigrationに頼っていた部分がSQLになるので，SQLの勉強をしてみたり。
どうやって実現していたか？のロジックを一から考え直してみたり…
簡単に実現することはできませんでしたが，自分の実力不足を痛感するとともに，勉強になったことは多かったように思います。
Intellij ショートカット 個人用メモ

個人用メモです。
残念なことに、MacとWindows両方使うので両方メモします。

■ コードをフォーマットする
ショートカットキー(Mac)：Command + Option + L
ショートカットキー(Windows)：Ctrl + Alt + L

■ なんでも検索
ショートカットキー：Shift 2回連打

■ ファイル横断テキスト検索
ショートカットキー(Mac)： Command + Ctrl + Shift + F
ショートカットキー(Windows)：Ctrl + Shift + F

■ ファイル名検索
ショートカットキー(Mac)： Command + Shift + O
ショートカットキー(Windows)：Ctrl + Shift + N

■ 宣言へジャンプ
ショートカットキー(Mac)：Command + B or Ctrl + Click
ショートカットキー(Windows)：Ctrl + B or Ctrl + Click

■ 実装クラスへジャンプ
ショートカットキー(Mac)：Command + Option + B or Ctrl + Click
ショートカットキー(Windows)：Ctrl + Alt + B or Ctrl + Click

■ 使用箇所の表示
ショートカットキー(Mac)：Option + F7
ショートカットキー(Windows)：Alt + F7

■ 型の継承階層を表示する
ショートカットキー(Mac)：Command + H
ショートカットキー(Windows)：Ctrl + H

■ クイックアウトライン (クラス内で宣言されている変数、メソッドの一覧)
ショートカットキー(Mac)：Command + F12
ショートカットキー(Windows)：Ctrl + F12

■ 戻る(進む)
ショートカットキー(Mac)： Command + Alt + ← (→)
ショートカットキー(Windows)：Ctrl + Alt + ← (→)

■ 現在開いているタブを閉じる
ショートカットキー(Mac)： Command + W
ショートカットキー(Windows)：Ctrl + F4
LaravelさんはどうやってAJAXかどうか区別してバリデーションエラーレスポンスでJSONを返してくるの？

# はじめに

我らがBOOM TECH CAFEの若きエース、 @miriwo さんの最新記事「[Laravel API データポスト時のバリデーションで弾かれた後、http://127.0.0.1:8000/にリダイレクトしてしまう](https://qiita.com/miriwo/items/976a25a31550973e73b8)」を読んで、「おや？　ワイのLaravelちゃんはAJAXでアクセスすると普通にバリデーションエラーのJSON返してくるんやが……？」と思って、調べてみました。

# そもそもAJAXかどうかどうやって判定しているの？

Laravelの公式ドキュメント日本語訳にはこんなふうに書かれてるわけですよ。
https://readouble.com/laravel/5.5/ja/validation.html

※一応、Laravel5.5での話をしていますが、後方バージョンでもだいたい同じだと思います。

> 伝統的なHTTPリクエストの場合は、リダイレクトレスポンスが生成され、一方でAJAXリクエストにはJSONレスポンスが返されます。

ほうほう、そうなんすね。
んで、AJAXリクエストか伝統的なHTTPリクエストかどうかはどこで判別してるねんと言うと、ここなわけです。

```php:vendor/laravel/framework/src/Illuminate/Http/Request.php(226-234)
    /**
     * Determine if the request is the result of an AJAX call.
     *
     * @return bool
     */
    public function ajax()
    {
        return $this->isXmlHttpRequest();
    }
```
```php:vendor/symfony/http-foundation/Request.php(1820-1833)
    /**
     * Returns true if the request is a XMLHttpRequest.
     *
     * It works if your JavaScript library sets an X-Requested-With HTTP header.
     * It is known to work with common JavaScript frameworks:
     *
     * @see http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
     *
     * @return bool true if the request is an XMLHttpRequest, false otherwise
     */
    public function isXmlHttpRequest()
    {
        return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
    }
```

なるほど、つまりRequest Headerに `X-Requested-With: XMLHttpRequest` ってのが入ってたらAJAXリクエストとして扱うってわけね……**え、そんなHeaderどこで入れてたっけ……？**

# そして我々は `X-Requested-With` を求めて旅に出た

ソースグレップするとこんなところにいるのを見つけます。

```javascript:resources/assets/js/bootstrap.js(16-24)
/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
```

なるほど、axiosのHeaderにデフォルトで入るようにしてるのね……え、でもBootstrap使ってないんやが……
そこで、肝心のAJAXしてるjsをのぞいてみると……

```javascript
require('./bootstrap');
```

**バッチリrequireしてたーーーーーー！！**

やー、無意識って怖いっすね。今回はいい勉強になりました。
HaskellでBuilderを作ろう with Lens

# HaskellでBuilderを作ろう

　Haskellには`Data.Default`というものがあり、これを使うとデフォルトの値を設定することができる。
　しかしこれは部分的なデフォルトの値を用意することはできず、ちょっと込み入ったことをしようと思うと急にクソダサ関数を用意する羽目になる。

```Haskell
makeHoge :: Int -> Hoge
makeHoge n = Hoge { essential = n, {デフォルトの値を頑張って書く} }
```

　そこで、JavaなんかでみるBuilderパターン的なやつをHaskell上に作ることを考える。
　理想的には、柔軟にデフォルト値を設定したり、この値は環境変数から読み込んだりといったことを明示できるようになると嬉しい。

## もくじ

1. Stateモナドで頑張ってみる
2. Lensで手間を削る
3. まとめ

## Stateモナドで頑張ってみる

　モナドはHaskellの言語内DSLであるという格言がある。そこで、モナドを使ってBuilderのDSLを作ることを考えよう。
　まずはサンプルとしてクソデカデータ`Hoge`を作る。

```Haskell
data Hoge = Hoge
    { _nParam :: Int
    , _mParam :: Maybe Int
    , _sParam :: String
    } deriving (Show)
```

　次に、どんなDSLを書きたいか想像する。個人的には、下のように書けたら素直でよいと思う。
　デフォルト値の設定などは見えないところでやってほしい。

```Haskell
build essential $ do
    nParam 10
    mParam $ Just 5
    sParam "hello"
```

　ビルダーモナドを作る。一から作るのはめんどいので、`State`モナドを流用する。
　最低限のDSL内の機能は`modify`を使えば簡単に実装できる。ここは単に値を設定するだけでなく、環境変数から値を読み取ったり、値をさらにビルダーで構成したり、値の取得に失敗する可能性を表現したり等、何でもやっていい場面である。

```Haskell
-- ビルダーモナド
type BuilderT = StateT Hoge

-- DSL内の機能
nParam :: Monad m => Int -> BuilderT m ()
nParam n = modify' $ \h -> h { _nParam = n }

mParam :: Monad m => Maybe Int -> BuilderT m ()
mParam m = modify' $ \h -> h { _mParam = m }

sParam :: Monad m => String -> BuilderT m ()
sParam s = modify' $ \h -> h { _sParam = s }
```

　最後に`build`関数を作る。ここではDSLで明示しなくて良い部分の全てを書く。
　ここでは以下のような仕様を考えた。

1. `nParam`は必ずビルド時に与えなければならない。
1. `mParam`はデフォルト値が`Nothing`である。
1. `sParam`はデフォルト値が`"sParamDefault"`である。しかし環境変数`sParam`がある場合はそちらをデフォルト値とする。
1. いずれもDSL内で指定があればそっちを優先する。

```Haskell
build :: MonadIO m => Int -> BuilderT m a -> m (a, Hoge)
build n b = do
    sEnv <- liftIO $ lookupEnv "sParam"
    let mParamDefault = Nothing
        sParamDefault = fromMaybe "sParamDefault" sEnv
    runStateT b $ Hoge n mParamDefault sParamDefault
```

　これでビルダーのDSLを書けるようになった。

```Haskell
>>> (_, hoge) <- build essential $ do
>>>     nParam 10
>>>     mParam $ Just 5
>>>     sParam "hello"
>>> print hoge
Hoge {_nParam = 10, _mParam = Just 5, _sParam = "hello"}
```

　目的は概ね達成できたといえる。問題はクソデカデータを作るというのにDSLの機能を全て手で実装しなければならない点だ。そこでLens先生の力を借りる。

## Lensで手間を削る

　クソデカデータを作るときに`Lens`を生成するようにする。これにはTemplateHaskell拡張と`lens`パッケージの追加が必要だ。

```Haskell
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

data Hoge = Hoge
    { _nParam :: Int
    , _mParam :: Maybe Int
    , _sParam :: String
    } deriving (Show)

makeLenses ''Hoge
```

　驚くべきことに準備はこれだけで良い。`BuilderT`と`build`はそのまま使うことができる。
　さっそく使ってみよう。

```Haskell
>>> (_, hoge) <- build essential $ do
>>>     nParam .= 10
>>>     mParam .= Just 5
>>>     sParam .= "hello"
>>> print hoge
Hoge {_nParam = 10, _mParam = Just 5, _sParam = "hello"}
```

　`.=`はLensの[State Combinators](https://hackage.haskell.org/package/lens-4.19.2/docs/Control-Lens-Setter.html#g:5)と呼ばれるもので、Lensを使ってStateモナドの中の状態を変更することができる演算子だ。
　他にもたくさんのコンビネータがあるので、アレないかな？　と思って調べればあることがある。

## まとめ

　クソデカデータを作るときにビルダーモナドを作ってDSLを書くようにすると便利な場面がある。
　Lensは泥臭い実装を大幅に減らしてくれることがある。
Git操作:タグとブランチ

* [自分とこの環境下におけるGit & GitLabレクチャー](https://qiita.com/NeK/private/dee76f411cf2488b6873)

研究室ではタグとブランチを使ったルールがあるのでその概要を示す．

# 更新履歴
2024/02/29:ブランチの作成・変更にcheckoutではなくswitchを利用するように変更

# タグ
Gitではcommitする毎にその時々のファイルの状態を保存している(snapshot機能)．タグはそれに名前を付ける機能である．
例えば前の状態に戻すときにタグ名をもとにもとに戻したりできる．

タグについて詳しくは[ここ](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%82%BF%E3%82%B0)を見るがよい．

## コマンド

```
git tag -a [tag名] -m "comment"
```

* 最新のcommitしたものにtag名を付与．

```
git tag [option]
```

* タグを表示
* option
    * なし
        * 既存のタグ一覧を表示．
    * -l "検索文字列"
        * 検索文字列に指定したタグの検索・表示．

```
git show [タグ名]
```

* 指定したタグ名の詳細を表示．

```
git push [repository name] --tags
```

* 全てのタグをGitLabにアップロード
    * git pushした後はタグもアップロードする癖をつけておく 



# ブランチ

Gitにてファイルのバージョン管理を行っていると「安定版」と「機能どんど追加していく版」に分けたくなったりする．バージョンの流れを必要に応じていくつか作り，何か変になったら安定版の流れにすぐ戻せたりできると楽である．このようなバージョンの流れを<font color="Red">ブランチ(branch)</font>という．

Gitではプロジェクトを最初に作った時にmainという名前のブランチが作成され，mainブランチ上でバージョン管理が開始される．そして任意の時点で新しいブランチを作ることができ(名前は自由)，また統合できる．統合とは，二つのブランチを一つにすることで，それぞれのブランチで行った作業の結果を一つにまとめることである．もちろん全く異なる進化をとげて内容が全く違うブランチを統合することは困難を極める．しかし一つのプロジェクトから始まっているので基本的には同じ目的のものを作っているので，一般に多少の手間で統合するメリットを大きく得られる．

![branch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284261/fc1dfa5a-1441-943b-2849-1ccb42b904cf.png)

## コマンド
注意: branchのコマンド操作をする場合には，<font color="Red">commitを行ったうえでbranchのコマンドを実行すること</font>．

```
git branch [option]
```

* ブランチを見る，作成する．
* option
    * なし
        * ブランチ一覧を表示．
    * ブランチ名
        * 指定したブランチ名で新しいブランチを作成．
    * -d ブランチ名
        * 指定したブランチを削除．commitしていなかったらエラー．
    * -D ブランチ名
        * 指定したブランチを削除．commitしてなくても強制的に削除．

```
git switch [option] [branch name]
```

* ブランチを切り替える．
* option
    * なし
        * 作業するブランチをbranch nameに変更．
    * -c
        * 指定したbranch nameで新しいブランチを作成し，そのブランチに変更．git branch [branch name] && git switch [branch name]と同等．

```
git merge [branch name]
```

* 複数のブランチを統合する．現在のブランチが統合する側で，branch nameが統合される側となる．
* 例: develブランチの内容をmainブランチに取り込む場合
    * git switch main # mainブランチにしておく
    * git merge devel
【dcoker, gitlab-ci】 ERROR: unsatisfiable constraints の対応

## 問題

gitlab-ci上でこれまで正常に動いていた処理にて、`ERROR: unsatisfiable constraints` が発生
alpineイメージ絡みの問題らしい。

## エラー内容

```
$ apk add --no-cache curl jq python3 py3-pip
 fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
 fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
 ERROR: unsatisfiable constraints:
   python (missing):
     required by: world[python]
```

## 対応方法

 - pythonをバージョン2から3ににする

```
$ apk add --no-cache curl jq python py-pip
```

## 参考

github
https://github.com/docker-library/docker/commit/eb305f7
alpineリリースノート
https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.12.0#python2_no_longer_provides_python_and_python-devel
Javascript用語集



### 5-3イメージの切り替え

:sunny:マッチする要素を全て取得する

```
document.querySelectorAll('CSSセレクタ')

例：const thumbs = document.querySelectprAll('.thumb');
```


:sunny:配列の各項目を繰り返し処理する(forEachメソッド)

```
配列.forEach(function(item,index){
　　処理内容をここに書く
});

```

:sunny:Javascriptでdata-なんでも属性の値を切り替える

```
<タグ名　data-A(自由に決めて良い) = "img1.jpg">

取得した要素.dataset.A

item.onclick =function(){
  console.log(this.dataset.image);
}
```

### 属性の書き換えについて

:sunny:属性の値を読み取る

```
取得した要素.属性
```

:sunny:属性の値を書き換える

```
取得した要素.属性　= 値;
```