Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
蜕变的菜鸟
glances
提交
baf79e9d
G
glances
项目概览
蜕变的菜鸟
/
glances
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
glances
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
baf79e9d
编写于
10月 21, 2016
作者:
N
nicolargo
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'issue937' into develop
上级
d37c4306
8c15914f
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
278 addition
and
15 deletion
+278
-15
NEWS
NEWS
+2
-1
README.rst
README.rst
+1
-0
conf/glances.conf
conf/glances.conf
+9
-0
docs/_static/wifi.png
docs/_static/wifi.png
+0
-0
docs/aoa/index.rst
docs/aoa/index.rst
+1
-0
docs/aoa/network.rst
docs/aoa/network.rst
+1
-1
docs/aoa/wifi.rst
docs/aoa/wifi.rst
+31
-0
docs/install.rst
docs/install.rst
+3
-2
docs/man/glances.1
docs/man/glances.1
+1
-1
glances/main.py
glances/main.py
+2
-0
glances/outputs/glances_curses.py
glances/outputs/glances_curses.py
+8
-1
glances/plugins/glances_plugin.py
glances/plugins/glances_plugin.py
+8
-8
glances/plugins/glances_wifi.py
glances/plugins/glances_wifi.py
+209
-0
setup.py
setup.py
+2
-1
未找到文件。
NEWS
浏览文件 @
baf79e9d
...
...
@@ -5,10 +5,11 @@ Glances Version 2
Version 2.8
===========
Enhancements and new features:
Enhancements and new
s
features:
* Add ZeroMQ exporter (issue #939)
* Add CouchDB exporter (issue #928)
* Add hotspot Wifi informations (issue #937)
* Highlight max stats in the processes list (issue #878)
* Docker alerts and actions (issue #875)
* Glances API returns the processes PPID (issue #926)
...
...
README.rst
浏览文件 @
baf79e9d
...
...
@@ -51,6 +51,7 @@ Optional dependencies:
- ``bernhard`` (for the Riemann export module)
- ``py-cpuinfo`` (for the Quicklook CPU info module)
- ``scandir`` (for the Folders plugin) [Only for Python < 3.5]
- ``wifi`` (for the wifi plugin) [Linux-only]
*Note for Python 2.6 users*
...
...
conf/glances.conf
浏览文件 @
baf79e9d
...
...
@@ -111,6 +111,15 @@ critical=90
#wlan0_tx_critical=1000000
#wlan0_tx_log=True
[
wifi
]
# Define the list of hidden wireless network interfaces (comma-separated regexp)
hide
=
lo
,
docker
.*
# Define SIGNAL thresholds in db (lower is better...)
# Based on: http://serverfault.com/questions/501025/industry-standard-for-minimum-wifi-signal-strength
careful
=-
65
warning
=-
75
critical
=-
85
#[diskio]
# Define the list of hidden disks (comma-separated regexp)
#hide=sda2,sda5,loop.*
...
...
docs/_static/wifi.png
0 → 100644
浏览文件 @
baf79e9d
8.5 KB
docs/aoa/index.rst
浏览文件 @
baf79e9d
...
...
@@ -26,6 +26,7 @@ Legend:
load
memory
network
wifi
ports
disk
fs
...
...
docs/aoa/network.rst
浏览文件 @
baf79e9d
...
...
@@ -11,7 +11,7 @@ dynamically (bit/s, kbit/s, Mbit/s, etc).
Alerts are only set if the maximum speed per network interface is
available (see sample in the configuration file).
It's also possib
i
le to define:
It's also possible to define:
- a list of network interfaces to hide
- per-interface limit values
...
...
docs/aoa/wifi.rst
0 → 100644
浏览文件 @
baf79e9d
.. _wifi:
Wifi
=====
*Availability: Linux*
.. image:: ../_static/wifi.png
Glances displays the Wifi hotspots' name and signal quality.
If Glances is ran as root, then all the available hotspots are displayed.
In the configuration file, you can define signal quality thresholds.
"Poor" quality is between -100 and -85dBm, "Good" quality between -85
and -60dBm, and "Excellent" between -60 and -40dBm.
It's also possible to disable the scan on a specific interface from the
configuration file (``[wifi]`` section). For example, if you want to
hide the loopback interface (lo) and all the virtual docker interfaces:
.. code-block:: ini
[wifi]
hide=lo,docker.*
# Define SIGNAL thresholds in dBm (lower is better...)
careful=-65
warning=-75
critical=-85
You can disable this plugin using the --disable-wifi option or by heating
the 'W' from the user interface.
docs/install.rst
浏览文件 @
baf79e9d
...
...
@@ -22,12 +22,13 @@ features (like the Web interface, exports modules, sensors...):
.. code-block:: console
pip install bottle requests batinfo py3sensors zeroconf netifaces pymdstat influxdb elasticsearch potsdb statsd pystache docker-py pysnmp pika py-cpuinfo bernhard cassandra scandir couchdb pyzmq
pip install bottle requests batinfo py3sensors zeroconf netifaces pymdstat influxdb elasticsearch potsdb statsd pystache docker-py pysnmp pika py-cpuinfo bernhard cassandra scandir couchdb pyzmq
wifi
To upgrade Glances
to the latest version
:
To upgrade Glances
and all its dependencies to the latests versions
:
.. code-block:: console
pip install --upgrade bottle requests batinfo py3sensors zeroconf netifaces pymdstat influxdb elasticsearch potsdb statsd pystache docker-py pysnmp pika py-cpuinfo bernhard cassandra scandir couchdb pyzmq wifi
pip install --upgrade glances
For additionnal installation methods, read the official `README`_ file.
...
...
docs/man/glances.1
浏览文件 @
baf79e9d
.\" Man page generated from reStructuredText.
.
.TH "GLANCES" "1" "Oct
15
, 2016" "2.8_DEVELOP" "Glances"
.TH "GLANCES" "1" "Oct
21
, 2016" "2.8_DEVELOP" "Glances"
.SH NAME
glances \- An eye on your system
.
...
...
glances/main.py
浏览文件 @
baf79e9d
...
...
@@ -113,6 +113,8 @@ Start the client browser (browser mode):\n\
dest
=
'disable_load'
,
help
=
'disable load module'
)
parser
.
add_argument
(
'--disable-network'
,
action
=
'store_true'
,
default
=
False
,
dest
=
'disable_network'
,
help
=
'disable network module'
)
parser
.
add_argument
(
'--disable-wifi'
,
action
=
'store_true'
,
default
=
False
,
dest
=
'disable_wifi'
,
help
=
'disable wifi module'
)
parser
.
add_argument
(
'--disable-ports'
,
action
=
'store_true'
,
default
=
False
,
dest
=
'disable_ports'
,
help
=
'disable ports scanner module'
)
parser
.
add_argument
(
'--disable-ip'
,
action
=
'store_true'
,
default
=
False
,
...
...
glances/outputs/glances_curses.py
浏览文件 @
baf79e9d
...
...
@@ -444,6 +444,9 @@ class _GlancesCurses(object):
elif
self
.
pressedkey
==
ord
(
'w'
):
# 'w' > Delete finished warning logs
glances_logs
.
clean
()
elif
self
.
pressedkey
==
ord
(
'W'
):
# 'W' > Enable/Disable Wifi plugin
self
.
args
.
disable_wifi
=
not
self
.
args
.
disable_wifi
elif
self
.
pressedkey
==
ord
(
'x'
):
# 'x' > Delete finished warning and critical logs
glances_logs
.
clean
(
critical
=
True
)
...
...
@@ -540,6 +543,8 @@ class _GlancesCurses(object):
stats_memswap
=
stats
.
get_plugin
(
'memswap'
).
get_stats_display
(
args
=
self
.
args
)
stats_network
=
stats
.
get_plugin
(
'network'
).
get_stats_display
(
args
=
self
.
args
,
max_width
=
plugin_max_width
)
stats_wifi
=
stats
.
get_plugin
(
'wifi'
).
get_stats_display
(
args
=
self
.
args
,
max_width
=
plugin_max_width
)
stats_irq
=
stats
.
get_plugin
(
'irq'
).
get_stats_display
(
args
=
self
.
args
,
max_width
=
plugin_max_width
)
try
:
...
...
@@ -718,13 +723,15 @@ class _GlancesCurses(object):
# ==================================================================
self
.
init_column
()
if
not
(
self
.
args
.
disable_network
and
self
.
args
.
disable_wifi
and
self
.
args
.
disable_ports
and
self
.
args
.
disable_diskio
and
self
.
args
.
disable_fs
and
self
.
args
.
disable_irq
and
self
.
args
.
disable_folder
and
self
.
args
.
disable_raid
and
self
.
args
.
disable_sensors
)
and
not
self
.
args
.
disable_left_sidebar
:
for
s
in
(
stats_network
,
stats_ports
,
stats_diskio
,
stats_fs
,
stats_irq
,
stats_folders
,
stats_raid
,
stats_sensors
,
stats_now
):
for
s
in
(
stats_network
,
stats_
wifi
,
stats_
ports
,
stats_diskio
,
stats_fs
,
stats_irq
,
stats_folders
,
stats_raid
,
stats_sensors
,
stats_now
):
self
.
new_line
()
self
.
display_plugin
(
s
)
...
...
glances/plugins/glances_plugin.py
浏览文件 @
baf79e9d
...
...
@@ -503,11 +503,11 @@ class GlancesPlugin(object):
# If is_max is set then display the value in MAX
ret
=
'MAX'
if
is_max
else
'OK'
try
:
if
value
>
self
.
__
get_limit
(
'critical'
,
stat_name
=
stat_name
):
if
value
>
=
self
.
get_limit
(
'critical'
,
stat_name
=
stat_name
):
ret
=
'CRITICAL'
elif
value
>
self
.
__
get_limit
(
'warning'
,
stat_name
=
stat_name
):
elif
value
>
=
self
.
get_limit
(
'warning'
,
stat_name
=
stat_name
):
ret
=
'WARNING'
elif
value
>
self
.
__
get_limit
(
'careful'
,
stat_name
=
stat_name
):
elif
value
>
=
self
.
get_limit
(
'careful'
,
stat_name
=
stat_name
):
ret
=
'CAREFUL'
elif
current
<
minimum
:
ret
=
'CAREFUL'
...
...
@@ -516,7 +516,7 @@ class GlancesPlugin(object):
# Manage log
log_str
=
""
if
self
.
__
get_limit_log
(
stat_name
=
stat_name
,
default_action
=
log
):
if
self
.
get_limit_log
(
stat_name
=
stat_name
,
default_action
=
log
):
# Add _LOG to the return string
# So stats will be highlited with a specific color
log_str
=
"_LOG"
...
...
@@ -537,7 +537,7 @@ class GlancesPlugin(object):
"""Manage the action for the current stat"""
# Here is a command line for the current trigger ?
try
:
command
=
self
.
__
get_limit_action
(
trigger
,
stat_name
=
stat_name
)
command
=
self
.
get_limit_action
(
trigger
,
stat_name
=
stat_name
)
except
KeyError
:
# Reset the trigger
self
.
actions
.
set
(
stat_name
,
trigger
)
...
...
@@ -578,7 +578,7 @@ class GlancesPlugin(object):
action_key
=
action_key
,
log
=
True
)
def
__
get_limit
(
self
,
criticity
,
stat_name
=
""
):
def
get_limit
(
self
,
criticity
,
stat_name
=
""
):
"""Return the limit value for the alert."""
# Get the limit for stat + header
# Exemple: network_wlan0_rx_careful
...
...
@@ -594,7 +594,7 @@ class GlancesPlugin(object):
# Return the limit
return
limit
def
__
get_limit_action
(
self
,
criticity
,
stat_name
=
""
):
def
get_limit_action
(
self
,
criticity
,
stat_name
=
""
):
"""Return the action for the alert."""
# Get the action for stat + header
# Exemple: network_wlan0_rx_careful_action
...
...
@@ -608,7 +608,7 @@ class GlancesPlugin(object):
# Return the action list
return
ret
def
__
get_limit_log
(
self
,
stat_name
,
default_action
=
False
):
def
get_limit_log
(
self
,
stat_name
,
default_action
=
False
):
"""Return the log tag for the alert."""
# Get the log tag for stat + header
# Exemple: network_wlan0_rx_log
...
...
glances/plugins/glances_wifi.py
0 → 100644
浏览文件 @
baf79e9d
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
#
# Glances is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Glances is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Wifi plugin."""
import
base64
import
operator
from
glances.logger
import
logger
from
glances.timer
import
getTimeSinceLastUpdate
from
glances.plugins.glances_plugin
import
GlancesPlugin
import
psutil
# Use the Wifi Python lib (https://pypi.python.org/pypi/wifi)
# Linux-only
try
:
from
wifi.scan
import
Cell
from
wifi.exceptions
import
InterfaceError
except
ImportError
as
e
:
logger
.
debug
(
"Wifi library not found. Glances cannot grab Wifi info."
)
wifi_tag
=
False
else
:
wifi_tag
=
True
class
Plugin
(
GlancesPlugin
):
"""Glances Wifi plugin.
Get stats of the current Wifi hotspots.
"""
def
__init__
(
self
,
args
=
None
):
"""Init the plugin."""
super
(
Plugin
,
self
).
__init__
(
args
=
args
)
# We want to display the stat in the curse interface
self
.
display_curse
=
True
# Init the stats
self
.
reset
()
def
get_key
(
self
):
"""Return the key of the list.
:returns: string -- SSID is the dict key
"""
return
'ssid'
def
reset
(
self
):
"""Reset/init the stats to an empty list.
:returns: None
"""
self
.
stats
=
[]
@
GlancesPlugin
.
_check_decorator
@
GlancesPlugin
.
_log_result_decorator
def
update
(
self
):
"""Update Wifi stats using the input method.
Stats is a list of dict (one dict per hotspot)
:returns: list -- Stats is a list of dict (hotspot)
"""
# Reset stats
self
.
reset
()
# Exist if we can not grab the stats
if
not
wifi_tag
:
return
self
.
stats
if
self
.
input_method
==
'local'
:
# Update stats using the standard system lib
# Grab network interface stat using the PsUtil net_io_counter method
try
:
netiocounters
=
psutil
.
net_io_counters
(
pernic
=
True
)
except
UnicodeDecodeError
:
return
self
.
stats
for
net
in
netiocounters
:
# Do not take hidden interface into account
if
self
.
is_hide
(
net
):
continue
# Grab the stats using the Wifi Python lib
try
:
wifi_cells
=
Cell
.
all
(
net
)
except
InterfaceError
:
# Not a Wifi interface
pass
else
:
for
wifi_cell
in
wifi_cells
:
hotspot
=
{
'key'
:
self
.
get_key
(),
'ssid'
:
wifi_cell
.
ssid
,
'signal'
:
wifi_cell
.
signal
,
'quality'
:
wifi_cell
.
quality
,
'encrypted'
:
wifi_cell
.
encrypted
,
'encryption_type'
:
wifi_cell
.
encryption_type
if
wifi_cell
.
encrypted
else
None
}
# Add the hotspot to the list
self
.
stats
.
append
(
hotspot
)
elif
self
.
input_method
==
'snmp'
:
# Update stats using SNMP
# Not implemented yet
pass
# Update the view
self
.
update_views
()
return
self
.
stats
def
get_alert
(
self
,
value
):
"""Overwrite the default get_alert method.
Alert is on signal quality where lower is better...
:returns: string -- Signal alert
"""
ret
=
'OK'
try
:
if
value
<=
self
.
get_limit
(
'critical'
,
stat_name
=
self
.
plugin_name
):
ret
=
'CRITICAL'
elif
value
<=
self
.
get_limit
(
'warning'
,
stat_name
=
self
.
plugin_name
):
ret
=
'WARNING'
elif
value
<=
self
.
get_limit
(
'careful'
,
stat_name
=
self
.
plugin_name
):
ret
=
'CAREFUL'
except
KeyError
:
ret
=
'DEFAULT'
return
ret
def
update_views
(
self
):
"""Update stats views."""
# Call the father's method
super
(
Plugin
,
self
).
update_views
()
# Add specifics informations
# Alert on signal thresholds
for
i
in
self
.
stats
:
self
.
views
[
i
[
self
.
get_key
()]][
'signal'
][
'decoration'
]
=
self
.
get_alert
(
i
[
'signal'
])
self
.
views
[
i
[
self
.
get_key
()]][
'quality'
][
'decoration'
]
=
self
.
views
[
i
[
self
.
get_key
()]][
'signal'
][
'decoration'
]
def
msg_curse
(
self
,
args
=
None
,
max_width
=
None
):
"""Return the dict to display in the curse interface."""
# Init the return message
ret
=
[]
# Only process if stats exist and display plugin enable...
if
not
self
.
stats
or
args
.
disable_wifi
or
not
wifi_tag
:
return
ret
# Max size for the interface name
if
max_width
is
not
None
and
max_width
>=
23
:
# Interface size name = max_width - space for encyption + quality
ifname_max_width
=
max_width
-
5
else
:
ifname_max_width
=
16
# Build the string message
# Header
msg
=
'{:{width}}'
.
format
(
'WIFI'
,
width
=
ifname_max_width
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
"TITLE"
))
msg
=
'{:>7}'
.
format
(
'dBm'
)
ret
.
append
(
self
.
curse_add_line
(
msg
))
# Hotspot list (sorted by name)
for
i
in
sorted
(
self
.
stats
,
key
=
operator
.
itemgetter
(
self
.
get_key
())):
# Do not display hotspot with no name (/ssid)
if
i
[
'ssid'
]
==
''
:
continue
ret
.
append
(
self
.
curse_new_line
())
# New hotspot
hotspotname
=
i
[
'ssid'
]
# Add the encryption type (if it is available)
if
i
[
'encrypted'
]:
hotspotname
=
hotspotname
+
' {}'
.
format
(
i
[
'encryption_type'
])
# Cut hotspotname if it is too long
if
len
(
hotspotname
)
>
ifname_max_width
:
hotspotname
=
'_'
+
hotspotname
[
-
ifname_max_width
+
1
:]
# Add the new hotspot to the message
msg
=
'{:{width}}'
.
format
(
hotspotname
,
width
=
ifname_max_width
)
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
'{:>7}'
.
format
(
i
[
'signal'
],
width
=
ifname_max_width
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
self
.
get_views
(
item
=
i
[
self
.
get_key
()],
key
=
'signal'
,
option
=
'decoration'
)))
return
ret
setup.py
浏览文件 @
baf79e9d
...
...
@@ -92,7 +92,8 @@ setup(
'EXPORT'
:
[
'influxdb>=1.0.0'
,
'elasticsearch'
,
'potsdb'
'statsd'
,
'pika'
,
'bernhard'
,
'cassandra-driver'
],
'ACTION'
:
[
'pystache'
],
'CPUINFO'
:
[
'py-cpuinfo'
],
'FOLDERS'
:
[
'scandir'
]
'FOLDERS'
:
[
'scandir'
],
'WIFI'
:
[
'wifi'
]
},
packages
=
[
'glances'
],
include_package_data
=
True
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录