Skip to content

Instantly share code, notes, and snippets.

@krzysztof-magosa
Last active March 21, 2019 19:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krzysztof-magosa/d9d96c8864a20dc3b47fd1eee1cfcc4f to your computer and use it in GitHub Desktop.
Save krzysztof-magosa/d9d96c8864a20dc3b47fd1eee1cfcc4f to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
#
# (c) Krzysztof Magosa
# License: MIT
# Use at your own risk.
#
# https://gist.github.com/krzysztof-magosa/d9d96c8864a20dc3b47fd1eee1cfcc4f
#
import argparse
import os
import heapq
parser = argparse.ArgumentParser()
parser.add_argument("--thresh", type=int, default=80, help="Maximum used space in %%")
parser.add_argument("--offenders", type=int, default=4096, help="Find N offenders at a time")
parser.add_argument("--hysteresis", type=int, default=5, help="Remove N more %%")
parser.add_argument("path", nargs=1, help="Path to scan")
args = parser.parse_args()
# Return % of disk used
def get_disk_percents(path):
vfs = os.statvfs(path)
return 100.0 * float((vfs.f_blocks - vfs.f_bfree) / float(vfs.f_blocks - vfs.f_bfree + vfs.f_bavail))
# Return files from path (recursively) as tuple of mtime+filename
def get_files(path):
for root, dirs, files in os.walk(path):
for name in files:
filename = os.path.join(root, name)
try:
# Only regular files
if os.path.isfile(filename):
mtime = os.path.getmtime(filename)
yield (mtime, filename)
except:
pass
# Get offenders from path
# Priority Queue is sorted by first element from tuple (mtime).
# Therefore files having oldest mtime are returned.
def get_offenders(path, limit):
offenders = []
for entry in get_files(path):
heapq.heappush(offenders, entry)
if len(offenders) > limit:
del offenders[-1]
return offenders
if __name__ == "__main__":
# Initial check whether we should do anything.
if get_disk_percents(args.path[0]) > args.thresh:
offenders = []
while True:
# Remove to reach thresh + hysteresis.
if get_disk_percents(args.path[0]) <= (args.thresh - args.hysteresis):
break
# We have no offenders available, find them.
if not offenders:
offenders = get_offenders(args.path[0], args.offenders)
# No offenders available, nothing we can do.
if not offenders:
break
# Remove oldest offender ignoring possible permission denied problems.
mtime, filename = heapq.heappop(offenders)
try:
print("Removing {}".format(filename))
os.unlink(filename)
except OSError:
pass
else:
print("Usage below threshold. Exiting...")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment