OmniAICreator/Qiita-1.07M huggingface dataset:
【図解付き】Docker Data Volumeのバックアップ・リストア方法

## バックアップ方法

```
$ docker run --rm --volumes-from [データボリュームのマウント先コンテナ名] -v `pwd`:/backup busybox tar cvf /backup/backup.tar [データボリュームのマウント先ディレクトリ]
```
もしくは

```
$ docker run --rm -v [データボリューム名]:[データボリュームのマウント先ディレクトリ] -v `pwd`:/backup busybox tar cvf /backup/backup.tar [データボリュームのマウント先ディレクトリ]
```

### 具体例
MySQLのデータベース情報が保存されているデータボリュームをバックアップしたい場合は以下のようになります。
データボリュームがマウントされているDBコンテナを`wp_db_con`とします。

```
$ docker run --rm --volumes-from wp_db_con -v `pwd`:/backup busybox tar cvf /backup/backup.tar /var/lib/mysql
```

図で表現すると以下のようになります。


![volume-backup-from-con-880-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140792/b06565f0-f8bb-f6a4-88d3-12385bb74fce.png)


もしくは以下のようになります。
データボリューム名を`my_wordpress_mysql_data`とします。

```
$ docker run --rm -v my_wordpress_mysql_data:/var/lib/mysql -v `pwd`:/backup busybox tar cvf /backup/backup.tar /var/lib/mysql
```

図で表現すると以下のようになります。

![volume-backup-from-volume-880-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140792/318073f3-586d-b49a-4c53-b04b51cf417a.png)



## リストア方法

```
$ docker run --rm --volumes-from [データボリュームのマウント先コンテナ名] -v `pwd`:/backup busybox tar xvf /backup/backup.tar
```

もしくは

```
$ docker run --rm -v [データボリューム名]:[データボリュームのマウント先ディレクトリ] -v `pwd`:/backup busybox tar xvf /backup/backup.tar
```

### 具体例
MySQLのデータベース情報が保存されているデータボリュームをリストアしたい場合は以下のようになります。


```
$ docker run --rm --volumes-from wp_db_con -v `pwd`:/backup busybox tar xvf /backup/backup.tar
```

もしくは以下のようになります。

```
$ docker run --rm -v my_wordpress_mysql_data:/var/lib/mysql -v `pwd`:/backup busybox tar xvf /backup/backup.tar
```


## さいごに

データボリュームのバックアップ・リストア方法の詳細については<a href="https://nishinatoshiharu.com/docker-volume-backup/" target="_blank">【Docker】具体例で理解するデータボリュームのバックアップ・リストア方法</a>でも紹介していますのでもし興味のある方はご覧になっていただければと思います。

ツイッター(<a href="https://twitter.com/nishina555" target="_blank" rel="noopener">@nishina555</a>)やってます。フォローしてもらえるとうれしいです！
Javascriptの正規表現メモ



##改行
###改行を含めたマッチ

```javascript
string.match(/([\n\r]|.)*/));
```
###改行を含めないマッチ
```javascript
string.match(/.*/));
```
##最長一致と最短一致
```javascript
// 最長一致
string.match(/PATTERN*/)

// 最短一致
string.match(/PATTERN*?/)
```
【初心者】Windowsコマンドプロンプトの使い方（基本）

こんにちは、[im90](https://twitter.com/ImMikieveryday)と申します。Udemyで現在独学中です。

私はWindowsを使っているのですが、Udemyの先生方がMacユーザーの方ばかりで、Windows用のコマンドをいちいち調べる・・という事をやっていたので、こちらにまとめることにしました。

#コンソールの開き方
左下の検索画面、もしくは「スタート」をクリックすると下に検索画面が出てくるので、そこで「コマンドプロンプト」と入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/0d967fcb-0783-831e-09eb-b3c826833221.png)
コマンドプロンプトをクリックすると、コンソールが出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/80bd7314-bcc8-718a-34f6-54a741b93fef.png)

#コマンド一覧（基礎中の基礎のみ）
###ディレクトリを見たいとき : `dir`
`dir`を入力しクリックすれば、今いる位置にどんなフォルダがあるのかを見ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/596ba3f7-1454-d4f0-a309-a6081412d4b7.png)

###ディレクトリを移動したいとき : `cd`
移動したいディレクトリ（フォルダ）のところに移動するには、`cd ディレクトリ名`で移動できます。階層を飛ばす事はできませんのでご注意ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/f4984c2a-d0ba-85f5-5ac3-6a7f8464da89.png)

一つ前のディレクトリに戻りたいときは、`cd ..`で戻ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/ff7fa4a6-b7df-9711-df2c-8bf2233c1e31.png)

ひとっ飛びで階層を移動したい場合は、`cd ディレクトリ名/下の階層/さらに下の階層`というように、`/`で区切ればOKです。

もしくは、開きたいフォルダを開いて、クイックアクセスのところに`cmd`と入力すれば、現在位置が反映された状態でコンソールが開かれるので便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/9567958e-530d-b145-a606-7965ae698c04.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/27f0375c-c06e-ceff-1cb9-518ea77d6c94.png)

###コンソールをキレイにしたいとき : `cls`
コンソールがぐちゃぐちゃになってきたら、`cls`でいったんキレイにしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461266/d8fb2fcb-d873-1855-e9ec-567f858a924a.png)


#おわり
今回は基本中の基本しか書けなかったのですが、勉強して情報を追加していきたいと思います。
CentOS 7にOpenJDK 11をインストール（Amazon Corretto）

# はじめに

Amazon Correttoを利用してCentOS7にOpenJDK11をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Debian ベースおよび RPM ベースの Linux ディストリビューションで Amazon Corretto 11 をインストールする手順 - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/generic-linux-install.html)

## サポート

本手法で導入した場合、[よくある質問 - Amazon Corretto | AWS](https://aws.amazon.com/jp/corretto/faqs/)より、2027-09がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

[Amazon Corretto 11 のダウンロード - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/downloads-list.html)より適切なファイルを確認。
リンク先のファイルが古いときは[英語版ページ](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html)を参照。

```shell-session
# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)

# yum install -y https://xxxx/11.xxxx/java-11-amazon-corretto-devel-11.xxxx.rpm
# yum install -y which
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "11.0.3" 2019-04-16 LTS
OpenJDK Runtime Environment Corretto-11.0.3.7.1 (build 11.0.3+7-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.3.7.1 (build 11.0.3+7-LTS, mixed mode)
```
CentOS 7にOpenJDK 8をインストール（Amazon Corretto）

---
# はじめに

Amazon Correttoを利用してCentOS7にOpenJDK８をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Debian ベースおよび RPM ベースの Linux ディストリビューション用の Amazon Corretto 8 のインストール手順 - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/generic-linux-install.html) 

## サポート

本手法で導入した場合、[よくある質問 - Amazon Corretto | AWS](https://aws.amazon.com/jp/corretto/faqs/)より、2026-05がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

[Amazon Corretto 8 のダウンロード - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/downloads-list.html)より適切なファイルを確認。
リンク先のファイルが古いときは[英語版ページ](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html)を参照。


```shell-session
# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)

# yum install -y https://xxxx/8.xxxx/java-1.8.0-amazon-corretto-devel-1.8.0_xxxx.rpm
# yum install -y which
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment Corretto-8.222.10.1 (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM Corretto-8.222.10.1 (build 25.222-b10, mixed mode)
```
CentOS 6にOpenJDK 11をインストール（Amazon Corretto）

# はじめに

Amazon Correttoを利用してCentOS6にOpenJDK11をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Debian ベースおよび RPM ベースの Linux ディストリビューションで Amazon Corretto 11 をインストールする手順 - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/generic-linux-install.html)

## サポート

本手法で導入した場合、[よくある質問 - Amazon Corretto | AWS](https://aws.amazon.com/jp/corretto/faqs/)より、2027-09がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

[Amazon Corretto 11 のダウンロード - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-11-ug/downloads-list.html)より適切なファイルを確認。
リンク先のファイルが古いときは[英語版ページ](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html)を参照。

```shell-session
# cat /etc/redhat-release
CentOS release 6.10 (Final)

# yum install -y https://xxxx/11.xxxx/java-11-amazon-corretto-devel-11.xxxx.rpm
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "11.0.3" 2019-04-16 LTS
OpenJDK Runtime Environment Corretto-11.0.3.7.1 (build 11.0.3+7-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.3.7.1 (build 11.0.3+7-LTS, mixed mode)
```
CentOS 6にOpenJDK 8をインストール（Amazon Corretto）

# はじめに

Amazon Correttoを利用してCentOS6にOpenJDK8をインストール
親記事：[OpenJDKの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/b179202216aab50b7090)
参考：[Debian ベースおよび RPM ベースの Linux ディストリビューション用の Amazon Corretto 8 のインストール手順 - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/generic-linux-install.html)

## サポート

本手法で導入した場合、[よくある質問 - Amazon Corretto | AWS](https://aws.amazon.com/jp/corretto/faqs/)より、2026-05がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## LOG

### インストール

[Amazon Corretto 8 のダウンロード - Amazon Corretto](https://docs.aws.amazon.com/ja_jp/corretto/latest/corretto-8-ug/downloads-list.html)より適切なファイルを確認。
リンク先のファイルが古いときは[英語版ページ](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html)を参照。

```shell-session
# cat /etc/redhat-release
CentOS release 6.10 (Final)

# yum install -y https://xxxx/8.xxxx/java-1.8.0-amazon-corretto-devel-1.8.0_xxxx.rpm
... 略
```

### 各種確認

```shell-session
# which java
/usr/bin/java

# java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment Corretto-8.222.10.1 (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM Corretto-8.222.10.1 (build 25.222-b10, mixed mode)
```
iOS13 での問題

iOS 13 がリリースされ、既存のアプリで問題が発生しているようなので、気づいたことをメモしたいと思います。

##iOS 13 での問題
- iPhone の電話履歴からVoIPアプリで発信できない
- iPad OS 13 で、[UIDocumentInteractionController](https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller) で開く共有の画面が正しく表示されない

##iPhone の電話履歴からVoIPアプリで発信できない

iPhone の電話帳や履歴から発信した場合、VoIP アプリの [application(_:continue:restorationHandler:)](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623072-application) が呼び出されます。
音声通話であれば [INStartAudioCallIntent](https://developer.apple.com/documentation/sirikit/instartaudiocallintent)、ビデオ通話であれば [INStartVideoCallIntent](https://developer.apple.com/documentation/sirikit/instartvideocallintent) が [userActivity](https://developer.apple.com/documentation/foundation/nsuseractivity).[interaction](https://developer.apple.com/documentation/foundation/nsuseractivity/1690346-interaction).[intent](https://developer.apple.com/documentation/sirikit/ininteraction/1638928-intent) に渡されます。
　
いえ、iOS 12 までは渡されていました・・・
　
iOS 13 では [INStartCallIntent](https://developer.apple.com/documentation/sirikit/instartcallintent) が渡されてくるようになりました。
音声かビデオかを判断するのは Intent の種類ではなく、[INStartCallIntent.callCapability](https://developer.apple.com/documentation/sirikit/instartcallintent/3165942-callcapability) で判断するようになります。
　
この渡される Intent が変更された件、困ったことに xcoode 11(iOS13 SDK) でビルドしたものではなく、xcode 10.x でビルドしたアプリも同じです・・・
　
VoIP アプリでは [application(_:continue:restorationHandler:)](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623072-application) に渡されてくる Intent から [contacts](https://developer.apple.com/documentation/sirikit/instartcallintent/3165943-contacts) を取得します。
Swift の場合、Intent をキャストした際、型が合わないと nil となりますが、Objective-C の場合、キャストしてもエラーにならず、存在しないメンバにアクセスした際に初めてエラーとなります。
したがって、contacts は INStartAudioCallIntent も INStartCallIntent にも含まれているため、Objective-C で書かれたプログラムでは書き方次第では iOS 13 でも動いているようです。

###2020/02/12 追記
あれ？
iOS 13.2.x では、userActivity.activityType が "INStartAudioCallIntent" になっていますね。。。
iOS 13.1.x では、INStartCallIntent だったのですが、Apple が修正したのでしょうか・・・？

##iPad OS 13 で、UIDocumentInteractionController で開く共有の画面が正しく表示されない
ファイルや写真などを他のアプリに共有する際に使用する [UIDocumentInteractionController](https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller) ですが、よくある書き方として以下のようなコードが散見されます。

```Swift
uiDocumentInteractionController.presentOpenInMenu(from: view.frame, in: view, animated: true) 
```
[UITabBarController](https://developer.apple.com/documentation/uikit/uitabbarcontroller) に追加した [ViewController](https://developer.apple.com/documentation/uikit/uiviewcontroller) の中でこのコードを実行すると、iPad OS 13 では、共有先選択画面が Tab のところに小さくなって表示されます。
View の下端に表示しようとするが、Tab の高さしかないため縦が小さくなっているのではないかと思われます。
よって、iPad OS 13 対応するためには、from と in に上の方にあるコントロールを指定する工夫が必要なようです。（バグとして iOS 側で修正が入るかもしれませんが・・・）
　
しかし、from と in を上方のコントロールに指定して、xcode 10.x でビルドしたところ、iPhone (iOS 13) では共有先選択画面が全画面表示してしまいました。。。
まぁ、見えないよりぜんぜん良いのですけどね。。。
　
ちなみに同じコードを xcode 11 でビルドすると、いつものように下半分くらいに共有先選択画面が表示されます。。。

Apple さん・・・・・
【Python入門】Pyenv環境設定

##目的
・pyenvを導入しPythonの複数バージョンを使い分けられる環境を準備する

##環境
| 項目 | 内容 |
|----------|:--------------:|
| Host OS | Windows10 |
| 仮想ツール | VirtualBox Ver.5.2.16 |
| 仮想 OS | Ubuntu 16.04 |

##作業環境前提
（1）Windows10上にVirtualBoxがインストール済み
（2）VirtualBox上にUbuntu16.04が設置済み

##作業の流れ
（1）下準備
（2）Pyenvをクローン
（3）Pyenvの設定
（4）Pyenvを使ってみる

##内容
（1）下準備
　・Ubuntuのターミナルを起動し下記コマンドを実行

```ubuntu:terminal
$ sudo apt-get -y update
$ sudo apt-get -y upgrade
$ sudo apt-get -y install git vim gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
```

（2）Pyenvをクローン
　・（1）同様に続けて下記コマンドを実行

```ubuntu:terminal
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```

　・無事実行できたら、カレントディレクトリの状態を確認

```ubuntu:terminal
$ ls -al
```

　▼実行結果
![o0915060414248329490.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/a7c66fa2-0db9-b769-3cc7-91bef0c8251a.jpeg)
　※「.pyenv」というフォルダが作成されている


（3）Pyenvの設定
　・下記の記述を「.profile」に追記する

　▼Vimを使って当該ファイルを編集

```ubuntu:terminal
$ sudo vi ~/.profile
```

　▼追記内容

```ubuntu:vim(.profile)
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
```

　▼編集時の画面
![o0911054714248329449.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/7515db80-a173-c63f-a8bb-949ff887dd78.jpeg)

　・フォルダの所有者を変更

　▼所有者とグループ確認

```ubuntu:terminal
$ ls -al
```

　▼表示結果抜粋
![o0911002214248333044.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/4fb9eac2-07be-72c7-77e4-f1be2643c30b.jpeg)

　▼所有者をrootからubuntuユーザへ変更

```ubuntu:terminal
$ sudo chown ubuntu:root ~/.pyenv
```

　▼設定内容を即座に反映

```ubuntu:terminal
$ source ~/.profile
```

（4）Pyenvを使ってみる
　・お試しとして、Python3 の Ver.3.6.6 をインストールしてみる

　▼まずはインストール可能なリストを確認

```ubuntu:terminal
$ pyenv install --list
```

　▼実行結果
![o0912039114248336901.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/a22b0fa9-78d9-44e0-941b-2113669e727e.jpeg)

　▼Ver.3.6.6 をインストールし現在利用可能なバージョンリストを確認

```ubuntu:terminal
$ pyenv install 3.6.6
$ pyenv versions
```

　▼実行結果
![o0916009314248343342.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/79da6511-3cd9-6a0c-cd9f-bbaeb663a013.jpeg)

　▼とりあえず、どの環境でも python3.6.6 が実行されるよう設定

```ubuntu:terminal
$ pyenv global 3.6.6
$ pyenv rehash
$ pyenv versions
```

　▼実行結果
![o0914010714248343414.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/5ecce65a-d297-a637-6ba0-bad287c0eab6.jpeg)

　▼最後に python コマンドを実行し実際に設定したバージョンで起動するか確認
![o0916009114248343704.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487902/a20bbd37-22c1-29ac-1eb6-a585bec800e6.jpeg)

以上！

##まとめ
・今回は、グローバルで設定しましたが、ワーキングフォルダ別に、利用するPythonのバージョンを分ける設定も可能ですので、色々試してみると面白いです。
IPAのネットワークスペシャリスト試験の過去問一括ダウンロードスクリプト

IPAのネットワークスペシャリスト試験の過去問を一括ダウンロードするスクリプト。
平成16年～平成20年は、午前がまとまっているので、午後の問題のみ。

### スクリプトはこんな感じ

```shell
#!/bin/bash

# *****************************************************************************
# * ネットワークスペシャリスト試験の過去問一括ダウンロードスクリプト
# *****************************************************************************

first_year=16 # 平成16年から
last_year=30  # 平成30年まで

base_url='https://www.jitec.ipa.go.jp/1_04hanni_sukiru'
dl_dir='dist'

dl_pdf() {
  year_label="${1}h${2}"
  fname="$3"

  url="${base_url}/mondai_kaitou_${year_label}_2/${year_label}a_${fname}.pdf"
  echo "#### DOWNLOAD: ${url}"

  wget ${url} -P "./${dl_dir}"
  sleep 1  # 1秒待つ
}

rm -rf ${dl_dir}
mkdir ${dl_dir}

for i in `seq ${first_year} ${last_year} | sort -r`;do
  year="$((1988 + i))"
  year2="${i}"
  echo "${year} - ${year2}"
  if [ $year2 -gt 21 ]; then
    dl_pdf "$year" "$year2" 'nw_am2_qs'
    dl_pdf "$year" "$year2" 'nw_am2_ans'
    dl_pdf "$year" "$year2" 'nw_pm1_qs'
    dl_pdf "$year" "$year2" 'nw_pm1_ans'
    dl_pdf "$year" "$year2" 'nw_pm1_cmnt'
    dl_pdf "$year" "$year2" 'nw_pm2_qs'
    dl_pdf "$year" "$year2" 'nw_pm2_ans'
    dl_pdf "$year" "$year2" 'nw_pm2_cmnt'
  elif [ $year2 -gt 18 ]; then
    dl_pdf "$year" "$year2" 'nw_pm1_qs'
    dl_pdf "$year" "$year2" 'nw_pm1_ans'
    dl_pdf "$year" "$year2" 'nw_pm1_cmnt'
    dl_pdf "$year" "$year2" 'nw_pm2_qs'
    dl_pdf "$year" "$year2" 'nw_pm2_ans'
    dl_pdf "$year" "$year2" 'nw_pm2_cmnt'
  else
    dl_pdf "$year" "$year2" 'nw_pm1_qs'
    dl_pdf "$year" "$year2" 'nw_pm1_ans'
    dl_pdf "$year" "$year2" 'nw_pm2_qs'
    dl_pdf "$year" "$year2" 'nw_pm2_ans'
  fi
done
```

こんな感じで実行すると...

```console
$ bash download_pdf_nw.sh 2>&1
```

こんな感じにdist配下にPDFをダウンロードしてきます。

<img width="457" alt="スクリーンショット 2019-10-12 12.22.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/576e7a19-7547-77f1-446d-750ae25aa018.png">

あとは、好きなのを印刷すればOK(*´ω｀*)


システムアーキテクトやデータベーススペシャリスト版はこちら。
・[システムアーキテクト試験の過去問一括ダウンロードスクリプト - くらげになりたい。](https://www.memory-lovers.blog/entry/2018/10/26/155638)
・[データベーススペシャリスト試験の過去問一括ダウンロードスクリプト - くらげになりたい。](https://www.memory-lovers.blog/entry/2019/04/07/130258)

以上！！

## こんなのつくってます!!

積読用の読書管理アプリ 『積読ハウマッチ』をリリースしました！
[積読ハウマッチ](https://tsundoku.site)は、Nuxt.js+Firebaseで開発してます!

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="200"/>

もしよかったら、遊んでみてくださいヽ(=´▽`=)ﾉ

要望・感想・アドバイスなどあれば、
公式アカウント([@MemoryLoverz](https://twitter.com/MemoryLoverz))や開発者([@kira_puka](https://twitter.com/kira_puka))まで♪
GitHub API v4 を適当な知識で使ってみる

## ドキュメント

- [GraphQL API v4 - GitHub Developer](https://developer.github.com/v4/)
- [GraphQL API v4 - GitHub Developer (Enterprise)](https://developer.github.com/enterprise/2.17/v4/)

## GraphQL クライアントの選択

GraphQL API を呼ぶためのクライアントは色々あります。

- [GraphiQL](https://github.com/skevy/graphiql-app)
- [Altair GraphQL Client](https://altair.sirmuel.design) ([Chrome extension](https://chrome.google.com/webstore/detail/altair-graphql-client/flnheeellpciglgpaodhkhmapeljopja))
- [GitHub GraphQL API Explorer](https://developer.github.com/v4/explorer/)

GitHub API 専用の GitHub GraphQL API Explorer を使うのが手っ取り早いかもしれませんが、ここでは Altair (アルタイル) を使ってみたいと思います。

## Altair の起動

サイトから Altair の Chrome extension をインストールして起動すると、以下のような画面が表示されます。エンドポイントに以下を入力し、おもむろに「Send Request」してみると、当然、認証エラーになります。

- GitHub `https://api.github.com/graphql`
- GitHub Enterprise の場合 `http(s)://[hostname]/api/graphql`

![認証失敗](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2019/10/12/f213f1be-3e35-40a6-96f4-861d79e153a2.png)

### 認証

GitHub にログインし、Settings > Developer Settings > Personal access tokens から、アクセストークンを生成します。アクセストークンには「Fine-grained tokens (Beta)」と「Tokens (classic)」に 2 種類があり、前者はより細かい権限設定ですが、ここでは「Tokens (classic)」を使いました。

「Scopes」には API 呼び出しに必要な権限を選択します。ここで設定した権限に不足がある場合は API 実行時に認可エラーになりますが、あとから設定変更もできるのでまずは適当に。とりあえず変なことはできないよう Read 系のみにするのが無難かと思います。

![Generate access token](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2019/10/12/bc399b73-2aea-4459-bee9-545136fb9946.png)

アクセストークンは一度しか表示されないので、忘れずにメモっておきます。

![Access token generated](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2019/10/12/bc8c46b6-21f6-4b13-ac99-ccadef20d66c.png)

生成したアクセストークンを使ってリクエストするため、Altair の画面左のナビゲーションにある「Set Headers」をクリックし、以下のように入力します。これにより、以降のリクエストすべてに設定したヘッダが送信されます。

|Header key|Header value|
|:--|:--|
|Authorization|bearer (アクセストークン)|

![Set headers](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2019/10/12/e23f89eb-3271-4ce9-b315-01a330f9185f.png)

### API ドキュメントの参照

「Send Request」の左にある「Docs」をクリックし、さらにその左の「Reload Docs」をクリックすると、認証が正常に通れば API ドキュメントが表示されます。「Query」は読み込み API、「Mutation」は書き込み API と分かれているので、まずは「Query」をクリックして確認してみましょう。API 一覧が表示されるので、好きなものをホバーして、表示される「ADD QUERY」ボタンをクリックすると、その API を呼ぶクエリの雛形がクエリペインに設定されます。

たとえば user のクエリは以下のようになりました。

```graphql

query{
  user(login: ______){
    anyPinnableItems(type: ______)
    avatarUrl(size: ______)
    bio
    bioHTML
    ...
  }
}
```

埋める必要のあるところは「______」になっていてそのままではエラーになるので、条件を埋めたり、取得する必要のないものは削除したりして、エラーが消えたら「Send Request」をおこないます。

## 実行例

![Query user](https://hirose-public.s3-ap-northeast-1.amazonaws.com/qiita/2020/07/04/4caabcec-6aa0-4dfe-93a6-478b8f968697.png)

## まとめ

GraphQL では API 仕様が実装に直結した形で取得できるため、クエリを自動生成する仕組みもクライアントで実装しやすく、ドキュメントとにらめっこしなくても適当に呼び出してみることができます。GraphQL として、読み取り専用の「Query」と、書き込みが発生する「Mutation」が明確に分かれているので、Query だけであれば怖がらずに試すことができます。より活用するには GitHub の API ドキュメントを参照しましょう！
複数列に同じ処理―Power Query反復処理①

最初の頃は分からず、対象が多い場合、Excelのワークシートでコードを複製したりしてました。そんな必要はないわけです。

##やろうとすること
後述のサンプルテーブルに対して、これの各列に同じ処理をしようというのが、今回の課題です。
簡単な例として、100を掛けてみましょう。

##サンプルテーブル
下記を詳細エディタに貼ると、テーブルになります。

```pq:サンプル
let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("ZY7LEcAgCAV74ewBNRo9JimDof82osEPTA46zLo+HhFc4OBu5wF2BCdim8u6O+tz+EgeJCirDhZxe8dgkiYvHo1YjSgsTVGxaKpUtWQFeiXGzXZFm5h/v2cTB4KKath3Mb8=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Column1 = _t, 列1 = _t, 列2 = _t]),
    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"A", Int64.Type}, {"B", Int64.Type}, {"C", Int64.Type}})
in
    #"Changed Type"
```
↓こんなテーブルです。

|A|B|C|
|---|---|---|
|700|800|800|
|0|200|600|
|200|800|900|
|300|200|400|
|700|300|1000|
|300|900|400|
|300|500|100|
|300|300|800|
|900|200|1000|
|100|300|300|
|1000|800|100|
|300|600|1000|
|1000|400|0|
|800|900|200|


##出発点：UI操作のみだと複数ステップを作るしかない
1列だと、UIの変換―標準のボタンが押せますが、複数列になると、グレーアウトしてしまいます。
1列ずつやれということらしいです。

##UI操作+αでいく
1列でやったコードを列分複製するというてもありますが、ここは別の方法でやってみましょう。
というのも、まとめての掛け算はできないのに、平方根など他の処理だと、まとめて処理ができたりするからです。なので、平方根をやっておいて、コードを書き換えることもできます。

###平方根をとる
UI操作：変換タブ―「数値の列」グループの「指数」―平方根
↓操作後の様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370992/91d314b3-c17d-a258-44c4-4ccbabb36036.png)

###コードを書き換える
`{"A", Number.Sqrt, type number}`といった部分の関数の箇所`Number.Sqrt`をそれぞれ、`each _*100`と書き換えるだけです。
この`_`（アンダーバー）のところに、その列の各値が引数として放り込まれるわけです。

↓出来上がり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370992/b8112b22-4b6c-5beb-b829-166f59f44db5.png)


##コードで書く
UI+αではいずれにしても、各列に応じて書き直しが必要になります。
コードをしっかり書けば、繰り返し書く必要はなくなります。

###全部の列を処理するコード
```
let
    Source = t_sample,
    Custom1 = Table.TransformColumns(Source,
                   List.Transform( Table.ColumnNames(Source),each {_,(x)=>x*100} )
              )
in
    Custom1
```
###捕捉
上のコードの`Table.ColumnNames(Source)`の箇所は列名のリストです。この例だと、

```
{"A","B","C"}
```
と書くのと結果は同じです。このリストを書き換えることで、処理対象を絞ることが出来ます。
例えば、B列は処理したくない場合、

```
List.RemoveMatchingItems(
  Table.ColumnNames(Source),{"B"}
)
```

とすればよいです。
↓書き換えたバージョンの様子
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370992/eb891b65-0703-510c-7166-c5c23f756651.png)
NumPyとpandas

いつもごっちゃになるので整理のため

NumPy
多次元配列。データの格納と操作を行うためによく使われる。

pandas
NumPyをベースとするライブラリ。
pandasはより高レベルなデータ操作ツールを提供する。


これらのツールを用いることで、表形式のデータの操作が更に便利になる。
$clog2によるビット幅算出のよくある間違い

\\$clog2()は2を基数としたlogの値を整数に切り上げした値(Ceiling Log2)を返すSystemVerilogのシステムタスクである。
ある値を表現するのに必要なビット数を計算するのによく使われ、そのように解説しているページをよく見かける。その事自体は正しいが、その使用方法の解説の多くが必ずしも正しくはないので、正しい解説をしておこうと思う。
尚、頂いたコメントの情報では、Vivadoの古いバージョンで\\$clog2()が切り下げの処理になってしまっており、正しく計算されない場合があるそうです。なので古いVivadoを使っていた人が記事を書いた場合そのような解説になっている可能性があるとの事です。Vivadoを使っていて\\$clog2の値がどうもおかしい場合にはバージョンを確認してみて下さい。

例えば0~7までの値を取る信号の場合ビット幅は\[2:0\]の3bitである。
\\$clog2(7)は3 (log2(7) = 2.???)なので\[\\$clog2(7)-1:0\]のビット幅となる。最大値7をパラメータ化して

```verilog:
parameter  MAX_VAL = 7;
parameter  WIDTH   = $clog2(MAX_VAL);  // 3
logic[WIDTH - 1 : 0]  val;
```

のように書ける。このような解説のページが多い。しかしこれは必ずしも正しくない。これが正しいのはMAX_VALが2のべき乗以外の場合のみである。
2のべき乗の時、例えば8の場合を見てみよう。
0~8の値を表すには0000~1000なので必要ビット幅は\[3:0\]の4bitとなる。それに対して\\$clog2(8)は3となる。なので、

```verilog:
parameter  MAX_VAL = 8;
parameter  WIDTH   = $clog2(MAX_VAL);  // 3
logic[WIDTH - 1 : 0]  val;
```

は間違っており、思わぬバグとなってしまう。じゃあどうすれば良いかと言うと

```verilog:
parameter  MAX_VAL = 8;
parameter  WIDTH   = $clog2(MAX_VAL+1);  // 4
logic[WIDTH - 1 : 0]  val;
```

が正しい。

\\$clog2(1) = 0  // log2(1) = 0
\\$clog2(2) = 1  // log2(2) = 1
\\$clog2(3) = 2  // log2(3) = 1.???
\\$clog2(4) = 2  // log2(4) = 2
\\$clog2(5) = 3  // log2(5) = 2.???
\\$clog2(6) = 3  // log2(6) = 2.???
\\$clog2(7) = 3  // log2(7) = 2.???
\\$clog2(8) = 3  // log2(8) = 3

と3は一つ上の2のべき乗の数4の仲間、5,6,7は8の仲間なのである。4は3ではなくて5,6,7の仲間に入れたい。8は9~15の仲間に入れたい。なので一つずらす為に+1をすればいいのである。

\\$clog2(1 + 1) = 1  // log(2) = 1
\\$clog2(2 + 1) = 2  // log(3) = 1.???
\\$clog2(3 + 1) = 2  // log(4) = 2
\\$clog2(4 + 1) = 3  // log(5) = 2.???
\\$clog2(5 + 1) = 3  // log(6) = 2.???
\\$clog2(6 + 1) = 3  // log(7) = 2.???
\\$clog2(7 + 1) = 3  // log(8) = 3
\\$clog2(8 + 1) = 4  // log(9) = 3.???

上記の例は信号の最大値 MAX_VALをパラメータにして必要バス幅を求めたが、メモリのワード数や配列の要素数からアドレスに必要なビット幅を求めるはどうするか考えてみよう。ワード数が8のメモリ或いは要素数が8個の配列の場合、アドレスは0~7の8個で

```verilog:
parameter  MEM_DEPTH = 8;
parameter  ADD_WIDTH = $clog2(MEM_DEPTH);  // 3
logic[ADD_WIDTH - 1 : 0]  addr;
logic[31:0]  mem[MEM_DEPTH];
```

となる。この場合にはMEM_DEPTHが他のどんな値でも正しい。なぜならアドレスが最大値7の0~7という**8種類**の値を取ると言うのをパラメータ MEM_DEPTHで使用したからである。つまりMEM_DEPTH = MAX_VAL + 1と最初から+1されてるからである。
要するに
**\\$clog2()を使って必要ビット幅を算出する場合、最大値で考えた場合+1が必要、個数で考えた場合はそのままの値でOK**
となる。

「\\$clog2()を使えば必要ビット幅が分かるんだ！」と慌てて飛び付くとこのような落とし穴にはまってしまうので十分気を付けてほしい。
cypherで「特定のnodeと同じ繋がりを持つnode」を探す

## 何がしたかったのか

例えばこんなグラフDBのデータがあったとします

```
CREATE
(q1:Question{questionId: randomUUID()}),
(q1)<-[:BELONGS_TO]-(a1:Answer{choice:1}),
(q1)<-[:BELONGS_TO]-(a2:Answer{choice:2}),
(q1)<-[:BELONGS_TO]-(a3:Answer{choice:3}),
(q1)<-[:BELONGS_TO]-(a4:Answer{choice:4}),

(q2:Question{questionId: randomUUID()}),
(q2)<-[:BELONGS_TO]-(a5:Answer{choice:1}),
(q2)<-[:BELONGS_TO]-(a6:Answer{choice:2}),
(q2)<-[:BELONGS_TO]-(a7:Answer{choice:3}),
(q2)<-[:BELONGS_TO]-(a8:Answer{choice:4})
```

４択問題があって、その質問（Question）と回答（Answer）が紐づいています。
とあるユーザが４択問題に回答した時は、こんなクエリを実行します

```
MATCH
(u:User{userId:'hoge'})

CREATE
(u)-[:CHOSE]->(a1),
(u)-[:CHOSE]->(a6)
```

これでユーザーhogeさんが、質問１に対して「１」、質問２に対して「２」と答えた状態が保存されます。


`ユーザーhogeさんと全問同じ回答のユーザを取得したい`

これが今回の目的です。

## 何も考えずに書いてみる

```
MATCH
(u:User{userId:'hoge'})-[:CHOSE]->(a:Answer),
(a)<-[:CHOSE]-(users:User)
RETURN
users
```

これだと「hogeさんと一つでも同じ回答をしたユーザ」を取得してしまいますから、「全問同じ回答のユーザ」ではありませんね。

## WHERE ALL を使う

```
MATCH (u:User{userId:"hoge"})-[:CHOSE]->(a:Answer)
WITH collect(a) as answers
WHERE ALL(answer in answers WHERE (u2:User)-[:CHOSE]-(answer))
return u2
```

ここでWITHとALL()を使ってみます。

ALL()は、LISTの全要素が与えられた条件を満たす場合にtrueを返します。
それを応用して、ここでは`hogeさんが選んだAnswerのLISTの全要素に対して[:CHOSE]を貼っているユーザを抽出する`というクエリを書いています。

ALL()を使うためにはLIST化する必要があるので、collect(ノード） as answers（LIST）で前処理を施しています。

これで表題の問題は解決です。


## もうちょっとクエリの効率を改善する
この状態だとクエリの効率が悪いので、少しだけ改善を試みます。

```
MATCH (u:User{userId:"1234"})-[:CHOSE]->(a:Answer)
WITH collect(a) as answers
WITH head(answers) as head, tail(answers) as answers
MATCH (u2:User)-[:CHOSE]-(head)
WHERE ALL(answer in answers WHERE (u2)-[:CHOSE]-(answer))
return u2
```

追加したのは以下２行です

```
WITH head(answers) as head, tail(answers) as answers
MATCH (u2:User)-[:CHOSE]-(head)
```

head()は与えられたLISTの最初の要素のみ抽出し、tail()は与えられたLISTの最初の要素`以外`を抽出します。（なんかセットに使われる事を前提に作られたリスト関数に見えるけど、tailを独立して使う事あるのかな・・・）

要は`なんでもいいからhogeさんの回答と同じ回答を１つ持つユーザに、最初に絞っておく`ことで、一問でも異なる回答をしたユーザを最初に弾いて、後の計算量を減らしています。２択問題だとユーザが絞りきれないのでイマイチかもしれませんが、１〜１０のスケールとか、一致する確率が低い問題になるほど効率化が図れるのではないでしょうか。


## まとめ

- all()を使う
- head/tailを使うと、LISTマッチ系のクエリは少し効率化できる場合がある



以上、apoc使わずintersectionを実装するとこんな感じだよ、という紹介でした
Simulinkで日付情報を表示する

# はじめに
前記事にて、その際に、時刻情報を数値データで出力してましたので、それを見やすくるする方法を記載します。
[M-FunctionでのMATLAB関数の使い方とmxArrayエラーの回避方法](https://qiita.com/nakaziki/items/623f55b3641570a21f47)


ここで起きている問題は、データ線には文字列を流すことはできないという点です
そのため解決策として、
・理解できる数値情報に分解して流す
・文字列をグラフなどに出力する

#1.文字列をSimulinkのデータ線に流すことはできない
前回の記事で、図のようなM-Functionを作成することで、日付情報を出力することができました。
![時刻出力成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/d56e54ed-e6d1-3c77-97a8-0701988f61e1.png)

ただ、数値のままでは読めないので、文字列にしたいと思いますが、
Simulinkのデータ線には文字列（String）のデータを流すことはできないので、
下記のようにしてもエラーになってしまいます。
![文字列出力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/6f1a6459-88d5-a555-9d27-ce1b926bbe59.png) 
![文字列出力エラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/21ad4162-9836-4521-2502-c29185a7479f.png)


#2.数値データを分割して出力
取得した時刻データを、datetime関数を使って時・分・秒の数値データに分け、
その結果を各displayに出力します。
![時分秒出力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/d4c9cbc8-f24f-09b3-e29f-059e459d386d.png)
![時分秒出力モデル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/5523726e-127b-c1fc-5be2-f625f6c61c99.png)
15(時) 19(分) 27.9(秒)と読めますね。

#3.Figureに出力
文字列を直接表示するモデルはありませんが、図には表示する機能があるので、それを利用します。
時刻を取得したM-Functionの中で、新しい図を開き、そのタイトルに日付の文字列をセットすると、
現在時刻を表示できます。
![時刻の図出力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/f2ae4646-c795-4a49-0943-8a8ebab02c41.png)
![時刻の図出力グラフ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406714/5ce84923-327b-d437-5bce-88f6f99051fd.png)

なお、figureの番号を指定しておかないと、新しい図がどんどん作られたり、他の処理で図を使っていると
そっちのタイトルが変更されてしまうので注意です。
また、今回は楽なのでタイトルを使いましたが、テキスト(text)や注釈(annotation)などを使えば
好きな位置に表示できます。

#おわりに
以上で現在時刻のリアルタイム表示ができました。
はっきりいって全然スマートな表示ではありませんが、比較的シンプルなことや、
他の文字列情報への対応も可能と言えばそうなので、何かの役に立てたら幸いです。

以上です。
JavaScriptで配列を一時的に逆順にしたい場合は slice().reverse()

JavaScriptで配列を逆順にするには、`reverse()` メソッドを使います。

```javascript
var table = ['a', 'b', 'c'];
console.log(table.reverse());
```

しかし、このメソッドは配列自体を加工してしまうため、それ以降配列が常に逆順になってしまいます。

表示するときだけ逆順にしたいなどの場合は、別の配列に移してもよいですが次のようにすると手軽です。

```javascript
console.log(table.slice().reverse());
```
webpacker の check_yarn_integrity オプションについて調べてみた

## はじめに

Rails アプリで [webpacker](https://github.com/rails/webpacker) を利用するケースが増えていると思います。Rails 5.1以上のアプリでは、`rails new myapp --webpack` というオプションをつける形でも webpacker をインストールできるようになっていますよね。

しかし個人的に、使い方を理解しきれていないことが多いです。そこで理解するためのとっかかりとして、`config/webpacker.yml` のオプションを調べてみようと思い、その中の `check_yarn_integrity` というオプションについて手始めに調べてみました。

## 何をするオプションなのか

[webpacker の README](https://github.com/rails/webpacker#yarn-integrity) を抜粋します。

```
By default, in development, webpacker runs a yarn integrity check to ensure that all local JavaScript packages are up-to-date.
This is similar to what bundler does currently in Rails, but for JavaScript packages.
If your system is out of date, then Rails will not initialize.
You will be asked to upgrade your local JavaScript packages by running yarn install.
```

こちらを意訳してみました。

* development 環境では、ローカルの全ての JavaScript パッケージが最新であるかを  yarn integrity check する
* Rails の `bundler` がやっていることと似てるが、これは JavaScript 用
* システムが古くなっていると、Rails は初期化されない
* `yarn install` でローカルの JavaScript パッケージをアップグレードするか尋ねられるようになる

## 実施していること

実際関連しているコード部分を抜粋すると以下になります。

https://github.com/rails/webpacker/blob/8845f37bb038ad0adff813326a7d6a034b9b9a81/lib/webpacker/railtie.rb#L16-L51

`config.webpacker.check_yarn_integrity = true`  にしておけば、`rails c` や `rails s` といった Rails アプリケーションを起動する際の初期化時に、 `yarn check --integrity` を実行し、エラーが出たら以下のようなエラーメッセージを出力してくれるようです。

```
========================================
  Your Yarn packages are out of date!
  Please run `yarn install` to update.
========================================


To disable this check, please add `config.webpacker.check_yarn_integrity = false`
to your Rails development config file (config/environments/development.rb).
```

不要な場合は `config.webpacker.check_yarn_integrity = false` にすれば OK のようです。 
パッケージが古くなっていたらエラーで知らせてくれるということなので、パッケージを最新の状態に保つ手助けになりそうですね。

## おわりに

JavaScript のパッケージ管理は複雑で理解が難しいですね。根気よく学習していきたいと思います。

## 参考

* [GitHub - rails/webpacker: Use Webpack to manage app-like JavaScript modules in Rails](https://github.com/rails/webpacker)

* [【保存版】Rails 5 Webpacker公式ドキュメントの歩き方+追加情報](https://techracho.bpsinc.jp/hachi8833/2018_05_17/56568)
* [Rails の初期化プロセス](https://railsguides.jp/initialization.html)
* [yarn check](https://yarnpkg.com/lang/ja/docs/cli/check/)
ビジネスロジックに関わるテストでは非プログラマ表現でテストケースの説明部分を書いてほしい

# 例

```
test 'buckets テーブルに apple レコード3個あることを検証する'
```

```
test 'バケットにりんごが3個ある'
```

どっちで書く？

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2574








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
初心者　Linuxコマンドその他用語集

①Linuxコマンド...LinuxというOSにコマンドを書いてCUIで操作するもの。

②CUI...Character User Interfaceの略。
マウスでクリックするとファイルが開かれるように絵やアイコンで操作する環境できる。
GUI(Graphical User Interface)とは違って文字のみで操作することを指す。主にターミナルを使っていく。

③ディレクトリ..端的にいうとフォルダの事を指す。 
/desktop/ファイル名/の様なディレクトリ階層の事をパスと呼ぶ。

基本的なLinuxコマンド一覧

| comaand    | 正式名称 | 意味 |
| :-:|:-:|:-:|
|    mkdir   |make directory   |  ディレクトリの作成 |
|  cd |  change directory | ディレクトリの移動  |
| ls  | list  | ディレクトリの中身を表示  |
| pwd  |print working directory   |現在のディレクトリの位置を確認する |
|  mv | move  |  ファイルの移動、ファイルの名前の変更(mv既存のファイル名　新しいファイル名 |
| rm  |remove   |  ファイルの削除 |
|touch |  touch    |  新規ファイルの作成、ファイルのタイムスタンプの変更 |
|  man |  manual |  マニュアルの表示 |
v-ifの条件式で比較演算子（＝＝）を使いたいメモ

すごい簡単なことだが、
Vue.jsの```v-if```の条件式で比較演算子（＝＝）を使用したいと思ったところ、
公式を見てもわかりにくかったのでメモ。

#コードを見れば一発

```vuejs

<template>
  <div>
    <button v-if="this.id == 1">新規作成</button>
  </div>
</template>

<script>
export default {
  name: "TestBtn",
  data: function(){
    return {
      id: 1
    }
  },
};
</script>
```
※コードは一部抜粋

vi-ifの中で条件式を書けばいいだけ。
権限が１なら、新規作成ができるみたいなイメージ。


これだけじゃ、味気ないので、
ボタンをクリックしたら、idを変更して、
新規作成ボタンが非表示になることも確認。


```vuejs

<template>
  <div>
    <button v-if="this.id == 1" v-on:click="changeId">新規作成</button>
  </div>
</template>

<script>
export default {
  name: "TestBtn",
  data: function(){
    return {
      id: 1
    }
  },
  methods: {
    changeRoleId: function() {
      this.id = 2;
    }
  }
};
</script>
```

リアクティブに動いていることを確認できました〜
【編集中】Jboss7でのUT000047: The number of parameters exceeded the maximum of ～

        <property name="org.apache.tomcat.util.http.Parameters.MAX_COUNT" value="5000"/>

↓

standalone.xmlのsystem-propertiesのMAX_COUNTをHTTP Listener、HTTPS Listenerに移行する。

```
<system-properties>
  <property name="org.apache.tomcat.util.http.Parameters.MAX_COUNT" value="7000"/>
  ・・・
</system-properties>

<subsystem xmlns="urn:jboss:domain:undertow:4.0">
  <buffer-cache name="default"/>
    <server name="default-server">
      <http-listener name="default" socket-binding="http" max-parameters="7000" redirect-socket="https" enable-http2="true"/>
      <https-listener name="https" socket-binding="https" max-parameters="7000" security-realm="ApplicationRealm" enable-http2="true"/>
```
VirtualBox でクローンすると ip address がおかしくなる現象について

VirtualBox でクローンすると ip address がおかしくなる現象について、解決策のメモです。

```
    1. クローン対象のマシンを立ち上げます。
    2. 以下のファイルを削除します。
    /etc/udev/rules.d/70-persistent-net.rules
    3. マシンをシャットダウンします。
    # shutdown -h now
    4. クローンします（MAC アドレスを再初期化にチェックを入れますFULL CLONE）
    5. 作成されたマシンを立ち上げます
    6. /etc/udev/rules.d/70-persistent-net.rules を削除します。
    7. マシンを再起動します。
    8. ip a コマンドを実行して、MAC アドレスを記録しておきます。
    9. /etc/sysconfig/network-scripts/ifcfg-eth0, eth1 を編集して、
    記録した MAC アドレスに修正します。
    10. /etc/udev/rules.d/70-persistent-net.rules を削除します。
    11. マシンを再起動します。
```

 以上となります。
[Swift]2001年1月1日からの日数をカウントするプログラム DateComponents

DateComponentsを利用していますが計算の本質ではないです。


```swift
extension DateComponents {
    //need year, month, day
    func dateCountFrom20010101() -> Int? {
        let y = year! - 2001
        let m = month! - 1
        let d = day! - 1
        var count = y * 365 + y/4 - y/100 + y/400
        if (year! % 4 == 0 && year! % 100 != 0) || year! % 400 == 0 { //uru doshi
            let tmp = [0,31,60,91,121,152,182,213,244,274,305,335]
            count += tmp[m] + d
        } else {
            let tmp = [0,31,59,90,120,151,181,212,243,273,304,334]
            count += tmp[m] + d
        }
        return count
    }
}
```

以下はテストコード。
20001/01/01のDateをとり、i日進めたものをnewDateとします。
newDateからnewCompを取り出して、dateCountFrom20010101の値とiを比較します。
10000年だと処理に1分くらいかかります（かかりました。）

```swift
        let a = 365 * 10000
        let b = DateComponents(calendar: nil, timeZone: nil, era: nil, year: 2001, month: 1, day: 1, hour: 12, minute: nil, second: nil, nanosecond: nil, weekday: nil, weekdayOrdinal: nil, quarter: nil, weekOfMonth: nil, weekOfYear: nil, yearForWeekOfYear: nil)
        let date20010101noon = Calendar(identifier: .gregorian).date(from: b)!
        let daysecond = 24 * 60 * 60
        print("start--------------------")
        for i in 0..<a {
            let newDate = Date(timeInterval: TimeInterval(daysecond * i), since: date20010101noon)
            let newComp = Calendar(identifier: .gregorian).dateComponents([.year,.month,.day], from: newDate)
            let j = newComp.dateCountFrom20010101()
            if i != j {
                print("failed:\(j)")
            }
        }
        print("end-------------------")
```
Ecto 3.17 から 3.2.2 にアップデート: Migration のテスト

[Ecto 3.17 から 3.2.2 にアップデート: use Ecto.Type](https://qiita.com/ishikawa@github/items/e1dee393ecbe2debb8ad) からのつづき。

Ecto.Migration に用意された関数だけでなく、いくつか独自の Migration ロジックがあるので、`Ecto.Migration.Supervisor` を使ってテストを書いていたがこれが動かなくなっていた。

```
     ** (exit) exited in: GenServer.call(Ecto.Migration.Supervisor, {:start_child, [#PID<0.1016.0>, MyApp.MasterRepo, MyApp.Migration.ResourceTest.MigrationModule, :forward, :up, %{level: :warn, sql: false}]}, :infinity)
         ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
```

そのため、[ecto_sql のテスト](https://github.com/elixir-ecto/ecto_sql/blob/980d67688ee41b5fd1def604b93f3dc2cd4d4548/test/ecto/migration_test.exs)を参考に、以下のように書き換えたところ動作した。

```elixir
   setup do
     level = Application.get_env(:logger, :level, :info)
     log = %{level: level, sql: false}
-    args = [self(), MasterRepo, MigrationModule, :forward, :up, log]
 
-    {:ok, runner} = Supervisor.start_child(Ecto.Migration.Supervisor, args)
-    Ecto.Migration.Runner.metadata(runner, prefix: "test.migration.resource")
+    {:ok, runner} =
+      Ecto.Migration.Runner.start_link({self(), MasterRepo, MigrationModule, :forward, :up, log})
 
+    Ecto.Migration.Runner.metadata(runner, prefix: "test.migration.resource")
     {:ok, %{runner: runner}}
   end
```

もっとも、Ecto の実装が変わるたびに書き換えが必要になるのはメンテナンス性が悪い（書き換えるのも二度目）。[ecto_sql の integration test](https://github.com/elixir-ecto/ecto_sql/blob/980d67688ee41b5fd1def604b93f3dc2cd4d4548/integration_test/sql/migration.exs) のように書いた方がいいかもしれない。
brewでRictyがインストールできない！


# 2019/10/20 追記
使えるようになったようです。
メンテナさんありがとうございました！

# はじめに
macでCatalinaがリリースされましたね！
皆さんはインストールしましたか？？
私はリリース翌日にインストールしましたが、32bit対策を事前にしていたので、特に問題なく利用できています。
私は新しいmacOSがリリースされるたびにクリーンインストールをしていますが、brewでRictyをインストールした際にエラーが出たので、同じ症状に悩む人がいる可能性も考えて執筆しました。
結論を言うと何も解決できていません。
自分だけじゃないのか！と安心してください。

# 症状
下記コマンドを実行するとエラーが出る。

```shell:command
$ brew tap sanemat/font
$ brew install sanemat/font/ricty
Updating Homebrew...
==> Installing ricty from sanemat/font
==> Downloading http://www.rs.tus.ac.jp/yyusa/ricty/ricty_generator-4.1.0.sh
==> Downloading from https://www.rs.tus.ac.jp/yyusa/ricty/ricty_generator-4.1.0.sh

curl: (22) The requested URL returned error: 403 Forbidden
Error: An exception occurred within a child process:
  DownloadError: Failed to download resource "ricty"
Download failed: http://www.rs.tus.ac.jp/yyusa/ricty/ricty_generator-4.1.0.sh
```

# 調査結果
403Forbiddenが出ているので、アドレス先の有効性について調査。

http://www.rs.tus.ac.jp/
上記URLは東京理科大学教職員のHPらしい。アクセス可能
http://www.rs.tus.ac.jp/yyusa/
上記URLは東京理科大学に所属している遊佐泰紀助教のページらしいが、現在アクセス不可となっている。
researchmapで調べてみると2019年9月まで東京理科大学の嘱託助教と記載があるので、御退任された可能性がある。
そのため、東京理科大学上に置かれているシェルスクリプトにアクセスできなくなり、Download failedとなったと考えられる。

# 結論
brewでRictyをインストールする際のシェルスクリプトが大学教員が作成したシェルスクリプトであったが、御退任に伴い、アクセス不可となった。
brew側にそれを伝える方法があればコメントください。
suの利用を制限する方法

#suを使用制限すると？

一部を除いたLinux初期設定では全ユーザがsuを使用することで、rootユーザになることが出来てしまいます。rootのパスワードが分ってしまえば誰でもssh経由でrootになれてしまいますのでセキュリティ上まずい場面もあると思います。今回は「su」を実行出来るユーザを制限する事にしました。

##注意点
この設定を行うと以下２点が実行できなくなります。
　　・wheelグループ以外のユーザが「su」コマンドでrootになれなくなります。
　　・他ユーザにもsuすることが出来なくなります。

今回は__wheelグループに所属しているユーザだけが「su」実行可能__という制限設定を構築していきたいと思います。

#具体的実行ステップ　設定項目

下記３ステップでsu利用制限させる事が出来ます。

　　__ステップ１__　/etc/pam.d/su　を編集する

　　__ステップ２__　su 許可ユーザをwheelグループに追加

　　__ステップ３__　動作確認

※　以前は「/etc/login.defs」ファイル内に「SU_WHEEL_ONLY yes」設定追加が必要でしたが、CentOS6及びCentOS7では不要です。

#ステップ１　/etc/pam.d/su
/etc/pam.d/su　のファイルの中にある「pam_wheel.so」モジュールを使用するように設定変更します。これによりwheelグループに属しているユーザだけが「su」が出来るように設定が変更になります。

```
# vi /etc/pam.d/su
```

#どこを変更するのか　設定内容変更箇所

下記コメントで無効化されている箇所の「#」を外して設定を有効化します。

#変更前
```
# Uncomment the following line to require a user to be in the "wheel" group.
#auth           required        pam_wheel.so use_uid
```
#変更後
```
# Uncomment the following line to require a user to be in the "wheel" group.
auth           required        pam_wheel.so use_uid
```
※別OS（ディストリビューション)やバージョンによっては、以下設定の場合もあります。

```
#auth required /lib/security/$ISA/pam_wheel.so use_uid
#auth required /lib/security/pam_wheel.so group=wheel
#auth required /lib/security/pam_wheel.so use_uid group=wheel
```

##ちょい注意ポイント　sufficient

間違って下記部分のコメントをはずすと　wheelグループに属しているユーザが「su」を実行するとパスワードなしでrootになれてしまいます。コメントを外す時は間違えないよう十分に注意してください。

```
# Uncomment the following line to implicitly trust users in the "wheel" group.
#auth           sufficient      pam_wheel.so trust use_uid
```

__設定を有効化させるのは「required」です。__


#ステップ２　ユーザをwheelグループに追加

「su」を許可するユーザをwheelグループへ追加します。追加方法は２つあります。下記のどちらかの方法で行うことが出来るのでそれぞれの方法を説明していきます。

__グループを追加する方法は２つある__
　１．　/etc/groupを編集する
　２．　usermodコマンドを使用する


##１つめ　/etc/groupファイルを編集
グループの設定ファイルである「/etc/group」を直接編集して、wheelグループにユーザを追加します。

```
# vi /etc/group
```

編集内容
今回は、hogeというユーザをwheelグループに追加してみます。複数のユーザを追加する際は「,」で区切っていきます。

編集前

```
wheel:x:10:
```
編集後

```
wheel:x:10:hoge  <--hogeユーザを追加しました。
```

##２つめ　usermod コマンドを使用
「usermod」コマンドを使用しwheelグループにユーザを追加する場合は「-G」オプションを使用し指定したユーザの副グループを指定します。

```
# usermod -G wheel ユーザ名
```

wheelグループにhogeユーザを追加する場合は、下記のようにコマンドを実行します。

```
# usermod -G wheel hoge
```

###グループがユーザに追加しているか設定を確認

設定が完了しましたら、念のため「/etc/group」ファイルの中身を確認してwheelグループにユーザが追加されているか確認してみましょう。

```
# grep wheel /etc/group
wheel:x:10:hoge
```

#ステップ３　動作確認

設定が完了しましたらsu実行可能userが制限できているか確認します。設定に間違いなどがあった場合ssh経由でrootになることが出来なくなる場合があるので、現在接続しているrootユーザでの接続は動作確認が取れるまで__絶対に切断しない__よう留意してください。sshで接続して動作確認を行う場合は、新規に接続を行って動作確認を行いましょう。

##wheelグループ以外のユーザで「su」を実行

wheelグループに登録されていないユーザで「su」コマンドを実行します。CentOS7の場合下記の通り「拒否されたパーミッション」といったメッセージが表示され「su」が出来なくなっているはずです。CentOS6の場合は「パスワードが違います」といったメッセージが表示され、「su」が出来なくなっているはずです。

```
$ su -
パスワード:
su: 拒否されたパーミッション
```

```
$ su -
Password:
su: パスワードが違います
```

##wheelグループのユーザで「su」を実行する
wheelグループに所属しているユーザで「su」を実行して、rootになれるか確認してみてください。問題なくrootユーザになれるようでしたら、設定作業は完了となります。

#余談
他の記事も参考にさせていただきながら実際に制限して思ったのですが、信頼できる仲間やシステム業者の方々と構築していく環境を整備していく方が楽しいし安心できるとおもいました。もちろん今回の実行権限をシステム制御する事は有効です。同時に例えば万全な制御をしない時に仲間からアラートで知らせてくれるような構築メンバーとの信頼関係を日頃から築いている事もかなり重要だと感じました。
Raspberry pi で使用する sdcard.img を編集する方法

Raspberry pi で使用する sdcard.img の中をいじりたいときがあります。その方法を紹介します。

1. 手動で頑張る方法

普通に、fdisk などで内容を確認します。以下は一例です。

```
    $ fdisk -lu sdcard.img
    ディスク sdcard.img: 532 MiB, 557842944 バイト, 1089537 セクタ
    単位: セクタ (1 * 512 = 512 バイト)
    セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
    I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
    ディスクラベルのタイプ: dos
    ディスク識別子: 0x00000000

    デバイス 起動 開始位置 終了位置 セクタ サイズ Id タイプ
    sdcard.img1 * 1 65536 65536 32M c W95 FAT32 (LBA)
    sdcard.img2 65537 1089536 1024000 500M 83 Linux
```

cfdisk だと、一見してファイルタイプも表示されるので、一見してわかりやすいでしょう（略）。

スタートセクターを指定してマウントする必要があります。まず、file コマンドで sdcard.img を確認します。

```
    $ file sdcard.img
    sdcard.img: DOS/MBR boot sector; partition 1 : ID=0xc, active, start-CHS (0x0,0,2), end-CHS (0x4,20,17), startsector 1, 65536 sectors; partition 2 : ID=0x83, start-CHS (0x4,20,18), end-CHS (0x43,209,15), startsector 65537, 1024000 sectors
```

 二つのパーティションがありますので、これらをそれぞれ作成したマウントポイントにマウントすれば OK です。こつは、startsector に 512 をかけることです。

上記の表示結果を使用した一例です。

partition 1 を /mnt/sdcard1 にマウントする例です。

```
     # mount -t vfat -o loop,offset=512 sdcard.img /mnt/sdcard1
```

 編集後は、umount してください。

```
    # umount /mnt/sdcard1
```

parttion 2 を /mnt/sdcard2 にマウントする例です。

```
    # mount -t ext4 -o loop,offset=33554944 sdcard.img /mnt/sdcard2
```

2. kpartx を利用する方法

sdcard.img を /dev/mapper にマップさせます。

```
    # kpartx -av sdcard.img
    add map loop0p1 (253:3): 0 65536 linear 7:0 1
    add map loop0p2 (253:4): 0 1024000 linear 7:0 65537
```

/dev/mapper を確認します。

```
    # ll /dev/mapper
    合計 0
    crw-------. 1 root root 10, 236 10月 9 18:49 control
    lrwxrwxrwx. 1 root root 7 10月 9 18:49 fedora-home -> ../dm-2
    lrwxrwxrwx. 1 root root 7 10月 9 18:49 fedora-root -> ../dm-0
    lrwxrwxrwx. 1 root root 7 10月 9 18:49 fedora-swap -> ../dm-1
    lrwxrwxrwx. 1 root root 7 10月 10 07:43 loop0p1 -> ../dm-3
    lrwxrwxrwx. 1 root root 7 10月 10 07:43 loop0p2 -> ../dm-4
```

細部を確認します。

```
    # dmsetup info

    Name: loop0p2
    State: ACTIVE
    Read Ahead: 256
    Tables present: LIVE
    Open count: 0
    Event number: 0
    Major, minor: 253, 4
    Number of targets: 1
    UUID: part2-devnode_7:0_Wh5pYvM

    Name: loop0p1
    State: ACTIVE
    Read Ahead: 256
    Tables present: LIVE
    Open count: 0
    Event number: 0
    Major, minor: 253, 3
    Number of targets: 1
    UUID: part1-devnode_7:0_Wh5pYvM
```

/dev/mapper/loop0p1 をマウントしてみます。

```
    # mount /dev/mapper/loop0p1 /mnt/sdcard1
    # ls /mnt/sdcard1
    bcm2709-rpi-2-b.dtb bootcode.bin cmdline.txt config.txt fixup.dat start.elf zImage
```

（参考）

https://www.raspberrypi.org/forums/viewtopic.php?t=28860

https://qiita.com/spicemanjp/items/1998a3f68cb369651584
macOSをCatalinaにアップデートしたらXcodeのBuildができなくなった

#なんでだろうね
Catalinaにアップデートしました豆岡です。そしたら、XcodeでBuildが、と言うか、cocoapods関連のところでエラーが発生してBuildできなくなってしまった。pod initもpod installもpod updateもできない。。。納期間近なのに。

#調べてみると
調べたら似たような悩みが1件だけ。
https://github.com/CocoaPods/Xcodeproj/issues/688
これを見てやったけど私は結局解決しませんでした。
試行錯誤して、関係しそうなものを片っ端からアップデートしたり入れ直したりして。。。結局、この方法で解決しました。

#結論

```
$ xcode-select --install
```
これを実行するとコマンドラインデベロッパーツールが必要ですとか出てくるので、素直にインストールする。

以上。

"""納期直前にmacOSのアップデートはしないように！"""
Ecto 3.17 から 3.2.2 にアップデート: use Ecto.Type

[Ecto](https://github.com/elixir-ecto/ecto) を 3.1.7 から 3.2.2 にアップデートしたところ、コンパイル時に大量の warning が出るようになってしまった。

```
warning: function embed_as/1 required by behaviour Ecto.Type is not implemented (in module MyApp.Ecto.SecretKey)
  lib/myapp/ecto/secret_key.ex:1: MyApp.Ecto.SecretKey (module)

warning: function equal?/2 required by behaviour Ecto.Type is not implemented (in module MyApp.Ecto.SecretKey)
  lib/myapp/ecto/secret_key.ex:1: MyApp.Ecto.SecretKey (module)

warning: function embed_as/1 required by behaviour Ecto.Type is not implemented (in module MyApp.Ecto.RandomSecretKey20)
  lib/myapp/ecto/random_secret_key.ex:42: MyApp.Ecto.RandomSecretKey20 (module)

warning: function equal?/2 required by behaviour Ecto.Type is not implemented (in module MyApp.Ecto.RandomSecretKey20)
  lib/myapp/ecto/random_secret_key.ex:42: MyApp.Ecto.RandomSecretKey20 (module)
```

Ecto.Type の `@callback` に追加された [`embed_as/1`](https://hexdocs.pm/ecto/3.2.2/Ecto.Type.html#c:embed_as/1) や [`equal?/2`](https://hexdocs.pm/ecto/3.2.2/Ecto.Type.html#c:equal?/2) が、[`use Ecto.Type` の導入](https://github.com/elixir-ecto/ecto/commit/c040b7c0f5bc5ac244cf3f4c0272ed684d9e8c52#diff-68b1275ffa052929bf96ca32ea92092d)に伴い `@optional_callback` から外されたのが原因のようだ。

自分のプロジェクトで `@behaviour Ecto.Type` をしている箇所を `use Ecto.Type` に置き換えれば、デフォルトの実装を提供してくれるので、上記の warning は収まる。

```diff
- @behaviour Ecto.Type
+ use Ecto.Type
```
プログラマーは最高の副業か？必要スキルは？

# 今は空前のプログラマー不足？
近頃、プログラマーが不足している様な状況を感じることも多いのではないでしょうか？

実態はどうかというと、、、
プログラマーの
[求人倍率は8.33倍に](https://doda.jp/guide/kyujin_bairitsu/)





自分へのスキルアップが最も効率の良い投資だ、とも言われています。




今後要求される[プログラミング言語](https://hackr.io/blog/best-programming-languages-to-learn-2019-jobs-future)は、
Python
Java
C/C++
JavaScript
Go programming language
R
Swift
PHP
C#
MATLAB

##[副業としてのプログラマーは？](https://youtu.be/xGbKuXgwelQ)

[他の副業との比較](https://youtu.be/xGbKuXgwelQ)を見て欲しい。

昨今ではリモートでできる事も副業としての可能性を高めていると思います。

# プログラマーの給料は？
月額関しては[100万円以上のフリーランス案件](https://px.a8.net/svt/ejp?a8mat=35O62V+A96ICA+3SLI+5YJRM)も多々ある状態です。

現状の市場の要求項目と自分のスキルをベースにどのレベルが妥当か見てみるのも良いでしょう。




# スキルアップの方法は？

シリコンバレーでも最も人気のある[オンライン学習プラットフォーム"Udemy"](https://px.a8.net/svt/ejp?a8mat=35OAS7+73GPSQ+3L4M+5YZ77)で独学で自分の時間を有効に使ってスキルアップする方法もおすすめです。


ネットで独学をする方法は他にもあり、有効にスキルアップができます。
<a href="https://px.a8.net/svt/ejp?a8mat=35O62V+A8L2QI+3GWO+6BMG2" rel="nofollow">オンラインブートキャンプ 無料体験</a>
<img border="0" width="1" height="1" src="https://www16.a8.net/0.gif?a8mat=35O62V+A8L2QI+3GWO+6BMG2" alt="">

# まとめ
2027年には正規雇用をフリーランスが上回るという米国市場の推定もあります。　今後は個の時代です、実質的な自分のスキルの向上に努めてください。　Be Happy!!