1.前言对于大部分人来说,解决bug就是靠关键词log来定位问题!在调试的情况下,我们可以在控制台实时查看日志;但是对于部署在服务器上的应用,日志是存放在服务器的某个目录下的,我们无法在本地查看,需要先登录服务器,然后进入日志目录文件夹,最后定位到通过日志文件出现问题;如果涉及到K8s容器,可能还需要使用kubectl命令进入服务对应的容器,进入日志目录,开始定位问题。非常繁琐和低效本文介绍一个Python依赖库:pexpect,作为一个命令行自动化工具,可以帮助我们一键获取日志,快速定位问题!2.pexpect简介Pexpect是用Python语言实现的类Expect的一个实现。它生成子应用程序并对其进行控制,并通过期望模式对子应用程序的输出进行相应的处理。主要模拟人机对话,实现一些自动化的场景,比如:用于与SSH、FTP、PASSWD、Telnet等命令行程序进行自动化交互。在使用之前,我们先安装依赖包#Installthedependency库pip3安装pexpect3。下面在实践中从服务器K8S容器获取日志举例说明3-1SSH登录首先使用pexpect模拟SSH远程登录服务器importpexpectPROMPT=['#','>>>','>','\$']deflogin_with_pexpect():"""Login-pexpect:return:"""#端口号port=**#用户名user=**#密码pwd=**#ip地址ip=**ssh_cmd="ssh-p{}{}@{}".format(port,user,ip)#指定登录命令,获取程序运行句柄child=pexpect.spawn(ssh_cmd,timeout=60,encoding='utf-8')#出现提示输入密码字符,否则超时re??t=child.expect([pexpect.TIMEOUT,'[P|p]assword:'],timeout=10)#匹配成功后,输入密码,执行登录操作ifret==1:#发送密码child.sendline(pwd)child.expect(PROMPT)returnchildelse:print('loginfailed!')其中pexpect.spawn():用于执行一个程序,返回一个操作句柄该方法的三个常用参数为如下:第一个参数是要执行的命令。第二个参数指定超时时间。程序执行后的输出检查。如果在指定时间内没有找到匹配的结果,将抛出异常。第三个参数用于设置编码格式child.expect():输出结果,使用正则表达式的关键字匹配代码的意思是在10s内等待关键字'[P|p]assword:'。最后如果匹配结果为1,则使用sendline()方法发送回车3-2封装发送命令接下来,我们将操作句柄的发送命令封装一次,得到返回结果defsend_command(child,cmd,expected_content=None,timeout=10):"""发送命令并打印结果:paramexpected_content::paramchild::paramcmd::return:"""#如果expected_content为None则发送命令:expected_content=["#"]child.sendline(cmd)#期望出现命令行提示符child.expect(expected_content,timeout=timeout)#输出之前的所有内容result=child.beforereturnresult需要指出的是child.before用于获取缓存中的所有现有数据,直到匹配到关键字。3-3进入容器pod日志目录使用上述方法通过kubectl进入对应的容器日志目录#Loginpodcontainerexec_enter_pod='kubectl-n%sexec-it%sbash'%(env,pod_name)#enterthecontainersend_command(child,exec_enter_pod)#进入日志目录send_command(child,"cdlogs",expected_content='tomcat/logs#')3-4获取日志内容最后我们只需要编写获取日志的命令.例如:使用grep/tail命令编写一条提取日志文件的命令,然后使用handle对象发送这条命令。最后,清理返回的内容。4.上篇文章使用pexpect实现其实大部分的人机对话自动化交互都可以通过它来实现,比如下载日志,实时配置,远程包下载等,最近上百G整理了Python学习资料,包括初学者电子书、教程、源码等,免费分享给大家!想上“Python编程学习圈”,发“J”免费领取
