python之ssh超级详解

环境

操作系统及内核版本

[root@ceph01 ssh]# cat /etc/redhat-release 
CentOS Linux release 7.8.2003 (Core)

[root@ceph01 ssh]# uname -a
Linux ceph01 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

python版本

[root@ceph01 ssh]# python -V
Python 2.7.5

安装依赖

yum install python-dev python-devel 
pip install pycrypto paramiko ssh

ssh之command模块详解

堆命令实现远程执行命令

写命令

cat /python/ssh/remote.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

myclient=paramiko.SSHClient()
myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
myclient.connect('192.168.229.121',port=22,username='root',password='einem@2')
stdin,stdout,stderr=myclient.exec_command('ls')
print (stdout.read())

执行

python remote.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
anaconda-ks.cfg
calicoctl
test

定义函数实现远程执行命令

定义函数

cat /python/ssh/fun_remote.py
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

def shell(host,port,user,password,command):
   myclient=paramiko.SSHClient()
   #当从来没有连接过某个主机的时候,本地的/root/.ssh/known_hosts文件里没有这个主机的信息,如果不加这句代码,会报错
   myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
   myclient.connect(hostname=host,port=port,username=user,password=password)
   stdin,stdout,stderr=myclient.exec_command(command) 
   print stdout.read()
shell('192.168.229.121',22,'root','einemc@2','ls')

运行

python fun_remote.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
anaconda-ks.cfg
calicoctl

注意事项

fun_remote.py文件里的代码
myclient.connect(hostname=host,port=port,username=user,password=password)和stdin,stdout,stderr=myclient.exec_command(command)
里边的host,port,user和command不要加引号,否则会出错,报错分别如下。
password可以加引号。
host加引号报错

[root@ceph01 ssh]# python fun_remote.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
Traceback (most recent call last):
  File "fun_remote.py", line 14, in <module>
    shell('192.168.229.121',22,'root','einemc@2','ls')
  File "fun_remote.py", line 11, in shell
    myclient.connect(hostname='host',port=port,username=user,password=password)
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 340, in connect
    to_try = list(self._families_and_addresses(hostname, port))
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 204, in _families_and_addresses
    hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
socket.gaierror: [Errno -2] Name or service not known

port加引号报错

python fun_remote.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
Traceback (most recent call last):
  File "fun_remote.py", line 14, in <module>
    shell('192.168.229.121',22,'root','einemc@2','ls')
  File "fun_remote.py", line 11, in shell
    myclient.connect(hostname=host,port='port',username=user,password=password)
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 340, in connect
    to_try = list(self._families_and_addresses(hostname, port))
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 204, in _families_and_addresses
    hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
socket.gaierror: [Errno -8] Servname not supported for ai_socktype

user加引号报错

python fun_remote.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
Traceback (most recent call last):
  File "fun_remote.py", line 14, in <module>
    shell('192.168.229.121',22,'root','einemc@2','ls')
  File "fun_remote.py", line 11, in shell
    myclient.connect(hostname=host,port=port,username='user',password=password)
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 446, in connect
    passphrase,
  File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 764, in _auth
    raise saved_exception
paramiko.ssh_exception.AuthenticationException: Authentication failed.

return方法报错
print stdout.read()写成return stdout.read(),执行查看类命令会显示不出任何东西

定义类实现远程执行命令

定义类

cat /python/ssh/class1_remote.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
import sys
import os

class Remote():
   def __init__(self,host,port,user,password):
      self.host=host
      self.port=port
      self.user=user
      self.password=password
      #self.hosts=hosts
   def hehe(self,command):
      self.command=command
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(self.host,port=self.port,username=self.user,password=self.password)
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print stdout.read()

c=Remote('192.168.229.121','22','root','einemc@2')
c.hehe('ls')

运行

python class1_remote.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
anaconda-ks.cfg
calicoctl
test

优化类

上面类中的函数功能没有做过细的拆分,这样当定义的函数多的时候,就会造成代码的臃肿。
这里做下拆分,拆分后的函数代码如下:

#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
import sys
import os

class Remote():
   def __init__(self,host,port,user,password):
      self.host=host
      self.port=port
      self.user=user
      self.password=password
      self.conn()
   def conn(self):
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)

   def hehe(self,command):
      self.command=command
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print stdout.read()

c=Remote('192.168.229.121','22','root','einemc@2')
c.hehe('ls')

堆命令实现远程执行命令(多主机)

写命令

cat /python/ssh/remote_mnay.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
hosts=('192.168.229.121','192.168.229.114')
myclient=paramiko.SSHClient()
myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for host in hosts:
   myclient.connect(host,port=22,username='root',password='einem@2')
   stdin,stdout,stderr=myclient.exec_command('ls')
   print('{}===>>>'.format(host))
   print (stdout.read())

执行

python remote_many.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

定义函数实现远程执行命令(多主机)

定义函数

cat /python/ssh/fun_remote_many.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

def shell(port,user,password,command,*hosts):
   myclient=paramiko.SSHClient()
   myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
   for host in hosts:
      myclient.connect(hostname=host,port=port,username=user,password='password')
      stdin,stdout,stderr=myclient.exec_command(command) 
      print('{}===>>>'.format(host))
      print stdout.read()
shell(22,'root','einemc@2','ls','192.168.229.121','192.168.229.114')

运行

python fun_remote_many.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

定义类实现远程执行命令(多主机)

定义类

cat /python/ssh/class1_remote_many.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

class Remote():
   def __init__(self,port,user,password,*hosts):
      self.port=port
      self.user=user
      self.password=password
      self.hosts=hosts
   def hehe(self,command):
      self.command=command
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      for host in self.hosts:
         self.myclient.connect(hostname=host,port=self.port,username=self.user,password=self.password)
         stdin,stdout,stderr=self.myclient.exec_command(self.command)
         print stdout.read()

c=Remote('22','root','einemc@2','192.168.229.121','192.168.229.114')
c.hehe('ls')

运行

[root@ceph01 ssh]# python class1_remote_many.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
anaconda-ks.cfg
calicoctl
test

all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

堆命令实现远程执行命令(多主机,不同的密码)

写命令

cat /python/ssh/remote_many2.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
hosts=('192.168.229.121','192.168.229.114')
passwords=('einemc@2','einemc@2')
myclient=paramiko.SSHClient()
myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for host,password in zip(hosts,passwords):
   myclient.connect(hostname=host,port=22,username='root',password=password)
   stdin,stdout,stderr=myclient.exec_command('ls')
   print('{}===>>>'.format(host))
   print (stdout.read())

运行

python remote_many2.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

定义函数实现远程执行命令(多主机,不同的密码)

定义函数

cat /python/ssh/fun_remote_many2.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

def shell(host,port,user,password,command):
   myclient=paramiko.SSHClient()
   myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
   myclient.connect(hostname=host,port=port,username=user,password=password)
   stdin,stdout,stderr=myclient.exec_command(command) 
   print('{}===>>>'.format(host))
   print stdout.read()


dict1={'192.168.229.121':'einemc@2','192.168.229.114':'einemc@2'}
for (k,v) in dict1.items():
   shell(k,'22','root',v,'ls')

运行

python fun_remote_many2.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

写代码过程中的思路及问题

由于要远程不同的主机,每个主机的密码也不同,并且主机名和密码要有严格的对应关系。
1、首先想到了在函数内循环多个变量类似于for i,j in (变量1,变量2)这种,因为这样不仅可以让多个ip和密码做到一一对应,而想要在函数里循环多个变量就需要先传进去变量,想到函数里定义两个args类型的参数,但是行不通,函数不可能同时定义两个args类型的参数。
2、后想到通过往函数里传字典类型的参数(**kwargs),但是也有问题,往函数里传参的时候ip地址没有引号报语法错误,如下所示

cat test.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-

#def shell(port,user,command,**kwargs):
def shell(**kwargs):
  for (k,v) in kwargs.items():
     print(k+':'+v) 
   #print(kwargs)
shell(192.168.229.121='einemc@2',192.168.229.114='einemc@2')
[root@ceph01 ssh]# python test.py 
  File "test.py", line 9
    shell(192.168.229.121='einemc@2',192.168.229.114='einemc@2')
                    ^
SyntaxError: invalid syntax

往函数里传参的时候ip地址有引号报keyword错误,如下所示

cat test.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-

#def shell(port,user,command,**kwargs):
def shell(**kwargs):
  for (k,v) in kwargs.items():
     print(k+':'+v) 
   #print(kwargs)
shell('192.168.229.121'='einemc@2','192.168.229.114'='einemc@2')
[root@ceph01 ssh]# python test.py 
  File "test.py", line 9
    shell('a'='qwe','b'='123')
SyntaxError: keyword can't be an expression

3、既然不能显示加引号,那么用for循环遍历一下ip地址,然后往函数里传参数如何呢

cat test.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-

def shell(**kwargs):
  for (k,v) in kwargs.items():
     print(k+':'+v) 
   #print(kwargs)
ips=('192.168.229.121','192.168.229.114')
for ip in ips:
   print ip
   shell(ip='einemc@2')
[root@ceph01 ssh]# python test.py 
192.168.229.121
ip:einemc@2
192.168.229.114
ip:einemc@2

从执行结果看到,没有解析变量。传入的那个key是个固定值。看来**kwargs是不可以传入变量=变量的。
4、最后想到字典本身就可以做到键值对一一对应,正好可以将ip和密码一一对应。
最终的代码才如下

cat /python/ssh/fun_remote_many2.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

def shell(host,port,user,password,command):
   myclient=paramiko.SSHClient()
   myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
   myclient.connect(hostname=host,port=port,username=user,password=password)
   stdin,stdout,stderr=myclient.exec_command(command) 
   print('{}===>>>'.format(host))
   print stdout.read()


dict1={'192.168.229.121':'einemc@2','192.168.229.114':'einemc@2'}
for (k,v) in dict1.items():
   shell(k,'22','root',v,'ls')

定义类实现远程执行命令(多主机,不同的密码)

定义类

cat /python/ssh/class1_remote_many2.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
   def hehe(self,command):
      self.command=command
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print('{}===>>>'.format(self.host))
      print stdout.read()

dict1={'192.168.229.121':'einemc@2','192.168.229.114':'einemc@2'}
for (k,v) in dict1.items():
   c=Remote('22','root',k,v)
   c.hehe('ls')

运行

python class1_remote_many2.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

优化类

上面类中的函数功能没有做过细的拆分,这样当定义的函数多的时候,就会造成代码的臃肿。
这里做下拆分,拆分后的函数代码如下:

#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
      self.conn()
   def conn(self):
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
   def hehe(self,command):
      self.command=command
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print('{}===>>>'.format(self.host))
      print stdout.read()
hosts=['192.168.229.121','192.168.229.114']
passwords=['einemc@2','einemc@2']

for k,v  in zip(hosts,passwords):
   remote=Remote('22','root',k,v)
   remote.hehe('ls')

调用配置文件实现远程管理主机

项目代码结构

[root@ceph01 ssh]# tree /python/
/python/
└── ssh
    ├── class1_remote_many2.py
    ├── class1_remote_many2.pyc
    ├── conf
    │   ├── ansible.conf
    │   ├── __init__.py
    │   ├── __init__.pyc
    │   └── sources
    │       ├── __init__.py
    │       ├── __init__.pyc
    │       ├── readconfig.py
    │       └── readconfig.pyc
    ├── exec.py

各个文件代码

主代码

cat /python/ssh/class1_remote_many2.py
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
   def command(self,command):
      self.command=command
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print('{}===>>>'.format(self.host))
      print stdout.read()

读取配置代码

cat /python/ssh/conf/sources/readconfig.py
#!/usr/bin/env python
# -*- coding:utf8 -*-
import configparser

cf = configparser.ConfigParser()
# 读取配置文件,如果写文件的绝对路径,就可以不用os模块
cf.read("/python/ssh/conf/ansible.conf")

# 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,
#secs = cf.sections()
#print(secs)

# 获取某个section名为Mysql-Database所对应的键
#options = cf.options("Mysql-Database")
#print(options)

# 获取section名为Mysql-Database所对应的全部键值对
#items = cf.items("Mysql-Database")
#print(items)

# 获取[Mysql-Database]中host对应的值
hosts = cf.get("hosts", "host")
passwords = cf.get("passwords","password")

配置文件

cat /python/ssh/conf/ansible.conf 
[hosts]
host='192.168.229.121','192.168.229.114'
[passwords]
password='einemc@2','einemc@2'

执行文件

cat /python/ssh/exec.py 
#!/usr/bin/env python
#coding:utf8
from class1_remote_many2 import *
from conf.sources.readconfig import *
#dict1={}
host = eval(hosts)
password = eval(passwords)
for (k,v) in zip(host,password):
   remote=Remote('22','root',k,v)
   remote.command('ls')

运行

python exec.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
mysql
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
python.py
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

优化exec

以上的exec.py执行的是远程主机上的ls命令,想执行其他命令需要更改文件中的内容,现在通过传参的方式执行不同的命令。改后的文件如下

cat /python/ssh/exec.py 
#!/usr/bin/env python
#coding:utf8
from class1_remote_many2 import *
from conf.sources.readconfig import *
import sys
#dict1={}
host = eval(hosts)
password = eval(passwords)
for (k,v) in zip(host,password):
   remote=Remote('22','root',k,v)
   remote.command(sys.argv[1])
运行
python exec.py "cd /tmp;ls"
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
systemd-private-384701818acf46e2bc207023c88a94ce-ceph-mds@ceph02.service-cF8cI3
systemd-private-384701818acf46e2bc207023c88a94ce-ceph-mon@ceph02.service-a1mlE5
systemd-private-384701818acf46e2bc207023c88a94ce-ceph-osd@1.service-KYMy9h
systemd-private-384701818acf46e2bc207023c88a94ce-ceph-osd@4.service-6AJ8Eu
systemd-private-384701818acf46e2bc207023c88a94ce-chronyd.service-mNaxhX
systemd-private-384701818acf46e2bc207023c88a94ce-mariadb.service-rnYIqr

192.168.229.114===>>>
ansible.tar
class1_remote_many2.py
conf
exec.py
file1
systemd-private-516b154bf67f4fbd916b240843079599-ceph-mds@ceph01.service-tFz7L8
systemd-private-516b154bf67f4fbd916b240843079599-ceph-mon@ceph01.service-Uq2sM1
systemd-private-516b154bf67f4fbd916b240843079599-ceph-osd@0.service-Zsreg2
systemd-private-516b154bf67f4fbd916b240843079599-ceph-osd@3.service-v01OK2
systemd-private-516b154bf67f4fbd916b240843079599-chronyd.service-OaLMyy
systemd-private-516b154bf67f4fbd916b240843079599-httpd.service-GnL0j8
systemd-private-516b154bf67f4fbd916b240843079599-mariadb.service-he2bKL
systemd-private-516b154bf67f4fbd916b240843079599-named.service-Bzyytp

ssh之transport模块详解

定义类实现上传下载文件

这里不再从堆命令到函数再到类来写代码,直接上类。

定义类

cat /python/ssh/class1_remote_many3.py
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
import sys

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
      self.transport()
      self.conn()
   def transport(self):
      self.transport=paramiko.Transport(self.host,self.port)
      self.transport.connect(username=self.user,password=self.password)
   def conn(self):
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
   def download(self,remotepath,localpath):
      self.remotepath=remotepath
      self.localpath=localpath
      self.sftp = paramiko.SFTPClient.from_transport(self.transport)
      self.sftp.get(self.remotepath,self.localpath)
   def put(self,localpath,remotepath):
      self.localpath=localpath
      self.remotepath=remotepath
      self.sftp = paramiko.SFTPClient.from_transport(self.transport)
      self.sftp.put(self.localpath,self.remotepath)
   def close(self):
      if self.transport:
         self.transport.close()
      if self.myclient:
         self.myclient.close()

remote=Remote('22','root','192.168.229.121','einemc@2')
remote.download('/tmp/ceph02','tmp/ceph01')
remote.put('/python/ssh//python/ssh/class1_remote_many3.py','/tmp//python/ssh/class1_remote_many3.py')

运行

从代码来看,运行后会将本地/python/ssh//python/ssh/class1_remote_many3.py文件上传到192.168.229.121的/tmp/目录下并保持文件名不变,并从192.168.229.121服务器的/tmp/目录下载ceph01到本地的/tmp/目录并重命名为ceph01。
运行代码之前先查看本地和192.168.229.121的/tmp/目录没有相应的文件。

[root@ceph02 tmp]# ll
总用量 4
-rw-r--r-- 1 root root  7 1120 11:17 ceph02
drwx------ 3 root root 17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-mds@ceph02.service-cF8cI3
drwx------ 3 root root 17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-mon@ceph02.service-a1mlE5
drwx------ 3 root root 17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-osd@1.service-KYMy9h
drwx------ 3 root root 17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-osd@4.service-6AJ8Eu
drwx------ 3 root root 17 1016 13:43 systemd-private-384701818acf46e2bc207023c88a94ce-chronyd.service-mNaxhX
drwx------ 3 root root 17 1118 17:56 systemd-private-384701818acf46e2bc207023c88a94ce-mariadb.service-rnYIqr
[root@ceph01 ssh]# ll /tmp/
总用量 0
drwxr-xr-x. 3 root root 80 1119 15:34 conf
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-mds@ceph01.service-tFz7L8
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-mon@ceph01.service-Uq2sM1
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-osd@0.service-Zsreg2
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-osd@3.service-v01OK2
drwx------. 3 root root 17 1012 10:28 systemd-private-516b154bf67f4fbd916b240843079599-chronyd.service-OaLMyy
drwx------. 3 root root 17 1118 15:58 systemd-private-516b154bf67f4fbd916b240843079599-httpd.service-GnL0j8
drwx------. 3 root root 17 1118 17:56 systemd-private-516b154bf67f4fbd916b240843079599-mariadb.service-he2bKL
drwx------. 3 root root 17 115 16:38 systemd-private-516b154bf67f4fbd916b240843079599-named.service-Bzyytp

运行代码

[root@ceph01 ssh]# python class1_remote_many3.py 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend

验证文件是否上传下载

[root@ceph01 ssh]# ll /tmp/
总用量 4
-rw-r--r--. 1 root root  7 1120 11:30 ceph01
drwxr-xr-x. 3 root root 80 1119 15:34 conf
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-mds@ceph01.service-tFz7L8
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-mon@ceph01.service-Uq2sM1
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-osd@0.service-Zsreg2
drwx------. 3 root root 17 119 16:05 systemd-private-516b154bf67f4fbd916b240843079599-ceph-osd@3.service-v01OK2
drwx------. 3 root root 17 1012 10:28 systemd-private-516b154bf67f4fbd916b240843079599-chronyd.service-OaLMyy
drwx------. 3 root root 17 1118 15:58 systemd-private-516b154bf67f4fbd916b240843079599-httpd.service-GnL0j8
drwx------. 3 root root 17 1118 17:56 systemd-private-516b154bf67f4fbd916b240843079599-mariadb.service-he2bKL
drwx------. 3 root root 17 115 16:38 systemd-private-516b154bf67f4fbd916b240843079599-named.service-Bzyytp
[root@ceph02 tmp]# ll /tmp/
总用量 8
-rw-r--r-- 1 root root    7 1120 11:17 ceph02
-rw-r--r-- 1 root root 1623 1120 11:30 class1_remote_many3.py
drwx------ 3 root root   17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-mds@ceph02.service-cF8cI3
drwx------ 3 root root   17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-mon@ceph02.service-a1mlE5
drwx------ 3 root root   17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-osd@1.service-KYMy9h
drwx------ 3 root root   17 119 16:05 systemd-private-384701818acf46e2bc207023c88a94ce-ceph-osd@4.service-6AJ8Eu
drwx------ 3 root root   17 1016 13:43 systemd-private-384701818acf46e2bc207023c88a94ce-chronyd.service-mNaxhX
drwx------ 3 root root   17 1118 17:56 systemd-private-384701818acf46e2bc207023c88a94ce-mariadb.service-rnYIqr

捕捉参数执行命令,上传下载文件

另外的实现方式详见python配置模块oslo.config

定义类实现远程执行命令,上传下载文件

cat /python/ssh/class1_remote_many_optimize.py
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
import sys

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
      self.transport()
      self.conn()
   def transport(self):
      self.transport=paramiko.Transport(self.host,self.port)
      self.transport.connect(username=self.user,password=self.password)
   def conn(self):
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
   def command(self,command):
      self.command=command
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print('{}===>>>'.format(self.host))
      print stdout.read()
   def download(self,remotepath,localpath):
      self.remotepath=remotepath
      self.localpath=localpath
      self.sftp = paramiko.SFTPClient.from_transport(self.transport)
      self.sftp.get(self.remotepath,self.localpath)
   def put(self,localpath,remotepath):
      self.localpath=localpath
      self.remotepath=remotepath
      self.sftp = paramiko.SFTPClient.from_transport(self.transport)
      self.sftp.put(self.localpath,self.remotepath)
   def close(self):
      if self.transport:
         self.transport.close()
      if self.myclient:
         self.myclient.close()

定义执行文件捕捉参数

要想通过命令行传参,需要用到python的sys模块,sys.argv代表所有参数,sys.argv[1]代表第一个参数,不过这个不玩这么简单的,因为使用程序的人并不会按常理出牌,可能随意输入。所以就需要加点循环和逻辑判断。
涉及到的知识点,这里仅仅简单列举下涉及到的单个知识点,至于知识点跟知识点结合的思想不写。

1、sys模块捕捉参数。
2、sys.argv是一个列表的数据类型。
3、sys.exit()表示退出脚本。
4、列表方法append()可以将输入的东西当成一个整体追加到列表里作为列表的一个元素。
5、列表方法index(列表元素)获得列表中元素的位置。
6list[n](列表[n])表示获取列表中第n-1个元素。
7print()换行用\n。
8、字符串方法str.split(',')表示将字符串按照逗号(,)分割成一个新的字符串,分割成的新字符串会放进列表里。
9、paramiko.util.log_to_file('ssh.log')表示打印日志到当前目录。
cat /python/ssh/exec_optimize.py 
#!/usr/bin/env python
#-*- encoding:utf8 -*-
from class1_remote_many_method import *
paramiko.util.log_to_file('ssh.log')
import sys
arg_list=[]
arg_list.extend(sys.argv)
def help():
   print("General usage:\n==============\nusage: python exec.py --help \n[-h hostname or hostname1,hostname2,...hostnamen] [--host hostname or hostname1,hostname2,...hostnamen]\n[-p hostnamepassword or hostname1password,hostname2password,...hostnamenpassword]\n[-c shellommand]\n[-d ]")   

if len(arg_list) <=1:
   print("请输入参数,具体用法用python exec.py --help查看")
   sys.exit()
for arg in arg_list:
   if arg == '--help':
      help()
      sys.exit()
command=''
d_remotefile=''
d_localfile=''
p_remotefile=''
p_localfile=''

for arg in arg_list:
   if arg == '--host' or arg == '-h':
      #print(arg)
      #print(arg_list.index(arg))
      location=arg_list.index(arg)
      host_list=[]
      #host_list.append(arg_list[location+1])
      str=arg_list[location+1]
      hosts=str.split(',')
      #host_list.append(str.split)
      #print(type(hosts)) 
   elif arg == '--password' or arg == '-p':
      location=arg_list.index(arg)
      pass_list=[]
      pass_list.append(arg_list[location+1])
      str=arg_list[location+1]
      passwords=str.split(',')
   elif arg == '--command' or arg == '-c':
      location=arg_list.index(arg)
      comm_list=[]
      comm_list.append(arg_list[location+1])
      command=(arg_list[location+1])

for arg in arg_list:
   if arg == '-d--remotefile':
      location=arg_list.index(arg)
      d_remotefile=(arg_list[location+1])
      print(d_remotefile)
      print(type(d_remotefile))
   elif arg == '-d--localfile':
      location=arg_list.index(arg)
      d_localfile=(arg_list[location+1])
   elif arg == '-p--remotefile':
      location=arg_list.index(arg)
      p_remotefile=(arg_list[location+1])
   elif arg == '-p--localfile':
      location=arg_list.index(arg)
      p_localfile=(arg_list[location+1])
#定义调用执行命令的函数
def exec_command():
   for k,v in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.command(command)
#定义上传文件的函数
def exec_put():
   for k,v in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.put(p_localfile,p_remotefile)
#定义下载文件的函数
def exec_download():
   for k,v in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.download(d_remotefile,d_localfile)

if len(command)>0:
   exec_command()

if len(p_remotefile)>0 and len(p_localfile)>0:
   exec_put()

if len(d_remotefile)>0 and len(d_localfile)>0 and len(hosts) < 2:  
   exec_download()
elif len(d_remotefile)>0 and len(d_localfile)>0 and len(hosts) >= 2:
   print('download的时候请只指定一个主机,如果是配置文件配置的主机组,请检查配置文件主机组中是不是有多个主机')

演示执行命令

注意:这里参数之间并没有严格的顺序。

[root@ceph01 ssh]# python exec_optimize.py -c ls -h 192.168.229.121 -p einemc@2 
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

通过命令行或配置文件传参执行命令上传下载文件

另外的实现方式详见python配置模块oslo.config

定义执行类

cat /python/ssh/class1_remote_many_method.py
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko
import sys

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
      self.transport()
      self.conn()
   def transport(self):
      self.transport=paramiko.Transport(self.host,self.port)
      self.transport.connect(username=self.user,password=self.password)
   def conn(self):
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
   def command(self,command):
      self.command=command
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print('{}===>>>'.format(self.host))
      print stdout.read()
   def download(self,remotepath,localpath):
      self.remotepath=remotepath
      self.localpath=localpath
      self.sftp = paramiko.SFTPClient.from_transport(self.transport)
      self.sftp.get(self.remotepath,self.localpath)
   def put(self,localpath,remotepath):
      self.localpath=localpath
      self.remotepath=remotepath
      self.sftp = paramiko.SFTPClient.from_transport(self.transport)
      self.sftp.put(self.localpath,self.remotepath)
   def close(self):
      if self.transport:
         self.transport.close()
      if self.myclient:
         self.myclient.close()

if __name__ == "__main__":
   remote=Remote('22','root','192.168.229.121','einemc@2')
   remote.download('/tmp/ceph02','/tmp/ceph01')
   remote.put('/python/ssh/class1_remote_many3.py','/tmp/class1_remote_many3.py')
   remote.command('ls')

读取配置文件

cat /python/ssh/conf/sources/readconfig.py
#!/usr/bin/env python
# -*- coding:utf8 -*-
import configparser

cf = configparser.ConfigParser()
# 读取配置文件,如果写文件的绝对路径,就可以不用os模块
cf.read("/python/ssh/conf/ansible.conf")

# 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,
secs = cf.sections()

# 获取某个section名为Mysql-Database所对应的键
#options = cf.options("Mysql-Database")
#print(options)

# 获取section名为Mysql-Database所对应的全部键值对
#items = cf.items("hosts")
#print(items)
 
# 获取[Mysql-Database]中host对应的值
for sec in secs: 
   hosts = cf.get(sec, "host")
   passwords = cf.get(sec,"password")


#print(hosts)
#print(type(hosts))
#print(passwords)

写配置文件

cat /python/ssh/conf/ansible.conf 
[web]
host='192.168.229.100','192.168.229.101'
password='einemc@2','einemc@2'

[web2]
host='192.168.229.121','192.168.229.114'
password='einemc@2','einemc@2'

[hosts]
host='192.168.229.118','192.168.229.200'
password='einemc@2','einemc@2'

写执行调用文件

cat /python/ssh/exec_conf_optimize.py 
#!/usr/bin/env python
#coding:utf8
from conf.sources.readconfig import *
import sys
from class1_remote_many_method import *

paramiko.util.log_to_file('ssh.log')

arg_list=[]
arg_list.extend(sys.argv)
def help():
   print("General usage:\n==============\nusage: python exec.py --help \n[-h hostname or hostname1,hostname2,...hostnamen] [--host hostname or hostname1,hostname2,...hostnamen] [hostgroup from *.conf file example:web01 web02 ... ]\n[-p hostnamepassword or hostname1password,hostname2password,...hostnamenpassword]\n[-c shellommand]\n[-d ]")  

if len(arg_list) <=1:
   print("请输入参数,具体用法用python exec.py --help查看")
   sys.exit()
for arg in arg_list:
   if arg == '--help':
      help()
      sys.exit()
command=''
d_remotefile=''
d_localfile=''
p_remotefile=''
p_localfile=''

for arg in arg_list:
   if arg == '--host' or arg == '-h':
      location=arg_list.index(arg)
      host_list=[]
      str=arg_list[location+1]
      hosts=str.split(',')
   elif arg == '--password' or arg == '-p':
      location=arg_list.index(arg)
      pass_list=[]
      pass_list.append(arg_list[location+1])
      str=arg_list[location+1]
      passwords=str.split(',')
   elif arg == '--command' or arg == '-c':
      location=arg_list.index(arg)
      comm_list=[]
      comm_list.append(arg_list[location+1])
      command=(arg_list[location+1])

   elif arg in secs:
      hosts = cf.get(arg, "host")
      passwords = cf.get(arg,"password")
      
      hosts = eval(hosts)
      passwords = eval(passwords)
for arg in arg_list:
   if arg == '-d--remotefile':
      location=arg_list.index(arg)
      d_remotefile=(arg_list[location+1])
   elif arg == '-d--localfile':
      location=arg_list.index(arg)
      d_localfile=(arg_list[location+1])
   elif arg == '-p--remotefile':
      location=arg_list.index(arg)
      p_remotefile=(arg_list[location+1])
   elif arg == '-p--localfile':
      location=arg_list.index(arg)
      p_localfile=(arg_list[location+1])
##定义调用执行命令的函数
def exec_command():
   for k,v in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.command(command)
##定义上传文件的函数
def exec_put():
   for k,v in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.put(p_localfile,p_remotefile)
##定义下载文件的函数
def exec_download():
   for k,v in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.download(d_remotefile,d_localfile)

if len(command)>0:
   exec_command()

if len(p_remotefile)>0 and len(p_localfile)>0:
   exec_put()

if len(d_remotefile)>0 and len(d_localfile)>0 and len(hosts) < 2:  
   exec_download()
elif len(d_remotefile)>0 and len(d_localfile)>0 and len(hosts) >= 2:
   print('download的时候请只指定一个主机,如果是配置文件配置的主机组,请检查配置文件主机组中是不是有多个主机')

运行演示

下载批量故意设置的只能从一个主机上下载,具体原因不再讲解。

python exec_conf_optimize.py web -d--remotefile /tmp/ceph02 -d--localfile /python/ssh/ceph01
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
download的时候请只指定一个主机,如果是配置文件配置的主机组,请检查配置文件主机组中是不是有多个主机
python exec_conf_optimize.py web2 -c ls
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

if name == “main”:调试代码

写的代码需要反复调试,如果执行自己执行,而别的文件调用这个文件不执行调试代码,可在调试代码的前面写上if name == “main”:,这之后的所有代码将不被其他调用执行,只能本文件执行。

cat class1_remote_many2_optimize.py
#!/usr/bin/env python
#-*- encoding:utf8 -*-
import paramiko

class Remote():
   def __init__(self,port,user,host,password):
      self.port=port
      self.user=user
      self.password=password
      self.host=host
      self.conn()
   def conn(self):
      self.myclient=paramiko.SSHClient()
      self.myclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      self.myclient.connect(hostname=self.host,port=self.port,username=self.user,password=self.password)
   def command(self,command):
      self.command=command
      stdin,stdout,stderr=self.myclient.exec_command(self.command)
      print('{}===>>>'.format(self.host))
      print stdout.read()

if __name__ == "__main__":
   print('开始执行调试代码===================================================')
   hosts=['192.168.229.121','192.168.229.114']
   passwords=['einemc@2','einemc@2']

   for k,v  in zip(hosts,passwords):
      remote=Remote('22','root',k,v)
      remote.command('ls')
   

运行

python class1_remote_many2_optimize.py
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
开始执行调试代码==============================================================================================================================================================
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

测试其他调用是否会执行

cat exec.py 
#!/usr/bin/env python
#coding:utf8
from class1_remote_many2_optimize import *
from conf.sources.readconfig import *
import sys
paramiko.util.log_to_file('ssh.log')
host = eval(hosts)
password = eval(passwords)

for k,v in zip(host,password):
   remote=Remote('22','root',k,v)
   remote.command(sys.argv[1])
python exec.py  ls
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml

测试其他调用是否会执行

cat exec.py 
#!/usr/bin/env python
#coding:utf8
from class1_remote_many2_optimize import *
from conf.sources.readconfig import *
import sys
paramiko.util.log_to_file('ssh.log')
host = eval(hosts)
password = eval(passwords)

for k,v in zip(host,password):
   remote=Remote('22','root',k,v)
   remote.command(sys.argv[1])

可以看到其他调用并没有执行调试代码

python exec.py  ls
/usr/lib/python2.7/site-packages/paramiko/transport.py:33: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  from cryptography.hazmat.backends import default_backend
192.168.229.121===>>>
anaconda-ks.cfg
calicoctl
test

192.168.229.114===>>>
all-2020-10-14.sql
anaconda-ks.cfg
a.out
calicoctl
calico.yaml
ceph-deploy-ceph.log
consul.tar.gz
crushmap-decompile
crushmap-decompiled
crushmapdump
crushmapdump-compiled
crushmapdump-decompiled
crushmap.txt
disk.py
ipPools
ipPools.bak
json
krakendash
newfile2.c
nohup.out
pflag.c
prometheus-2.20.1.linux-amd64.tar.gz
setuptools-0.6c11
setuptools-0.6c11.tar.gz
show_index.sh
show_mysql_all_tables_index.sh
test
test.link
test.sh
yaml
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Paramiko是Python中用于SSH协议的一个库,可以用于远程登录、传输文件等操作。下面是Paramiko库的详解: 1. 安装 使用pip进行安装: ```python pip install paramiko ``` 2. 连接远程服务器 ```python import paramiko # 创建SSH客户端 ssh = paramiko.SSHClient() # 自动添加主机密钥 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接远程服务器 ssh.connect('hostname', port=22, username='username', password='password') # 执行命令 stdin, stdout, stderr = ssh.exec_command('ls') # 输出命令执行结果 print(stdout.read().decode()) # 关闭连接 ssh.close() ``` 3. 传输文件 ```python import paramiko # 创建SSH客户端 ssh = paramiko.SSHClient() # 自动添加主机密钥 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 连接远程服务器 ssh.connect('hostname', port=22, username='username', password='password') # 创建SFTP客户端 sftp = ssh.open_sftp() # 上传文件 sftp.put('local_path', 'remote_path') # 下载文件 sftp.get('remote_path', 'local_path') # 关闭连接 sftp.close() ssh.close() ``` 4. 高级用法 - 使用密钥登录 ```python import paramiko # 创建SSH客户端 ssh = paramiko.SSHClient() # 自动添加主机密钥 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 密钥文件路径 key_path = '/root/.ssh/id_rsa' # 密钥密码,如果没有设置则为None key_password = 'password' # 密钥对象 private_key = paramiko.RSAKey.from_private_key_file(key_path, password=key_password) # 连接远程服务器 ssh.connect('hostname', port=22, username='username', pkey=private_key) # 执行命令 stdin, stdout, stderr = ssh.exec_command('ls') # 输出命令执行结果 print(stdout.read().decode()) # 关闭连接 ssh.close() ``` - 自定义日志 ```python import paramiko import logging # 创建SSH客户端 ssh = paramiko.SSHClient() # 自动添加主机密钥 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 创建日志记录器 logger = logging.getLogger('paramiko') logger.setLevel(logging.DEBUG) # 创建日志处理器 handler = logging.StreamHandler() handler.setLevel(logging.DEBUG) # 创建日志格式化器 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) # 添加日志处理器 logger.addHandler(handler) # 连接远程服务器 ssh.connect('hostname', port=22, username='username', password='password') # 执行命令 stdin, stdout, stderr = ssh.exec_command('ls') # 输出命令执行结果 print(stdout.read().decode()) # 关闭连接 ssh.close() ``` 总之,Paramiko库是Python中一个非常强大的SSH协议库,其功能十分丰富,可以满足大部分远程操作的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时空无限

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值