enable df path selection
This commit is contained in:
@@ -1,249 +1,312 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import sys,os,glob
|
import sys, os, glob
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import re,signal,time
|
import re, signal, time
|
||||||
import subprocess
|
import subprocess
|
||||||
#,threading
|
|
||||||
|
|
||||||
VERSION=3
|
# ,threading
|
||||||
|
|
||||||
W= '30'
|
VERSION = 3
|
||||||
R= '31'
|
|
||||||
G= '32'
|
W = "30"
|
||||||
Y= '33'
|
R = "31"
|
||||||
B= '34'
|
G = "32"
|
||||||
M= '35'
|
Y = "33"
|
||||||
C= '36'
|
B = "34"
|
||||||
S= '1'
|
M = "35"
|
||||||
E= '0'
|
C = "36"
|
||||||
BR= '41'
|
S = "1"
|
||||||
CLR = '\033[2J'
|
E = "0"
|
||||||
SAVE = '\033[s'
|
BR = "41"
|
||||||
LOAD = '\033[u'
|
CLR = "\033[2J"
|
||||||
CLRLN = '\033[K'
|
SAVE = "\033[s"
|
||||||
CLRBLN = '\033[1K'
|
LOAD = "\033[u"
|
||||||
DOWN = '\033[1B'
|
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():
|
def setup_options():
|
||||||
''' Setup the command line options '''
|
""" Setup the command line options """
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
parser=ArgumentParser(description='''
|
parser = ArgumentParser(
|
||||||
|
description="""
|
||||||
Shows the output of df in colour.
|
Shows the output of df in colour.
|
||||||
''',formatter_class=argparse.RawTextHelpFormatter)
|
""",
|
||||||
|
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()
|
|
||||||
|
|
||||||
|
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
|
return options
|
||||||
|
|
||||||
|
|
||||||
def c(attribs):
|
def c(attribs):
|
||||||
''' ANSI colorizer '''
|
""" ANSI colorizer """
|
||||||
if not options.colors:
|
if not options.colors:
|
||||||
return ""
|
return ""
|
||||||
return '\033['+';'.join(attribs)+'m'
|
return "\033[" + ";".join(attribs) + "m"
|
||||||
|
|
||||||
|
|
||||||
def pos(y,x):
|
def pos(y, x):
|
||||||
''' ANSI absolute position set '''
|
""" ANSI absolute position set """
|
||||||
return "\033["+str(y)+";"+str(x)+"H"
|
return "\033[" + str(y) + ";" + str(x) + "H"
|
||||||
|
|
||||||
|
|
||||||
def colorize(string):
|
def colorize(string):
|
||||||
''' colorizes a string based on color_match '''
|
""" colorizes a string based on color_match """
|
||||||
if not options.colors:
|
if not options.colors:
|
||||||
return string
|
return string
|
||||||
for co in color_match:
|
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
|
return string
|
||||||
|
|
||||||
|
|
||||||
def count_running(string, stats):
|
def count_running(string, stats):
|
||||||
''' Counts the running executions '''
|
""" Counts the running executions """
|
||||||
|
|
||||||
spl=[i for i in " ".join(string.split()).split(' ')]
|
spl = [i for i in " ".join(string.split()).split(" ")]
|
||||||
if len(spl)!=7:
|
if len(spl) != 7:
|
||||||
return stats
|
return stats
|
||||||
if spl[6] in stats['files']:
|
if spl[6] in stats["files"]:
|
||||||
index=stats['files'].index(spl[6])
|
index = stats["files"].index(spl[6])
|
||||||
speed_history=stats['running'][index][1][1:]
|
speed_history = stats["running"][index][1][1:]
|
||||||
speed_history.append((int(spl[4])*1024-(stats['running'][index][0]))/stats['delay'])
|
speed_history.append(
|
||||||
stats['running'][index]=(int(spl[4])*1024, # free space
|
(int(spl[4]) * 1024 - (stats["running"][index][0])) / stats["delay"]
|
||||||
speed_history, # change speed
|
)
|
||||||
spl[6], # mount point
|
stats["running"][index] = (
|
||||||
stats['running'][index][3], # free space program start
|
int(spl[4]) * 1024, # free space
|
||||||
spl[5], # usage in %
|
speed_history, # change speed
|
||||||
spl[1], # mount type
|
spl[6], # mount point
|
||||||
int(spl[2])*1024 # total space
|
stats["running"][index][3], # free space program start
|
||||||
)
|
spl[5], # usage in %
|
||||||
|
spl[1], # mount type
|
||||||
|
int(spl[2]) * 1024, # total space
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
stats['running'].append((int(spl[4])*1024,
|
stats["running"].append(
|
||||||
[int(0)]*5,
|
(
|
||||||
spl[6],
|
int(spl[4]) * 1024,
|
||||||
int(spl[4])*1024,
|
[int(0)] * 5,
|
||||||
spl[5],
|
spl[6],
|
||||||
spl[1],
|
int(spl[4]) * 1024,
|
||||||
int(spl[2])*1024
|
spl[5],
|
||||||
))
|
spl[1],
|
||||||
stats['running'].sort(key=SORTKEY)
|
int(spl[2]) * 1024,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
stats["running"].sort(key=SORTKEY)
|
||||||
|
|
||||||
stats['files']=[i[2] for i in stats['running']]
|
stats["files"] = [i[2] for i in stats["running"]]
|
||||||
totalfree=sum([i[0] for i in stats['running']])
|
totalfree = sum([i[0] for i in stats["running"]])
|
||||||
total=sum([i[6] for i in stats['running']])
|
total = sum([i[6] for i in stats["running"]])
|
||||||
stats['totals']=[totalfree, total]
|
stats["totals"] = [totalfree, total]
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
|
|
||||||
class EndProgram( Exception ):
|
class EndProgram(Exception):
|
||||||
''' Nice way of exiting the program '''
|
""" Nice way of exiting the program """
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def is_number(s):
|
def is_number(s):
|
||||||
''' Check if string is float '''
|
""" Check if string is float """
|
||||||
try:
|
try:
|
||||||
out=float(s)
|
out = float(s)
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def str_short(s,stats):
|
def str_short(s, stats):
|
||||||
''' shorten text to fit screen '''
|
""" shorten text to fit screen """
|
||||||
maxL=stats['size'][1] - 16
|
maxL = stats["size"][1] - 16
|
||||||
if len(s)<maxL:
|
if len(s) < maxL:
|
||||||
return s
|
return s
|
||||||
spl=s.split('/')
|
spl = s.split("/")
|
||||||
sNew=spl[0]+'/...'+'/'.join(spl[1:])[-(maxL-len(spl[0])-5):]
|
sNew = spl[0] + "/..." + "/".join(spl[1:])[-(maxL - len(spl[0]) - 5) :]
|
||||||
return sNew
|
return sNew
|
||||||
|
|
||||||
|
|
||||||
def print_stats(stats):
|
def print_stats(stats):
|
||||||
''' Prints logged errors, and the status line '''
|
""" Prints logged errors, and the status line """
|
||||||
#sys.stdout.write(SAVE)
|
# sys.stdout.write(SAVE)
|
||||||
e=0
|
e = 0
|
||||||
sys.stdout.write(pos(e+1,0)+c((S,C))+"= DISK FREE = "+c((E))+
|
sys.stdout.write(
|
||||||
human_time(stats['time'])+'=>'+c((S,G))+human_time()+c((E))+CLRLN)
|
pos(e + 1, 0)
|
||||||
if (stats['running']):
|
+ c((S, C))
|
||||||
|
+ "= DISK FREE = "
|
||||||
|
+ c((E))
|
||||||
|
+ human_time(stats["time"])
|
||||||
|
+ "=>"
|
||||||
|
+ c((S, G))
|
||||||
|
+ human_time()
|
||||||
|
+ c((E))
|
||||||
|
+ CLRLN
|
||||||
|
)
|
||||||
|
if stats["running"]:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
sys.stdout.write(pos(e+2,0)+" TotalDiff Free Total (usage%) Diff/s (positive=more free space)"+CLRLN)
|
sys.stdout.write(
|
||||||
for ex in enumerate(stats['running']):
|
pos(e + 2, 0)
|
||||||
sys.stdout.write(pos(e+3+ex[0],0)+'('+str(ex[0]+1).rjust(2)+') '+
|
+ " TotalDiff Free Total (usage%) Diff/s (positive=more free space)"
|
||||||
' '.join([human_size(ex[1][0]-ex[1][3]).rjust(10),
|
+ CLRLN
|
||||||
human_size(ex[1][0]).rjust(10),
|
)
|
||||||
human_size(ex[1][6]).rjust(8),
|
for ex in enumerate(stats["running"]):
|
||||||
colorize_usage(ex[1][4]),
|
sys.stdout.write(
|
||||||
(human_size(mean_speed(ex[1][1]))+"/s").rjust(10),
|
pos(e + 3 + ex[0], 0)
|
||||||
ex[1][2],
|
+ "("
|
||||||
"("+ex[1][5]+")"])+
|
+ str(ex[0] + 1).rjust(2)
|
||||||
CLRLN)
|
+ ") "
|
||||||
sys.stdout.write(pos(e+4+ex[0],0)+'Total:'+
|
+ " ".join(
|
||||||
' '.join([' '.rjust(9),
|
[
|
||||||
human_size(stats['totals'][0]).rjust(10),
|
human_size(ex[1][0] - ex[1][3]).rjust(10),
|
||||||
'/',
|
human_size(ex[1][0]).rjust(10),
|
||||||
human_size(stats['totals'][1]).ljust(10)
|
human_size(ex[1][6]).rjust(8),
|
||||||
])+
|
colorize_usage(ex[1][4]),
|
||||||
CLRLN)
|
(human_size(mean_speed(ex[1][1])) + "/s").rjust(10),
|
||||||
for i in range(stats['size'][0]-7-len(stats['running'])):
|
ex[1][2],
|
||||||
sys.stdout.write(pos(e+5+ex[0]+i,0)+" "+CLRLN)
|
"(" + 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(DOWN + CLRBLN + CLRLN)
|
||||||
#sys.stdout.write(LOAD)
|
# sys.stdout.write(LOAD)
|
||||||
|
|
||||||
|
|
||||||
def print_stats_once(stats):
|
def print_stats_once(stats):
|
||||||
''' Prints logged errors, once '''
|
""" Prints logged errors, once """
|
||||||
e=0
|
e = 0
|
||||||
sys.stdout.write(c((S,C))+"= DISK FREE = "+c((E,))+CLRLN+'\n')
|
sys.stdout.write(c((S, C)) + "= DISK FREE = " + c((E,)) + CLRLN + "\n")
|
||||||
if (stats['running']):
|
if stats["running"]:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
sys.stdout.write(" Total Used Use% Free"+CLRLN+'\n')
|
sys.stdout.write(" Total Used Use% Free" + CLRLN + "\n")
|
||||||
for ex in enumerate(stats['running']):
|
for ex in enumerate(stats["running"]):
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
' '.join([
|
" ".join(
|
||||||
human_size(ex[1][6]).rjust(8),
|
[
|
||||||
human_size(ex[1][6]-ex[1][0]).rjust(10),
|
human_size(ex[1][6]).rjust(8),
|
||||||
colorize_usage(ex[1][4]),
|
human_size(ex[1][6] - ex[1][0]).rjust(10),
|
||||||
human_size(ex[1][0]).rjust(10),
|
colorize_usage(ex[1][4]),
|
||||||
ex[1][2],
|
human_size(ex[1][0]).rjust(10),
|
||||||
"("+ex[1][5]+")"])+
|
ex[1][2],
|
||||||
CLRLN+'\n')
|
"(" + ex[1][5] + ")",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ CLRLN
|
||||||
|
+ "\n"
|
||||||
|
)
|
||||||
sys.stdout.write(
|
sys.stdout.write(
|
||||||
' '.join([
|
" ".join(
|
||||||
human_size(stats['totals'][1]).rjust(8),
|
[
|
||||||
human_size(stats['totals'][1]-stats['totals'][0]).rjust(10), ' ',
|
human_size(stats["totals"][1]).rjust(8),
|
||||||
human_size(stats['totals'][0]).rjust(10)
|
human_size(stats["totals"][1] - stats["totals"][0]).rjust(10),
|
||||||
])+
|
" ",
|
||||||
CLRLN+'\n')
|
human_size(stats["totals"][0]).rjust(10),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+ CLRLN
|
||||||
|
+ "\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def colorize_usage(string):
|
def colorize_usage(string):
|
||||||
''' colorizes the usage string '''
|
""" colorizes the usage string """
|
||||||
# string length indicates value <10
|
# string length indicates value <10
|
||||||
if len(string)<3:
|
if len(string) < 3:
|
||||||
return c((S,G))+" "+string+c((E))
|
return c((S, G)) + " " + string + c((E))
|
||||||
# string lenght indicates 100%
|
# string lenght indicates 100%
|
||||||
if len(string)==4:
|
if len(string) == 4:
|
||||||
return c((S,R))+string+c((E))
|
return c((S, R)) + string + c((E))
|
||||||
usage=int(string[0:2])
|
usage = int(string[0:2])
|
||||||
if usage>95:
|
if usage > 95:
|
||||||
return c((S,R))+" "+string+c((E))
|
return c((S, R)) + " " + string + c((E))
|
||||||
if usage<80:
|
if usage < 80:
|
||||||
return c((S,G))+" "+string+c((E))
|
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):
|
def mean_speed(history):
|
||||||
speed=sum(history)/len(history)
|
speed = sum(history) / len(history)
|
||||||
return int(speed)
|
return int(speed)
|
||||||
|
|
||||||
|
|
||||||
def human_time(dt=False):
|
def human_time(dt=False):
|
||||||
if not dt:
|
if not dt:
|
||||||
dt=datetime.now()
|
dt = datetime.now()
|
||||||
return dt.strftime("%H:%M:%S")
|
return dt.strftime("%H:%M:%S")
|
||||||
|
|
||||||
|
|
||||||
def human_size(size,precision=1):
|
def human_size(size, precision=1):
|
||||||
if size==None:
|
if size == None:
|
||||||
return 'nan'
|
return "nan"
|
||||||
sign=""
|
sign = ""
|
||||||
if size<0:
|
if size < 0:
|
||||||
sign="-"
|
sign = "-"
|
||||||
size=-size
|
size = -size
|
||||||
suffixes=['B','KB','MB','GB','TB','PB','EB','ZB']
|
suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]
|
||||||
suffixIndex = 0
|
suffixIndex = 0
|
||||||
defPrecision=0
|
defPrecision = 0
|
||||||
while size > 1024:
|
while size > 1024:
|
||||||
suffixIndex += 1
|
suffixIndex += 1
|
||||||
size = size/1024.0
|
size = size / 1024.0
|
||||||
defPrecision=precision
|
defPrecision = precision
|
||||||
return "%s%.*f%s"%(sign,defPrecision,size,suffixes[suffixIndex])
|
return "%s%.*f%s" % (sign, defPrecision, size, suffixes[suffixIndex])
|
||||||
|
|
||||||
|
|
||||||
def readinput(lf):
|
def readinput(lf):
|
||||||
try:
|
try:
|
||||||
line = lf.stdout.readline()
|
line = lf.stdout.readline()
|
||||||
#line=lf.readline()
|
# line=lf.readline()
|
||||||
return line
|
return line
|
||||||
except:
|
except:
|
||||||
return "CleanerTimeout"
|
return "CleanerTimeout"
|
||||||
@@ -251,30 +314,31 @@ def readinput(lf):
|
|||||||
|
|
||||||
def termsize():
|
def termsize():
|
||||||
try:
|
try:
|
||||||
rows, columns = os.popen('stty size', 'r').read().split()
|
rows, columns = os.popen("stty size", "r").read().split()
|
||||||
except:
|
except:
|
||||||
(rows,columns)=(25,80)
|
(rows, columns) = (25, 80)
|
||||||
return (int(rows),int(columns))
|
return (int(rows), int(columns))
|
||||||
|
|
||||||
|
|
||||||
options=setup_options()
|
options = setup_options()
|
||||||
|
|
||||||
color_match={#'line_ends':(re.compile('$'),c.END),
|
color_match = { #'line_ends':(re.compile('$'),c.END),
|
||||||
'err':(re.compile('(Failed)'),c([R,S])+'\\1'+c([E])),
|
"err": (re.compile("(Failed)"), c([R, S]) + "\\1" + c([E])),
|
||||||
'done':(re.compile('(Done)'),c([G,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])),
|
"percent": (re.compile("([0-9]+%)"), c([Y, S]) + "\\1" + c([E])),
|
||||||
}
|
}
|
||||||
|
|
||||||
stats={'time':datetime.now(),
|
stats = {
|
||||||
'running':[],
|
"time": datetime.now(),
|
||||||
'files':[],
|
"running": [],
|
||||||
'totals':[],
|
"files": [],
|
||||||
'size': termsize(),
|
"totals": [],
|
||||||
'delay': options.delay
|
"size": termsize(),
|
||||||
}
|
"delay": options.delay,
|
||||||
|
}
|
||||||
|
|
||||||
if not options.once:
|
if not options.once:
|
||||||
sys.stdout.write(CLR+pos(0,0)+"Launching...")
|
sys.stdout.write(CLR + pos(0, 0) + "Launching...")
|
||||||
omit_opts = []
|
omit_opts = []
|
||||||
for omit in options.exclude.split(","):
|
for omit in options.exclude.split(","):
|
||||||
omit_opts.append("-x")
|
omit_opts.append("-x")
|
||||||
@@ -283,16 +347,16 @@ while 1:
|
|||||||
|
|
||||||
try:
|
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.
|
# set a 5 second timeout for the line read.
|
||||||
#~ signal.signal(signal.SIGALRM, transfers.readline)
|
# ~ signal.signal(signal.SIGALRM, transfers.readline)
|
||||||
#~ signal.alarm(5)
|
# ~ signal.alarm(5)
|
||||||
stdout,stderr=proc.communicate()
|
stdout, stderr = proc.communicate()
|
||||||
if not stdout:
|
if not stdout:
|
||||||
raise EndProgram
|
raise EndProgram
|
||||||
|
|
||||||
for line in stdout.decode('utf-8').split('\n')[1:]:
|
for line in stdout.decode("utf-8").split("\n")[1:]:
|
||||||
stats=count_running(line,stats)
|
stats = count_running(line, stats)
|
||||||
|
|
||||||
if options.once:
|
if options.once:
|
||||||
print_stats_once(stats)
|
print_stats_once(stats)
|
||||||
@@ -302,9 +366,7 @@ while 1:
|
|||||||
time.sleep(options.delay)
|
time.sleep(options.delay)
|
||||||
|
|
||||||
except (EndProgram, KeyboardInterrupt):
|
except (EndProgram, KeyboardInterrupt):
|
||||||
sys.stdout.write(DOWN+'\n')
|
sys.stdout.write(DOWN + "\n")
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user