应用场景
在一些系统开发中,需要远程到linux机器执行某个任务。我们的要求是:
- 实时获取执行日志
- 生命周期一致,意思是,后端服务如果挂了,linux任务也得自动挂掉,防止僵尸进程
- 如何判断任务的状态,因为实时收集日志,因此可以在linux放一个封装好的执行脚本,
脚本做好异常捕捉,这样后端可通过关键字匹配任务是否失败,除了失败就是成功。且后端采集日志的
代码是while True 的样式,不断尝试获取一定字节的日志。 当未跳出while True期间任务状态就是running
代码
import io
import json
import traceback
import paramiko
class LinuxCMDClient(object):
def __init__(self, ip, port, username, password):
self.ssh = paramiko.SSHClient()
self.establish = False
self.ip = ip
self.port = port
self.username = username
self.password = password
self.sftp = None
# ssh建立和linux的连接
def connect(self, timeout=15):
# 创建SSHClient实例对象
try:
print("[ETL] [LinuxCMDClient] Attempt to establish a connection.")
# 调用方法,标识没有远程机器的公钥,允许访问
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接远程机器 地址端口用户名密码
self.ssh.connect(self.ip, self.port, self.username, self.password, timeout=timeout)
self.establish = True
except Exception as e:
print("[LinuxCMDClient] {ip=%s,port=%s,user=%s,password=%s}, error=%s" %(self.ip,
self.port,
self.username,
self.password,
traceback.format_exc())
)
if self.ssh:
self.ssh.close()
# 执行linux命令
def exec_cmd(self, cmds,path):
print("[ETL] [LinuxCMDClient] exec cmd=%s" % cmds)
if self.establish is False:
self.connect()
stdin, stdout, stderr = self.ssh.exec_command(cmds, get_pty=True)
with open(path, "a+", encoding="utf-8") as f:
while True:
msg = stdout.channel.recv(1024).decode()
if msg is "":
f.write("执行结束")
break
else:
f.write(msg.replace("\n", ""))
# __del__ 魔法函数用于对象销毁之后的资源回收,此处十分有效,不需要手动调用,此函数是自发行为
def __del__(self):
if self.ssh:
self.ssh.close()