Sambaのdfree command

2020年2月15日LinuxCentOS,Samba

Sambaのdfree command
うちでは、CentOSにSambaをインストールして、ファイルサーバーとして使っています。

Sambaで共有しているフォルダに、ストレージ用のHDDをマウントしているのですが、トータル容量が表示されなかったり大きなファイルのコピーができなかったり困ったことが起きてしまいました。

Sambaにはdfree commandという設定があり、これに自作スクリプトを登録すると不具合の解消ができたので、その紹介です。

環境

CentOS側では、/mnt/share以下に、各HDDをマウントしています。

パス実体空き容量(例)
/mnt/share/システムドライブ(SSD)30GB
/mnt/share/Share1/1個目のHDD1000GB
/mnt/share/Share2/2個目のHDD800GB
/mnt/share/Share3/3個目のHDD900GB

Sambaの設定(/etc/samba/smb.conf)では、/mnt/share/を「Share」という名前で共有するように設定しています。つまり、クライアントのWindows機から\\server\Shareにアクセスすると、Share1~Share3フォルダが表示されます。

不具合

コピーがうまくいかない

クライアントのWindows機からファイルサーバーのCentOS機にファイルをコピーすると、なぜかWindowsは共有ドライブのルートの空き容量を見に行って、コピー先に充分な容量があるか確認してしまいます。

つまり、HDD1に空き容量がたくさんあるにもかかわらず、大量のファイルをHDD1にコピーしようとすると、CentOSのシステムドライブの空き容量と比較してしまうため、「空き容量が足りない」というメッセージが出てコピーができません。

FireFileCopyのようなファイルのコピー・移動ソフトを使うと、宛先フォルダの空き容量を問い合わせてくれるようなので問題ありませんが、Windows標準のコピー・移動を使うと上記のようになります。(Windowsのバグ?)

これでは、一度にコピーできる容量がCentOSシステムドライブの空き容量までになってしまうため、非常に不便です。

トータルの記憶容量が分からない

Sambaは、クライアントから空き容量の問い合わせがあったとき、そのフォルダの空き容量を返すようです。つまりShare1フォルダを開くと1個目のHDDの空き容量「1000GB」を返してくれます。が、共有ルート(\\server\Share)ではシステムドライブ(/mnt/share/)の空き容量「30GB」を返してしまいます。

クライアントのWindows機で「ネットワークドライブの割り当て」をすると、コンピュータ上に共有フォルダがマウントされます。

このとき、コンピュータに表示される空き容量は共有ルートのものになるため、CentOS機のシステムドライブの空き容量が表示されてしまいます。

本当はShare1~Share3のトータル空き容量を表示してほしいのですが、これでは不便です。

ちなみに、私はClassic Explorerというソフトを入れており、これでステータスバーを表示すると、現在のフォルダの空き容量が表示されます。この表示は前述の表の通りで、共有ルートではCentOSのシステムドライブの、Share1などではそのHDDの空き容量が表示されますので、一応は問題ありません。

dfree commandを自作して対策してみる

Sambaでは、dfree commandという設定項目があり、ここに自作スクリプトを指定すると、空き容量の応答を変えることができます。

dfree commandの仕様

下記仕様のスクリプトを作成すれば良いそうです。参考にさせていただいたのはこちらこちらのサイトです。

  • スクリプト実行時のワーキングディレクトリは、共有ルート(今回の場合/mnt/share)
  • 引数として、ワーキングディレクトリから見た、問い合わせフォルダの相対パスが渡される。例えば \\server\Share\Share1\MyDoc にアクセスした場合は、Share1/MyDoc が渡される。共有ルート(\\server\Share\)の場合は「. (ピリオド)」が渡される。
  • スクリプトは、スペース一つ開けて整数を二つ標準出力する。一つ目はトータル容量、二つ目は空き容量で、ともにキロバイト単位で表示する。

方針

下記のような空き容量を表示するスクリプトを作成してみます。

パス実体実空き容量表示空き容量
/mnt/share/システムドライブ(SSD)30GB2700GB
/mnt/share/Share1/以下1個目のHDD1000GB1000GB
/mnt/share/Share2/以下2個目のHDD800GB800GB
/mnt/share/Share3/以下3個目のHDD900GB900GB

つまり、Share1など以下ではそのHDDの実空き容量を表示し、共有ルートではShare1~Share3のトータル空き容量を表示します。

これによって、

  • Share1など以下では、Classic Explorerのステータスバーに各HDDの空き容量が表示される
  • コンピュータ上にマウントしたときの容量表示が、Share1~Share3の合算になる
  • CentOSシステムドライブの空き容量によらず、大量のファイルをコピーできる

を実現します。

スクリプト

つたないですが、実際に作成したスクリプトはこちらです。

#!/bin/bash

PWD=`pwd`
if [ $1 = '.' ]; then
	RETURN=`df |grep $PWD |gawk '{i= i+ $2}{j = j + $4}END{printf "%d %d \n",i,j}'`
else
	RETURN=`df $1 |tail -1|gawk '{print $2,$4}'`
fi
echo $RETURN

ピリオドが渡された場合(共有ルートの空き容量問い合わせがあった場合)は、全ドライブの内、/mnt/shareにマウントされているドライブの全容量・空き容量を合算して返します。

ピリオド以外が渡された場合(Share1以下のフォルダの空き容量問い合わせがあった場合)は、そのフォルダの全容量・空き容量を返します。

このスクリプトをCentOS上のどこかに保存して、実行権限を与えます。

Sambaの設定

/etc/samba/smb.confを設定します。[global]にdfree commandの行を書き足し、前述のスクリプトのパスを指定します。

[global]
  dfree command = /mnt/share/dfree.sh

dfree cache timeも設定してもいいかもしれませんが、私はしていません。

smb.confの編集が終わったら、Sambaを再起動します。

sudo systemctl restart smb

設定の確認

Windows側からコンピュータ上の表示が合算表示になったことと、大容量のファイルコピーができるようになっていればOKです。

注意点

二点注意が必要です。

一つ目はSELinuxです。Sambaがdfree.shを実行できるようにSELinuxの設定をしないといけません。私の場合、そこの設定が解決できなかったため、SELinuxを無効にしました。

二つ目は、各フォルダの空き容量を超えてファイルをコピーする場合です。Windows標準のファイルコピーでは、共有ルートの空き容量を見てコピーできるか判断しています。ですので、各フォルダの空き容量より大きなファイル(例えばShare2に850GB)をコピーしようとすると、実際に空き容量がゼロになったとき(800GBコピーしたとき)に「空きがない」と言ってきます。

ファイルのコピーやCentOS内でのファイルの移動であれば問題ないようですが、「別PCの共有フォルダからこのCentOSの共有フォルダにファイルを移動する」場合はファイルが消失することがあるようです。(これもWindowsのバグ?)

2020/7/19 説明がわかりにくい気がしたので追記:

前述の表の例では、HDD1には1000GBの空き容量があります。例えば、Windows機から、このHDD1へ1200GBの(実空き容量より大きい)フォルダ・ファイルを移動すると、ファイルが一つ消失します。

  • Windows機からCentOS共有フォルダのHDD1へ、1200GBのファイルを移動する操作をする
  • 移動開始時、Windowsは共有ルートの空き容量(2700GB)と比べて空きが足りているか確認するので、エラーなど表示されずにファイルの移動が始まる
  • ファイルの移動が進んでいく
  • ファイルの移動が1000GBに達すると、移動先のHDD1が満タンになるので、この時初めて「空き容量が足りない」とエラーが表示されて、移動も中断される
  • このとき移動中だったファイル(ちょうど1000GB目のファイル)が消失する(移動元にも移動先にもない状態になる)
  • 1000GBまでのファイルは移動先フォルダに、1000GB目より後の残り200GBは移動元フォルダにある状態でファイルの移動が中断される

もちろん、ファイルのコピーであれば、コピー元のファイルは操作されませんので消えたりしません。