mirror of https://github.com/nicolargo/glances.git
Add Windows client support
This commit is contained in:
parent
44e8d34694
commit
6dd98074f2
|
|
@ -115,7 +115,9 @@ MacPorts
|
|||
Windows
|
||||
-------
|
||||
|
||||
Windows only support Glances in server mode. Glances will automatically run in server mode on it.
|
||||
Glances 1.7.2 proposes a Windows client based on the `colorconsole`_ Python librairy.
|
||||
|
||||
Version < 1.7.2 only support Glances in server mode. Glances will automatically run in server mode on it.
|
||||
|
||||
Thanks to Nicolas Bourges, Glances can be easily installed using a Windows installer:
|
||||
|
||||
|
|
@ -126,6 +128,7 @@ Otherwise, you have to follow these steps:
|
|||
|
||||
- Install Python for Windows: http://www.python.org/getit/
|
||||
- Install the psutil library: https://code.google.com/p/psutil/downloads/list
|
||||
- Install the colorconsole library: http://code.google.com/p/colorconsole/downloads/list
|
||||
- Download Glances from here: http://nicolargo.github.io/glances/
|
||||
|
||||
Source
|
||||
|
|
@ -183,5 +186,6 @@ LGPL. See ``COPYING`` for more details.
|
|||
.. _MacPorts: https://www.macports.org/
|
||||
.. _glances-1.6.1-x86.exe: https://s3.amazonaws.com/glances/glances-1.6.1-x86.exe
|
||||
.. _glances-1.6.1-x64.exe: https://s3.amazonaws.com/glances/glances-1.6.1-x64.exe
|
||||
.. _colorconsole: https://pypi.python.org/pypi/colorconsole
|
||||
.. _Puppet: https://puppetlabs.com/puppet/what-is-puppet/
|
||||
.. _glances-doc: https://github.com/nicolargo/glances/blob/master/docs/glances-doc.rst
|
||||
|
|
|
|||
|
|
@ -88,6 +88,162 @@ if not is_Windows:
|
|||
print('Curses module not found. Glances cannot start.')
|
||||
sys.exit(1)
|
||||
|
||||
is_ColorConsole = False
|
||||
if is_Windows:
|
||||
try:
|
||||
import colorconsole, colorconsole.terminal
|
||||
import threading
|
||||
import msvcrt
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
import Queue as queue
|
||||
except ImportError:
|
||||
# Python 3
|
||||
import queue
|
||||
|
||||
class ListenGetch(threading.Thread):
|
||||
def __init__(self, nom = ''):
|
||||
threading.Thread.__init__(self)
|
||||
self.Terminated = False
|
||||
self.q = queue.Queue()
|
||||
|
||||
def run(self):
|
||||
while not self.Terminated:
|
||||
char = msvcrt.getch()
|
||||
self.q.put(char)
|
||||
|
||||
def stop(self):
|
||||
self.Terminated = True
|
||||
msvcrt.putch(' ')
|
||||
while not self.q.empty():
|
||||
self.q.get()
|
||||
|
||||
def get(self, default=None):
|
||||
try:
|
||||
return ord(self.q.get_nowait())
|
||||
except:
|
||||
return default
|
||||
|
||||
class Screen():
|
||||
|
||||
COLOR_DEFAULT_WIN = '0F'#07'#'0F'
|
||||
COLOR_BK_DEFAULT = colorconsole.terminal.colors["BLACK"]
|
||||
COLOR_FG_DEFAULT = colorconsole.terminal.colors["WHITE"]
|
||||
|
||||
def __init__(self, nc):
|
||||
self.nc = nc
|
||||
self.term = colorconsole.terminal.get_terminal()
|
||||
if os.name == "nt":
|
||||
os.system('color %s' % self.COLOR_DEFAULT_WIN)
|
||||
self.listen = ListenGetch()
|
||||
self.listen.start()
|
||||
|
||||
self.term.clear()
|
||||
|
||||
def subwin(self, x, y):
|
||||
return self
|
||||
|
||||
def keypad(self, id):
|
||||
return None
|
||||
|
||||
def nodelay(self, id):
|
||||
return None
|
||||
|
||||
def getch(self):
|
||||
return self.listen.get(27)
|
||||
#return self.term.getch()
|
||||
|
||||
def erase(self):
|
||||
self.reset()
|
||||
return None
|
||||
|
||||
def addnstr(self, y, x, msg, ln, typo= 0):
|
||||
try:
|
||||
fgs, bks = self.nc.colors[typo]
|
||||
except:
|
||||
fgs, bks = self.COLOR_FG_DEFAULT, self.COLOR_BK_DEFAULT
|
||||
self.term.set_color(fg=fgs, bk=bks)
|
||||
self.term.print_at(x, y, msg.ljust(ln))
|
||||
self.term.set_color(fg=self.COLOR_FG_DEFAULT, bk=self.COLOR_BK_DEFAULT)
|
||||
|
||||
def getmaxyx(self):
|
||||
x = self.term._Terminal__get_console_info().srWindow.Right - self.term._Terminal__get_console_info().srWindow.Left +1
|
||||
y = self.term._Terminal__get_console_info().srWindow.Bottom - self.term._Terminal__get_console_info().srWindow.Top +1
|
||||
return [y,x]
|
||||
|
||||
def reset(self):
|
||||
self.term.clear()
|
||||
self.term.reset()
|
||||
return None
|
||||
|
||||
def restore_buffered_mode(self):
|
||||
self.term.restore_buffered_mode()
|
||||
return None
|
||||
|
||||
class WCurseLight():
|
||||
|
||||
COLOR_WHITE = colorconsole.terminal.colors["WHITE"]
|
||||
COLOR_RED = colorconsole.terminal.colors["RED"]
|
||||
COLOR_GREEN = colorconsole.terminal.colors["GREEN"]
|
||||
COLOR_BLUE = colorconsole.terminal.colors["LBLUE"]
|
||||
COLOR_MAGENTA = colorconsole.terminal.colors["LPURPLE"]
|
||||
COLOR_BLACK = colorconsole.terminal.colors["BLACK"]
|
||||
A_UNDERLINE = 0
|
||||
A_BOLD = 0
|
||||
COLOR_PAIRS = 9
|
||||
colors = {}
|
||||
|
||||
def __init__(self):
|
||||
self.term = Screen(self)
|
||||
|
||||
def initscr(self):
|
||||
return self.term
|
||||
|
||||
def start_color(self):
|
||||
return None
|
||||
|
||||
def use_default_colors(self):
|
||||
return None
|
||||
|
||||
def noecho(self):
|
||||
return None
|
||||
|
||||
def cbreak(self):
|
||||
return None
|
||||
|
||||
def curs_set(self, y):
|
||||
return None
|
||||
|
||||
def has_colors(self):
|
||||
return True
|
||||
|
||||
def echo(self):
|
||||
return None
|
||||
|
||||
def nocbreak(self):
|
||||
return None
|
||||
|
||||
def endwin(self):
|
||||
self.term.reset()
|
||||
self.term.restore_buffered_mode()
|
||||
self.term.listen.stop()
|
||||
|
||||
def napms(self, t):
|
||||
time.sleep(t/1000 if t > 1000 else 1)
|
||||
|
||||
def init_pair(self, id, fg, bk):
|
||||
self.colors[id] = [max(fg, 0), max(bk, 0)]
|
||||
|
||||
def color_pair(self, id):
|
||||
return id
|
||||
|
||||
curses = WCurseLight()
|
||||
is_ColorConsole = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
# psutil is the main library used to grab stats
|
||||
import psutil
|
||||
|
|
@ -1392,13 +1548,13 @@ class GlancesStats:
|
|||
if psutil_net_io_counters:
|
||||
# psutil >= 1.0.0
|
||||
try:
|
||||
get_net_io_counters = psutil.net_io_counters(pernic=True)
|
||||
get_net_io_counters = psutil.net_io_counters(pernic=True)
|
||||
except IOError:
|
||||
self.network_error_tag = True
|
||||
else:
|
||||
# psutil < 1.0.0
|
||||
try:
|
||||
get_net_io_counters = psutil.network_io_counters(pernic=True)
|
||||
get_net_io_counters = psutil.network_io_counters(pernic=True)
|
||||
except IOError:
|
||||
self.network_error_tag = True
|
||||
|
||||
|
|
@ -1408,7 +1564,7 @@ class GlancesStats:
|
|||
except IOError:
|
||||
self.network_error_tag = True
|
||||
except UnboundLocalError:
|
||||
self.network_error_tag = True
|
||||
self.network_error_tag = True
|
||||
else:
|
||||
self.network_new = get_net_io_counters
|
||||
for net in self.network_new:
|
||||
|
|
@ -2258,31 +2414,32 @@ class glancesScreen:
|
|||
# Get stats for processes (used in another functions for logs)
|
||||
processcount = stats.getProcessCount()
|
||||
processlist = stats.getProcessList(screen.getProcessSortedBy())
|
||||
|
||||
# Display stats
|
||||
self.displaySystem(stats.getHost(), stats.getSystem())
|
||||
cpu_offset = self.displayCpu(stats.getCpu(), stats.getPerCpu(), processlist)
|
||||
load_offset = self.displayLoad(stats.getLoad(), stats.getCore(), processlist, cpu_offset)
|
||||
self.displayMem(stats.getMem(), stats.getMemSwap(), processlist, load_offset)
|
||||
network_count = self.displayNetwork(stats.getNetwork(), error=stats.network_error_tag)
|
||||
sensors_count = self.displaySensors(stats.getSensors(),
|
||||
self.network_y + network_count)
|
||||
hddtemp_count = self.displayHDDTemp(stats.getHDDTemp(),
|
||||
self.network_y + network_count + sensors_count)
|
||||
diskio_count = self.displayDiskIO(stats.getDiskIO(),
|
||||
offset_y=self.network_y + sensors_count +
|
||||
network_count + hddtemp_count,
|
||||
error=stats.diskio_error_tag)
|
||||
fs_count = self.displayFs(stats.getFs(),
|
||||
self.network_y + sensors_count +
|
||||
network_count + diskio_count +
|
||||
hddtemp_count)
|
||||
log_count = self.displayLog(self.network_y + sensors_count + network_count +
|
||||
diskio_count + fs_count +
|
||||
hddtemp_count)
|
||||
self.displayProcess(processcount, processlist, stats.getSortedBy(),
|
||||
log_count=log_count, core=stats.getCore(), cs_status=cs_status)
|
||||
self.displayCaption(cs_status=cs_status)
|
||||
|
||||
if not self.help_tag:
|
||||
# Display stats
|
||||
self.displaySystem(stats.getHost(), stats.getSystem())
|
||||
cpu_offset = self.displayCpu(stats.getCpu(), stats.getPerCpu(), processlist)
|
||||
load_offset = self.displayLoad(stats.getLoad(), stats.getCore(), processlist, cpu_offset)
|
||||
self.displayMem(stats.getMem(), stats.getMemSwap(), processlist, cpu_offset)
|
||||
network_count = self.displayNetwork(stats.getNetwork(), error=stats.network_error_tag)
|
||||
sensors_count = self.displaySensors(stats.getSensors(),
|
||||
self.network_y + network_count)
|
||||
hddtemp_count = self.displayHDDTemp(stats.getHDDTemp(),
|
||||
self.network_y + network_count + sensors_count)
|
||||
diskio_count = self.displayDiskIO(stats.getDiskIO(),
|
||||
offset_y=self.network_y + sensors_count +
|
||||
network_count + hddtemp_count,
|
||||
error=stats.diskio_error_tag)
|
||||
fs_count = self.displayFs(stats.getFs(),
|
||||
self.network_y + sensors_count +
|
||||
network_count + diskio_count +
|
||||
hddtemp_count)
|
||||
log_count = self.displayLog(self.network_y + sensors_count + network_count +
|
||||
diskio_count + fs_count +
|
||||
hddtemp_count)
|
||||
self.displayProcess(processcount, processlist, stats.getSortedBy(),
|
||||
log_count=log_count, core=stats.getCore(), cs_status=cs_status)
|
||||
self.displayCaption(cs_status=cs_status)
|
||||
self.displayHelp(core=stats.getCore())
|
||||
self.displayBat(stats.getBatPercent())
|
||||
self.displayNow(stats.getNow())
|
||||
|
|
@ -4191,8 +4348,8 @@ def main():
|
|||
html_tag = False
|
||||
csv_tag = False
|
||||
client_tag = False
|
||||
if is_Windows:
|
||||
# Force server mode for Windows OS
|
||||
if is_Windows and not is_ColorConsole:
|
||||
# Force server mode for Windows OS without Colorconsole
|
||||
server_tag = True
|
||||
else:
|
||||
server_tag = False
|
||||
|
|
|
|||
7
setup.py
7
setup.py
|
|
@ -28,6 +28,11 @@ data_files.append((etc_path, ['glances/conf/glances.conf']))
|
|||
for mo in glob.glob('i18n/*/LC_MESSAGES/*.mo'):
|
||||
data_files.append((os.path.dirname(mo).replace('i18n/', 'share/locale/'), [mo]))
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
requires = ['psutil>=0.5.1', 'colorconsole==0.6']
|
||||
else:
|
||||
requires = ['psutil>=0.5.1']
|
||||
|
||||
setup(
|
||||
name='Glances',
|
||||
version='1.7.1',
|
||||
|
|
@ -39,7 +44,7 @@ setup(
|
|||
# Alternative download_url='https://s3.amazonaws.com/glances/glances-1.7.1.tar.gz',
|
||||
license="LGPL",
|
||||
keywords="cli curses monitoring system",
|
||||
install_requires=['psutil>=0.5.1'],
|
||||
install_requires=requires,
|
||||
extras_require={
|
||||
'HTML': ['jinja2'],
|
||||
'SENSORS': ['pysensors'],
|
||||
|
|
|
|||
Loading…
Reference in New Issue