Manage error while scanning folder

This commit is contained in:
nicolargo 2023-08-19 11:06:32 +02:00
parent 99d05fdd63
commit 8f57fd3612
5 changed files with 46 additions and 56 deletions

View File

@ -13,22 +13,9 @@ from __future__ import unicode_literals
import os
from glances.timer import Timer
from glances.globals import nativestr
from glances.globals import nativestr, folder_size
from glances.logger import logger
# Use the built-in version of scandir/walk if possible, otherwise
# use the scandir module version
scandir_tag = True
try:
# For Python 3.5 or higher
from os import scandir
except ImportError:
# For others...
try:
from scandir import scandir
except ImportError:
scandir_tag = False
class FolderList(object):
@ -62,12 +49,9 @@ class FolderList(object):
self.first_grab = True
if self.config is not None and self.config.has_section('folders'):
if scandir_tag:
# Process monitoring list
logger.debug("Folder list configuration detected")
self.__set_folder_list('folders')
else:
logger.error('Scandir not found. Please use Python 3.5+ or install the scandir lib')
# Process monitoring list
logger.debug("Folder list configuration detected")
self.__set_folder_list('folders')
else:
self.__folder_list = []
@ -132,23 +116,6 @@ class FolderList(object):
else:
return None
def __folder_size(self, path):
"""Return the size of the directory given by path
path: <string>"""
ret = 0
for f in scandir(path):
if f.is_dir(follow_symlinks=False) and (f.name != '.' or f.name != '..'):
ret += self.__folder_size(os.path.join(path, f.name))
else:
try:
ret += f.stat().st_size
except OSError:
pass
return ret
def update(self, key='path'):
"""Update the command result attributed."""
# Only continue if monitor list is not empty
@ -163,16 +130,13 @@ class FolderList(object):
# Set the key (see issue #2327)
self.__folder_list[i]['key'] = key
# Get folder size
try:
self.__folder_list[i]['size'] = self.__folder_size(self.path(i))
except OSError as e:
logger.debug('Cannot get folder size ({}). Error: {}'.format(self.path(i), e))
if e.errno == 13:
# Permission denied
self.__folder_list[i]['size'] = '!'
else:
self.__folder_list[i]['size'] = '?'
# Reset the timer
self.__folder_list[i]['size'], self.__folder_list[i]['errno'] = folder_size(self.path(i))
if self.__folder_list[i]['errno'] != 0:
logger.debug('Folder size ({} ~ {}) may not be correct. Error: {}'.format(
self.path(i),
self.__folder_list[i]['size'],
self.__folder_list[i]['errno']))
# Reset the timer
self.timer_folders[i].reset()
# It is no more the first time...

View File

@ -372,3 +372,29 @@ def string_value_to_float(s):
def file_exists(filename):
"""Return True if the file exists and is readable."""
return os.path.isfile(filename) and os.access(filename, os.R_OK)
def folder_size(path, errno=0):
"""Return a tuple with the size of the directory given by path and the errno.
If an error occurs (for example one file or subfolder is not accessible),
errno is set to the error number.
path: <string>
errno: <int> Should always be 0 when calling the function"""
ret_size = 0
ret_err = errno
try:
f_list = os.scandir(path)
except OSError as e:
return 0, e.errno
for f in f_list:
if f.is_dir(follow_symlinks=False) and (f.name != '.' or f.name != '..'):
ret = folder_size(os.path.join(path, f.name), ret_err)
ret_size += ret[0]
ret_err = ret[1]
else:
try:
ret_size += f.stat().st_size
except OSError as e:
ret_err = e.errno
return ret_size, ret_err

View File

@ -330,6 +330,7 @@ class _GlancesCurses(object):
'PASSWORD': curses.A_PROTECT,
'SELECTED': self.selected_color,
'INFO': self.ifINFO_color,
'ERROR': self.selected_color,
}
def set_cursor(self, value):

View File

@ -64,8 +64,8 @@ class PluginModel(GlancesPluginModel):
def get_alert(self, stat, header=""):
"""Manage limits of the folder list."""
if not isinstance(stat['size'], numbers.Number):
ret = 'DEFAULT'
if stat['errno'] != 0:
ret = 'ERROR'
else:
ret = 'OK'
@ -108,15 +108,15 @@ class PluginModel(GlancesPluginModel):
ret.append(self.curse_new_line())
if len(i['path']) > name_max_width:
# Cut path if it is too long
path = '_' + i['path'][-name_max_width + 1 :]
path = '_' + i['path'][-name_max_width + 1:]
else:
path = i['path']
msg = '{:{width}}'.format(nativestr(path), width=name_max_width)
ret.append(self.curse_add_line(msg))
try:
if i['errno'] != 0:
msg = '?{:>8}'.format(self.auto_unit(i['size']))
else:
msg = '{:>9}'.format(self.auto_unit(i['size']))
except (TypeError, ValueError):
msg = '{:>9}'.format(i['size'])
ret.append(self.curse_add_line(msg, self.get_alert(i, header='folder_' + i['indice'])))
return ret

View File

@ -9,8 +9,8 @@ from io import open
from setuptools import setup, Command
if sys.version_info < (3, 4):
print('Glances requires at least Python 3.4 to run.')
if sys.version_info < (3, 8):
print('Glances requires at least Python 3.8 to run.')
sys.exit(1)
# Global functions
@ -60,7 +60,6 @@ def get_install_extras_require():
'graphitesender', 'influxdb>=1.0.0', 'influxdb-client', 'pymongo',
'kafka-python', 'pika', 'paho-mqtt', 'potsdb', 'prometheus_client',
'pyzmq', 'statsd'],
'folders': ['scandir'],
'gpu': ['py3nvml'],
'graph': ['pygal'],
'ip': ['netifaces'],