python3 网络设备基于paramiko模块ssh远程连接怎么执行多条命令
程序员文章站
2022-03-20 14:05:34
...
今天本来写个脚本方便删除离职人员的vpn账号(9台防火墙),写好后发现运行后没有生效
初步的代码
import paramiko
ip = [
(),
(),
(),
()
] #存在了9个设备的IP,端口,用户,密码信息
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for ip_addr,port,user,passw in ip:
try:
ssh.connect(hostname=ip_addr,port=port,username=user,password=passw,timeout=20)
except Exception as e:
print(ip_addr,e)
continue
stdin, stdout, stderr = ssh.exec_command('show') #这段是生效的
conf = stdout.read().decode('utf-8')
if 'yangshihu' in conf:
print(ip_addr)
ssh.exec_command('config user loacl') #没有生效
ssh.exec_command('delete username') #没有生效
else:
continue
ssh.close()
已解决的代码
import paramiko
ip = [
(),
(),
(),
()
] #存在了9个设备的IP,端口,用户,密码信息
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for ip_addr,port,user,passw in ip:
try:
ssh.connect(hostname=ip_addr,port=port,username=user,password=passw,timeout=20)
except Exception as e:
print(ip_addr,e)
continue
stdin, stdout, stderr = ssh.exec_command('show')
conf = stdout.read().decode('utf-8')
chan = ssh.invoke_shell()
if 'yangshihu' in conf:
print(ip_addr)
chan.send('config user group \n')
chan.send('edit SSLVPN-GROUP \n')
chan.send('unselect member HD-wangqingzhan \n')
chan.send('end \n')
time.sleep(5)
chan = ssh.invoke_shell()
chan.send('config user local \n')
chan.send('delete HD-wangqingzhan \n')
chan.send('end \n')
time.sleep(5)
else:
continue
ssh.close()
百度上找到文档说是paramiko命令执行结束后,默认就变回之前的状态,也就是刚进入的视图,我这边把没有生效的命令通过stdout输出打印后,果然印证这个事实
解决思路:
1、怎么才能一次运行多条命令
后来发现这个是要基于系统本身支持的,linux系统默认是可以同时一次输出执行多个命令。cd /home;mkdir test,就是中间加分号就好了,但是网络设备,不支持,放弃
ssh.exec_command('cd /home;mkdir test')
2、pexpect模块,可以实现自动交互
需要借助ssh工具,如果系统是windows就不支持了,这个方案linux系统上可行的,但是也很不方便,因为进入任何视图是没有信息提示的,只有命令行发生了改变,那么就只能捕捉命令行进行交互才行了
child.expect('login:')#提示用户登录,输入帐号,交换机不同,有所不同。捕捉
child.sendline("admin") # 输入账户
child.expect('(?i)ssword:')#提示输入密码 捕捉
child.sendline("%s"%passwd) #输入密码
child.expect('<%s>'%name) #捕捉
child.sendline("display cpu-usage")#查看cpu状态
child.expect('<%s>'%name) #捕捉
child.sendline("display memory")#查看内存状态
child.expect('<%s>'%name) #捕捉
child.sendline("display environment")#运行温度
这段代码看就很多的重复语句捕捉交互,如果要进入到接口下,执行,捕捉信息又会发生改变,这样显得太麻烦还导致代码变多
3、paramiko模块,发现是有个功能能够实现的
channel = ssh.invoke_shell(); channel.send(cmd"\n")
调用一个单独的shell,也就是单独运行一个子进程来执行,还有个问题就是主进程运行到子进程的时候是不会等待子进程运行完后才继续执行下面的操作,所以一般还要借助time.sleep(5)来等待子进程运行好,时间根据情况自己定义
chan = ssh.invoke_shell() #定义ssh调用子进程
if 'yangshihu' in conf:
print(ip_addr)
chan.send('config user group \n') #\n表示执行的意思
chan.send('edit SSLVPN-GROUP \n')
chan.send('unselect member HD-wangqingzhan \n')
chan.send('end \n')
time.sleep(5)
chan = ssh.invoke_shell() #再次调用子进程
chan.send('config user local \n')
chan.send('delete HD-wangqingzhan \n')
chan.send('end \n')
time.sleep(5)
测试发现我只要命令退出到初始状态后,下面再运行的命令都是失效的,说明子进程肯定是结束了,下面再次运行还需要再调用才行(谁明白这个是什么原因,我是没有整明白o(╥﹏╥)o)
代码本身还有很多需要优化的部分,目前只是简单能实现功能