本文转载自微信公众号“AirPython”,作者邢安国。转载本文请联系AirPython公众号.1.前言对于大部分人来说,解决bug就是靠关键词log来定位问题!在调试的情况下,我们可以在控制台实时查看日志;但是对于部署在服务器上的应用来说,日志是存放在服务器的某个目录下的,如果这种情况无法在本地查看,我们需要先登录服务器,然后进入日志目录文件夹,最后定位问题通过日志文件;如果涉及到K8s容器,我们可能还需要使用kubectl命令进入服务对应的容器,进入日志目录开始定位问题。这一切都非常繁琐且效率低下。本文介绍一个Python依赖库:pexpect,作为一个命令行自动化工具,它可以帮助我们一键获取日志,快速定位问题!2.pexpect简介Pexpect是用Python语言实现的Expect类的一个实现。它生成子应用程序并对其进行控制,并通过预期的方式响应子应用程序的输出。处理项目地址:https://github.com/pexpect/pexpect/tree/5eed1a31a2853a09b7367c59fbd1a4a0b53341df主要模拟人机对话,实现一些自动化场景如:用于与SSH、FTP、PASSWD、Telnet等命令行程序通信在使用它进行自动化交互之前,我们先安装依赖包#安装依赖库pip3installpexpect3。实践中我们以从服务器K8S容器获取日志为例进行说明3-1SSH登录首先使用pexpect模拟SSH远程登录服务器importpexpectPROMPT=['#','>>>','>','\$']deflogin_with_pexpect():"""login-pexpect:return:"""#portnumberport=**#usernameuser=**#Passwordpwd=**#ipaddressip=**ssh_cmd="ssh-p{}{}@{}".format(port,user,ip)#指定登录命令,获取程序运行句柄child=pexpect.spawn(ssh_cmd,timeout=60,encoding='utf-8')#出现提示输入密码的字符,否则超时ret=child.expect([pexpect.TIMEOUT,'[P|p]assword:'],timeout=10)#匹配成功后,输入密码,执行登录操作ifret==1:#发送密码child.sendline(pwd)child.expect(PROMPT)returnchildelse:print('loginfailed!')其中pexpect.spawn():用于执行一个程序,返回一个操作句柄该方法的三个常用参数如下:第一个参数是命令被执行,第二个参数指定超时时间,程序执行后的输出校验,如果在指定时间内没有匹配到结果,则抛出异常第三个参数用于设置编码格式child.expect():对于输出结果,使用正则表达式进行关键字匹配代码中的意思是等待关键字'[P|p]assword:'在10s内出现。最后,如果匹配结果为1,则使用sendline()方法发送一个带回车的字符串,模拟输入密码。完成登录操作3-2封装发送命令接下来我们封装一次操作句柄的发送命令,得到返回结果defsend_command(child,cmd,expected_content=None,timeout=10):"""发送命令并打印出来Result:paramexpected_content::paramchild::paramcmd::return:"""#Sendacommandifexpected_contentisNone:expected_content=["#"]child.sendline(cmd)#期望命令提示字符出现child.expect(expected_content,timeout=timeout)#输出之前的内容result=child.beforereturnresult需要指出的是,child.before是用来获取缓存中所有已有的数据,直到匹配到关键字为止3-3进入容器pod日志目录并使用上面通过kubectl进入对应的容器日志目录#登录pod容器exec_enter_pod='kubectl-n%sexec-it%sbash'%(env,pod_name)#进入容器send_command(child,exec_enter_pod)#进入日志目录send_command(child,"cdlogs",expected_content='tomcat/logs#')3-4获取日志内容最后我们只需要编写获取日志的命令例如:使用grep/tail命令组成一个Extract日志文件的命令,然后使用handle对象发送这个命令,最后只需清理返回的内容即可实现,例如下载日志,实时配置,远程包下载等。
