前提:
以前能力不足,只能用linux命令行形式写了个线上发布工具。采用的是paramiko来调用远程指令。
最近自学了点前端的东西,打算用django写一个web版的发布工具,在做正常异步远程操作时候发现都没有什么问题。
但是当调用我们游戏的可执行文件启动时候,问题出现了:远程执行启动指令以后,无法退出。
正常情况:
可是我们游戏的情况就是这样,有点类似于socket接口一样在等待着输入,但实际上return已经返回了。
当时问题点:
1、尝试用& nohup都无法解决问题。
2、使用>/dev/null将输出全部丢弃掉,能够退出远程连接。
3、但是我需要查看输出来确定操作结果是否正常,于是考虑到用>/tmp/XXX & cat /tmp/XXX的形式解决。这种方法是可以解决我的需求的。但是我们游戏代码结构比较复杂,又分多国家多地区多版本发布。所有地区、所有进程要各地区的开发都做这类修改的话需要一定的时间。这个方案当做备选方案。
4、直接登录到服务器上,执行admin.sh start all又能完美退出。
正式搭建中问题点:
第一种方式:
import paramikossh = paramiko.SSHClient()# 执行命令stdin, stdout, stderr = ssh.exec_command(self.echo_cmd)# 获取命令结果res = stdout.read().decode()# 获取返回状态EXIT = stdout.channel.recv_exit_status()
最开始我使用stdin,stout,stdeer形式执行指令,但是发现与shell操作类似,无法退出远程操作,一直在等待中,即使使用了return,exit等也无法退出。
第二种方式:
self.chan =self.ssh.get_transport().open_session()self.chan.exec_command(self.echo_cmd)#查看返回状态self.EXIT = self.chan.recv_exit_status()#查看返回结果self.res = self.chan.recv(10000)
然后我改用了get_transport().open_session()打开一个会话的形式。发现能完美执行完指令后退出远程连接。这时候我还高兴了一会儿,但是随后我做异常处理检查时发现问题来了。
例如:我执行一个错误指令,用第一种方式能正常获取到错误返回提示:文件或目录不存在。
而采用第二种get_transport().open_session()会话的方式,能够看到exit返回值不是0的状态,但是res里面确实没有任何内容的。
如上测试,LS指令是不存在的,我后面查看return返回值提示不为0,但是执行结果却没有将"LS指令不存在"这个提示抓取到。
这就陷入到一个死循环了,我这游戏只有开启终端的形式才能正常执行相关admin.sh指令并退出,用类似ssh "ls" 这种远程指令形式是无法退出的。
在这里解决了查找文档搞了2个小时,最后无意间发现
stdin, stdout, stderr = ssh.exec_command(self.echo_cmd, get_pty=True)
##get_pty=True 加一个虚拟tty,问题得到解决。
后续:
我后来查了下aget_pty=True,很多人说有些场景不能用这个参数,可能会出现一些问题,我暂时还没遇到问题点,这里备注下。