Skip to content

Instantly share code, notes, and snippets.

@philgyford
Created July 22, 2017 13:56
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 philgyford/43e47a9bb885437d466be7fc34200785 to your computer and use it in GitHub Desktop.
Save philgyford/43e47a9bb885437d466be7fc34200785 to your computer and use it in GitHub Desktop.
File for displaying %CPU and RAM usage on a system. Not sure where I got this from originally.
#!/usr/bin/env python2.7
import subprocess
import sys
import re
import os,pwd
from pprint import pprint
class TerminalController:
"""
Terminal coloring module from http://code.activestate.com/recipes/475116/
A class that can be used to portably generate formatted output to
a terminal.
`TerminalController` defines a set of instance variables whose
values are initialized to the control sequence necessary to
perform a given action. These can be simply included in normal
output to the terminal:
>>> term = TerminalController()
>>> print 'This is '+term.GREEN+'green'+term.NORMAL
Alternatively, the `render()` method can used, which replaces
'${action}' with the string required to perform 'action':
>>> term = TerminalController()
>>> print term.render('This is ${GREEN}green${NORMAL}')
If the terminal doesn't support a given action, then the value of
the corresponding instance variable will be set to ''. As a
result, the above code will still work on terminals that do not
support color, except that their output will not be colored.
Also, this means that you can test whether the terminal supports a
given action by simply testing the truth value of the
corresponding instance variable:
>>> term = TerminalController()
>>> if term.CLEAR_SCREEN:
... print 'This terminal supports clearning the screen.'
Finally, if the width and height of the terminal are known, then
they will be stored in the `COLS` and `LINES` attributes.
"""
# Cursor movement:
BOL = '' #: Move the cursor to the beginning of the line
UP = '' #: Move the cursor up one line
DOWN = '' #: Move the cursor down one line
LEFT = '' #: Move the cursor left one char
RIGHT = '' #: Move the cursor right one char
# Deletion:
CLEAR_SCREEN = '' #: Clear the screen and move to home position
CLEAR_EOL = '' #: Clear to the end of the line.
CLEAR_BOL = '' #: Clear to the beginning of the line.
CLEAR_EOS = '' #: Clear to the end of the screen
# Output modes:
BOLD = '' #: Turn on bold mode
BLINK = '' #: Turn on blink mode
DIM = '' #: Turn on half-bright mode
REVERSE = '' #: Turn on reverse-video mode
NORMAL = '' #: Turn off all modes
# Cursor display:
HIDE_CURSOR = '' #: Make the cursor invisible
SHOW_CURSOR = '' #: Make the cursor visible
# Terminal size:
COLS = None #: Width of the terminal (None for unknown)
LINES = None #: Height of the terminal (None for unknown)
# Foreground colors:
BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = ''
# Background colors:
BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = ''
BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = ''
_STRING_CAPABILITIES = """
BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1
CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold
BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0
HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split()
_COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split()
_ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
def __init__(self, term_stream=sys.stdout):
"""
Create a `TerminalController` and initialize its attributes
with appropriate values for the current terminal.
`term_stream` is the stream that will be used for terminal
output; if this stream is not a tty, then the terminal is
assumed to be a dumb terminal (i.e., have no capabilities).
"""
# Curses isn't available on all platforms
try: import curses
except: return
# If the stream isn't a tty, then assume it has no capabilities.
if not term_stream.isatty(): return
# Check the terminal type. If we fail, then assume that the
# terminal has no capabilities.
try: curses.setupterm()
except: return
# Look up numeric capabilities.
self.COLS = curses.tigetnum('cols')
self.LINES = curses.tigetnum('lines')
# Look up string capabilities.
for capability in self._STRING_CAPABILITIES:
(attrib, cap_name) = capability.split('=')
setattr(self, attrib, self._tigetstr(cap_name) or '')
# Colors
set_fg = self._tigetstr('setf')
if set_fg:
for i,color in zip(range(len(self._COLORS)), self._COLORS):
setattr(self, color, curses.tparm(set_fg, i) or '')
set_fg_ansi = self._tigetstr('setaf')
if set_fg_ansi:
for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
setattr(self, color, curses.tparm(set_fg_ansi, i) or '')
set_bg = self._tigetstr('setb')
if set_bg:
for i,color in zip(range(len(self._COLORS)), self._COLORS):
setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '')
set_bg_ansi = self._tigetstr('setab')
if set_bg_ansi:
for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS):
setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '')
def _tigetstr(self, cap_name):
# String capabilities can include "delays" of the form "$<2>".
# For any modern terminal, we should be able to just ignore
# these, so strip them out.
import curses
cap = curses.tigetstr(cap_name) or ''
return re.sub(r'\$<\d+>[/*]?', '', cap)
def render(self, template):
"""
Replace each $-substitutions in the given template string with
the corresponding terminal control string (if it's defined) or
'' (if it's not).
"""
return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
def _render_sub(self, match):
s = match.group()
if s == '$$': return s
else: return getattr(self, s[2:-1])
CMD = "ps -o pid,pcpu,rss,command -u %s"
TERM = TerminalController()
def main():
user = pwd.getpwuid(os.getuid())[0]
total_cpu = 0
total_mem = 0
memproc = sys.argv[0]
psproc = CMD % user
proclist = []
user = pwd.getpwuid(os.getuid())[0]
print TERM.render ('(user ${YELLOW}%s${NORMAL})' % user)
proc = subprocess.Popen(CMD % user, shell=True, stdout=subprocess.PIPE)
for line in proc.stdout:
if line.strip().startswith('PID'):
print line,
continue
proctype = ''
pid,pcpu,rss,command = line.strip().split(None,3)
if '/usr/local/apache2-mpm-peruser/bin/httpd' in command:
proctype = 'memfree'
if command == psproc or command.endswith(memproc):
proctype = 'free'
proclist.append ( (pid,pcpu,rss,command,proctype))
# sort by mem
proclist = sorted (proclist,key=lambda x: int(x[2]),reverse=True)
# generate output
for entry in proclist:
pid,pcpu,rss,command,proctype = entry
f_cpu = float(pcpu.strip())
f_mem = float(rss.strip())/1024
if not proctype:
total_cpu += f_cpu
total_mem += f_mem
memcolor = cpucolor = 'YELLOW'
elif proctype == 'memfree':
total_cpu += f_cpu
memcolor = 'GREEN'
cpucolor = 'YELLOW'
elif proctype == 'free':
memcolor = cpucolor = 'GREEN'
pcpu = '${%s}%s${NORMAL}' % (cpucolor,pcpu.rjust(4))
rss = '${%s}%s${NORMAL}' % (memcolor,('%.1fM' % f_mem).rjust(6))
output = ''
output += TERM.render (pid.ljust(6))
output += TERM.render (pcpu)
output += TERM.render (rss)
output += TERM.render (' ' + command)
print output
print '-'*24
print TERM.render ('${YELLOW}Total %.1f %.1fM${NORMAL}' % (total_cpu, total_mem))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment