【シェル芸人への道】Bash on Windowsを探検する

# **Bash on Windows**

知っている人は知っていますが、Windows 10に今夏のアップデートで **Bash** が入るなんていうシェル芸人を目指す人間としては聞き逃せないニュースが入ってきました。
少し出遅れましたが、探検してみたいと思います。

## **インストール**

Insider Previewを有効にしてもなかなか落ちてこないという焦らしプレイ以外には特に困った点もないです。
ここで丁寧に解説するようなものでもないので他記事のリンクで割愛します。

**[Windows 10のbash on Windowsを試す](http://kkamegawa.hatenablog.jp/entry/2016/04/07/055830)**
**[Bash on Windows 10を使い始めてみた。](http://qiita.com/kmry2045/items/15697e734b32da2c8b51)** **( @kmry2045 )**

初回起動の使用許諾的なところまでは進んでから探検を開始します。

(**備考**)
上で紹介した記事は `Windows 10 build 14316` ベースで書かれています。
この記事を書き始めてから妙にPCが重かったので再起動したところ、 Windows Updateが入って上の記事同様に `Windows 10 build 14316` だったウチのPCが **進化してしまいました** 。
PCが重かったのは裏でアップデートをせっせと準備していたからのようです。
というわけで、この記事は **`Windows 10 build 14328`** ベースで書かれています。

```
PS C:\WINDOWS\system32> Get-WmiObject Win32_OperatingSystem
SystemDirectory : C:\WINDOWS\system32
Organization    :
BuildNumber     : 14328
RegisteredUser  : ******
SerialNumber    : *****-*****-*****-*****
Version         : 10.0.14328
```
# **とりあえず探検**

それでは思いつくままに未開の地、**Bash on Windows**を探検したいと思います。

## **起動**

まずは起動です。
bashはスタートメニューに登録されている、 `Bash on Ubuntu on Windows` から起動できます。

![WS000010.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/7e165aff-f286-1b55-a8c4-c724fcbe0293.jpeg)

なんということでしょう、いとも簡単に Bash が起動してしｍ...

ちょっと待ってください。いったいこの `Bash on Ubuntu on Windows` は何者なのでしょうか。
プロパティを見てみます。

![WS000009.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/1567cfa4-c0da-5b35-c1c0-04c24576122d.jpeg)

どうやらこいつは `C:\Windows\System32\bash.exe` のショートカット、本体は `bash.exe` というWindowsアプリのようです。

### **bash.exe**

Bash on Ubuntu on Windowsがそもそもどう動いているかという話なのですが、MSDNが公開している **[Bash on Ubuntu on Windows](https://msdn.microsoft.com/en-us/commandline/wsl/about)** の中に、

![INewImage-9.png](https://qiita-image-store.s3.amazonaws.com/0/45253/d9a15655-df5b-c17a-df6c-e06e3923a7e6.png)

という画像が出てきます。
今回のbashを動かすWindows機能の総称として、 **Windows Subsystem for Linux(WSL)** という名称が使われていますが、その管理コマンド `lxrun` について、

> lxrun: The lxrun command is used to manage the **WSL instance**.

という記述が確認できます。
インスタンス、とのことなのでユーザごとに何かしらの空間があり、それを呼び出す大本のコマンドが `bash.exe` という感じなのでしょうか。

## **基本コマンド**

それでは実際にコマンドを実行していきます。
まずは、ここはどこ、私はだぁれ？的に以下から。

- pwd
- id
- hostname
- uname -a
- bash --version

```console
root@PERSONAL:~# pwd
/root

root@PERSONAL:~# id
uid=0(root) gid=0(root) groups=0(root)
```

デフォルトではrootユーザとしてログインした状態のようですね。

```console
root@PERSONAL:~# hostname
PERSONAL
```

![WS000003.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/9d47948d-b881-d92c-95da-4cb067b7a363.jpeg)


ホスト名はWindows自体のホスト名をそのまま(ただし大文字で)引き継ぐようです。

```console
root@PERSONAL:~# uname -a
Linux PERSONAL 3.4.0+ #1 PREEMPT Thu Aug 1 17:06:05 CST 2013 x86_64 x86_64 x86_64 GNU/Linux
```

この通り、環境上注意しておくこととすれば、Linuxとしては **Kernel 3.4.0+** に見えているということですね。

```console
root@PERSONAL:/proc# bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
```

WSLにおけるbashは **4.3.11** です。これシェル芸テストに出ます。

## **ファイル**

それでは色々なディレクトリからファイルを漁りつつを探検していきます。
まず `df` でもやってみましょう。

```console
root@PERSONAL:~# df
df: cannot read table of mounted file systems: No such file or directory
```

あら、dfコマンドは使えないようです。諦めましょう。

### **/proc**

それではシステムのお城、/procを探検しましょう。
どれどれ。

```console
root@PERSONAL:~# cd /proc/
root@PERSONAL:/proc# ls -la
total 4
dr-xr-xr-x 1 root root 0 Apr 25 17:19 .
drwxrwxr-x 2 root root 0 Jan  1  1970 ..
dr-xr-xr-x 1 root root 0 Apr 25 17:20 1
dr-xr-xr-x 1 root root 0 Apr 25 17:20 2
dr-xr-xr-x 1 root root 0 Apr 25 18:08 30
-r--r--r-- 1 root root 0 Apr 25 17:19 cmdline
-r--r--r-- 1 root root 0 Apr 25 17:19 cpuinfo
-r--r--r-- 1 root root 0 Apr 25 17:19 filesystems
-r--r--r-- 1 root root 0 Apr 25 17:19 interrupts
-r--r--r-- 1 root root 0 Apr 25 17:19 loadavg
-r--r--r-- 1 root root 0 Apr 25 17:19 meminfo
lrwxrwxrwx 1 root root 0 Apr 25 17:19 mounts -> self/mounts
lrwxrwxrwx 1 root root 0 Apr 25 17:19 net -> /proc/self/net
lrwxrwxrwx 1 root root 0 Apr 25 17:19 self -> /proc/30
-r--r--r-- 1 root root 0 Apr 25 17:19 stat
dr-xr-xr-x 1 root root 0 Apr 25 17:19 sys
-r--r--r-- 1 root root 0 Apr 25 17:19 uptime
-r--r--r-- 1 root root 0 Apr 25 17:19 version
```

いくつか見てみましょう。

```console
root@PERSONAL:/proc# cat meminfo
MemTotal:        1031052 kB
MemFree:          680736 kB
Buffers : 34032 kB
Cached : 188576 kB
SwapCached : 0 kB
Active : 167556 kB
Inactive : 157876 kB
           Active(anon) : 103104 kB
           Inactive(anon) : 17440 kB
           Active(file) : 64452 kB
           Inactive(file) : 140436 kB
(略)
```

あれ？meminfo自体珍しいことではないんですが...

```console
root@PERSONAL:/proc# free -h
             total       used       free     shared    buffers     cached
Mem:          1.0G       342M       664M         0B         0B         0B
-/+ buffers/cache:       342M       664M
Swap:           0B         0B         0B
```

やはりメモリ合計が1.0GBで認識されているようですね。
このPC自体は4GBメモリを積んでいるのですが、固定なんでしょうか？詳細不明です。

```console
root@PERSONAL:/proc# cat cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 69
model name      : Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz
stepping        : 1
microcode       : 0xffffffff
cpu MHz         : 2394.000
cache size      : 256 KB
physical id     : 0
siblings        : 4
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 6
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes xsave osxsave avx f16c rdrand
bogomips        : 4788.00
clflush size    : 64
cache_alignment : 64
address sizes   : 36 bits physical, 48 bits virtual
power management:

(略)
root@PERSONAL:/proc# cat cpuinfo | grep processor
processor       : 0
processor       : 1
processor       : 2
processor       : 3
```

これはまぁいいでしょう。HT込みの論理4コアはWindowsから見たものと同じです。
では/procは次でいったん最後に。

```console
root@PERSONAL:/proc# cat mounts
rootfs / rootfs ro,relatime 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
```

以上、/procでした。

### **/mnt**

おや、これは...。

```console
root@PERSONAL:~# cd /mnt/
root@PERSONAL:/mnt# ls -la
total 12
drwxrwxr-x 2 root 1000 0 Jan  1  1970 .
drwxrwxr-x 2 root root 0 Jan  1  1970 ..
drwxrwxrwx 2 root root 0 Apr 25 17:20 c
```

どうやらここからCドライブが見えるようです。
さきほど `/proc/mounts` を見ていますが、どうやってマウントしているかは謎です。

```console
root@PERSONAL:/mnt# cd c
root@PERSONAL:/mnt/c# ls -la
ls: cannot access Documents and Settings: Input/output error
ls: cannot access hiberfil.sys: Permission denied
ls: cannot access pagefile.sys: Permission denied
ls: cannot access swapfile.sys: Permission denied
total 8676
drwxrwxrwx 2 root root       0 Apr 25 17:20 .
drwxrwxr-x 2 root 1000       0 Jan  1  1970 ..
-rwxrwxrwx 1 root root  398156 Jul 26  2012 bootmgr
-rwxrwxrwx 1 root root       1 Apr 19 07:21 BOOTNXT
drwxrwxrwx 2 root root       0 Apr  3 16:33 Data
d????????? ? ?    ?          ?            ? Documents and Settings
drwxrwxrwx 2 root root       0 Sep  5  2015 ESD
drwxrwxrwx 2 root root       0 Dec 25 17:27 HashiCorp
-????????? ? ?    ?          ?            ? hiberfil.sys
drwxrwxrwx 2 root root       0 Sep  6  2015 Intel
drwxrwxrwx 2 root root       0 Apr 25 17:20 OneDriveTemp
-????????? ? ?    ?          ?            ? pagefile.sys
drwxrwxrwx 2 root root       0 Apr 19 07:30 PerfLogs
drwxrwxrwx 2 root root       0 Apr 25 16:56 ProgramData
drwxrwxrwx 2 root root       0 Apr 25 16:49 Program Files
drwxrwxrwx 2 root root       0 Apr 25 16:49 Program Files (x86)
drwxrwxrwx 2 root root       0 Apr 25 16:48 Recovery
drwxrwxrwx 2 root root       0 Aug  4  2015 $Recycle.Bin
-rwxrwxrwx 1 root root    2243 Jan  4  2015 RHDSetup.log
drwxrwxrwx 2 root root       0 Sep 21  2015 Ruby22-x64
drwxrwxrwx 2 root root       0 Jan  4  2015 sources
-????????? ? ?    ?          ?            ? swapfile.sys
drwxrwxrwx 2 root root       0 Sep 21  2015 System Volume Information
-rwxrwxrwx 1 root root 8388608 Apr 25 16:42 tmpgfile.sys
drwxrwxrwx 2 root root       0 Mar 19 15:18 Update
drwxrwxrwx 2 root root       0 Apr 25 16:49 Users
drwxrwxrwx 2 root root       0 Dec 30 07:51 vagrant
drwxrwxrwx 2 root root       0 Apr 25 16:54 Windows
drwxrwxrwx 2 root root       0 Apr 25 16:28 $WINDOWS.~BT
drwxrwxrwx 2 root root       0 Apr 25 16:39 Windows.old
drwxrwxrwx 2 root root       0 Sep  5  2015 $Windows.~WS
```

パーミッションが全て `777` のようで落ち着きませんが、MSDNの **[FAQ](https://msdn.microsoft.com/ja-jp/commandline/wsl/faq)** によると

> All permissions are set to 777 (full permissions of the user who launched the bash session)

とのことで、bash実行ユーザの全権限みたいな感じのようです。
あとはパーミッションが `?` だったり、rootユーザなのにPermission deniedだったりと怪しい感じですね。当然ここはWindowsの領域なのでパーミッションっていう概念がそもそも合わないのであれこれ考えること自体がナンセンスかもしれないですね。
今後のアップデートでどうなっていくかを見守りましょう。

## **実体**

さて、なんとなく探検を済ませてきましたが、こいつの実体は一体なんなのかという気持ちになってきました。
bashくん、君はいったいどこにいるの？

```console
root@PERSONAL:~# which bash
/bin/bash
```

というように、bash自身はまるで「俺？Linuxの住人だけど？」とでも言いたそうな感じですが、悲しいかなここはWindowsです。
無慈悲にエクスプローラで検索をかけてみましょう。

![WS000005.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/ecf291a1-561d-7f27-8fb8-7fd38e5058c9.jpeg)

おやおや、ずらずらと出てまいりました。

`C:\Users\[Username]\AppData\Local\lxss\rootfs`

見つけました。
どうやらここがLinuxにおけるrootのようです。lxssは「linux subsystem」あたりでしょうか。
ただし、隠しファイルを含めて全表示にしていたところで、lxss以降こいつを普通に辿ろうとしても見えません。
とはいえパスを直打ちすると普通に入れてしまいます。

中身を覗いてみると、

![WS000006.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/72dfe97f-eef5-1e4a-5bd8-7f45a16db06e.jpeg)

というように `/bin` と思われる場所にたくさんファイルがありました。
当然完全なバイナリファイルですが、触れ込みによるとこいつをUbuntuに持っていってもそのまま動くということなのでしょう。

一方で、 `/proc` なんかを見てみると空っぽになっています。

![WS000007.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/490e02af-34e0-f90e-6cc6-e480fdce4655.jpeg)

動的ファイルが見えない感じなんでしょうか。これも詳細不明です。

# **自由探検**

あとは個人的に気になるところをいくつかチェックします。

## **/mnt経由でまた/**

先ほど、

- `/mnt` にCドライブがマウントされていること
- ユーザディレクトリにrootfsが置かれていること

を確認しました。
もしや、/mntからrootfsに入り、また/mntからrootfsに入れるのでは...などと危険なことを考えました。

```console
root@PERSONAL:~# cd /mnt/c/Users/[Username]/AppData/Local/lxss/rootfs/
root@PERSONAL:/mnt/c/Users/[Username]/AppData/Local/lxss/rootfs# ls -la
total 128
drwxrwxrwx 2 root root     0 Apr 10 17:55 .
drwxrwxrwx 2 root root     0 Apr 25 17:19 ..
drwxrwxrwx 2 root root     0 Apr 10 17:55 acct
drwxrwxrwx 2 root root     0 Apr 10 17:54 bin
drwxrwxrwx 2 root root     0 Apr 10 17:54 boot
drwxrwxrwx 2 root root     0 Apr 10 17:55 cache

(略)

drwxrwxrwx 2 root root     0 Apr 10 17:55 usr
drwxrwxrwx 2 root root     0 Apr 10 17:55 var
```

とりあえず予定通り、2回目のrootにやってくることができました。
ただし、実際のパーミッションは以下の感じなのであくまでWindows領域のファイルとして見えているようです。

```console
root@PERSONAL:/# ls -la
total 125
drwxrwxr-x 2 root root     0 Jan  1  1970 .
drwxrwxr-x 2 root root     0 Jan  1  1970 ..
drwxr-xr-x 2 root root     0 Apr 25 18:59 acct
drwxr-xr-x 2 root root     0 Mar 23 20:45 bin
drwxr-xr-x 2 root root     0 Mar 23 20:54 boot
drwxrwx--- 2 1000 2001     0 Jan  1  1970 cache

(略)

drwxr-xr-x 2 root root     0 Mar 23 20:41 usr
drwxr-xr-x 2 root root     0 Mar 23 20:45 var
```

さらに、mntの中身が空っぽだったのでもう1周とはいきませんでした。

```console
root@PERSONAL:/mnt/c/Users/[Username]/AppData/Local/lxss/rootfs# cd mnt/
root@PERSONAL:/mnt/c/Users/[Username]/AppData/Local/lxss/rootfs/mnt# ls -la
total 4
drwxrwxrwx 2 root root 0 Apr 10 17:54 .
drwxrwxrwx 2 root root 0 Apr 10 17:55 ..
```

とても危険な香りのするアイデアだったのですが、残念です。

## **その他コマンド**

以下のコマンドを試します。

- ps aux
- top
- netstat -tanp
- ifconfig

```console
root@PERSONAL:~# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0      0     0 ?        Ss    2385   0:00 /init
root         2  0.0  0.0      0     0 ?        Ss    2385   0:01 /bin/bash
root        66  0.0  0.0      0     0 ?        R     2385   0:00 ps aux
```

PID 1でinitが動いているのは至極まっとうな感じがしますね。

```console
root@PERSONAL:~# top
top - 19:05:44 up  1:46,  0 users,  load average: 0.52, 0.58, 0.59
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.1 us, 49.1 sy,  0.0 ni, 46.6 id,  0.0 wa,  0.2 hi,  0.0 si,  0.0 st
KiB Mem:   1031052 total,   350316 used,   680736 free,        0 buffers
KiB Swap:        0 total,        0 used,        0 free.        0 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    1 root      20   0       0      0      0 S   0.0  0.0   0:00.01 init
    2 root      20   0       0      0      0 S   0.0  0.0   0:01.12 bash
   67 root      20   0       0      0      0 R   0.0  0.0   0:00.01 top
```

さて、これがなんだという話なのですが、topコマンドは `build 14316` では動かなかったんですよね。
私も「よーし、探検記事書くかー」と思った段階でさらっと触っていて噂通り動かないことを確認していました。

```console
root@PERSONAL:~# netstat -tanp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
```

netstatで見たところは、特にリッスンしたりしているポートはないように見えます。

```console
root@PERSONAL:~# ifconfig
Warning: cannot open /proc/net/dev (No such file or directory). Limited output.
```

あら、NICすら見えないようですね。

```console
root@PERSONAL:~# ping localhost
ping: icmp open socket: Socket type not supported
root@PERSONAL:~# ping 127.0.0.1
ping: icmp open socket: Socket type not supported
```

pingすら通らないとは一大事ですね。仕事中だったら泡吹いて倒れているところです。
FAQによれば、

> Why isn't ICMP working?
> This is a known issues that will effect several networking commands such as ping. Stay tuned for updates.

ネットワークがダメなことは分かってるから待っててね、とのことらしいです。気長に待ちましょう。

## **apt-get**

Ubuntuファミリーとして、apt-getが使えるようです。

```console
root@PERSONAL:~# apt-get install sl
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libfreetype6 os-prober
Use 'apt-get autoremove' to remove them.
The following NEW packages will be installed:
  sl
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 26.7 kB of archives.
After this operation, 126 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ trusty/universe sl amd64 3.03-17 [26.7 kB]
Fetched 26.7 kB in 2s (9,698 B/s)
E: Can not write log (Is /dev/pts mounted?) - openpty (2: No such file or directory)
Selecting previously unselected package sl.
(Reading database ... 25130 files and directories currently installed.)
Preparing to unpack .../archives/sl_3.03-17_amd64.deb ...
Unpacking sl (3.03-17) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Setting up sl (3.03-17) ...
```

![WS000011.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/83613893-65a2-b27c-e91f-a094928ce778.jpeg)

やった！SLが走った！

![WS000012.JPG](https://qiita-image-store.s3.amazonaws.com/0/45253/a0bb3c69-098b-8c43-b35b-1d7d07bc5a59.jpeg)

やった！牛がしゃべった！

## **シェル芸**

シェル芸タグをつけながら芸っぽいことを何もやらないのはあれなのでシェル芸をひとつ。

```console
root@PERSONAL:/# yes takasukurinikku
```

そうなんです。
残念ながら、まだこの Bash on Ubuntu on Windows 環境は **日本語入力に対応していない** のです。

しかし、安心してください。まだ道はあります。
Windows側から例のキーワードを入れたテキストファイルを作ってください。もちろんUTF-8で。

```console
root@PERSONAL:/# KEYWORD=$(cat yes_utf8.txt)
root@PERSONAL:/# yes ${KEYWORD}
高須クリニック
高須クリニック
高須クリニック
(略)
```

このように、UTF-8であれば文字化けもなく表示可能なようです。

もう1つ。
このbash、Powershell含め従来のWindows CLIから起動できます。

```
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\WINDOWS\system32> bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
PS C:\WINDOWS\system32> bash -c "echo 'Hello Bash!'"
Hello Bash!
```

そして、Powershell自体は日本語入力に対応しています。つまり...

```
PS C:\WINDOWS\system32> bash -c "yes 高須クリニック"
高須クリニック
高須クリニック
高須クリニック
(略)
```

のようなことが可能です。

# **build 14328**

さて、記事を書いている途中で `build 14328` に変わったわけですが、何が変わったのでしょうか。

**[Release Notes](https://msdn.microsoft.com/en-us/commandline/wsl/release_notes)**

色々書いてありますが、

> Hostname is now set to the Windows computer name, no more @localhost

とあるように、プロンプトでWindowsのホスト名を引き継ぐこと、

> top and htop now display

topが正しく表示されることは `build 14328` からのようです。

初めてのbash公開から約2週間ですが、こうやって着実に良くなっていくことを期待しています。