webdavへのバックアップ
写真ファイルをバックアップするため、日本のどこかで動いてるLinuxサーバーのapacheにwebdavを仕込んで、作業用のWindows PC内の対象のディレクトリの内容をそっくりコピーし、同期するようにしている。
コピーに際しては、Windowsに付属のrobocopyコマンドというのを使うようにしていて、新しく追加したり更新したファイルだけを選択的にコピーしつつ、ローカル側で削除したファイルはリモート側からも削除させている。こうすることで、日本のどこかで動いているサーバー上のディレクトリを、バックアップ対象としているPCのディレクトリの内容と同期させている。
リモート側からの削除はいつも行う必要もないのだが、ローカル側に比べてリモート側のストレージは使用料が高いので、まめに削除して容量を節約している。
PCにつながったUSB HDDなどにもバックアップをとっているが、こちらはローカル側で間違って削除したものがすぐに復活できるよう、追加と更新のみ(削除は無し)としている。
webdav用バックアップバッチファイル
だいたい作業を終えてPCの前から離れるとき、以下のようなバッチファイルを実行し、バックアップとシャットダウンを行わせている。
1 2 3 4 5 6 7 8 9 10 |
dir n: if %ERRORLEVEL% equ 0 goto ok net use n: https://fqd-server-name/webdav PASSWORD /user:USERNAME if %ERRORLEVEL% neq 0 exit /B 1 :ok robocopy d:\Photos\jpeg n:\Photos\jpeg /XF desktop.ini Thumbs.db /MIR /NP /FFT /R:0 /W:1 > log.log shutdown /s /t 0 |
このバッチファイルでは、サーバーのwebdavディレクトリをローカルドライブのN:にマップして使っている。
そのため、まずは N: がすでに存在しているかどうかを調べ、存在していなければ、net use コマンドを使ってfqd-server-nameで示すサーバーの/webdavディレクトリをN:ドライブにマップする。サーバー側の/webdavディレクトリには基本認証を掛けてあるので、認証情報を PASSWORDとUSERNAME に与えている。
net useが成功するかすでに N: が存在していれば、robocopyコマンドにより、送り側 (d:\Photos\jpeg)ディレクトリのサブディレクトリを含めた全内容を、受け側 (n:\Photos\jpeg) ディレクトリに同期コピーしている。
最後に、shutdownコマンドを使ってPCをシャットダウンしている。おおむねこの方法でバックアップとシャットダウンが完了するのだが、まれに異常に時間がかかってrobocopyの実行が終わらないときがある。そういうときは、翌朝になって正常動作していないことにようやく気が付くことになる。
ただ、Windowsデスクトップのスリープタイムアウト設定も入れてあるのでrobocopyが終わらなくても無意味にPCの電源がオンになっているということはない。翌朝スリープ状態になっていることで異常に気がつく。
robocopyのオプション
/MIR
上記のバッチファイルでは、robocopyに /MIR というオプションを付けている。MIRはMIRRORを短縮したものなのだろう。だいたい以下のように動作する。
- 送り側にあって、受け側にないものはサブディレクトリも含めて全部コピー(新規)。
- 受け側に送り側と同じ名前のファイルがある場合、送り側のタイムスタンプが新しければコピー(更新)。
- 受け側にあって送り側になければ、受け側の該当ファイル/ディレクトリを削除(削除)。
受け側がapacheのwebdavの場合、ファイル実体のほかにタイムスタンプとファイル属性はコピーされるが、NTFSのセキュリティ情報やオーナー情報はコピーされないようだ。これらも何かのオプションで可能なように構成できるのかもしれないが、とりあえず気にしていない。
/FFT
webdavをnet useでマップした場合、FATファイルシステムに見えるようだ。この場合、タイムスタンプの粒度が2 秒間になるので、送り側と受け側のタイムスタンプの2秒の相違を無視させる。
/XF desktop.ini Thumbs.db
この2つのファイルをコピーしても意味がないので除外している。
/NP /W:1 /R:0
- NPは、コピーの進行状況を出力させないため。標準出力をlog.logに残しているので、進行状況は邪魔なだけである。
- R:0は、コピー失敗時の再試行回数だが、これを0として再試行はさせないようにしている。1回くらいやってもいいのだが。
- W:1は、失敗時の再試行間隔時間(秒)。R:0としているので省略してもいいのかもしれない。
ログファイルを書かせるオプションもあるが、robocopyの出力をリダイレクトしてやればだいたいのことは分かるので使っていない。
Windows10のrobocopyはおかしい?
今使っているPCを入れたときに 写真編集用PCを導入 という話を書いたのだけど、この記事の中でもrobocopyの動作がWindows 7のそれと変わってしまって困った、という話を書いた。
内容としては、受け側がwebdavの場合送り側と受け側の同期がとれているのに、まず受け側のファイルやディレクトリをすべて消してからコピーを始めるので、毎度送り側の全ファイルのコピーが行われ、転送量は増えるわ時間がかかるわで、とても使えない、というもの。
今回、Windows 10 Homeの1809版というのに更新してみたが、この動作はまったく同じでやはり使えない。
受け側がUSB HDDやLAN内にあるNAS(samba)なら問題なく動作するのたが、webdavが相手だと相変わらず削除から始まる (送り側に同じファイルがある受け側ファイルを、EXTRA Fileと認識するところから始まるので、/MIRによって削除される)。
なので、相変わらず Windows Server 2003 Resource Kit Tools 内のrobocopyコマンドを利用している。こちらは意図通り、従来通りに動いてくれるので、余計なコピーは行われない。
ディレクトリ内のファイル数に制限がある?
ここからが本題になるのだが、ある朝やはりrobocopyを含んだバッチファイルが正常終了しておらずPCがスリープしていた。どうやら、8200個ほどのファイルを含んだディレクトリの全内容をコピーしているうちにスリープタイムアウトに達したようだった。今年に入ってせいぜい20個くらいしか追加していないのになんでだろうと思って再現させてみると、robocopyが以下のようなメッセージを出力していた。
1 2 |
2019/01/10 07:48:38 ERROR 31 (0x0000001F) Scanning Destination Directory n:\Photos\jpeg\昆虫\ システムに接続されたデバイスが機能していません。 |
そして、その後はローカルの昆虫ディレクトリの全内容のコピーを開始していた。
Windows10のwebdavクライアント(webclient)にはファイル数に何かの制限があるのかもしれない。
webclientのパラメータ変更
webclientについて調べてみると以下のようなことが書いてあった。https://support.microsoft.com/ja-jp/help/912152/you-cannot-access-a-webdav-web-folder-from-a-windows-based-client-comp
これは、WindowsXPのときの話なのだが、Windows7, 8, 8.1にも適用されるとのこと。Windows10ではどうなのか。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters\
値: FileAttributesLimitInBytes
データの種類: DWORD
既定値: 1,000,000 10 進数 (1 MB)
説明: このレジストリ サブキーには、WebDAV リダイレクターによって許可されている 1 つのフォルダー内のすべてのファイル属性の集合的な最大のサイズを決定します。この属性の制限では、すべての実行とする反応について説明します。問題は、WebDAV サーバーによって返されるすべてのファイル属性のサイズが予想よりもかなり大きいために発生します。既定では、このサイズは 1 MB に制限します。この制限は、セキュリティ上の理由です。の詳細については、マイクロソフト サポート技術情報の記事を表示するのには次の資料番号をクリックします:
相変わらず意味が分からないのだが、「集合的な最大のサイズ」というのは、各ファイル属性の合計サイズのことだろう。 レジストリエディタで実際の値を確認してみると、やはり1,000,000 になっている。
1,000,000バイトになっている理由については、セキュリティ上の理由と書いてあるが、回避策によればもっと大きな値にすれば解決すると書いてある。おそらく、確保したメモリが開放されないことを嫌ったものなのだろう。
注: 1,000,000 (1 MB) を既定値には、Windows により、最大で 1 つのフォルダーに約 1,000 のファイルが列挙されます。ファイルの実際の最大数は、ファイル属性またはファイルのプロパティの数によって異なる場合があります。既定で、WebClient サービスが特定の WebDAV プロパティを求めません。したがって、サーバーは、すべてのファイル属性を返します。WebDAV の特定のプロパティは、Microsoft Office に統合された web フォルダー リダイレクターを求めています。
どうやらMicrosoftは1ファイルあたりの属性サイズを1000バイトとして見積もっているようだが、実際にサーバーでのファイル数を調べてみると約8200個だった。そのちょっと前までうまくいっていたとすると、webdavでの1ファイルあたりの属性サイズは125バイト弱程度と考えてもいいのかもしれない。
上記のサポートページにも、FileAttributesLimitInBytes を大きくしろと書いてあるので、さっそくFileAttributesLimitInBytesを2,000,000としてwebclientサービスを再起動して試してみたところ、去年までと同様、うまく更新コピーが動くようになった。
きょうのまとめ
- Windows10版robocopyの残念な動作には変化はなかった。Windows10のrobocopyをwebdav相手に、まともに使えるようにして欲しい。以前の実験では、IISで実装されているらしいOneDriveのwebdav用URLを net use コマンドでマップしても同じくダメだった。
- support.microsoft.com の912152は、Windows 10にも同じように適用できることが分かった。このパラメータ変更で、あと8000ファイル増やしても大丈夫だろう。
- 原文のURLはこちらです。https://support.microsoft.com/en-us/help/912152/you-cannot-access-a-webdav-web-folder-from-a-windows-based-client-comp たぶん、こっちの方が内容が伝わりやすい。