linuxBean14.04(180)古いファイルを削除してディスク空き容量を保つPythonスクリプト

2018-09-14

旧ブログ

t f B! P L
指定のフォルダの残り使用可能容量を計算して、指定の空き容量(%で指定)以下になったら、指定の空き容量になるように指定のフォルダ内の古い順にファイルを削除するPythonスクリプトです。空き容量の割合の分母となるフォルダと、削除するファイルのあるフォルダは別個のものに指定できます。

前の関連記事:linuxBean14.04(179)vsftpdでFTPサーバーにする


(2018.9.21追記。このPythonスクリプトではなくてlinuxBean14.04(183)古いファイルから削除してディスク使用容量割合を保つシェルスクリプトを使うことにしました。)

(2018.9.29追記。ディレクトリ内に循環参照しているシンボリックリンクがあるとOSError: [Errno 40] Too many levels of symbolic linksといわれて先に進めません。回避する方法はわかりませんでした。とういうことでこのPythonスクリプトには汎用性がありません。)

古いファイルを削除してディスク空き容量を保つPythonスクリプトkeepfreespace.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
from pathlib import Path
def main(folderpath, freespacerate, disk):  # disk: 容量割合計算の分母にするフォルダのパス, folderpath: 空き容量確保のために削除できるファイルがあるフォルダのパス、freespacerate: 空き容量の%を整数で渡す。
 files = []
 folders = []
 for p in Path(folderpath).rglob("*"):  # サブフォルダのPathオブジェクトをイテレート。ファイルとフォルダに振り分ける。
  if p.is_file():
   files.append(p)
  else:
   folders.append(p)
 files.sort(key=lambda x: x.stat().st_mtime)  # 更新日時の昇順にファイルの相対パスをソート。
 for file in files:  # 古いファイルからイテレート。
  statvfs = os.statvfs(disk)  # ルートディレクトリの情報を取得。動くのはUnixのみ。
  if int(statvfs.f_bavail/statvfs.f_blocks*100)<freespacerate:  # 規定の空き容量割合を達成していない時。
   file.unlink()  # ファイルを削除。
   print("The oldest file {} has been removed.".format(file.name))
  else:  # 空き容量が確保出来ていた時はループを出る。
   break 
 folders.sort(key=lambda x: len(x.parents), reverse=True)  # 階層が深い降順に並べる。
 for folder in folders:  # 深い階層から空フォルダを削除する。
  if next(folder.iterdir(), None) is None:  # フォルダ内に子要素がない時。
   folder.rmdir()  # フォルダを削除。 
   print("The empty folder {} has been removed.".format(folder.name))
if __name__ == "__main__": 
 import sys
 defaults = "./public", 5, "/"  # デフォルト引数。
 args = list(sys.argv)  # コマンドラインの引数を取得。インデックス0はスクリプトのパスなど。
 for i in defaults[len(args)-1:]:  # 足りない引数をデフォルトから補う。
  args.append(i)
 args[2] = int(args[2])  # 引数は文字列で返るので整数に変換する。
 main(*args[1:])
main()関数の引数freespacerateには整数で、空き容量の%を渡します。

空き容量の計算の分母にするフォルダを引数diskに渡します。

その分母に指定するフォルダのブロック数に、ユーザーが利用できる空ブロック数が占める%と比較しています。

空き容量がfreespacetateで指定した割合を下回っている時、引数folderpathに指定したフォルダ内のファイルを古い順から削除します。

削除するファイルがすべてなくなってしまったら、もう何もしません。

最後に、そのフォルダにある空きフォルダをすべて削除します。

linuxBean14.04(Python 3.4.3)では動作確認しましたが、空き容量の計算にos.statvfs()を使っているのでWindowsでは動きません。

また、どれぐらいの数のファイル数まで実用的に対応できるのか未知数です。

Pentium 4 2GHz M 512MBで、100GiBの空き容量にIPカメラからFTPで飛ばした1つ1MB程度の動画ファイルの管理を予定しています。

1ファイル2MiBとすると、空き容量5%として100GiBには100GiB*95/100%/2MiB=100*2^30*0.95/2*2^20=48640だいたいファイル数5万ぐらいですね。

思ったより少ないので、このままで動きそうな気もします。

計算間違いで1000ぐらいと思っていましたが、5万ファイルとなると結構な処理時間がかかりそうです。

cronで定期的にスクリプトを実行する


常に空き容量を確保するには上記のスクリプトを定期実行しないといけません。

定期的に実行するにはcronを使います。

まずcronに登録するためのコマンドのテキストファイルを作成します。

 分 時 日 月 曜日 コマンド

設定の書き方はcron の設定ガイドに詳しいです。
*/5 * * * * python3 keepfreespace.py
今回はこのように書いたテキストファイルをcron.confという名前で作成しました。

(2018.9.19追記

0 0,4,8,12,16,20 * * * python3 keepfreespace.py ./ipcamera1
0 2,6,10,14,18,22 * * * python3 keepfreespace.py ./ipcamera2

結局2つのフォルダに分けて2時間ごとにスクリプトを走らせようと思いますが、Pentium4-Mで、FTPで受信しながら、Sambaで送信するときがあるので、処理できないかも、、、)

最後に空行を挿入していないと、ファイルの終わりがわからないと言われます。

分のところに*/5とすると5分おきの実行になるようです。

crontab cron.conf

Terminalでcrontabコマンドにcron.confを渡します(定期的にスクリプトを自動実行させる)。

既に登録してあるコマンドは削除されます。

crontab -l

このコマンドでcronの登録内容が確認できます。

crontab -r

これで登録内容がすべて削除されます。

参考にしたサイト


定期的にスクリプトを自動実行させる
Linuxでコマンドを定期実行させるcronの設定方法。

cron の設定ガイド
cronの設定の書き方の解説。

ディスク容量(df)を監視して、規定値以上を超えたらアラートメールを送るシェル – KYO's Tech
容量計算のシェルスクリプトの例。

ディスクの空き容量を調べる - Pythonを書く
os.statvfs()の解説。

次の関連記事:linuxBean14.04(181)使用するカーネルのバージョンを指定する

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ