发现问题
几天前做基于tornado的web系统的时候,启动系统后发现无法访问,而且监听特定端口只能同时开启一个进程的web程序居然能开启无限多个,使用netstat -ano |grep 端口号
发现web程序根本没有占用端口,说明程序根本没有启动成功,在程序中打断点也没有反应,最后发现程序在import一个文件后就直接挂起了。
这个文件定义了几个控制器类,其开始部分有这样几行代码
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
client.connect(srv['hostname'], srv['port'], srv['username'], srv['password'])
clients.append(client)
经过调试,在执行client.connect()
之后进程就挂起了,下面的代码都无法执行,整个系统就在这里停住了。
寻找答案
首先我百度了很久,结果没有找到什么有用的解释,最后用Google搜到了相关问题(Google大法好!),而且
github上还有专门对此问题开的一个issue,Thread/import related hang issues #104,其中有一个人解释:当paramiko成功读取远程ssh标题并尝试str.decode(’utf-8’),它隐式地从编码模块导入utf-8解码器时,发生导入死锁。
他给出的解决方法是提前调用一次str.decode('utf-8')
,防止由于模块导入副作用导致的特定导入,但这个方法我试了之后没有起作用,作者的观点是不推荐在模块中执行模块级别的ssh连接,因为导入产生线程的模块本身就不安全。
看来只能把ssh代码封装到一个类里了,这个问题感觉算不上解决,以后要继续关注,看看有没有什么更优的解决方案。