ROBOCOPY で取得したバックアップのファイルが削除できないことがあるので調べてみた。
バックアップ取得後に一定期間を経過したファイルは、Remove-Item コマンドで自動削除されるようにスクリプトを回しているが、削除できなくてファイルがたまり続けるという面倒な事態。原因はファイル名が260文字以上となっているため。260文字以上のファイル名のファイルは同様に作成できないのだが、Robocopy でコピーはできてしまっている状況。
消し方とたくさん溜まってしまったときの自動削除用のスクリプトを作成したのでメモ。
削除できなくなった
まずは、削除されずに残ったフォルダの削除を試してみると以下のエラー。ちなみに、スクリプトは Powershell で書いています。
1 2 3 4 5 6 7 |
> rm ${BACKUP_DIR}\20170820 -Recurse -Force rm : 指定されたパス、ファイル名、またはその両方が長すぎます。完全限定型名は 260 文字未満で指定し、ディレクトリ名は 248 未満で指定してください。 発生場所 行:1 文字:1 + rm .\20170820 -Recurse -Force + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (${BACKUP_DIR}\20170820:String) [Remove-Item], PathTooLongException + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand |
260文字未満で指定するようにある完全限定型名というのが、ファイルのフルパスになるんでしょうね。強制オプションを付与していますが、やっぱり削除できません。。。
ちなみ削除できないファイルと同名(パスも含めて)のファイルを作成しようとしても不可でした。同じエラーが発生します。ただ、ロボコピーでのコピーはできてしまう、という状況。ROBOCOPYのオプションでコピーできないようにもできるのか?それは今度調べるとして、ひとまず削除しないとディスク容量がすぐにいっぱいになってしまう。。。
2017/10/08追記:MSのTechnetに記載がありました。
以下のオプションによってコピーしないようにできるようです。ただ、よくよく考えるとバックアップなのでコピーしないという選択肢はなかったのであった。。。
/256 非常に長いパス (256 文字より長い) のサポートをオフにします。
削除する方法
何とかして削除する方法として、フルパスの長さが260文字未満になれば良いので、途中のフォルダに対してネットワークドライブを割り当てることで削除できるようになる。例えば以下のように。
1 2 3 |
D:\BackupDirectory\yyyymmdd\kaisou1\kaisou2\kaisou3.... ↓ Z:\kaisou1\kaisou2\kaisou3.... |
ただ、浅い階層に対して割り当てると「260文字未満」をクリアできないこともあると思います。
ぴぐろぐで遭遇した環境は、1日1回バックアップを行っており、日付フォルダを作成しているので、その日付フォルダに対してネットワークドライブを割り当てることにできればよかったが、それだと260文字以上になってしまった。そのため、更に深い階層に割り当てる必要があったので、その場合のスクリプトを作成した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
### Debug Set-PSDebug -trace 2 ### Variable $BAK_DIR = "\\${FileServer}\${BackupFolder}" $TARGETS = 20170817..20170823 $NWD = "Q" ### Delete foreach($TARGET in $TARGETS){ $NWD_DIR = "${BAK_DIR}\${TARGET}\${AllocateFolder}" net use ${NWD}: ${NWD_DIR} Remove-Item ${NWD}:\* -Recurse -Force net use /delete ${NWD}: /y Remove-Item ${BAK_DIR}\${TARGET} -Recurse -Force } |
具体的には以下↓↓↓のようなフォルダ構成で、AllocateFolder に対してネットワークドライブを割り当てている。たいがい260文字以上にもなるファイルはそうそう無いので、AllocateFolder が複数存在する想定ではない。複数ある場合は更に foreach で回せばよいだけ。
\\10.1.1.10\BackupFolder\yyyymmdd\AllocateFolder
$TARGETS の値は、20170817~20170823までのフォルダを削除したい場合の例で、Get-childitem $BAK_DIR\201708* -name などでもいけるし適宜修正。あと、せっかく Powershell 使ってるのに net use かよ、というつっこみはなしで。
-Recurse -Force で強制していたのでエラー判定は行っていなかった。それはそれで良いと思ってるが全く気づけ無いのは良くないのでzabbixかなんかで監視サーバたてるか。。。いや、Windowsだからクオータ設定いれればいいだけか。
以上です。
↓↓↓ 持っていると便利な一冊。