Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
蜕变的菜鸟
glances
提交
4f2e051b
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,发现更多精彩内容 >>
提交
4f2e051b
编写于
4月 19, 2015
作者:
A
Alessio Sergi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add sort processes by USER
上级
3d89e34c
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
64 addition
and
76 deletion
+64
-76
NEWS
NEWS
+4
-0
docs/glances-doc.rst
docs/glances-doc.rst
+2
-0
glances/core/glances_processes.py
glances/core/glances_processes.py
+23
-44
glances/outputs/glances_curses.py
glances/outputs/glances_curses.py
+5
-1
glances/plugins/glances_help.py
glances/plugins/glances_help.py
+17
-16
glances/plugins/glances_processlist.py
glances/plugins/glances_processlist.py
+10
-15
man/glances.1
man/glances.1
+3
-0
未找到文件。
NEWS
浏览文件 @
4f2e051b
...
...
@@ -10,10 +10,14 @@ Changes:
* Glances doesn't provide a system-wide configuration file by default anymore.
Just copy it in any of the supported locations. See glances-doc.html for
more information.
* The default key bindings have been changed to:
- 'u': sort processes by USER
- 'U': show cumulative network I/O
Enhancements and new features:
* Implement a 'quick look' plugin (issue #505)
* Add sort processes by USER (issue #531)
* Add a new IP information plugin (issue #509)
* Add RabbitMQ export module (issue #540 Thk to @Katyucha)
* Add a quiet mode (-q), can be useful using with export module
...
...
docs/glances-doc.rst
浏览文件 @
4f2e051b
...
...
@@ -266,6 +266,8 @@ The following commands (key pressed) are supported while in Glances:
``T``
View network I/O as combination
``u``
Sort processes by USER
``U``
View cumulative network I/O
``w``
Delete finished warning log messages
...
...
glances/core/glances_processes.py
浏览文件 @
4f2e051b
...
...
@@ -19,7 +19,6 @@
# Import Python lib
import
collections
import
operator
import
os
import
re
...
...
@@ -50,13 +49,13 @@ class ProcessTreeNode(object):
We avoid recursive algorithm to manipulate the tree because function calls are expensive with CPython.
"""
def
__init__
(
self
,
process
=
None
,
stats
=
None
,
sort_key
=
None
,
root
=
False
):
def
__init__
(
self
,
process
=
None
,
stats
=
None
,
sort_key
=
None
,
sort_reverse
=
True
,
root
=
False
):
self
.
process
=
process
self
.
stats
=
stats
self
.
children
=
[]
self
.
children_sorted
=
False
self
.
sort_key
=
sort_key
self
.
reverse_sorting
=
(
self
.
sort_key
!=
"name"
)
self
.
sort_reverse
=
sort_reverse
self
.
is_root
=
root
def
__str__
(
self
):
...
...
@@ -87,7 +86,7 @@ class ProcessTreeNode(object):
def
set_sorting
(
self
,
key
,
reverse
):
""" Set sorting key or func for user with __iter__ (affects the whole tree from this node). """
if
self
.
sort_key
!=
key
or
self
.
reverse_sorting
!=
reverse
:
if
self
.
sort_key
!=
key
or
self
.
sort_reverse
!=
reverse
:
nodes_to_flag_unsorted
=
collections
.
deque
([
self
])
while
nodes_to_flag_unsorted
:
current_node
=
nodes_to_flag_unsorted
.
pop
()
...
...
@@ -98,7 +97,7 @@ class ProcessTreeNode(object):
def
get_weight
(
self
):
""" Return "weight" of a process and all its children for sorting. """
if
self
.
sort_key
==
"name"
:
if
self
.
sort_key
==
'name'
or
self
.
sort_key
==
'username'
:
return
self
.
stats
[
self
.
sort_key
]
# sum ressource usage for self and children
...
...
@@ -138,7 +137,7 @@ class ProcessTreeNode(object):
# optimization to avoid sorting twice (once when limiting the maximum processes to grab stats for,
# and once before displaying)
self
.
children
.
sort
(
key
=
self
.
__class__
.
get_weight
,
reverse
=
self
.
reverse_sorting
)
key
=
self
.
__class__
.
get_weight
,
reverse
=
self
.
sort_reverse
)
self
.
children_sorted
=
True
for
child
in
self
.
children
:
for
n
in
iter
(
child
):
...
...
@@ -156,7 +155,7 @@ class ProcessTreeNode(object):
# optimization to avoid sorting twice (once when limiting the maximum processes to grab stats for,
# and once before displaying)
self
.
children
.
sort
(
key
=
self
.
__class__
.
get_weight
,
reverse
=
self
.
reverse_sorting
)
key
=
self
.
__class__
.
get_weight
,
reverse
=
self
.
sort_reverse
)
self
.
children_sorted
=
True
for
child
in
self
.
children
:
if
not
exclude_incomplete_stats
or
"time_since_update"
in
child
.
stats
:
...
...
@@ -172,14 +171,14 @@ class ProcessTreeNode(object):
nodes_to_search
.
extend
(
current_node
.
children
)
@
staticmethod
def
build_tree
(
process_dict
,
sort_key
,
hide_kernel_threads
):
def
build_tree
(
process_dict
,
sort_key
,
sort_reverse
,
hide_kernel_threads
):
""" Build a process tree using using parent/child relationships, and return the tree root node. """
tree_root
=
ProcessTreeNode
(
root
=
True
)
nodes_to_add_last
=
collections
.
deque
()
# first pass: add nodes whose parent are in the tree
for
process
,
stats
in
process_dict
.
items
():
new_node
=
ProcessTreeNode
(
process
,
stats
,
sort_key
)
new_node
=
ProcessTreeNode
(
process
,
stats
,
sort_key
,
sort_reverse
)
try
:
parent_process
=
process
.
parent
()
except
psutil
.
NoSuchProcess
:
...
...
@@ -347,6 +346,14 @@ class GlancesProcesses(object):
""" Return True if process tree is enabled, False instead. """
return
self
.
_enable_tree
@
property
def
sort_reverse
(
self
):
"""Return True to sort processes in reverse 'key' order, False instead."""
if
self
.
sort_key
==
'name'
or
self
.
sort_key
==
'username'
:
return
False
return
True
def
__get_mandatory_stats
(
self
,
proc
,
procstat
):
"""
Get mandatory_stats: need for the sorting/filter step
...
...
@@ -355,8 +362,9 @@ class GlancesProcesses(object):
procstat
[
'mandatory_stats'
]
=
True
# Process CPU, MEM percent and name
procstat
.
update
(
proc
.
as_dict
(
attrs
=
[
'cpu_percent'
,
'memory_percent'
,
'name'
,
'cpu_times'
],
ad_value
=
''
))
procstat
.
update
(
proc
.
as_dict
(
attrs
=
[
'username'
,
'cpu_percent'
,
'memory_percent'
,
'name'
,
'cpu_times'
],
ad_value
=
''
))
if
procstat
[
'cpu_percent'
]
==
''
or
procstat
[
'memory_percent'
]
==
''
:
# Do not display process if we cannot get the basic
# cpu_percent or memory_percent stats
...
...
@@ -611,6 +619,7 @@ class GlancesProcesses(object):
if
self
.
_enable_tree
:
self
.
process_tree
=
ProcessTreeNode
.
build_tree
(
processdict
,
self
.
sort_key
,
self
.
sort_reverse
,
self
.
no_kernel_threads
)
for
i
,
node
in
enumerate
(
self
.
process_tree
):
...
...
@@ -636,8 +645,9 @@ class GlancesProcesses(object):
# Sort the internal dict and cut the top N (Return a list of tuple)
# tuple=key (proc), dict (returned by __get_process_stats)
try
:
processiter
=
sorted
(
processdict
.
items
(),
key
=
lambda
x
:
x
[
1
][
self
.
sort_key
],
reverse
=
True
)
processiter
=
sorted
(
processdict
.
items
(),
key
=
lambda
x
:
x
[
1
][
self
.
sort_key
],
reverse
=
self
.
sort_reverse
)
except
(
KeyError
,
TypeError
)
as
e
:
logger
.
error
(
"Cannot sort process list by {0}: {1}"
.
format
(
self
.
sort_key
,
e
))
logger
.
error
(
"%s"
%
str
(
processdict
.
items
()[
0
]))
...
...
@@ -707,36 +717,5 @@ class GlancesProcesses(object):
def
sort_key
(
self
,
key
):
"""Set the current sort key."""
self
.
_sort_key
=
key
if
not
self
.
auto_sort
and
self
.
_enable_tree
and
self
.
process_tree
is
not
None
:
self
.
process_tree
.
set_sorting
(
key
,
key
!=
"name"
)
def
getsortlist
(
self
,
sortedby
=
None
):
"""Get the sorted processlist."""
if
sortedby
is
None
:
# No need to sort...
return
self
.
processlist
sortedreverse
=
True
if
sortedby
==
'name'
:
sortedreverse
=
False
if
sortedby
==
'io_counters'
:
# Specific case for io_counters
# Sum of io_r + io_w
try
:
# Sort process by IO rate (sum IO read + IO write)
self
.
processlist
.
sort
(
key
=
lambda
process
:
process
[
sortedby
][
0
]
-
process
[
sortedby
][
2
]
+
process
[
sortedby
][
1
]
-
process
[
sortedby
][
3
],
reverse
=
sortedreverse
)
except
Exception
:
self
.
processlist
.
sort
(
key
=
operator
.
itemgetter
(
'cpu_percent'
),
reverse
=
sortedreverse
)
else
:
# Others sorts
self
.
processlist
.
sort
(
key
=
operator
.
itemgetter
(
sortedby
),
reverse
=
sortedreverse
)
return
self
.
processlist
glances_processes
=
GlancesProcesses
()
glances/outputs/glances_curses.py
浏览文件 @
4f2e051b
...
...
@@ -328,7 +328,11 @@ class _GlancesCurses(object):
# 'T' > View network traffic as sum Rx+Tx
self
.
args
.
network_sum
=
not
self
.
args
.
network_sum
elif
self
.
pressedkey
==
ord
(
'u'
):
# 'u' > View cumulative network IO (instead of bitrate)
# 'u' > Sort processes by USER
glances_processes
.
auto_sort
=
False
glances_processes
.
sort_key
=
'username'
elif
self
.
pressedkey
==
ord
(
'U'
):
# 'U' > View cumulative network I/O (instead of bitrate)
self
.
args
.
network_cumul
=
not
self
.
args
.
network_cumul
elif
self
.
pressedkey
==
ord
(
'w'
):
# 'w' > Delete finished warning logs
...
...
glances/plugins/glances_help.py
浏览文件 @
4f2e051b
...
...
@@ -89,44 +89,49 @@ class Plugin(GlancesPlugin):
msg
=
msg_col2
.
format
(
"w"
,
_
(
"Delete warning alerts"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"
p"
,
_
(
"Sort processes by name
"
))
msg
=
msg_col
.
format
(
"
u"
,
_
(
"Sort processes by USER
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"x"
,
_
(
"Delete warning and critical alerts"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"
i"
,
_
(
"Sort processes by I/O rat
e"
))
msg
=
msg_col
.
format
(
"
p"
,
_
(
"Sort processes by nam
e"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"1"
,
_
(
"Global CPU or per-CPU stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"
t"
,
_
(
"Sort processes by CPU times
"
))
msg
=
msg_col
.
format
(
"
i"
,
_
(
"Sort processes by I/O rate
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"
h"
,
_
(
"Show/hide this help screen
"
))
msg
=
msg_col2
.
format
(
"
D"
,
_
(
"Enable/disable Docker stats
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"
d"
,
_
(
"Show/hide disk I/O stats
"
))
msg
=
msg_col
.
format
(
"
t"
,
_
(
"Sort processes by TIME
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"T"
,
_
(
"View network I/O as combination"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"d"
,
_
(
"Show/hide disk I/O stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"U"
,
_
(
"View cumulative network I/O"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"f"
,
_
(
"Show/hide filesystem stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"
u"
,
_
(
"View cumulative network I/O
"
))
msg
=
msg_col2
.
format
(
"
F"
,
_
(
"Show filesystem free space
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"n"
,
_
(
"Show/hide network stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"
F"
,
_
(
"Show filesystem free space
"
))
msg
=
msg_col2
.
format
(
"
g"
,
_
(
"Generate graphs for current history
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"s"
,
_
(
"Show/hide sensors stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"
g"
,
_
(
"Generate graphs for curren
t history"
))
msg
=
msg_col2
.
format
(
"
r"
,
_
(
"Rese
t history"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"2"
,
_
(
"Show/hide left sidebar"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
msg_col2
.
format
(
"
r"
,
_
(
"Reset history
"
))
msg
=
msg_col2
.
format
(
"
h"
,
_
(
"Show/hide this help screen
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"z"
,
_
(
"Enable/disable processes stats"
))
...
...
@@ -134,19 +139,15 @@ class Plugin(GlancesPlugin):
msg
=
msg_col2
.
format
(
"q"
,
_
(
"Quit (Esc and Ctrl-C also work)"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"e"
,
_
(
"Enable/disable top extended stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"/"
,
_
(
"Enable/disable short processes name"
))
msg
=
msg_col
.
format
(
"3"
,
_
(
"Enable/disable quick look plugin"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"
D"
,
_
(
"Enable/disable Docker
stats"
))
msg
=
msg_col
.
format
(
"
e"
,
_
(
"Enable/disable top extended
stats"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
msg
=
msg_col
.
format
(
"
3"
,
_
(
"Enable/disable Quicklook plugin
"
))
msg
=
msg_col
.
format
(
"
/"
,
_
(
"Enable/disable short processes name
"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
ret
.
append
(
self
.
curse_new_line
())
msg
=
'{0}: {1}'
.
format
(
"ENTER"
,
_
(
"Edit the process filter pattern"
))
...
...
glances/plugins/glances_processlist.py
浏览文件 @
4f2e051b
...
...
@@ -379,7 +379,7 @@ class Plugin(GlancesPlugin):
msg
=
'{0:>6}'
.
format
(
_
(
"PID"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
' {0:10}'
.
format
(
_
(
"USER"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_add_line
(
msg
,
sort_style
if
process_sort_key
==
'username'
else
'DEFAULT'
))
msg
=
'{0:>4}'
.
format
(
_
(
"NI"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
msg
=
'{0:>2}'
.
format
(
_
(
"S"
))
...
...
@@ -397,14 +397,13 @@ class Plugin(GlancesPlugin):
self
.
tag_proc_time
=
True
if
glances_processes
.
is_tree_enabled
():
ret
.
extend
(
self
.
get_process_tree_curses_data
(
self
.
sortstats
(
process_sort_key
),
args
,
first_level
=
True
,
max_node_count
=
glances_processes
.
max_processes
))
ret
.
extend
(
self
.
get_process_tree_curses_data
(
self
.
sort_stats
(
process_sort_key
),
args
,
first_level
=
True
,
max_node_count
=
glances_processes
.
max_processes
))
else
:
# Loop over processes (sorted by the sort key previously compute)
first
=
True
for
p
in
self
.
sortstats
(
process_sort_key
):
for
p
in
self
.
sort
_
stats
(
process_sort_key
):
ret
.
extend
(
self
.
get_process_curses_data
(
p
,
first
,
args
))
# End of extended stats
first
=
False
...
...
@@ -412,16 +411,12 @@ class Plugin(GlancesPlugin):
# Return the message with decoration
return
ret
def
sortstats
(
self
,
sortedby
=
None
):
def
sort
_
stats
(
self
,
sortedby
=
None
):
"""Return the stats sorted by sortedby variable."""
if
sortedby
is
None
:
# No need to sort...
return
self
.
stats
sortedreverse
=
True
if
sortedby
==
'name'
:
sortedreverse
=
False
tree
=
glances_processes
.
is_tree_enabled
()
if
sortedby
==
'io_counters'
and
not
tree
:
...
...
@@ -432,18 +427,18 @@ class Plugin(GlancesPlugin):
self
.
stats
.
sort
(
key
=
lambda
process
:
process
[
sortedby
][
0
]
-
process
[
sortedby
][
2
]
+
process
[
sortedby
][
1
]
-
process
[
sortedby
][
3
],
reverse
=
sorted
reverse
)
reverse
=
glances_processes
.
sort_
reverse
)
except
Exception
:
self
.
stats
.
sort
(
key
=
operator
.
itemgetter
(
'cpu_percent'
),
reverse
=
sorted
reverse
)
reverse
=
glances_processes
.
sort_
reverse
)
else
:
# Others sorts
if
tree
:
self
.
stats
.
set_sorting
(
sortedby
,
sorted
reverse
)
self
.
stats
.
set_sorting
(
sortedby
,
glances_processes
.
sort_
reverse
)
else
:
try
:
self
.
stats
.
sort
(
key
=
operator
.
itemgetter
(
sortedby
),
reverse
=
sorted
reverse
)
reverse
=
glances_processes
.
sort_
reverse
)
except
(
KeyError
,
TypeError
):
self
.
stats
.
sort
(
key
=
operator
.
itemgetter
(
'name'
),
reverse
=
False
)
...
...
man/glances.1
浏览文件 @
4f2e051b
...
...
@@ -205,6 +205,9 @@ Sort process by CPU times (TIME+)
View network I/O as combination
.TP
.B u
Sort processes by USER
.TP
.B U
View cumulative network I/O
.TP
.B w
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录