1、安裝paramiko模塊
pip install paramiko
可以修改ssh連接超時時間,windows下路徑:在安裝路徑Python\Python36\Lib\site-packages\paramiko\transport.py,修改self.banner_timeout = 60(設置ssh超時為60秒)
2、利用python進行ssh
import paramiko,getpass #getpass是隱藏密碼
def ssh_connect(password): host_ip = '192.168.0.150' user_name = 'root' host_port ='22'
# 待執行的命令
sed_command = "sed -i 's/123/abc/g' /root/test/test.txt" ls_command = "ls /root/test/"
# 注意:依次執行多條命令時,命令之間用分號隔開
command = sed_command+";"+ls_command
# SSH遠程連接
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #指定當對方主機沒有本機公鑰的情況時應該怎么辦,AutoAddPolicy表示自動在對方主機保存下本機的秘鑰
ssh.connect(host_ip, host_port, user_name, password) # 執行命令並獲取執行結果
stdin, stdout, stderr = ssh.exec_command(command) out = stdout.readlines() err = stderr.readlines()
#關閉連接 ssh.close() return out,err if __name__ == '__main__': pwd = getpass.getpass("請輸入密碼:")
#有了密碼,開始調用函數
result = ssh_connect(pwd)
print(result)
python中的paramiko模塊是用來實現ssh連接到遠程服務器上的庫,在進行連接的時候,可以用來執行命令,也可以用來上傳文件。
1、得到一個連接的對象
在進行連接的時候,可以使用如下的代碼:
def connect(host): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: #ssh.connect(host,username='root',allow_agent=True,look_for_keys=True)
ssh.connect(host,username='root',password='root',allow_agent=True)
return ssh except: return None
在connect函數中,參數是一個主機的IP地址或者是主機名稱,在執行這個方法之后,如果成功的連接到服務器,那么就會返回一個sshclient對象。
第一步是建立一個SSHClient的對象,然后設置ssh客戶端允許連接不在know_host文件中的機器,然后就嘗試連接服務器。
在連接服務器的時候,可以使用兩種方式:
(1)方式是使用秘鑰的方式,也就是參數look_for_keys
(2)用設置密碼尋找,也可以直接使用密碼的方式,也就是直接使用參數password,從而最后返回一個連接的對象。
2、 獲取設置的命令
在進行paramiko連接之后,那么必須要得到需要執行的命令,如下代碼所示:
def command(args,outpath): cmd = '%s %s' % (outpath,args) return cmd
在參數中,一個是args,一個outpath,args表示命令的參數,而outpath表示為可執行文件的路徑,例如/usr/bin/ls -l。在其中outpath也就是/usr/bin/ls ,而參數為-l
這個方法主要是用來組合命令,將分開的參數作為命令的一部分進行組裝。
3、 執行命令
在連接過后,可以進行直接執行命令,那么就有了如下的函數:
def exec_commands(conn,cmd): stdin,stdout,stderr = conn.exec_command(cmd) results=stdout.read() return results
在此函數中,傳入的參數一個為連接的對象conn,一個為需要執行的命令cmd,最后得到執行的結果,也就是stdout.read(),最后返回得到的結果
4、 上傳文件
在使用連接對象的時候,也可以直接進行上傳相關的文件,如下函數:
def copy_moddule(conn,inpath,outpath): ftp = conn.open_sftp() ftp.put(inpath,outpath) ftp.close() return outpath
此函數的主要參數為,一個是連接對象conn,一個是上傳的文件名稱,一個上傳之后的文件名稱,在此必須寫入完整的文件名稱包括路徑。
做法主要是打開一個sftp對象,然后使用put方法進行上傳文件,最后關閉sftp連接,最后返回一個上傳的文件名稱的完整路徑
5、 執行命令得到結果
最后就是,執行命令,得到返回的結果,如下代碼:
def excutor(host,outpath,args): conn = connect(host) if not conn: return [host,None]
#調用函數 exec_commands(conn,'chmod +x %s' % outpath)
#調用函數,獲得命令參數及其路徑 cmd =command(args,outpath)
#調用函數執行命令 result = exec_commands(conn,cmd)
print '%r' % result result = json.loads(result) return [host,result]
首先,進行連接服務器,得到一個連接對象,如果連接不成功,那么返回主機名和None,表示沒有連接成功,如果連接成功,那么修改文件的執行權限,從而可以執行文件,然后得到執行的命令,最后,進行執行命令,得到結果,將結果用json格式表示返回,從而結果能得到一個美觀的json格式,最后和主機名一起返回相關的信息
6、 測試代碼
測試代碼如下:
if __name__ == '__main__': print json.dumps(excutor('192.168.1.165','ls',' -l'),indent=4,sort_keys=True) print copy_module(connect('192.168.1.165'),'kel.txt','/root/kel.1.txt') exec_commands(connect('192.168.1.165'),'chmod +x %s' % '/root/kel.1.txt')
第一步測試命令執行,第二步測試上傳文件,第三部測試修改上傳文件的權限。
完整代碼如下:
#!/usr/bin/env python
import json import paramiko def connect(host): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: #ssh.connect(host,username='root',allow_agent=True,look_for_keys=True)
ssh.connect(host,username='root',password='root',allow_agent=True) return ssh except: return None def command(args,outpath): cmd = '%s %s' % (outpath,args) return cmd def exec_commands(conn,cmd): stdin,stdout,stderr = conn.exec_command(cmd) results=stdout.read() return results def excutor(host,outpath,args): conn = connect(host) if not conn: return [host,None] #exec_commands(conn,'chmod +x %s' % outpath)
cmd =command(args,outpath) result = exec_commands(conn,cmd) result = json.dumps(result) return [host,result] def copy_module(conn,inpath,outpath): ftp = conn.open_sftp() ftp.put(inpath,outpath) ftp.close() return outpath if __name__ == '__main__': print json.dumps(excutor('192.168.1.165','ls',' -l'),indent=4,sort_keys=True) print copy_module(connect('192.168.1.165'),'kel.txt','/root/kel.1.txt') exec_commands(connect('192.168.1.165'),'chmod +x %s' % '/root/kel.1.txt')
Python實現ssh批量登錄並執行命令
pexpect模塊版本
#!/usr/bin/env python # -*- coding: utf-8 -*-
import pexpect def ssh_cmd(ip, passwd, cmd): ret = -1 ssh = pexpect.spawn('ssh root@%s "%s"' % (ip, cmd)) try: i = ssh.expect(['password:', 'continue connecting (yes/no)?'], timeout=5) if i == 0 : ssh.sendline(passwd) elif i == 1: ssh.sendline('yes\n') ssh.expect('password: ') ssh.sendline(passwd) ssh.sendline(cmd) r = ssh.read() print r ret = 0 except pexpect.EOF: print "EOF" ssh.close() ret = -1
except pexpect.TIMEOUT: print "TIMEOUT"
ssh.close() ret = -2
return ret
aramiko模塊版本
#-*- coding: utf-8 -*- #!/usr/bin/python import paramiko import threading def ssh2(ip,username,passwd,cmd): try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(ip,22,username,passwd,timeout=5) for m in cmd: stdin, stdout, stderr = ssh.exec_command(m) #stdin.write("Y") #簡單交互,輸入 ‘Y' out = stdout.readlines() #屏幕輸出 for o in out: print o, print '%s\tOK\n'%(ip) ssh.close() except : print '%s\tError\n'%(ip) if __name__=='__main__': cmd = ['cal','echo hello!']#你要執行的命令列表 username = "" #用戶名 passwd = "" #密碼 threads = [] #多線程 print "Begin......" for i in range(1,254): ip = '192.168.1.'+str(i)
#開啟多線程執行命令 a=threading.Thread(target=ssh2,args=(ip,username,passwd,cmd)) a.start()
python 切換root 執行命令的方法
import paramiko
def create_user(root_pwd,username,password): result = []
ssh = paramiko.SSHClient()
#把要連接的機器添加到known_hosts文件中
ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect( hostname = settings.HOST, port = settings.PORT, username = settings.USERNAME, password = settings.PASSWORD, timeout = 60, ) sc = ssh.invoke_shell()
#定義函數 def exe_cmd(cmd,t=0.1): sc.send(cmd) sc.send("\n") time.sleep(t) resp = sc.recv(9999).decode("utf8") #print "cmd='%s',echo='%s'\n"%(cmd,resp)
return resp #切換root賬號
resp = exe_cmd("su root",t=1) if resp.endswith(u"密碼:"): resp = exe_cmd(root_pwd) #創建用戶
cmd_create_user = "useradd {username} -d /home/{username}".format( username = username, ) exe_cmd(cmd_create_user) #修改密碼
cmd_change_user_pwd = """echo "{password}" | passwd --stdin {username}""".format( username = username, password = password, ) exe_cmd(cmd_change_user_pwd)
Python實現SSH遠程登陸,並執行命令的方法
import paramiko def sshclient_execmd(hostname, port, username, password, execmd):
paramiko.util.log_to_file("paramiko.log") s = paramiko.SSHClient() s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
#連接 s.connect(hostname=hostname, port=port, username=username, password=password)
#執行 stdin, stdout, stderr = s.exec_command (execmd) stdin.write("Y") # Generally speaking, the first connection, need a simple interaction.
print stdout.read() s.close() def main(): hostname = '10.***.***.**' port = 22 username = 'root' password = '******' execmd = "free"
#調用函數 sshclient_execmd(hostname, port, username, password, execmd) if __name__ == "__main__": main()
Python 實現遠程服務器(ssh)批量執行命令
import paramiko
#實例化ssh客戶端
ssh = paramiko.SSHClient()
#創建默認的白名單
policy = paramiko.AutoAddPolicy()
#設置白名單
ssh.set_missing_host_key_policy(policy)
#鏈接服務器
ssh.connect( hostname = "192.168.2.186", #服務器的ip
port = 22, #服務器的端口
username = "root", #服務器的用戶名
password = "123" #用戶名對應的密碼
)
#遠程執行命令
stdin,stdout,stderr = ssh.exec_command("ls") #exec_command 返回的對象都是類文件對象
#stdin 標准輸入 用於向遠程服務器提交參數,通常用write方法提交
#stdout 標准輸出 服務器執行命令成功,返回的結果 通常用read方法查看
#stderr 標准錯誤 服務器執行命令錯誤返回的錯誤值 通常也用read方法 #查看結果,注意在Python3 字符串分為了:字符串和字節兩種格式,文件返回的是字節
result = stdout.read().decode() print(result)
使用SSHClient封裝Transport
我們可能會遇到 需要傳輸文件,有需要執行Linux命令的情況, 因為Transport對象只能傳輸文件,不能執行Linux命令,所以我們只需要創建一個SSHClient,然后通過SSHClient的 get_transport() 來創建Transport對象
paramiko遠程上傳和下載
import paramiko transport = paramiko.Transport(('192.168.1.1',22)) transport.connect(username='weiheng',password='weiheng123') sftp = paramiko.SFTPClient.from_transport(transport) # 將HelloWorld.py 上傳至服務器 /tmp/1.py sftp.put('/tmp/HelloWorld.py', '/tmp/1.py') # 將1.py 下載到本地 HelloWorld sftp.get('/tmp/1.py', '/tmp/HelloWorld') transport.close()
'''給遠程主機上傳一個文件'''
from paramiko.ssh_exception import NoValidConnectionsError,AuthenticationException import paramiko def put(hostname,password,local_name,remote_name): try: transport = paramiko.Transport((hostname,22)) transport.connect(username='root',password=password) sftp = paramiko.SFTPClient.from_transport(transport) except AuthenticationException as e: return '主機%s密碼錯誤' %(hostname) except Exception as e: return '未知錯誤: ',e else: sftp.put(local_name,remote_name) ##上傳文件
try: # 如果遠程主機有這個文件則返回一個對象,否則拋出異常
sftp.file(remote_name) print("上傳成功.") except IOError: print("上傳失敗!") finally: transport.close() put('172.25.254.221','redhat','/home/kiosk/passwd','/mnt/test') ##遠程主機ip,密碼,本地文件,上傳后的文件保存位置
'''從遠程主機下載文件'''
from paramiko.ssh_exception import NoValidConnectionsError,AuthenticationException import paramiko import os def get(hostname,password,remote_name,local_name): try: transport = paramiko.Transport((hostname,22)) transport.connect(username='root',password=password) sftp = paramiko.SFTPClient.from_transport(transport) except AuthenticationException as e: return '主機%s密碼錯誤' %(hostname) except Exception as e: return '未知錯誤: ',e else: #sftp.put(local_name,remote_name) ##上傳文件
sftp.get(remote_name,local_name) ##下載文件
if os.path.exists(local_name): print('下載成功.') else: print('下載失敗') finally: transport.close() get('172.25.254.221','redhat','/mnt/test','/home/kiosk/test111.txt')
sftp.close() 關閉sftp
sftp.file(filename, mode=‘r’, bufsize=-1) 讀取文件
sftp.from_transport(s) 創建客戶端通道
sftp.open(filename, mode=‘r’, bufsize=-1) 在遠程服務器打開文件
sftp.put(localpath, remotepath, callback=None) localpath文件上傳到遠程服務器remotepath
sftp.get(remotepath, localpath, callback=None) 從遠程服務器remotepath拉文件到本地localpath
sftp.remove(path) 刪除文件
import paramiko # 創建SSH對象
ssh = paramiko.SSHClient() # 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 連接服務器
ssh.connect(hostname='192.168.1.1', port=22, username='weiheng', password='weiheng123')
# 獲取Transport對象
trans_obj = ssh_client.get_transport() sftp_obj = paramiko.SFTPClient.from_transport(trans_obj) sftp_obj.get_channel()
# 使用sftp_obj上傳和下載文件
sftp_obj.put('source','target') sftp_obj.get('source','target') # 執行命令
stdin, stdout, stderr = ssh.exec_command('ls') # 獲取命令結果
result = stdout.read()
# 關閉連接
ssh.close()
基於公鑰密鑰方式連接:
import paramiko private_key = paramiko.RSAKey.from_private_key_file('/home/haoren/.ssh/id_rsa') # 創建SSH對象
ssh = paramiko.SSHClient() # 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 連接服務器
ssh.connect(hostname='192.168.1.10', port=22, username='zt', key=private_key) # 執行命令
stdin, stdout, stderr = ssh.exec_command('ls -l') # 獲取命令結果
result = stdout.read() # 關閉連接
ssh.close()
批量連接主機
from paramiko.ssh_exception import NoValidConnectionsError,AuthenticationException def connect(cmd,hostname,user,password): import paramiko client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect( hostname=hostname, username=user, password=password ) stdin, stdout, stderr = client.exec_command(cmd) a = stdout.read().decode('utf-8') print(stdout.read().decode('utf-8')) return a except NoValidConnectionsError as e: return '主機%s連接失敗' %(hostname) except AuthenticationException as e: return '主機%s密碼錯誤' %(hostname) except Exception as e: return '未知錯誤:',e finally: client.close() with open('/home/kiosk/passwd') as f: ##文件格式按照下面的要求書寫(ip:用戶名:密碼)
for line in f: hostname,username,password = line.strip().split(':') res = connect('hostname',hostname,username,password) #調用函數 # print(hostname.center(50,'*'))
print('主機名:', res)
paramiko+threading 實現遠程服務器批量執行命令
#coding:utf-8
import sys import paramiko import threading def getConnection(ip,username,password,command,port = 22):
#實例化對象 ssh = paramiko.SSHClient() policy = paramiko.AutoAddPolicy() ssh.set_missing_host_key_policy(policy)
#連接 ssh.connect( hostname = ip, # 服務器的ip
port = port, # 服務器的端口
username = username, # 服務器的用戶名
password = password # 用戶名對應的密碼
)
#執行 stdin, stdout, stderr = ssh.exec_command(command) result = stdout.read().decode() error = stderr.read().decode() print("+++++++++++++++++++++++start++++++++++++++++++++") print("[connect success] | ip : %s" % ip) print("result: \n %s"%result) if error != " ": print("error: \n %s"%error) print("+++++++++++++++++++++++done++++++++++++++++++++") ssh.close()
#我們采用多線程
def main(host_list,command): thread_list = []
for ip,username,password in host_list:
thread = threading.Thread(target = getConnection, args = (ip,username,password,command)) thread_list.append(thread)
for t in thread_list: t.start() for t in thread_list: t.join() if __name__ == "__main__": host_list = [ ("192.168.2.186", "root", "123"), ("192.168.2.88", "root", "123"), ] command = sys.argv[1] main(host_list,command)
#單線程運行
from time import sleep def loop(num,sleeptime): """ 當前函數作為功能函數 :param num: 函數的編號 :param sleeptime: 睡眠的時間 """
print("loop %s is start"%num) sleep(sleeptime) print("loop %s is done"%num) def main(): sleep_list = [3,2] #睡眠時間
lenth = len(sleep_list) #獲取列表長度
print("all is start") for i in range(lenth): loop(i,sleep_list[i]) #按照列表長度和列表內容調用函數
print("all is down") if __name__ == "__main__": main() #多線程運行
import threading from time import sleep def loop(num,sleeptime): """ 當前函數作為功能函數 :param num: 函數的編號 :param sleeptime: 睡眠的時間 """
print("loop %s is start"%num) sleep(sleeptime) print("loop %s is done"%num) def main(): sleep_list = [3,2] #睡眠時間
lenth = len(sleep_list) #獲取列表長度
thread_list = [] print("all is start") for i in range(lenth):
#threading.Thread 就是用線程來執行我們的功能
t = threading.Thread(target = loop,args = (i,sleep_list[i])) #按照列表長度和列表內容調用函數
thread_list.append(t) #將生成的線程添加到列表里
for t in thread_list: t.start() #開始執行線程
for t in thread_list: t.join() #掛起線程,到所有線程結束
print("all is down")