完整的代码已经在github开源:github.com/CTC-maxiao/…
设计Task执行器
Task执行器是根据输入的执行字典,来完成执行相应的Task的程序,这也是我们程序的核心部分。我们设计TaskExecutor类来做Task执行器:
class TaskExecutor:
def __init__(self): #类的初始化函数
pass
def run_task(self,task_dict): #根据指定执行task的host和action类型来分配任务
if task_dict["task_host"] == "localhost":
ssh=""
else:
ssh = self.get_ssh_session(task_dict)
if task_dict["action_type"] == "shell": #shell类型任务是指运行linux命令及程序相关的任务
self.run_shell_task(ssh,task_dict)
elif task_dict["action_type"] == "slack": #slack类型任务是用来和聊天工具slack进行交互的任务
self.run_slack_task(ssh,task_dict)
else: #可以灵活的扩展任务类型,只需要将写好的任务处理函数加进来
return False
def get_ssh_session(self,task_dict): #获取ssh的session,用来执行需要在远程主机执行的任务
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=task_dict["task_host"],
port=task_dict["ssh_port"],
username=task_dict["ssh_user"],
password=task_dict["ssh_pwd"])
return ssh
def run_shell_task(self,ssh,task_dict):
command = task_dict["action"]
if task_dict["become"] == "yes": #这里用管道实现用户切换,算是一种投机取巧的方式
command = "echo "+task_dict["become_pwd"]+" |sudo -S su - "+task_dict["become_user"]+" -c '"+command+"'"
if ssh == "":
stdin, stdout, stderr = os.popen(command)
else:
stdin, stdout, stderr = ssh.exec_command(command)
ssh.close()
return stdin, stdout, stderr
def run_slack_task(self,ssh,action): #和slack交互的任务处理函数,还没写好,后续会完善
pass
复制代码
程序使用paramiko来ssh到远程机器,通过管道来实现切换用户执行任务,和ansible实现方式不同。在ansible下切换用户必须提供要切换用户的密码,比如要切换到root用户就需要提供root的密码,这是很不实用的。在现实环境中我想大部分用户都没有root用户的密码。通过管道来实现用户切换只需要提供当前用户的密码,能够很好的绕开linux服务器的安全限制。
在使用这种切换方式之前我尝试了使用pexpect,但切换后无法返回新的ssh session。如果谁有更好的做法,请务必告诉我。谢谢!