linuxBean14.04(183)古いファイルから削除してディスク使用容量割合を保つシェルスクリプト

2018-09-21

旧ブログ

t f B! P L
linuxBean14.04(180)古いファイルを削除してディスク空き容量を保つPythonスクリプトよりシェルスクリプトの方が速く動きそうな気がするので、シェルスクリプトで書き直しました。

前の関連記事:linuxBean14.04(182)無線LANカード WLI-CB-AMG54 を使う


古いファイルから削除してディスク使用容量割合を保つシェルスクリプト

(2020.7.24追記。この記事のスクリプトは使わずに古いファイルから削除してディスク使用容量割合を保つシェルスクリプト-p--qで作り直しました。)

(2018.9.30追記linuxBean14.04(185)ディレクトリツリー内の一番古いファイルを抽出する方法の結果を反映してシェルスクリプトを書き直しました。
#!/bin/bash
# dashではdoneへのリダイレクトが使えない。
# 削除対象のファイルがあるディレクトリパス。このディレクトリも空になると削除される。
DIRNAME=public/videos
# ディスク使用容量%。この容量を超えると古いファイルから削除していく。
P=95
# ディスク容量が指定%以上の間、古いファイルから削除していく。
while read -r line ; do
  if  [ $(df / | tail -1 | sed 's/^.* \([0-9]*\)%.*$/\1/') -gt $P ]; then
    rm "$line"
  else
    break
  fi
done < <(find $DIRNAME -type f -printf "%T@ %p\0" | sort -nz | grep -zo ".*" | sed 's/[^ ]* //')
# 指定ディレクトリ以下の空ディレクトリを削除。最下層からイテレートされて指定ディレクトリも削除される。
find $DIRNAME -type d -empty -delete
6行目で一定に保つディスク使用容量を%で指定します。6行目で削除対象となるファイルがあるディレクトリを指定します。
2020.7.24追記。 このスクリプトは改行のあるファイル名のファイルを処理できないことと、grepのバージョンによって挙動が異なるので採用をやめました。)

#!/bin/bash
# 削除対象のファイルがあるディレクトリパス。このディレクトリも空になると削除される。
DIRNAME=public/videos
# ディスク使用容量%。
P=95
# Bashスクリプト内でエイリアスを有効にする。
shopt -s expand_aliases
# ディスクの使用容量割合を%で取得するコマンドのエイリアスを作成。
alias dval="df / | tail -1 | sed 's/^.* \([0-9]*\)%.*$/\1/'"
# 指定ディレクトリ以下のファイル名一覧を取得するコマンドのエイリアスを作成。
alias findfile="find $DIRNAME -type f"
# ディスク容量がP%以上、かつ、DIRNAMEディレクトリ以下のファイル名一覧が取得できている間実行。
while [ $(dval) -gt $P ] && [ -n "$(findfile)" ]; do
  # 一番古いファイルを削除。
 rm "$(findfile | xargs ls -t | tail -1)"
done
# 指定ディレクトリ以下の空ディレクトリを削除。最下層からイテレートされて引数のディレクトリも空になれば削除される。
find $DIRNAME -type d -empty -delete 
(2018.9.29追記。このシェルスクリプトでは、ファイル数が膨大になり、xargsで1回で渡せる引数の長さの制限を超えた場合は一番古いファイルを正しく選択できません。またパスに空白があるとエラーがでます。)

5行目で一定に保つディスク使用容量を%で指定します。

上記では95%を指定しているので、ディスク使用容量が95%を上回ると指定したディレクトリ内のファイルを古い順から削除します。

3行目で削除対象となるファイルがあるディレクトリを指定します。

上記ではpublic/videosを指定しているので、このスクリプトのあるディレクトリにあるpublicディレクトリのサブディレクトリのvideosディレクトリ内のファイルを削除していきます。

このディレクトリにあるすべてのファイルを削除しても、ディスク使用容量が指定割合を超えているときは、もうあきらめます。

最後の行で削除するファイルがあるディレクトリ内の空ディレクトリをすべて削除しています。

すべてのファイルを削除したときは指定ディレクトリすら削除されます。

わざわざエイリアスを使っているのは、コマンドが長くて見にくいので、それを見やすくするためだけの目的です。

このスクリプトをkeepspace.shという名前で保存して実行パーミッションを「すべて」に変更しました。
.
├── keepspace.sh
└── public
    └── videos
同じディレクトリにpublic/videoディレクトリを作成して、容量調節のために削除するファイルはこのディレクトリに入るようにしました。

videosディレクトリはその中のファイルがすべて削除されると、videosディレクトリ自身も削除されます。

どれぐらいのファイル数でどれぐらいの処理時間がかかるかはまだ未確認です。

cronでkeepspace.shを定期実行する


(2018/11/30追記。cronについてはlinuxBean14.04(180)古いファイルを削除してディスク空き容量を保つPythonスクリプトでもやりました。)

0 * * * * ./keepspace.sh

最後に空行を挿入してこれをcron.confという名前で保存しました。
(2018.11.30追記。コマンドへのパスはlinuxBean14.04(188)cronの実行ログ、cronで実行させたコマンド出力、の取得方法の方法でpwdの出力を取得してみるとcrontabを登録したユーザーのホームフォルダでした。つまり~と.は同じになります。)

これで毎時0分にこのスクリプトが実行されます。

crontab cron.conf

あとはこのコマンドでcronに登録しました。

参考にしたサイト


サーバーの空き容量を監視してアラートメールを送ってくれるシェルスクリプトを書いたよ | IDEA*IDEA
ディスク使用容量割合を取得する方法。

using alias in shell script? - Stack Overflow
Bashスクリプト内でエイリアスを使用する方法。

unix - How do I list all the files in a directory and subdirectories in reverse chronological order? - Stack Overflow
サブディレクトリ以下のファイルのみ取得する方法。

シェルスクリプトで空文字列かどうか調べる。 - masa.edw the ハバネロブリーダー
展開した引数にクォーテーションをつける必要があります。

linux - how can I recursively delete empty directories in my home directory? - Unix & Linux Stack Exchange
空ディレクトリをすべて削除する方法。

linux - Bash script to remove the oldest file from from a folder - Unix & Linux Stack Exchange
ディレクトリから一番古いファイルを削除する方法。

次の関連記事:linuxBean14.04(184)デュアルディスプレイを使う

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ