gevent backdoor 实践

gevent 提供了一个后门server,可以用来debug正在运行的进程,官方文档是这样描述的

The BackdoorServer provides a REPL inside a running process. As long as the process is monkey-patched, the BackdoorServer can coexist with other elements of the process.

下面这个例子是从stackoverflow上看到的,这里自己实践一下

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
import json
from gevent import pywsgi
from gevent import monkey
from gevent import event
from gevent.backdoor import BackdoorServer
import time

monkey.patch_all()

a = "foo"

def build_response(response):
return json.dumps(response)


def start_process(environ, start_response):
'''
{"content": {"code": 0, "req_id": "20160420154445000"}, "res": "ok", "err_code": 0}
'''
risk_id = 0
response = dict()
response = {
'err_code': 0,
'res': 'ok',
'content': dict()
}
status = '200 OK'
response_headers = [('Content-type', 'text/html'), ('Connection', 'close')]
start_response(status, response_headers)
return build_response(response)


def main():
stop_event = event.Event()
servers = [BackdoorServer(('127.0.0.1', 5001),
banner="Hello from gevent backdoor!",
locals={'foo': "From defined scope!"}), pywsgi.WSGIServer(('127.0.0.1', 5002),
start_process, ), ]
for server in servers:
if not server.started:
server.start()
stop_event.wait()
for server in servers:
if server.started:
server.stop()


if __name__ == '__main__':
main()

将这个python文件run起来,然后执行telnet 127.0.0.1 5001就可以链接到上面的进程中去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#  telnet 127.0.0.1 5001
>>> import greenlet, inspect
# 获取当前协程
>>> greenlet.getcurrent()
<_Greenlet_stdreplace at 0x10bd40448: _handle_and_close_when_done(<bound method BackdoorServer.handle of <BackdoorSe, <bound method StreamServer.do_close of <BackdoorSe, (<gevent._socket3.socket object, fd=8, family=2, t)>
# 获取当前协程的父协程,看到是hub,这其实是gevent的调度协程
>>> greenlet.getcurrent().parent
<Hub '' at 0x10bcdd6d8 select default pending=0 ref=2 resolver=<gevent.resolver_thread.Resolver at 0x10bd167f0 pool=<ThreadPool at 0x10bd169b0 0/1/10 hub=<Hub at 0x10bcdd6d8 thread_ident=0x140736039191424>>> threadpool=<ThreadPool at 0x10bd169b0 0/1/10 hub=<Hub at 0x10bcdd6d8 thread_ident=0x140736039191424>> thread_ident=0x7fffa99f8380>
# 再网上走一层,这里就到了我们运行main的协程
>>> inspect.getouterframes(greenlet.getcurrent().parent.parent.gr_frame)
[FrameInfo(frame=<frame object at 0x7faecf476e48>, filename='xxxxxxxxxx', lineno=100, function='main', code_context=[' stop_event.wait()\n'], index=0), FrameInfo(frame=<frame object at 0x7faecf41ea78>, filename='xxxxxxxxxxx', lineno=107, function='<module>', code_context=[' main()\n'], index=0)]
>>> inspect.getouterframes(greenlet.getcurrent().parent.parent.gr_frame)[1][0]
<frame object at 0x7faecf41ea78>
# 通过inspect可以获取变量a的值,这样就可以debug当前的进程了
>>> inspect.getargvalues(inspect.getouterframes(greenlet.getcurrent().parent.parent.gr_frame)[1][0]).locals['a']
'foo'

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×