DebianをWindows10上で動かす その6: Linuxとファイルを共有する

2019/04/13 更新

Windows10 バージョン1809 (October 2018 Update)で再インストールしたので、それに合わせて記事を見直しました。

前回はWindows Subsystem for Linux (WSL)上にインストールしたDebian GNU/LinuxにSSHで接続する方法を紹介しました。

今回はネットワーク上にあるLinuxとファイルを共有する方法を紹介します。

前提となるネットワーク構成

私が普段作業してる環境は、ファイルサーバとして動かしているLinuxがあり、Windows10上から共有フォルダとしてLinux上のファイルを見えるようにしています。

つまりLinuxにはSambaが導入されていることになります。

現時点でのネットワーク構成

ここでWindows10にWSLでDebianを導入したので、このDebianからファイルサーバ(Linux)のHDDを見たいというのが私の希望です。

特に、ファイルサーバのLinuxのホームディレクトリには各種設定ファイルやデータがあるので、できればこのホームディレクトリをWSLのホームディレクトリとして使いたいところです。

実現したいネットワーク構成

ファイル共有の方法

ファイル共有の方法としては大きく分けて二つの方法がありそうです。

  1. WSLがWindows10経由でファイルサーバ(Linux)にアクセスする
  2. WSLから直接ファイルサーバ(Linux)にアクセスする

とりあえず試行錯誤してみたいと思います。

Windows10経由でファイルサーバにアクセス

WSLにはWindows10のディスクドライブをマウントする「drvfs」という機能があります。

従って、ファイルサーバの共有フォルダをネットワークドライブに割り当てていれば、drvfsでマウントすることができるはずです。

イメージとしてはこんな感じです。

Windows10経由

例えば、共有フォルダをネットワークドライブとして「z:」に割り当ててあったとします。

この場合は次のようにマウントすればOKです。

$ sudo mkdir -p /mnt/z
$ sudo mount -t drvfs -orw,noatime,uid=1000,gid=1000,umask=22,fmask=111 z: /mnt/z

これで/mnt/z以下にファイルサーバの共有フォルダが見えるようになります。

1年前のWSLでは次のような問題がありました。

  1. 全てのファイルパーミッションが「777」となってしまう
  2. ファイルやディレクトリの名前は見えるが、中身が見えない (permission deniedになる)
  3. なぜかtouchコマンドを使うと空ファイルの作成だけはできる

しかし、今回試してみるとこれらの問題は解消していました。

ただ残る課題が一つありました。それはファイル名・ディレクトリ名でアルファベットの大文字・小文字の区別ができないことです。例えば、test.txtとTest.txtは同じファイルをあらわすことになります。

マウントオプションで「case=force」を試してみましたが「permission denied」となってしまいます。

この大文字・小文字問題に注意すれば、ネットワークドライブを快適に使うことができそうです。

大文字・小文字問題はLinuxで作成したファイルをWSL側で見る場合に問題になるかもしれません。

例えば、Linux側で「Test.txt」と「test.txt」を作成した場合、WSL側ではファイルは二つに見えますが、「cat Test.txt」を実行しても表示されるのは「test.txt」になってしまいます。

直接ファイルサーバにアクセス

WSL上で動いているといるとはいえLinuxはLinuxです。

Linuxのネットワークファイルシステムといわれる仕組みと使うと、ファイルサーバのLinuxとファイル共有ができる可能性があります。

いくつかのネットワークファイルシステムを試してみたいと思います。

NFS → 失敗

Linux間でネットワークでファイルを共有する際の定番なのはNFSです。

私も最初はNFSを使おうと思っていました。

しかし、WSLがサポートしているファイルシステムをチェックしてみるとNFSが入っていません。

$ cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
nodev   tmpfs
nodev   binfmt_misc
nodev   debugfs
nodev   sockfs
nodev   usbfs
nodev   pipefs
nodev   anon_inodefs
nodev   devpts
ext3
ext2
ext4
nodev   ramfs
nodev   hugetlbfs
vfat
msdos
iso9660
fuseblk
nodev   fuse
nodev   fusectl
yaffs
yaffs2
nodev   overlayfs
nodev   overlay
nodev   mqueue

これではNFSは使えません。

ためしに使ってみたところ「unknown filesystem type ‘nfs’」になってしまいました。

$ sudo mount -t nfs 192.168.10.1:/home /mnt/nfs/
mount: unknown filesystem type 'nfs'

SMB/CIFS → 失敗

ファイルサーバではSMB/CIFSサーバであるSambaが動いています。

従って、WSLのDebianがSMB/CIFSクライアントになればファイルサーバとファイルを共有できるはずです。

しかしWSLがサポートしているファイルシステムには「cifs」が含まれていないので、そのままではWSLはSMB/CIFSクライアントにはなれません。

そこでFUSEというシステムでSMB/CIFSクライアントになることができる、「fusesmb」を試してみます。

SMB/CIFSの利用

まずはインストールです。

$ sudo apt-get install fusesmb

私の場合は依存しているパッケージがたくさんあって、27個のパッケージがインストールされました。

インストールが完了したら設定ファイルを作ります。

まずサンプルをコピーしてパーミッションを設定します。

$ mkdir .smb
$ cp /usr/share/doc/fusesmb/examples/fusesmb.conf.ex .smb/fusesmb.conf
$ chmod 600 .smb/fusesmb.conf

そしてこのファイルを編集して、最後に次のような内容を付け加えます。

[/ファイルサーバの名前/共有フォルダ名]
username=ファイルサーバでのアカウント名
password=ファイルサーバでのパスワード

ここまできたらfusesmbを使ってみます。

$ mkdir mnt
$ fusesmb mnt/
fuse: device not found, try 'modprobe fuse' first

残念ながらエラーが出てしまいました。

「modprobe fuse」をしてみろということなのでやってみます。

$ sudo modprobe fuse
modprobe: ERROR: ../libkmod/libkmod.c:586 kmod_search_moddep() could not open moddep file '/lib/modules/4.4.0-17763-Microsoft/modules.dep.bin'
modprobe: FATAL: Module fuse not found in directory /lib/modules/4.4.0-17763-Microsoft

fuseのカーネルモジュールがないためロードに失敗しました。

マウント時の動作を確認してみると/dev/fuseのオープンに失敗していることがわかります。

$ strace fusesmb mnt/
execve("/usr/bin/fusesmb", ["fusesmb", "mnt/"], [/* 18 vars */]) = 0
省略
open("/dev/fuse", O_RDWR)               = -1 ENOENT (No such file or directory)
write(2, "fuse: device not found, try 'mod"..., 50fuse: device not found, try 'modprobe fuse' first
) = 50
exit_group(0)                           = ?
+++ exited with 0 +++

どうも /dev/fuse がなくて止まっているようです。

そこで手動で/dev/fuseを作成してみます。Linuxカーネルのドキュメントを見るとメジャー番号は10、マイナー番号は229とのことです。

そこで下記のコマンドで/dev/fuseを作成します。

$ sudo mknod -m 0666 /dev/fuse c 10 229

これで再度fusesmbを使ってみます。

$ fusesmb mnt/
fuse: device not found, try 'modprobe fuse' first

結果は・・・同じく「device not found」でエラーになってしまいました。

WSLのfuseは完全に実装されていないのかもしれません。

調べてみるとfuse実装の希望はかなり上がっていますが・・・将来のバージョンで改善されるのを期待しましょう。

SSH → 可能

SSHはリモートログインするためのプロトコルです。

しかし、SSHにはscpやsftpというようなファイル転送の機能もあります。この機能を使うとファイルサーバ(Linux)のファイルをWSLから取得したり、WSLのファイルをファイルサーバ(Linux)に送信することができます。

SSHの利用

本当はこのSSHのファイル転送機能を使ってSSHサーバをファイルシステムとしてマウントできるsshfsという仕組みがあります。

しかし、このsshfsはfuseという仕組みをベースとしているので現時点でのWSLでは動作しません

今回はscpコマンドのを使えるところまで設定してみます。ただし、ファイルサーバ(Linux)では既にSSHサーバが起動しているものとします。

まず、WSLのDebianにSSHクライアントをインストールします。

$ sudo apt-get install openssh-client

続いてWSLで秘密鍵と公開鍵のペアを作成します。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/foo/.ssh/id_rsa): ← リターンキーを入力
Enter passphrase (empty for no passphrase):  ← パスフレーズを入力 (不要な場合は単にリターンを入力)
Enter same passphrase again:  ← パスフレーズの再入力 (不要な場合は単にリターンを入力)
Your identification has been saved in /home/foo/.ssh/id_rsa.
Your public key has been saved in /home/foo/.ssh/id_rsa.pub.
以下省略

パスフレーズで保護した方が安全ですが、パスフレーズがない方が利便性が高くなります。私はパスフレーズはなしにしました。

これでホームディレクトリの.sshディレクトリにid_rsa.pubという公開鍵ファイルが作成されているはずです。

このファイルの中身をファイルサーバのLinuxの「ホームディレクトリ/.ssh/authorized_keys」に追記します。WSLのターミナル画面に中身を表示させてコピペをすれば良いでしょう。

ここまできたら接続できることを確認して見ます。

$ ssh ユーザ名@ホスト名(IPアドレス)

これでパスワードの入力なしに接続できればOKです。

あとはscpコマンドでファイルをコピーするだけです。

scpコマンドの使い方は下記のようになります。

$ scp ユーザ名@サーバ名:ファイルパス ファイルパス     (サーバからWLSにコピーする場合)
$ scp ファイルパス ユーザ名@サーバ名:ファイルパス ファイルパス     (WLSからサーバにコピーする場合)

例えば、ファイルサーバ(192.168.10.1)のユーザfooのホームディレクトリにあるtest.txtをWSLに持ってくる場合は下記のようになります。

$ scp foo@192.168.10.1:~/test.txt .

ちなみにファイルサーバとWSLのユーザ名が一致していれば「foo@」の部分も省略することができます。

ファイルシステムとしてマウントしたときのように手軽には使えませんが、とりあえずこれでファイルサーバとファイルをやりとりをできるようになります。

scpコマンドが動くので、rsyncコマンドなどでファイルの同期も可能となります。

まとめ

今回はWindows Subsystem for Linuxとネットワーク上にあるLinuxファイルサーバ間でファイルを共有する方法を紹介しました。

Windows10 October UpdateのWSLではネットワークドライブもマウントできるようになりました。ネットワークドライブのファイル名では大文字・小文字区別ができないという課題はあるものの、なんとか実用になりそうです。

次回はWSLとしてインストールしたDebian GNU/LinuxでGUIを使ってみます。