# 读取服务器日志,并打印 if __name__ == '__main__': # with SSHTunnelForwarder( # ('120.25.*.*', 22), #跳板机IP,端口 # ssh_username="root", #跳板机用户名 # ssh_password="i8khGtwa7sQra5hXXXXX", #跳板机密码 # # ssh_pkey="./rsa", #ssh 连接使用密钥证书登录,该参数必须;该路径为目标服务器的公钥证书 # # ssh_private_key_password="i8khGtwa7sXXXX", #如果公钥证书有密码,该参数必须,如果没有密码,该参数注释掉 # remote_bind_address=('10.20.XXX', 22), #远程服务器地址、端口 # local_bind_address=('127.0.0.1', 10022) #本机固定127 # ) as tunnel: #以上跳板机代码注销后,下面是直接访问服务器代码 client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect('10.206.28.139', 22, username='haitian', password='Sf123456!@#', timeout=30) # do some operations with client session remote_command = "tail -fn 50 /app/deploy/nwms-base/logs/error.log " stdin, stdout, stderr = client.exec_command(remote_command) last_line = stdout.read() # 此处程序会死锁 a = last_line.decode('utf - 8') print(a) client.close() 死锁:(引用 https://blog.csdn.net/weixin_39629617/article/details/110773119)
如果设置了stdout或stderr,subprocess就会调用os.pipe创建一个管道用于其和子进程之间的通信,而上面的问题正好是cmd输出的数据把pipe塞满,无法继续往pipe里写入数据导致程序hang住,而我们没有去读出pipe数据,而是死等子进程完成,导致死锁。
具体大小的话windows只有4kb,而linux有64kb(辣鸡windows)
那么如何解决呢
解决办法一:
使用communicate及时读出pipe中内容,避免堵死,但在输出量非常大的情况下会影响性能:
这也是官方文档里推荐的做法,但是不能乱用,因为会影响性能.
解决办法二:
使用文件代替PIPE,但是这样子的话传给客户端的就只能是文件了。
fdout = open(len(procs)+".out", 'w')
fderr = open(len(procs)+".err", 'w')
总结:
两种方法需要自己根据情况进行取舍,都有各自的优势和劣势。