Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
蜕变的菜鸟
glances
提交
83026909
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,体验更适合开发者的 AI 搜索 >>
提交
83026909
编写于
8月 15, 2014
作者:
N
Nicolargo
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add the process filter feature
上级
37edbfc5
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
158 addition
and
23 deletion
+158
-23
glances/core/glances_main.py
glances/core/glances_main.py
+3
-1
glances/core/glances_processes.py
glances/core/glances_processes.py
+47
-3
glances/core/glances_standalone.py
glances/core/glances_standalone.py
+4
-0
glances/outputs/glances_curses.py
glances/outputs/glances_curses.py
+88
-16
glances/plugins/glances_help.py
glances/plugins/glances_help.py
+6
-0
glances/plugins/glances_processcount.py
glances/plugins/glances_processcount.py
+10
-3
未找到文件。
glances/core/glances_main.py
浏览文件 @
83026909
...
...
@@ -111,6 +111,8 @@ class GlancesMain(object):
parser
.
add_argument
(
'-w'
,
'--webserver'
,
action
=
'store_true'
,
default
=
False
,
dest
=
'webserver'
,
help
=
_
(
'run Glances in web server mode'
))
# Display (Curses) options
parser
.
add_argument
(
'-f'
,
'--process-filter'
,
default
=
None
,
type
=
str
,
dest
=
'process_filter'
,
help
=
_
(
'set the process filter patern (regular expression)'
))
parser
.
add_argument
(
'-b'
,
'--byte'
,
action
=
'store_true'
,
default
=
False
,
dest
=
'byte'
,
help
=
_
(
'display network rate in byte per second'
))
parser
.
add_argument
(
'-1'
,
'--percpu'
,
action
=
'store_true'
,
default
=
False
,
...
...
@@ -141,7 +143,7 @@ class GlancesMain(object):
# In web server mode, defaul refresh time: 5 sec
if
args
.
webserver
:
args
.
time
=
5
args
.
time
=
5
# Server or client login/password
args
.
username
=
self
.
username
...
...
glances/core/glances_processes.py
浏览文件 @
83026909
...
...
@@ -17,10 +17,13 @@
# 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/>.
# Import Glances lib
from
glances.core.glances_globals
import
is_linux
,
is_bsd
,
is_mac
,
is_windows
,
logger
from
glances.core.glances_timer
import
Timer
,
getTimeSinceLastUpdate
# Import Python lib
import
psutil
import
re
class
GlancesProcesses
(
object
):
...
...
@@ -59,6 +62,13 @@ class GlancesProcesses(object):
# None if no limit
self
.
max_processes
=
None
# Process filter is a regular expression
self
.
process_filter
=
None
self
.
process_filter_re
=
None
# !!! ONLY FOR TEST
# self.set_process_filter('.*python.*')
def
enable
(
self
):
"""Enable process stats."""
self
.
disable_tag
=
False
...
...
@@ -86,6 +96,37 @@ class GlancesProcesses(object):
"""Get the maximum number of processes showed in the UI interfaces"""
return
self
.
max_processes
def
set_process_filter
(
self
,
value
):
"""Set the process filter"""
logger
.
info
(
_
(
"Set process filter to %s"
)
%
value
)
self
.
process_filter
=
value
if
value
is
not
None
:
try
:
self
.
process_filter_re
=
re
.
compile
(
value
)
logger
.
debug
(
_
(
"Process filter regular expression compilation OK: %s"
)
%
self
.
get_process_filter
())
except
:
logger
.
error
(
_
(
"Can not compile process filter regular expression: %s"
)
%
value
)
self
.
process_filter_re
=
None
else
:
self
.
process_filter_re
=
None
return
self
.
process_filter
def
get_process_filter
(
self
):
"""Get the process filter"""
return
self
.
process_filter
def
get_process_filter_re
(
self
):
"""Get the process regular expression compiled"""
return
self
.
process_filter_re
def
is_filtered
(
self
,
value
):
"""Return True if the value should be filtered"""
if
self
.
get_process_filter
()
is
None
:
# No filter => Not filtered
return
False
else
:
return
self
.
get_process_filter_re
().
match
(
value
)
is
None
def
__get_process_stats
(
self
,
proc
,
mandatory_stats
=
True
,
standard_stats
=
True
,
...
...
@@ -237,9 +278,12 @@ class GlancesProcesses(object):
for
proc
in
psutil
.
process_iter
():
# If self.get_max_processes() is None: Only retreive mandatory stats
# Else: retreive mandatoryadn standard stast
processdict
[
proc
]
=
self
.
__get_process_stats
(
proc
,
mandatory_stats
=
True
,
standard_stats
=
self
.
get_max_processes
()
is
None
)
s
=
self
.
__get_process_stats
(
proc
,
mandatory_stats
=
True
,
standard_stats
=
self
.
get_max_processes
()
is
None
)
if
self
.
is_filtered
(
s
[
'name'
]):
continue
processdict
[
proc
]
=
s
# ignore the 'idle' process on Windows and *BSD
# ignore the 'kernel_task' process on OS X
# waiting for upstream patch from psutil
...
...
glances/core/glances_standalone.py
浏览文件 @
83026909
...
...
@@ -51,6 +51,10 @@ class GlancesStandalone(object):
logger
.
debug
(
_
(
"Extended stats for top process is enabled (default behavor)"
))
glances_processes
.
enable_extended
()
# Manage optionnal process filter
if
args
.
process_filter
is
not
None
:
glances_processes
.
set_process_filter
(
args
.
process_filter
)
# Initial system informations update
self
.
stats
.
update
()
...
...
glances/outputs/glances_curses.py
浏览文件 @
83026909
...
...
@@ -31,6 +31,7 @@ if not is_windows:
try
:
import
curses
import
curses.panel
from
curses.textpad
import
Textbox
,
rectangle
except
ImportError
:
logger
.
critical
(
'Curses module not found. Glances cannot start in standalone mode.'
)
sys
.
exit
(
1
)
...
...
@@ -70,11 +71,7 @@ class GlancesCurses(object):
curses
.
noecho
()
if
hasattr
(
curses
,
'cbreak'
):
curses
.
cbreak
()
if
hasattr
(
curses
,
'curs_set'
):
try
:
curses
.
curs_set
(
0
)
except
Exception
:
pass
self
.
set_cursor
(
0
)
# Init colors
self
.
hascolors
=
False
...
...
@@ -136,6 +133,7 @@ class GlancesCurses(object):
'BOLD'
:
A_BOLD
,
'SORT'
:
A_BOLD
,
'OK'
:
self
.
default_color2
,
'FILTER'
:
self
.
ifCAREFUL_color2
,
'TITLE'
:
self
.
title_color
,
'PROCESS'
:
self
.
default_color2
,
'STATUS'
:
self
.
default_color2
,
...
...
@@ -158,6 +156,9 @@ class GlancesCurses(object):
# Init process sort method
self
.
args
.
process_sorted_by
=
'auto'
# Init edit filter tag
self
.
edit_filter
=
False
# Catch key pressed with non blocking mode
self
.
term_window
.
keypad
(
1
)
self
.
term_window
.
nodelay
(
1
)
...
...
@@ -174,6 +175,18 @@ class GlancesCurses(object):
args
.
enable_history
=
False
logger
.
error
(
'Stats history disabled because graph lib is not available'
)
def
set_cursor
(
self
,
value
):
"""Configure the cursor
0: invisible
1: visible
2: very visible
"""
if
hasattr
(
curses
,
'curs_set'
):
try
:
curses
.
curs_set
(
value
)
except
Exception
:
pass
def
__get_key
(
self
,
window
):
# Catch ESC key AND numlock key (issue #163)
keycode
=
[
0
,
0
]
...
...
@@ -197,6 +210,9 @@ class GlancesCurses(object):
self
.
end
()
logger
.
info
(
"Stop Glances"
)
sys
.
exit
(
0
)
elif
self
.
pressedkey
==
10
:
# 'ENTER' > Edit the process filter
self
.
edit_filter
=
not
self
.
edit_filter
elif
self
.
pressedkey
==
ord
(
'1'
):
# '1' > Switch between CPU and PerCPU information
self
.
args
.
percpu
=
not
self
.
args
.
percpu
...
...
@@ -463,19 +479,41 @@ class GlancesCurses(object):
self
.
history_tag
=
False
self
.
reset_history_tag
=
False
# Display edit filter popup
if
self
.
edit_filter
:
new_filter
=
self
.
display_popup
(
_
(
"Filter: "
),
is_input
=
True
,
input_value
=
glances_processes
.
get_process_filter
())
glances_processes
.
set_process_filter
(
new_filter
)
self
.
edit_filter
=
False
return
True
def
display_popup
(
self
,
message
,
size_x
=
None
,
size_y
=
None
,
duration
=
3
):
def
display_popup
(
self
,
message
,
size_x
=
None
,
size_y
=
None
,
duration
=
3
,
is_input
=
False
,
input_size
=
20
,
input_value
=
None
):
"""
Display a centered popup with the given message during duration seconds
If size_x and size_y: set the popup size
else set it automatically
Return True if the popup could be displayed
If is_input is False:
Display a centered popup with the given message during duration seconds
If size_x and size_y: set the popup size
else set it automatically
Return True if the popup could be displayed
If is_input is True:
Display a centered popup with the given message and a input field
If size_x and size_y: set the popup size
else set it automatically
Return the input string or None if the field is empty
"""
# Center the popup
if
size_x
is
None
:
size_x
=
len
(
message
)
+
4
# Add space for the input field
if
is_input
:
size_x
+=
input_size
if
size_y
is
None
:
size_y
=
message
.
count
(
'
\n
'
)
+
1
+
4
screen_x
=
self
.
screen
.
getmaxyx
()[
1
]
...
...
@@ -488,7 +526,7 @@ class GlancesCurses(object):
# Create the popup
popup
=
curses
.
newwin
(
size_y
,
size_x
,
pos_y
,
pos_x
)
# Fill the popup
popup
.
border
()
...
...
@@ -498,11 +536,32 @@ class GlancesCurses(object):
popup
.
addnstr
(
2
+
y
,
2
,
m
,
len
(
m
))
y
+=
1
# Display the popup
popup
.
refresh
()
curses
.
napms
(
duration
*
1000
)
return
True
if
is_input
:
# Create a subwindow for the text field
subpop
=
popup
.
derwin
(
1
,
input_size
,
2
,
2
+
len
(
m
))
subpop
.
attron
(
self
.
__colors_list
[
'FILTER'
])
# Init the field with the current value
if
input_value
is
not
None
:
subpop
.
addnstr
(
0
,
0
,
input_value
,
len
(
input_value
))
# Display the popup
popup
.
refresh
()
subpop
.
refresh
()
# Create the textbox inside the subwindows
self
.
set_cursor
(
2
)
textbox
=
glances_textbox
(
subpop
,
insert_mode
=
False
)
textbox
.
edit
()
self
.
set_cursor
(
0
)
if
textbox
.
gather
()
!=
''
:
logger
.
debug
(
_
(
"User enters the following process filter patern: %s"
)
%
textbox
.
gather
())
return
textbox
.
gather
()[:
-
1
]
else
:
logger
.
debug
(
_
(
"User clears the process filter patern"
))
return
None
else
:
# Display the popup
popup
.
refresh
()
curses
.
napms
(
duration
*
1000
)
return
True
def
display_plugin
(
self
,
plugin_stats
,
display_optional
=
True
,
...
...
@@ -648,3 +707,16 @@ class GlancesCurses(object):
return
0
else
:
return
c
+
1
class
glances_textbox
(
Textbox
):
"""
"""
def
__init__
(
*
args
,
**
kwargs
):
Textbox
.
__init__
(
*
args
,
**
kwargs
)
def
do_command
(
self
,
ch
):
if
ch
==
10
:
# Enter
return
0
if
ch
==
127
:
# Enter
return
8
return
Textbox
.
do_command
(
self
,
ch
)
\ No newline at end of file
glances/plugins/glances_help.py
浏览文件 @
83026909
...
...
@@ -129,5 +129,11 @@ 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
())
ret
.
append
(
self
.
curse_new_line
())
msg
=
'{0}: {1}'
.
format
(
"ENTER"
,
_
(
"Edit the process filter patern"
))
ret
.
append
(
self
.
curse_add_line
(
msg
))
# Return the message with decoration
return
ret
glances/plugins/glances_processcount.py
浏览文件 @
83026909
...
...
@@ -69,9 +69,6 @@ class Plugin(GlancesPlugin):
ret
=
[]
# Only process if stats exist and display plugin enable...
# if self.stats == {} or args.disable_process:
# return ret
if
args
.
disable_process
:
msg
=
_
(
"PROCESSES DISABLED (press 'z' to display)"
)
ret
.
append
(
self
.
curse_add_line
(
msg
))
...
...
@@ -80,6 +77,16 @@ class Plugin(GlancesPlugin):
if
self
.
stats
==
{}:
return
ret
# Display the filter (if it exists)
if
glances_processes
.
get_process_filter
()
is
not
None
:
msg
=
_
(
"Processes filter:"
)
ret
.
append
(
self
.
curse_add_line
(
msg
,
"TITLE"
))
msg
=
_
(
" {0} "
).
format
(
glances_processes
.
get_process_filter
())
ret
.
append
(
self
.
curse_add_line
(
msg
,
"FILTER"
))
msg
=
_
(
"(press ENTER to edit)"
)
ret
.
append
(
self
.
curse_add_line
(
msg
))
ret
.
append
(
self
.
curse_new_line
())
# Build the string message
# Header
msg
=
_
(
"TASKS "
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录