之所以有这个需求是因为我们想把一些操作自动化,方便平时的运维管理。比如,我的linux上有很多docker容器,我想批量的重启这些容器,或者需要获取机器的状态信息等等。
Python提供了paramiko这个库通过ssh连接linux,发送命令,返回结果,下面总结一下具体的用法。
- 首先安装,pip install paramiko。
- windows安装的时候可能会出现一个错误。error: Microsoft Visual C++ 14.0 or greater is required,解决方法可以参考这个链接。
- 接下来就通过代码看看你如何使用吧。
def ssh_connect(ip):
ssh = paramiko.SSHClient()
# 允许将信任的主机自动加入到host_allow 列表,此方法必须放在connect方法的前面
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(hostname=ip, port=22, username='root', password='123456', timeout=5)
ssh_transp = ssh.get_transport()
except Exception:
return None
return ssh_transp
connect方法的主要参数就是我们平时通过ssh工具连接linux的时候提供的一些参数,timeout的单位是秒,本例中如果5s以后还没有连接到主机,就报异常,如果成功的话,会返回一个ssh_transp对象,用来执行接下来的指令。
def exec_command(ssh_transp, command_str):
print(f'要执行的指令是:{command_str}')
# chanel执行完毕以后就会关闭,所以每次执行一个新的命令,必须新开启一个channel
chan = ssh_transp.open_session()
sleeptime = 0.001
outdata = ''
errdata = ''
chan.setblocking(0)
chan.exec_command(command_str)
# 某些指令的执行时间比较长,所以这里等待该指令返回结果。所以该函数属于阻塞式的函数,调用以后,必须等待结果返回。
while True:
while chan.recv_ready():
outdata += chan.recv(1000).decode('utf-8', errors='ignore')
while chan.recv_stderr_ready():
errdata += chan.recv_stderr(1000).decode()
if chan.exit_status_ready():
break
time.sleep(sleeptime)
# 获取命令执行返回的状态码
retcode = chan.recv_exit_status()
if outdata:
# 这里可以对正常的返回结果进行一些初步的处理
pass
if errdata or retcode != 0:
# 这里的这个错误,是我自己定义的一个错误类型,关于错误处理这块,大家可以自行决定。
raise SSHExcuteException()
return outdata
调用上边这个函数的时候,需要传入ssh_transp和要执行的指令。ssh每次执行完毕以后,都会把执行该指令的session关闭,所以每次都需要一个新的session。
containers = exec_command(ssh_transp, "docker ps | sed -n '2,$ p' | awk '{print $NF}'")
print(containers)
以上这条命令返回在我机器上运行的docker容器名称。
最后不要忘记关闭ssh_trans。
ssh_transp.close()
更多的技术教程以及讨论可以关注以下的公众号。