From 92c72edd02107483e89d7b35fa792dfb2d3fe77b Mon Sep 17 00:00:00 2001 From: Ville Rantanen Date: Mon, 1 Mar 2021 10:10:41 +0200 Subject: [PATCH] enable df path selection --- files/diskfree-tracker | 420 +++++++++++++++++++++++------------------ 1 file changed, 241 insertions(+), 179 deletions(-) diff --git a/files/diskfree-tracker b/files/diskfree-tracker index 2f8f78d..9ba29cf 100755 --- a/files/diskfree-tracker +++ b/files/diskfree-tracker @@ -1,249 +1,312 @@ #!/usr/bin/env python3 -import sys,os,glob +import sys, os, glob from datetime import datetime from datetime import timedelta -import re,signal,time +import re, signal, time import subprocess -#,threading -VERSION=3 +# ,threading -W= '30' -R= '31' -G= '32' -Y= '33' -B= '34' -M= '35' -C= '36' -S= '1' -E= '0' -BR= '41' -CLR = '\033[2J' -SAVE = '\033[s' -LOAD = '\033[u' -CLRLN = '\033[K' -CLRBLN = '\033[1K' -DOWN = '\033[1B' +VERSION = 3 + +W = "30" +R = "31" +G = "32" +Y = "33" +B = "34" +M = "35" +C = "36" +S = "1" +E = "0" +BR = "41" +CLR = "\033[2J" +SAVE = "\033[s" +LOAD = "\033[u" +CLRLN = "\033[K" +CLRBLN = "\033[1K" +DOWN = "\033[1B" + +SORTKEY = lambda key: (key[2].split("/")[-1].lower()) -SORTKEY = lambda key: (key[2].split('/')[-1].lower()) def setup_options(): - ''' Setup the command line options ''' + """ Setup the command line options """ from argparse import ArgumentParser import argparse - parser=ArgumentParser(description=''' + parser = ArgumentParser( + description=""" Shows the output of df in colour. -''',formatter_class=argparse.RawTextHelpFormatter) - - parser.add_argument("--no-colors",'--nc',action="store_false",dest="colors",default=True, - help="Disable colored output") - parser.add_argument("-n",type=int,dest="delay",default=3, - help="Refresh delay") - parser.add_argument("-1",action="store_true",dest="once",default=False, - help="Run once and exit") - parser.add_argument("-x",'--exclude',type=str,dest="exclude",default="tmpfs,devtmpfs,squashfs,overlay", - help="Comma separated list of excluded filesystem types. Defaults: %(default)s") - parser.add_argument("--version",action='version', version=VERSION) - options=parser.parse_args() +""", + formatter_class=argparse.RawTextHelpFormatter, + ) + parser.add_argument( + "--no-colors", + "--nc", + action="store_false", + dest="colors", + default=True, + help="Disable colored output", + ) + parser.add_argument("-n", type=int, dest="delay", default=3, help="Refresh delay") + parser.add_argument( + "-1", action="store_true", dest="once", default=False, help="Run once and exit" + ) + parser.add_argument( + "-x", + "--exclude", + type=str, + dest="exclude", + default="tmpfs,devtmpfs,squashfs,overlay", + help="Comma separated list of excluded filesystem types. Defaults: %(default)s", + ) + parser.add_argument("--version", action="version", version=VERSION) + parser.add_argument("paths", action="store", nargs="*", help="Only include disks. Defaults to all.") + options = parser.parse_args() return options def c(attribs): - ''' ANSI colorizer ''' + """ ANSI colorizer """ if not options.colors: return "" - return '\033['+';'.join(attribs)+'m' + return "\033[" + ";".join(attribs) + "m" -def pos(y,x): - ''' ANSI absolute position set ''' - return "\033["+str(y)+";"+str(x)+"H" +def pos(y, x): + """ ANSI absolute position set """ + return "\033[" + str(y) + ";" + str(x) + "H" def colorize(string): - ''' colorizes a string based on color_match ''' + """ colorizes a string based on color_match """ if not options.colors: return string for co in color_match: - string=color_match[co][0].sub(color_match[co][1],string) + string = color_match[co][0].sub(color_match[co][1], string) return string def count_running(string, stats): - ''' Counts the running executions ''' + """ Counts the running executions """ - spl=[i for i in " ".join(string.split()).split(' ')] - if len(spl)!=7: + spl = [i for i in " ".join(string.split()).split(" ")] + if len(spl) != 7: return stats - if spl[6] in stats['files']: - index=stats['files'].index(spl[6]) - speed_history=stats['running'][index][1][1:] - speed_history.append((int(spl[4])*1024-(stats['running'][index][0]))/stats['delay']) - stats['running'][index]=(int(spl[4])*1024, # free space - speed_history, # change speed - spl[6], # mount point - stats['running'][index][3], # free space program start - spl[5], # usage in % - spl[1], # mount type - int(spl[2])*1024 # total space - ) + if spl[6] in stats["files"]: + index = stats["files"].index(spl[6]) + speed_history = stats["running"][index][1][1:] + speed_history.append( + (int(spl[4]) * 1024 - (stats["running"][index][0])) / stats["delay"] + ) + stats["running"][index] = ( + int(spl[4]) * 1024, # free space + speed_history, # change speed + spl[6], # mount point + stats["running"][index][3], # free space program start + spl[5], # usage in % + spl[1], # mount type + int(spl[2]) * 1024, # total space + ) else: - stats['running'].append((int(spl[4])*1024, - [int(0)]*5, - spl[6], - int(spl[4])*1024, - spl[5], - spl[1], - int(spl[2])*1024 - )) - stats['running'].sort(key=SORTKEY) + stats["running"].append( + ( + int(spl[4]) * 1024, + [int(0)] * 5, + spl[6], + int(spl[4]) * 1024, + spl[5], + spl[1], + int(spl[2]) * 1024, + ) + ) + stats["running"].sort(key=SORTKEY) - stats['files']=[i[2] for i in stats['running']] - totalfree=sum([i[0] for i in stats['running']]) - total=sum([i[6] for i in stats['running']]) - stats['totals']=[totalfree, total] + stats["files"] = [i[2] for i in stats["running"]] + totalfree = sum([i[0] for i in stats["running"]]) + total = sum([i[6] for i in stats["running"]]) + stats["totals"] = [totalfree, total] return stats -class EndProgram( Exception ): - ''' Nice way of exiting the program ''' +class EndProgram(Exception): + """ Nice way of exiting the program """ + pass def is_number(s): - ''' Check if string is float ''' + """ Check if string is float """ try: - out=float(s) + out = float(s) return True except: return False -def str_short(s,stats): - ''' shorten text to fit screen ''' - maxL=stats['size'][1] - 16 - if len(s)" + + c((S, G)) + + human_time() + + c((E)) + + CLRLN + ) + if stats["running"]: pass else: return - sys.stdout.write(pos(e+2,0)+" TotalDiff Free Total (usage%) Diff/s (positive=more free space)"+CLRLN) - for ex in enumerate(stats['running']): - sys.stdout.write(pos(e+3+ex[0],0)+'('+str(ex[0]+1).rjust(2)+') '+ - ' '.join([human_size(ex[1][0]-ex[1][3]).rjust(10), - human_size(ex[1][0]).rjust(10), - human_size(ex[1][6]).rjust(8), - colorize_usage(ex[1][4]), - (human_size(mean_speed(ex[1][1]))+"/s").rjust(10), - ex[1][2], - "("+ex[1][5]+")"])+ - CLRLN) - sys.stdout.write(pos(e+4+ex[0],0)+'Total:'+ - ' '.join([' '.rjust(9), - human_size(stats['totals'][0]).rjust(10), - '/', - human_size(stats['totals'][1]).ljust(10) - ])+ - CLRLN) - for i in range(stats['size'][0]-7-len(stats['running'])): - sys.stdout.write(pos(e+5+ex[0]+i,0)+" "+CLRLN) + sys.stdout.write( + pos(e + 2, 0) + + " TotalDiff Free Total (usage%) Diff/s (positive=more free space)" + + CLRLN + ) + for ex in enumerate(stats["running"]): + sys.stdout.write( + pos(e + 3 + ex[0], 0) + + "(" + + str(ex[0] + 1).rjust(2) + + ") " + + " ".join( + [ + human_size(ex[1][0] - ex[1][3]).rjust(10), + human_size(ex[1][0]).rjust(10), + human_size(ex[1][6]).rjust(8), + colorize_usage(ex[1][4]), + (human_size(mean_speed(ex[1][1])) + "/s").rjust(10), + ex[1][2], + "(" + ex[1][5] + ")", + ] + ) + + CLRLN + ) + sys.stdout.write( + pos(e + 4 + ex[0], 0) + + "Total:" + + " ".join( + [ + " ".rjust(9), + human_size(stats["totals"][0]).rjust(10), + "/", + human_size(stats["totals"][1]).ljust(10), + ] + ) + + CLRLN + ) + for i in range(stats["size"][0] - 7 - len(stats["running"])): + sys.stdout.write(pos(e + 5 + ex[0] + i, 0) + " " + CLRLN) - sys.stdout.write(DOWN+CLRBLN+CLRLN) - #sys.stdout.write(LOAD) + sys.stdout.write(DOWN + CLRBLN + CLRLN) + # sys.stdout.write(LOAD) def print_stats_once(stats): - ''' Prints logged errors, once ''' - e=0 - sys.stdout.write(c((S,C))+"= DISK FREE = "+c((E,))+CLRLN+'\n') - if (stats['running']): + """ Prints logged errors, once """ + e = 0 + sys.stdout.write(c((S, C)) + "= DISK FREE = " + c((E,)) + CLRLN + "\n") + if stats["running"]: pass else: return - sys.stdout.write(" Total Used Use% Free"+CLRLN+'\n') - for ex in enumerate(stats['running']): + sys.stdout.write(" Total Used Use% Free" + CLRLN + "\n") + for ex in enumerate(stats["running"]): sys.stdout.write( - ' '.join([ - human_size(ex[1][6]).rjust(8), - human_size(ex[1][6]-ex[1][0]).rjust(10), - colorize_usage(ex[1][4]), - human_size(ex[1][0]).rjust(10), - ex[1][2], - "("+ex[1][5]+")"])+ - CLRLN+'\n') + " ".join( + [ + human_size(ex[1][6]).rjust(8), + human_size(ex[1][6] - ex[1][0]).rjust(10), + colorize_usage(ex[1][4]), + human_size(ex[1][0]).rjust(10), + ex[1][2], + "(" + ex[1][5] + ")", + ] + ) + + CLRLN + + "\n" + ) sys.stdout.write( - ' '.join([ - human_size(stats['totals'][1]).rjust(8), - human_size(stats['totals'][1]-stats['totals'][0]).rjust(10), ' ', - human_size(stats['totals'][0]).rjust(10) - ])+ - CLRLN+'\n') + " ".join( + [ + human_size(stats["totals"][1]).rjust(8), + human_size(stats["totals"][1] - stats["totals"][0]).rjust(10), + " ", + human_size(stats["totals"][0]).rjust(10), + ] + ) + + CLRLN + + "\n" + ) def colorize_usage(string): - ''' colorizes the usage string ''' + """ colorizes the usage string """ # string length indicates value <10 - if len(string)<3: - return c((S,G))+" "+string+c((E)) + if len(string) < 3: + return c((S, G)) + " " + string + c((E)) # string lenght indicates 100% - if len(string)==4: - return c((S,R))+string+c((E)) - usage=int(string[0:2]) - if usage>95: - return c((S,R))+" "+string+c((E)) - if usage<80: - return c((S,G))+" "+string+c((E)) + if len(string) == 4: + return c((S, R)) + string + c((E)) + usage = int(string[0:2]) + if usage > 95: + return c((S, R)) + " " + string + c((E)) + if usage < 80: + return c((S, G)) + " " + string + c((E)) - return c((S,Y))+" "+string+c((E)) + return c((S, Y)) + " " + string + c((E)) def mean_speed(history): - speed=sum(history)/len(history) + speed = sum(history) / len(history) return int(speed) def human_time(dt=False): if not dt: - dt=datetime.now() + dt = datetime.now() return dt.strftime("%H:%M:%S") -def human_size(size,precision=1): - if size==None: - return 'nan' - sign="" - if size<0: - sign="-" - size=-size - suffixes=['B','KB','MB','GB','TB','PB','EB','ZB'] +def human_size(size, precision=1): + if size == None: + return "nan" + sign = "" + if size < 0: + sign = "-" + size = -size + suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"] suffixIndex = 0 - defPrecision=0 + defPrecision = 0 while size > 1024: suffixIndex += 1 - size = size/1024.0 - defPrecision=precision - return "%s%.*f%s"%(sign,defPrecision,size,suffixes[suffixIndex]) + size = size / 1024.0 + defPrecision = precision + return "%s%.*f%s" % (sign, defPrecision, size, suffixes[suffixIndex]) def readinput(lf): try: line = lf.stdout.readline() - #line=lf.readline() + # line=lf.readline() return line except: return "CleanerTimeout" @@ -251,30 +314,31 @@ def readinput(lf): def termsize(): try: - rows, columns = os.popen('stty size', 'r').read().split() + rows, columns = os.popen("stty size", "r").read().split() except: - (rows,columns)=(25,80) - return (int(rows),int(columns)) + (rows, columns) = (25, 80) + return (int(rows), int(columns)) -options=setup_options() +options = setup_options() -color_match={#'line_ends':(re.compile('$'),c.END), - 'err':(re.compile('(Failed)'),c([R,S])+'\\1'+c([E])), - 'done':(re.compile('(Done)'),c([G,S])+'\\1'+c([E])), - 'percent':(re.compile('([0-9]+%)'),c([Y,S])+'\\1'+c([E])), +color_match = { #'line_ends':(re.compile('$'),c.END), + "err": (re.compile("(Failed)"), c([R, S]) + "\\1" + c([E])), + "done": (re.compile("(Done)"), c([G, S]) + "\\1" + c([E])), + "percent": (re.compile("([0-9]+%)"), c([Y, S]) + "\\1" + c([E])), } -stats={'time':datetime.now(), - 'running':[], - 'files':[], - 'totals':[], - 'size': termsize(), - 'delay': options.delay - } +stats = { + "time": datetime.now(), + "running": [], + "files": [], + "totals": [], + "size": termsize(), + "delay": options.delay, +} if not options.once: - sys.stdout.write(CLR+pos(0,0)+"Launching...") + sys.stdout.write(CLR + pos(0, 0) + "Launching...") omit_opts = [] for omit in options.exclude.split(","): omit_opts.append("-x") @@ -283,16 +347,16 @@ while 1: try: - proc = subprocess.Popen(['df','-T'] + omit_opts,stdout=subprocess.PIPE) + proc = subprocess.Popen(["df", "-T"] + omit_opts + options.paths, stdout=subprocess.PIPE) # set a 5 second timeout for the line read. - #~ signal.signal(signal.SIGALRM, transfers.readline) - #~ signal.alarm(5) - stdout,stderr=proc.communicate() + # ~ signal.signal(signal.SIGALRM, transfers.readline) + # ~ signal.alarm(5) + stdout, stderr = proc.communicate() if not stdout: raise EndProgram - for line in stdout.decode('utf-8').split('\n')[1:]: - stats=count_running(line,stats) + for line in stdout.decode("utf-8").split("\n")[1:]: + stats = count_running(line, stats) if options.once: print_stats_once(stats) @@ -302,9 +366,7 @@ while 1: time.sleep(options.delay) except (EndProgram, KeyboardInterrupt): - sys.stdout.write(DOWN+'\n') + sys.stdout.write(DOWN + "\n") sys.stdout.flush() sys.exit(0) - -