1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# SPDX-FileCopyrightText: 2023 Nicolas Hennion <nicolas@nicolargo.com>
#
# SPDX-License-Identifier: LGPL-3.0-only
#
#
"""Init the Glances software."""
# Import system libs
import tracemalloc
import locale
import platform
import signal
import sys
# Global name
# Version should start and end with a numerical char
# See https://packaging.python.org/specifications/core-metadata/#version
__version__ = '4.0.0_beta01'
__apiversion__ = '4'
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
__license__ = 'LGPLv3'
# Import psutil
try:
from psutil import __version__ as psutil_version
except ImportError:
print('psutil library not found. Glances cannot start.')
sys.exit(1)
# Import Glances libs
# Note: others Glances libs will be imported optionally
from glances.logger import logger
from glances.main import GlancesMain
from glances.timer import Counter
# Check locale
try:
locale.setlocale(locale.LC_ALL, '')
except locale.Error:
print("Warning: Unable to set locale. Expect encoding problems.")
# Check Python version
if sys.version_info < (3, 4):
print('Glances requires at least Python 3.4 to run.')
sys.exit(1)
# Check psutil version
psutil_min_version = (5, 3, 0)
psutil_version_info = tuple([int(num) for num in psutil_version.split('.')])
if psutil_version_info < psutil_min_version:
print('psutil 5.3.0 or higher is needed. Glances cannot start.')
sys.exit(1)
# Trac malloc is only available on Python 3.4 or higher
def __signal_handler(signal, frame):
logger.debug("Signal {} catched".format(signal))
end()
def end():
"""Stop Glances."""
try:
mode.end()
except (NameError, KeyError):
# NameError: name 'mode' is not defined in case of interrupt shortly...
# ...after starting the server mode (issue #1175)
pass
logger.info("Glances stopped gracefully")
# The end...
sys.exit(0)
def start(config, args):
"""Start Glances."""
# Load mode
global mode
if args.trace_malloc or args.memory_leak:
tracemalloc.start()
start_duration = Counter()
if core.is_standalone():
from glances.standalone import GlancesStandalone as GlancesMode
elif core.is_client():
if core.is_client_browser():
from glances.client_browser import GlancesClientBrowser as GlancesMode
else:
from glances.client import GlancesClient as GlancesMode
elif core.is_server():
from glances.server import GlancesServer as GlancesMode
elif core.is_webserver():
from glances.webserver import GlancesWebServer as GlancesMode
# Init the mode
logger.info("Start {} mode".format(GlancesMode.__name__))
mode = GlancesMode(config=config, args=args)
# Start the main loop
logger.debug("Glances started in {} seconds".format(start_duration.get()))
if args.stop_after:
logger.info('Glances will be stopped in ~{} seconds'.format(args.stop_after * args.time))
if args.memory_leak:
print(
'Memory leak detection, please wait ~{} seconds...'.format(
args.stop_after * args.time * args.memory_leak * 2
)
)
# First run without dump to fill the memory
mode.serve_n(args.stop_after)
# Then start the memory-leak loop
snapshot_begin = tracemalloc.take_snapshot()
if args.stdout_issue or args.stdout_apidoc:
# Serve once for issue/test mode
mode.serve_issue()
else:
# Serve forever
mode.serve_forever()
if args.memory_leak:
snapshot_end = tracemalloc.take_snapshot()
snapshot_diff = snapshot_end.compare_to(snapshot_begin, 'filename')
memory_leak = sum([s.size_diff for s in snapshot_diff])
print("Memory consumption: {0:.1f}KB (see log for details)".format(memory_leak / 1000))
logger.info("Memory consumption (top 5):")
for stat in snapshot_diff[:5]:
logger.info(stat)
elif args.trace_malloc:
# See more options here: https://docs.python.org/3/library/tracemalloc.html
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics("filename")
print("[ Trace malloc - Top 10 ]")
for stat in top_stats[:10]:
print(stat)
# Shutdown
mode.end()
def main():
"""Main entry point for Glances.
Select the mode (standalone, client or server)
Run it...
"""
# SIGHUP not available on Windows (see issue #2408)
if sys.platform.startswith('win'):
signal_list = (signal.SIGTERM, signal.SIGINT)
else:
signal_list = (signal.SIGTERM, signal.SIGINT, signal.SIGHUP)
# Catch the kill signal
for sig in signal_list:
signal.signal(sig, __signal_handler)
# Log Glances and psutil version
logger.info('Start Glances {}'.format(__version__))
logger.info(
'{} {} ({}) and psutil {} detected'.format(
platform.python_implementation(), platform.python_version(), sys.executable, psutil_version
)
)
# Share global var
global core
# Create the Glances main instance
# Glances options from the command line are read first (in __init__)
# then the options from the config file (in parse_args)
core = GlancesMain()
# Glances can be ran in standalone, client or server mode
start(config=core.get_config(), args=core.get_args())
|