mirror of
https://github.com/nicolargo/glances.git
synced 2025-01-02 22:54:49 +03:00
Merge branch 'develop' of https://github.com/nicolargo/glances into issue1182
This commit is contained in:
commit
eef4fd7e32
4
AUTHORS
4
AUTHORS
@ -7,8 +7,8 @@ http://blog.nicolargo.com
|
||||
https://twitter.com/nicolargo
|
||||
https://github.com/nicolargo
|
||||
nicolashennion@gmail.com
|
||||
PGP Fingerprint: 835F C447 3BCD 60E9 9200 2778 ABA4 D1AB 9731 6A3C
|
||||
PGP Public key: gpg --keyserver pgp.mit.edu --recv-keys 0xaba4d1ab97316a3c
|
||||
PGP Fingerprint: A0D9 628F 5A83 A879 48EA B1FE BA43 C11F 2C8B 4347
|
||||
PGP Public key: gpg --keyserver pgp.mit.edu --recv-keys 0xba43c11f2c8b4347
|
||||
|
||||
Alessio Sergi (aka) Al3hex
|
||||
https://twitter.com/al3hex
|
||||
|
2
NEWS
2
NEWS
@ -25,6 +25,8 @@ Bugs corrected:
|
||||
* Add missing mount-observe and system-observe interfaces #1179
|
||||
* OS specific arguments should be documented and reported #1180
|
||||
* 'ascii' codec can't encode character u'\U0001f4a9' in position 4: ordinal not in range(128) #1185
|
||||
* KeyError: 'memory_info' on stats sum #1188
|
||||
* Electron/Atom processes displayed wrong in process list #1192
|
||||
|
||||
Backward-incompatible changes:
|
||||
|
||||
|
@ -92,7 +92,7 @@ if PY3:
|
||||
def b(s):
|
||||
if isinstance(s, binary_type):
|
||||
return s
|
||||
return s.encode('latin-1')
|
||||
return s.encode('utf-8')
|
||||
|
||||
def nativestr(s):
|
||||
if isinstance(s, text_type):
|
||||
|
@ -135,6 +135,7 @@ class Config(object):
|
||||
def read(self):
|
||||
"""Read the config file, if it exists. Using defaults otherwise."""
|
||||
for config_file in self.config_file_paths():
|
||||
logger.info('Search glances.conf file in {}'.format(config_file))
|
||||
if os.path.exists(config_file):
|
||||
try:
|
||||
with open(config_file, encoding='utf-8') as f:
|
||||
@ -142,7 +143,7 @@ class Config(object):
|
||||
self.parser.read(f)
|
||||
logger.info("Read configuration file '{}'".format(config_file))
|
||||
except UnicodeDecodeError as err:
|
||||
logger.error("Cannot decode configuration file '{}': {}".format(config_file, err))
|
||||
logger.error("Can not read configuration file '{}': {}".format(config_file, err))
|
||||
sys.exit(1)
|
||||
# Save the loaded configuration file path (issue #374)
|
||||
self._loaded_config_file = config_file
|
||||
|
@ -95,7 +95,7 @@ class _GlancesCurses(object):
|
||||
_left_sidebar = ['network', 'wifi', 'ports', 'diskio', 'fs',
|
||||
'irq', 'folders', 'raid', 'sensors', 'now']
|
||||
_left_sidebar_min_width = 23
|
||||
_left_sidebar_max_width = 84
|
||||
_left_sidebar_max_width = 64
|
||||
|
||||
# Define right sidebar
|
||||
_right_sidebar = ['docker', 'processcount', 'amps', 'processlist', 'alert']
|
||||
@ -135,9 +135,6 @@ class _GlancesCurses(object):
|
||||
# Init main window
|
||||
self.term_window = self.screen.subwin(0, 0)
|
||||
|
||||
# Init refresh time
|
||||
self.__refresh_time = args.time
|
||||
|
||||
# Init edit filter tag
|
||||
self.edit_filter = False
|
||||
|
||||
@ -498,7 +495,9 @@ class _GlancesCurses(object):
|
||||
ret = {}
|
||||
|
||||
for p in stats.getAllPlugins(enable=False):
|
||||
if p == 'quicklook':
|
||||
if p == 'quicklook' or p == 'processlist':
|
||||
# processlist is done later
|
||||
# because we need to know how many processes could be displayed
|
||||
continue
|
||||
|
||||
# Compute the plugin max size
|
||||
@ -538,7 +537,7 @@ class _GlancesCurses(object):
|
||||
# Update the stats messages
|
||||
###########################
|
||||
|
||||
# Update the client server status
|
||||
# Get all the plugins but quicklook and proceslist
|
||||
self.args.cs_status = cs_status
|
||||
__stat_display = self.__get_stat_display(stats, layer=cs_status)
|
||||
|
||||
@ -560,6 +559,7 @@ class _GlancesCurses(object):
|
||||
logger.debug("Set number of displayed processes to {}".format(max_processes_displayed))
|
||||
glances_processes.max_processes = max_processes_displayed
|
||||
|
||||
# Get the processlist
|
||||
__stat_display["processlist"] = stats.get_plugin(
|
||||
'processlist').get_stats_display(args=self.args)
|
||||
|
||||
@ -694,7 +694,8 @@ class _GlancesCurses(object):
|
||||
if self.args.full_quicklook:
|
||||
quicklook_width = self.screen.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column)
|
||||
else:
|
||||
quicklook_width = min(self.screen.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column), 79)
|
||||
quicklook_width = min(self.screen.getmaxyx()[1] - (stats_width + 8 + stats_number * self.space_between_column),
|
||||
self._left_sidebar_max_width - 5)
|
||||
try:
|
||||
stat_display["quicklook"] = stats.get_plugin(
|
||||
'quicklook').get_stats_display(max_width=quicklook_width, args=self.args)
|
||||
@ -961,13 +962,18 @@ class _GlancesCurses(object):
|
||||
self.erase()
|
||||
self.display(stats, cs_status=cs_status)
|
||||
|
||||
def update(self, stats, cs_status=None, return_to_browser=False):
|
||||
def update(self,
|
||||
stats,
|
||||
duration=3,
|
||||
cs_status=None,
|
||||
return_to_browser=False):
|
||||
"""Update the screen.
|
||||
|
||||
Wait for __refresh_time sec / catch key every 100 ms.
|
||||
Catch key every 100 ms.
|
||||
|
||||
INPUT
|
||||
stats: Stats database to display
|
||||
duration: duration of the loop
|
||||
cs_status:
|
||||
"None": standalone or server mode
|
||||
"Connected": Client is connected to the server
|
||||
@ -983,9 +989,15 @@ class _GlancesCurses(object):
|
||||
# Flush display
|
||||
self.flush(stats, cs_status=cs_status)
|
||||
|
||||
# If the duration is < 0 (update + export time > refresh_time)
|
||||
# Then display the interface and log a message
|
||||
if duration <= 0:
|
||||
logger.debug('Update and export time higher than refresh_time.')
|
||||
duration = 0.1
|
||||
|
||||
# Wait
|
||||
exitkey = False
|
||||
countdown = Timer(self.__refresh_time)
|
||||
countdown = Timer(duration)
|
||||
while not countdown.finished() and not exitkey:
|
||||
# Getkey
|
||||
pressedkey = self.__catch_key(return_to_browser=return_to_browser)
|
||||
|
@ -20,10 +20,11 @@
|
||||
"""Process list plugin."""
|
||||
|
||||
import os
|
||||
import shlex
|
||||
from datetime import timedelta
|
||||
|
||||
from glances.compat import iteritems
|
||||
from glances.globals import LINUX, WINDOWS
|
||||
from glances.globals import WINDOWS
|
||||
from glances.logger import logger
|
||||
from glances.processes import glances_processes, sort_stats
|
||||
from glances.plugins.glances_core import Plugin as CorePlugin
|
||||
@ -43,16 +44,16 @@ def convert_timedelta(delta):
|
||||
|
||||
def split_cmdline(cmdline):
|
||||
"""Return path, cmd and arguments for a process cmdline."""
|
||||
path, cmd = os.path.split(cmdline[0])
|
||||
arguments = ' '.join(cmdline[1:]).replace('\n', ' ')
|
||||
# XXX: workaround for psutil issue #742
|
||||
if LINUX and any(x in cmdline[0] for x in ('chrome', 'chromium')):
|
||||
try:
|
||||
exe, arguments = cmdline[0].split(' ', 1)
|
||||
path, cmd = os.path.split(exe)
|
||||
except ValueError:
|
||||
arguments = None
|
||||
# There is an issue in PsUtil for Electron/Atom processes (maybe others...)
|
||||
# Tracked by https://github.com/nicolargo/glances/issues/1192
|
||||
# https://github.com/giampaolo/psutil/issues/1179
|
||||
# Add this dirty workarround (to be removed when the PsUtil is solved)
|
||||
if len(cmdline) == 1:
|
||||
cmdline = shlex.split(cmdline[0])
|
||||
# /End of the direty workarround
|
||||
|
||||
path, cmd = os.path.split(cmdline[0])
|
||||
arguments = ' '.join(cmdline[1:])
|
||||
return path, cmd, arguments
|
||||
|
||||
|
||||
@ -605,6 +606,9 @@ class Plugin(GlancesPlugin):
|
||||
# Compute stats summary
|
||||
ret = 0
|
||||
for p in self.stats:
|
||||
if key not in p:
|
||||
# Correct issue #1188
|
||||
continue
|
||||
if indice is None:
|
||||
ret += p[key]
|
||||
else:
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
import operator
|
||||
|
||||
from glances.compat import u
|
||||
from glances.compat import b
|
||||
from glances.logger import logger
|
||||
from glances.plugins.glances_plugin import GlancesPlugin
|
||||
|
||||
@ -101,8 +101,9 @@ class Plugin(GlancesPlugin):
|
||||
# Grab the stats using the Wifi Python lib
|
||||
try:
|
||||
wifi_cells = Cell.all(net)
|
||||
except InterfaceError:
|
||||
except InterfaceError as e:
|
||||
# Not a Wifi interface
|
||||
logger.debug("WIFI plugin: Scan InterfaceError ({})".format(e))
|
||||
pass
|
||||
except Exception as e:
|
||||
# Other error
|
||||
@ -195,7 +196,7 @@ class Plugin(GlancesPlugin):
|
||||
if len(hotspotname) > ifname_max_width:
|
||||
hotspotname = '_' + hotspotname[-ifname_max_width + 1:]
|
||||
# Add the new hotspot to the message
|
||||
msg = '{:{width}}'.format(u(hotspotname),
|
||||
msg = '{:{width}}'.format(b(hotspotname),
|
||||
width=ifname_max_width)
|
||||
ret.append(self.curse_add_line(msg))
|
||||
msg = '{:>7}'.format(i['signal'], width=ifname_max_width)
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
"""Manage the Glances standalone session."""
|
||||
|
||||
import sched
|
||||
import time
|
||||
|
||||
from glances.globals import WINDOWS
|
||||
from glances.logger import logger
|
||||
@ -28,6 +26,7 @@ from glances.processes import glances_processes
|
||||
from glances.stats import GlancesStats
|
||||
from glances.outputs.glances_curses import GlancesCursesStandalone
|
||||
from glances.outdated import Outdated
|
||||
from glances.timer import Counter
|
||||
|
||||
|
||||
class GlancesStandalone(object):
|
||||
@ -82,41 +81,35 @@ class GlancesStandalone(object):
|
||||
# Check the latest Glances version
|
||||
self.outdated = Outdated(config=config, args=args)
|
||||
|
||||
# Create the schedule instance
|
||||
self.schedule = sched.scheduler(
|
||||
timefunc=time.time, delayfunc=time.sleep)
|
||||
|
||||
@property
|
||||
def quiet(self):
|
||||
return self._quiet
|
||||
|
||||
def __serve_forever(self):
|
||||
"""Main loop for the CLI."""
|
||||
# Reschedule the function inside itself
|
||||
self.schedule.enter(self.refresh_time, priority=0,
|
||||
action=self.__serve_forever, argument=())
|
||||
# Start a counter used to compute the time needed for
|
||||
# update and export the stats
|
||||
counter = Counter()
|
||||
|
||||
# Update system informations
|
||||
# Update stats
|
||||
self.stats.update()
|
||||
logger.debug('Stats updated in {} seconds'.format(counter.get()))
|
||||
|
||||
# Update the screen
|
||||
if not self.quiet:
|
||||
self.screen.update(self.stats)
|
||||
|
||||
# Export stats using export modules
|
||||
# Export stats
|
||||
counter_export = Counter()
|
||||
self.stats.export(self.stats)
|
||||
logger.debug('Stats exported in {} seconds'.format(counter_export.get()))
|
||||
|
||||
# Display stats
|
||||
# and wait refresh_time - counter
|
||||
if not self.quiet:
|
||||
self.screen.update(self.stats,
|
||||
duration=self.refresh_time - counter.get())
|
||||
|
||||
def serve_forever(self):
|
||||
"""Wrapper to the serve_forever function.
|
||||
|
||||
This function will restore the terminal to a sane state
|
||||
before re-raising the exception and generating a traceback.
|
||||
"""
|
||||
self.__serve_forever()
|
||||
try:
|
||||
self.schedule.run()
|
||||
finally:
|
||||
self.end()
|
||||
"""Wrapper to the serve_forever function."""
|
||||
while True:
|
||||
self.__serve_forever()
|
||||
|
||||
def end(self):
|
||||
"""End of the standalone CLI."""
|
||||
|
Loading…
Reference in New Issue
Block a user