windowsにおける環境構築について書いてみる

# はじめに

windowsでの環境構築に関して、自分の中で統一的な環境構築方法を確立したいというモチベーション。

## Windows
windowsなのは慣れとかキーボードとか日本での生きやすさとかが理由で、そこを掘り下げる気はない。
エンジニアリングならMacという文化は浸透していて、windowsについてのドキュメントは比較的少ない。
逆にwindowsのドキュメントというだけで一定の価値があるのでは？とチャンスと考えて、執筆。


## 自由という不自由さ
以下実体験。
これはwindowsに限らずエンジニアリング全般の話だけど、特にローカルの中では何の制約も無く自由に構築できる。だからドキュメントの記述はあくまで一例。ドキュメントによって少しずつ構築方法が違っていたりするけど、動きには問題ない。

どうやって環境構築すれば良いですか→動けば何でも良い。

これが結果的にローカルをchaosなものにしてしまっていた。
どこに何があるのか、どうやって入れて再現方法はどんな形か。
これが説明できない自分のローカルって考えると、なかなかエンジニアとして良くないなと思う。

いつPCを変えることになっても、同じ環境が構築できるように。再現性のある環境構築方法を模索。

## WSLとの出会い

wslリリース以前からエンジニアリングと呼ばれる行為は行っていたが、環境構築が一番嫌いだった。
hello world!までのハードルが凄く高く感じた。
統合開発環境も多種多機能すぎてこれというものを見つけられず、思えばここからモチベーションが始まっていたのかも。
幸いなことに、エンジニア職に就いたときにはwslがリリースされており、ここからはじめようと感じた。

## wsl2
wsl2がかなり快適なので、すべてwsl2に寄せていく。wslとは根本的にかなり違う点に注意。
wsl2はlinuxがベースになっているので、unixの知識をベースに現れた差異に着目するような流れ。windows用のエンジニアリングツールは使わず、wsl2内でlinux用のものを使う。

wslとの違いは色々あるが、基本的にメリットばかり。
特にdockerが純粋にlinuxのdockerで完結する点が大きい。
wslで実現する手順は不安定かつ複雑すぎてドキュメントにしたくない。

デメリットとしてあげられるものにファイルシステムの違い?があり、windowsのシステム側で作られたファイルをwsl2から読もうとすると重いみたいな話がある。
単にディレクトリの問題のようなので、wsl2側に作りましょうという話で大した問題ではない。
確かに異なるOSで同じディレクトリ操作しようとすると重くなりそう。


## GUIはなるべく回避
端末を一つ決めて、それ以外のGUIは極力使わない方針。
.exeを大量に用意する方法もあるけれど、GUIは手順をまとめたり再現するのがとにかく手間で複雑。
他人に共有するとき、検証するとき、そもそも自分で再構築するときなど、様々なタイミングでGUIを使うメリットが見いだせなかったので、すべてコマンドベースで管理する方針でいく。

## vimを習得する
エディタに関しては汎用性重視でvimを習得する。
環境構築段階でエディタが必要になる場面は多く、多くの環境で使えるvimを習得するだけで効率がかなり上がる。
腰を据えて開発する際のエディタに関してはちゃんと設定したうえで使用すれば良い。
共通で必要になりそうなvimは環境構築で習得する。

今ではvimしか使えなくなってしまった。。。

## dotfilesリポジトリを用意する
ドットファイルというのは.vimrc、.bash_profileなど、ドットから始まるファイルのことで、linuxでは隠しファイル扱い。(windowsだと普通に表示されててちょっと萎える)

各種設定はドットファイルで書けることが多いので、自分用のドットファイルを一つ用意し、色々な環境で同じ設定を反映させる方針。

特にローカル以外で開発する機会が多い場合は、どんなに簡単でも良いので用意しておくと、どんどん育てていける。


# GUIを脱するために

GUIベースでの操作がどうしても必要になるので、無事CUIベースに移行するまでの手順を紹介する。

## wsl2インストール

[公式](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)の手順通りで特に問題なく導入できた。
Linux ディストリビューションはUbuntu 20.04 LTSを使っている。Ubuntuはかなり安定している印象がある。
[新しい Linux ディストリビューションのユーザー アカウントとパスワードを作成する](https://docs.microsoft.com/ja-jp/windows/wsl/user-support)まで行い、ubuntuを実行して、ターミナルが開いてコマンドが打てる状態になったら完了。

手順中、Windows ターミナルをインストールする手順がありますが、現状不要かなと。
Windows ターミナルはまだリリースから間も無く、毎月アップデートされている。
将来的に使っていきたいので、安定してきたら挑戦してみたいです。

## 端末エミュレータの選択とインストール

直接ubuntuで作業する前に、[端末エミュレータ](https://ja.wikipedia.org/wiki/%E7%AB%AF%E6%9C%AB%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF)の設定を行います。

デフォルトの端末ではなく、端末エミュレータを挟むことで、色の設定や複数タブの設定など、様々な設定をエミュレータ1つに集約させることが出来る。今回はubuntu用に設定しますが、これはエミュレータなのでコマンドプロンプトやPowerShellなど、インストールされているシェルならば何でも開ける。
環境構築においてはこれが大きく、以後使うGUIはエミュレータのみに限ることが出来る。

そしていろいろ使ってみて最終的に決めたのが[conemu](https://conemu.github.io/)。

ほとんど消去法で、正常に動く+多機能という軸で決定。
「正常に動く」のハードルが意外と高かった。
選ぶ際に気を付けたいことは以下の通り。

* 256色使えること
8色しかうまく表示されなかったり、色が変だったり。sshした先でも要確認。[スクリプト](https://qiita.com/soramugi/items/ab82f30a5906851472cc)を用意しておくと確認が楽。

* 上下左右キーが使えること
キーボードの右下の上下左右キーは、結構うまく使えないことが多い。使わない人からすると関係ないかもしれないけど、そもそも使えないキーがある環境を構築したくない

* lsコマンドやviコマンドを使ったときに、文字が崩れない
崩れる理由はいくつかあって、エミュレータが理由ではないこともあるけれど、明らかに崩れるエミュレータは敬遠。

インストール方法は調べてもらうとして、以下ではubuntuをconemuから開けるように設定。
[僕の時には無かったありがたい記事](https://qiita.com/murachi1208/items/4bd7015349c00d7ebb96)

## conemuの設定
conemuの設定欄はかなり充実していると思う。
GUIをいじるのはこれが最後になるようにめちゃめちゃカスタマイズする。
ここでは特にフォントの話をします。

フォントは結構大事。
こだわりが無く、特に違和感を感じなければ読み飛ばしてもらっても構いません。
自分が気になったのは以下の点

* そもそも表示が崩れる
特にvimでコーディング、つまり半角英数のみで書く場合に縦の列がそろわないのは致命的。
表示が崩れる原因の一つにフォントがあり、自分はここでハマった。

* 全角、日本語表示が崩れる
これはさらに起こりやすい事象で、特に半角英数だと上手くいくのに全角だと崩れる場合はフォントが良くない可能性が高い。
コーディングではあまり出てこないと思いきや、コメントアウトや文字列でお世話になるので軽視しづらい。

* フォントが読みづらい
これは個人差があり、慣れの問題でもあるのであまり大きな問題点ではない。選ぶ余裕があれば、読みやすいものを選びましょう程度。
特に自分が気にするのは、
全角スペース(フォントによっていろんな表現があり、程良い目立ち方が良い)
バッククオート(他のクオートと識別できることが重要)
アルファベットのアイやオー(oと0の識別などはフォントごとに工夫されている。個人的に中点は読みづらい)
など

自分が使っているのは[Ricty Diminished](https://nelog.jp/how-to-use-ricty-diminished-font)。
[僕の時には無かったありがたい記事](https://qiita.com/murachi1208/items/4bd7015349c00d7ebb96)でも推されているのでメジャーなフォントかも。
特徴的な点は特に無いかなと思うのですが、特徴的な点がなく、いずれの設定でも崩れないことが一番良いことだと感じている。そもそも崩れない条件が結構厳しい。。。

> 例えば、英語の小文字のエル「l」や、大文字のアイ「I」、数字の「1」、その他にも英語のオー「O」と、数字のゼロ「0」などの見分けがつきやすいように作成されています。
それに加えて、Ricty Diminishedでは、視認性の高い日本語文字が使用されており、半角と全角が 1:2 に調節されているので、日本語で入ったコメントなども綺麗に表示されます。"

なるほど崩れないのは一つの特徴かもしれない。

# CUIに定住するために

CUIで開発が可能になったので、ここからはCUIで開発し続けることが出来るための環境を整える。

## コマンドインストール

ubuntuベースで環境を整えるため、brewやyumは使えない。aptを中心に使う。

最初に、今後も定期的に行うコマンドとして以下を行う。

```
$ sudo apt update
$ sudo apt upgrade
```


呪文のように覚えてしまいがちだからここで一回理解する。

updateはインストール可能なパッケージの「一覧」を更新する。

upgradeは「有効なパッケージ一覧」を元に、インストール済みのパッケージ更新をおこない、新しいバージョンにアップグレードする。

と一度理解しておけば、順番で迷うことは少なくなる。(理解するまでは2回ずつ行っていた)


### brewを入れる

aptをメインで使うことに決めたものの、brewで入れたいものがあるので、ここで入れておく。
[参考にした記事](https://qiita.com/amenoyoya/items/ca9210593395dbfc8531#%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB%E5%B0%8E%E5%85%A5)

```
# Linuxbrew (Linux版の Homebrew パッケージマネージャ) 導入
## Linuxbrew を使うことで最新の開発ツール等を導入しやすくなる
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
## PATHを通す
$ echo 'export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc
```

### anyenvを入れる
brewを入れたい理由がこれ。

anyenvは、様々なenv系のバージョンを複数インストールできる管理ツールで、開発用の言語はこれを使って管理する。

※現状なぜかphpenvだけうまくいかないみたいなので、phpだけは普通にインストールする必要があるっぽい

```
# Linuxbrew で anyenv 導入
$ brew install anyenv
$ anyenv install --init
## Do you want to checkout ? [y/N]: <= y
 
# anyenv 初期化スクリプトを .bashrc に記述
$ echo 'eval "$(anyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc
 
# anyenv update plugin の導入
$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
$ anyenv update
 
# バージョン確認
$ anyenv -v
anyenv 1.1.1
```

## 各開発用言語インストール

anyenvを使ったインストール例としてruby,javascriptのインストールを紹介する。

### rubyインストール
rubyをインストールするため、まずはrbenvをインストールする。

```
$ anyenv install rbenv
$ exec $SHELL -l
$ rbenv install -l
```

これで任意のバージョンのrubyをインストールできるようになった。

```
$ rbenv install 2.7.1 // 時間がかかるが正常
$ rbenv versions
  system
* 2.7.1 (set by $HOME/.anyenv/envs/rbenv/version)
$ which ruby
$HOME/.anyenv/envs/rbenv/shims/ruby //renv内のrubyに設定されていることを確認
```

切り替えは rbenv version localでsetできるので、これでプロジェクトによって使うrubyのバージョンを切り替えられる。

### javascriptインストール
nodeをインストールするため、まずはnodenvをインストールする。

```
$ anyenv install nodenv
$ exec $SHELL -l
$ nodenv install -l
```

これで任意のバージョンのnodeをインストールできるようになった。

```
$ nodenv install 14.8.0 // 時間がかかるが正常
$ nodenv versions
  system
* 14.8.0 (set by $HOME/.anyenv/envs/nodenv/version)
```

nodeの中にnpmやnpxなども含まれる

## そのほかのローカルPCの設定

開発環境がec2インスタンス、そこへsshするローカルpcという構成における、ローカルPCの設定を記す。

方針としては、ローカルPCは一度設定すれば良いので、時間がかかってもしっかり設定する。

ec2インスタンス、つまりssh先での設定はインスタンス毎に必要になるので、なるべく少ない工数で環境を構築できるようにする。

ということでローカルPCの設定。目的に応じて必要な設定が行える状態が好ましい。



### sshconfigの設定
ローカルpcでec2インスタンスにsshするときに使われる設定ファイルがsshconfig。

必要な設定をsshconfigに書いておき、sshする時にその設定名を指定することで、設定値を気にせずにssh出来る環境を作る。

```
$ cat  ~/.ssh/config
Include ./config.d/*
```

自分は~/.ssh/configというテキストファイルに設定している。

ここにすべて書いても良いが、ある程度以上設定が多くなってくると、ファイルを分けたほうが管理しやすい。

またその中身は一行だけで、sshconfig用に作成したディレクトリ以下の設定ファイルをすべて読み込むようになっている。

```
$ ls -al .ssh/config.d/
合計 8
drwxrwxrwx 1 hoge hoge 4096 11月 30 18:52 .
drwx------ 1 hoge hoge 4096 12月 15 12:44 ..
-rw------- 1 hoge hoge  915 11月 28  2019 hoge.conf
-rw------- 1 hoge hoge   54 11月 30 18:52 github.conf
-rw------- 1 hoge hoge  410 10月 28 19:57 fuga.conf
-rw------- 1 hoge hoge  545  9月 29 18:54 dev.conf
```

一例

```
$ cat .ssh/config.d/dev.conf
Host bastion # bastionのところは任意の文字列。自分で打ちやすいもの。
# bastion
    HostName XX.YYY.ZZZ.AA # ec2インスタンスのIPアドレス(グローバル)
    Port     22 # sshなので基本的には22を使う
    User     user # 以下の鍵情報と合わせてec2インスタンスにsshする際に認証に使われる
    IdentityFile ~/.ssh/id_rsa # 認証に使われる鍵
# dev
Host dev # devのところは任意の文字列。自分で打ちやすいもの。
    HostName XXX.YY.ZZ.AAA # ec2インスタンスのIPアドレス(ローカル)
    IdentityFile ~/.ssh/id_rsa # 認証に使われる鍵
    ProxyCommand ssh -W %h:%p bastion # 踏み台として使う場合の設定
```

普通のsshについては上のbastionの方が参考になる。

踏み台としてbastionを使う場合は下が参考になる。

踏み台の説明は省くが、適切に設定することでsshの際に意識する必要がなくなる。


## ssh先での環境構築

ローカルではない、ssh先での環境構築に関して記す。

どちらかと言うと方法よりも、これだけで完結するようにしたいですね的な話です。
なお、これは自身のdotfilesリポジトリや、使いたいdotfilesリポジトリが決まっている場合のお話。
自作するところからならば、以下は参考程度に読んだうえで、[こちら](https://qiita.com/Kitasan_White/items/0702be2ac74a06123f55)も読んでみてほしいです。

### githubにkeyを登録する

環境構築に自作のdotfilesリポジトリを使いたい。

なのでgithubに接続できるようするところは手動で頑張るしかない。

一応scpで送ることもできるけど、リポジトリの更新を反映させることを考えるとgithubの設定はしておきたい。

また自身の環境設定のためだからと、自身のシークレットキーをgithubにあげるようなことが無いように注意。

認証情報だけはインスタンス毎に設定する必要があるので、githubの認証だけは毎回やるようにする。(実際の手順は他の記事に譲ります)

自身のdotfilesをcloneできたら成功。

### dotfilesをcloneしてくる

dotfilesをcloneしてくる。

どこにcloneしても良い設計が好ましい。

自分はpullしてくる手間も考えてホームディレクトリに置くようにしています。

```
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
 
https://aws.amazon.com/amazon-linux-2/
-bash-4.2$ ls -al
合計 4
drwxr-xr-x  3 developer developer  39  1月  8 16:10 .
drwxr-xr-x 16 root     root      228 12月  9 17:04 ..
-rw-------  1 developer developer 164  1月  8 16:10 .bash_history
drwxr-xr-x  2 developer developer  53 11月 10 18:27 .ssh
-bash-4.2$ git clone git@github.com:kitajima-mamoru/dotfiles.git
Cloning into 'dotfiles'...
remote: Enumerating objects: 257, done.
remote: Counting objects: 100% (257/257), done.
remote: Compressing objects: 100% (180/180), done.
remote: Total 576 (delta 138), reused 193 (delta 76), pack-reused 319
Receiving objects: 100% (576/576), 63.13 KiB | 355.00 KiB/s, done.
Resolving deltas: 100% (316/316), done.
-bash-4.2$ cd dotfiles/
-bash-4.2$ ls -al
合計 16
drwxr-xr-x 5 kitajima developer  107  1月  8 16:13 .
drwxr-xr-x 4 root     developer   55  1月  8 16:13 ..
drwxr-xr-x 8 kitajima developer  163  1月  8 16:13 .git
-rw-r--r-- 1 kitajima developer  300  1月  8 16:13 .vintrc.yaml
-rw-r--r-- 1 kitajima developer  458  1月  8 16:13 README.md
-rwxr-xr-x 1 kitajima developer 2855  1月  8 16:13 install.sh
drwxr-xr-x 4 kitajima developer   29  1月  8 16:13 rc
drwxr-xr-x 2 kitajima developer   88  1月  8 16:13 src
-rw-r--r-- 1 kitajima developer   45  1月  8 16:13 vimrc
```

### install.shを実行する

ここはinstall.shを実行するだけが望ましい。

中身は色々書き方があるので、ここでは結果だけ。

```
-bash-4.2$ cd
-bash-4.2$ ls -al
合計 84
drwxr-xr-x  5 kitajima developer   177  1月  8 16:14 .
drwxr-xr-x 16 root     root        228 12月  9 17:04 ..
-rw-------  1 kitajima developer   164  1月  8 16:10 .bash_history
lrwxrwxrwx  1 kitajima developer    41  1月  8 16:14 .bash_profile -> /home/kitajima/dotfiles/src/.bash_profile
lrwxrwxrwx  1 kitajima developer    35  1月  8 16:14 .bashrc -> /home/kitajima/dotfiles/src/.bashrc
lrwxrwxrwx  1 kitajima developer    34  1月  8 16:14 .ctags -> /home/kitajima/dotfiles/src/.ctags
-rw-r--r--  1 kitajima developer 78003  1月  8 16:14 .git-completion.bash
lrwxrwxrwx  1 kitajima developer    38  1月  8 16:14 .gitconfig -> /home/kitajima/dotfiles/src/.gitconfig
drwxr-xr-x  2 kitajima developer    53 11月 10 18:27 .ssh
lrwxrwxrwx  1 kitajima developer    34  1月  8 16:14 .tigrc -> /home/kitajima/dotfiles/src/.tigrc
drwxr-xr-x  8 kitajima developer   114  1月  8 16:14 .vim
drwxr-xr-x  5 kitajima developer   107  1月  8 16:13 dotfiles
```

このようにcloneしてきたdotfiles以下のコードへのシンボリックリンクが生成されている状態が好ましい。

シンボリックリンクを貼っただけだとbash関連の設定は反映されないので、sourceするか再sshを推奨

これでdotfilesの設定が反映されれば成功。


# まとめ
windowsでの開発環境の構築について一通り書いてみました。
PCがクラッシュしたり買い換えた際は、この記事を頼りに環境を再構築したいと思っています。
関連する記事として、[dotfilesに関する記事](https://qiita.com/Kitasan_White/items/0702be2ac74a06123f55)も書いたので、よろしければこちらも読んでもらえると嬉しいです。

## 参考文献
https://qiita.com/murachi1208/items/4bd7015349c00d7ebb96
https://qiita.com/amenoyoya/items/ca9210593395dbfc8531#%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB%E5%B0%8E%E5%85%A5