目錄
1、 定義
模塊的定義:用來從邏輯上組織python代碼(變量、函數、類、邏輯:實現一個功能),本質上就是.py結尾的python文件(文件名:test.py,對應的模塊名:test)
包的定義:用來從邏輯上組織模塊,本質就是一個目錄(文件夾),必須帶有一個_ _ init _ _().py的文件
2、使用方法(導入方法)
import module_name
import module1_name, module2_name
from module_name import * # 不建議使用
from module_name import logger as log
from . import test # 從當前目錄下導入test,用在導入包下的模塊,寫在__init__.py文件中
3、import的本質
就是把python文件解釋一遍
import module_name --> modle_name = all_code
from module_name import name --> 進入module_name文件找到name
導入包的本質:就是解釋包下面的_ _ init _ _.py文件
要想導入包中的文件需要在init中導入模塊即可
這裏存在一個問題就是,模塊和要導入模塊的文件不在同一個目錄下該怎麼辦呢?看下面怎麼解決這個問題
import sys,os
print(sys.path) # 導入模塊時,是在這個列表中的路徑中查找我們要導入的模塊的
os.path.abspath(__file__) # 獲得當前文件的絕對路徑
os.path.dirname(os.path.abspath(__file__)) # 獲取上一層的絕對路徑
sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 加入列表
上面的方法,我們就可以找到需要導入的模塊的位置
4、導入優化
from module import test # 相比於import module速度更快
5、模塊的分類
a.標準庫
b.開源模塊
c.自定義模塊
自定義模塊和開源模塊的使用參考: http://www.cnblogs.com/wupeiqi/articles/4963027.html
6、內置模塊
time和datetime模塊
在python中,通常有這幾種方式來表示時間:
a.時間戳
時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。用time.time()來獲得這個偏移量,返回的是float類型,單位是秒。
注:1970年是unix誕生年
xue@xue-MacBookAir:~$ python3
Python 3.5.2 (default, Oct 8 2019, 13:06:37)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> time.time()
1577024037.3293345
>>> 1577024037.3293345/3600/24/365
50.0071041771098
>>> 1970+50
2020
>>>
b.格式化的時間字符串
c.元組(struct_time)共九個元素
UTC(Coordinated Universal Time)即格林威治天文時間,世界標準時間。在中國爲UTC+8(東八區,全球24個時區),比標準時間早8小時。DST(Daylight Saving Time)即夏令時。
>>> import time
>>> time.localtime()
time.struct_time(tm_year=2019, tm_mon=12, tm_mday=22, tm_hour=22, tm_min=24, tm_sec=23, tm_wday=6, tm_yday=356, tm_isdst=0)
tm_wday:一個星期中的第幾天,tm_yday:一年中的第幾天,tm_isdst:是不是夏令時
time.timezone # 當地時間和世界標準時間的差值,單位秒
time.gmtime() # 無參時,是把本地的時間傳入,轉換成struct_time,返回值是0區的時間
time.localtime() # 無參時,傳入的是本地時間,轉換成struct_time,返回值是本地的時間
x = time.localtime()
x.tm_year
time.mktime(struct_time) # struct_time轉換成時間戳
time.strftime(format, struct_time) # struct_time轉換成格式化的時間字符串
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
time.strptime(str, format) # 格式化的時間字符串轉換成struct_time
time.strftime('2019-12-22 23:12:32', "%Y-%m-%d %H:%M:%S")
time.asctime() # struct_time--->str
time.ctime() # timestamp--->str
import datetime
datetime.datetime.now() # 獲取當前的時間
datetime.datetime.now()+datetime.timedelta(3) # 當天時間+3天
datetime.datetime.now()+datetime.timedelta(-3) # 當天時間-3天
datetime.datetime.now()+datetime.timedelta(hours=3) # 當天時間+3h
datetime.datetime.now()+datetime.timedelta(hours=-3) # 當天時間-3h
datetime.datetime.now()+datetime.timedelta(minutes=3) # 當天時間+3分鐘
c_time = datetime.datetime.now()
c_time.replace(hour=3, minute=30) # 時間的替換
random模塊
import random
random.random() # [0, 1)之間的一個隨機浮點數
random.randint(1, 3) # [1, 3]之間的一個隨機整數
random.uniform(1, 3) # (1, 3)之間的隨機浮點數
random.randrange(1, 10, 2) # [1, 10)之間的一個隨機整數,步數爲2,步數不寫,默認爲1
random.choice()
random.choice("helloworld")
random.choice(["1","2","3","4","6","8","9"])
random.choice(("1","2","3","4","6","8","9"))
random.sample()
random.sample("hello") # 從前面的序列中,隨機的取兩位返回
random.shuffle(items) # 打亂順序
實際應用:
#隨機選取0到100間的偶數
random.randrange(0, 100, 2) # 4
#隨機浮點數
random.random() #0.2784394798375937597
random.uniform(1, 10) # 9.435457568567835
# 隨機字符
random.choice('asdsfdeerdgs') # f
#多個字符中選取特定數量的字符
random.sample('asdfghjkl', 3) # ['d', 'g', 'h']
#隨機選取字符串
random.choice(['apple', 'pear', 'banana', 'lemon']) # apple
#洗牌
items = [1,2,3,4,5,6,7,8]
random.shuffle(items)
隨機驗證碼的功能
# Author: Mr.Xue
# 2019.10.25
import random
checkcode = ''
for i in range(4):
tmp = random.randint(0,1)
if tmp == 1:
tmp2 = chr(random.randint(65, 90)) # ['A', 'Z']
checkcode += tmp2
else:
tmp2 = random.randint(0, 9)
checkcode += str(tmp2)
print(checkcode)
os模塊
提供對操作系統進行調用的接口
os.getcwd() # 獲取當前的工作目錄,返回str
os.chdir("dirname") # 切換目錄
os.curdir # 返回當前目錄
os.pardir # 返回上一級目錄
os.makedirs('dirname1/dirname2/dirname3') # 遞歸創建多級目錄
os.removedirs('dirname1') # 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,也刪除,以此類推
os.mkdir('dirname') # 生成單級目錄
os.rmdir('dirname') # 刪除單級目錄,若目錄不爲空則無法刪除,報錯
os.listdir('dirname') # 列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表形式打印
os.remove() # 刪除一個文件
os.rename('oldname', 'newname') # 重命名文件/目錄
os.stat('path/filename') # 獲取文件/目錄信息
os.sep # 輸出操作系統特定的路徑分隔符,win下爲"\\",linux下爲"/"
os.linesep # 輸出當前平臺使用的行終止符,win下爲"\r\n",linux下爲"\n"
os.pathsep # 輸出用於分割文件路徑的字符串,win下爲";",linux下爲":"
os.environ # 獲取系統環境變量,返回一個字典類型
os.name # 輸出字符串指示當前使用平臺,win下爲'nt',linux下爲'posix'
os.system("bash command") # 執行shell命令
os.path.abspath(path) # 返回path的絕對路徑
os.path.split(path) # 將path分割成目錄和文件名,返回一個元組
os.path.dirname(path) # 返回目錄,即文件所在的路徑
os.path.basename(path) # 返回path最後的文件名,如果path以'/'或'\'結尾,則返回空值
os.path.exists(path) # 如果path存在則返回True,否則返回False
os.path.isabs(path) # 如果path是絕對路徑,返回True,否則返回False
os.path.isfile(path) # 如果path是一個存在的文件,則返回True,否則返回False
os.path.isdir(path) # 如果path是一個存在的目錄,則返回True,否則返回False
os.path.join(path1[, path2[, ...]]) # 將多個路徑組合後返回
os.path.join(r'C:', r'\a.txt')
os.path.getatime(path) # 返回path所指向的文件或目錄的最後存取時間
os.path.getmtime(path) # 返回path所指向的文件或目錄的最後修改時間
sys模塊
sys.argv # 命令行參數List,第一個元素是程序本身的路徑
# test.py
import sys
print(sys.argv)
python3 test.py 1 2 3 4
sys.exit(n) # 退出程序,正常退出是exit(0)
sys.version # 獲取python解釋程序的版本信息
sys.maxint # 最大的Int值
sys.path # 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform # 返回操作系統平臺名稱
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]
shutil模塊
高級的文件、文件夾、壓縮包 處理模塊
shutil.copyfileobj(fsrc, fdst[, length]) # 把文件內容拷貝到另一個文件中,可以部分內容
# 源碼如下
def copyfileobj(fsrc, fdst, length=16*1024):
"""copy data from file-like object fsrc to file-like object fdst"""
while 1:
buf = fsrc.read(length)
if not buf:
break
fdst.write(buf)
# example
import shutil
f1 = open("本節筆記", encoding="utf-8")
f2 = open("筆記2", "w", encoding="utf-8")
shutil.copyfileobj(f1, f2)
shutil.copyfile(src, dst) # 拷貝文件
# 直接傳入文件名,就可以實現copy
shutil.copyfile("筆記1", "筆記2")
shutil.copymode(src, dst) # 僅拷貝權限,內容、組、 均不變
shutil.copystat(src, dst) # 拷貝狀態的信息,包括:mode bits, atime, mtime, flags
shutil.copy(src, dst) # 拷貝文件和權限
shutil.copy2(src, dst) # 拷貝文件和狀態信息
shutil.copytree(src, dst, symlink=False, ignore=None) # 遞歸的去拷貝文件目錄和文件
shutil.rmtree(dst) # 刪除目錄
shutil.move(src, dst) # 遞歸的去移到文件
"""
創建壓縮包並返回文件路徑,例如:zip、tar
base_name: 壓縮包的文件名,也可以是壓縮包的路徑,只是文件名時,則保存至當前目錄,否則保存至指定路徑,如:www ---> 保存至當前路徑;如:/User/xue/www ---> 保存至/User/xue
format: 壓縮包種類,如:zip, tar
root_dir: 要壓縮的文件夾路徑(默認當前目錄)
owner: 用戶,默認當前用戶
group: 組,默認當前組
logger: 用於記錄日誌,通常是logging.Logger對象
"""
shutil.make_archive(base_name, format, ...)
# example:
# 將/Users/xue/Downloads/test 下的文件打包放置當前程序目錄
import shutil
ret = shutil.make_archive("www", "gztar", root_dir="/Users/xue/Downloads/test")
# 將/Users/xue/Downloads/test 下的文件打包放置/Users/xue/目錄
import shutil
ret = shutil.make_archive("/Users/xue/www", "gztar",root_dir="/Users/xue/Downloads/test")
shutil對壓縮包的處理是調用ZipFile和TarFile兩個模塊來處理的,下面來詳細看看這兩個模塊
import zipfile
# 壓縮,單獨一個一個壓縮文件
z = zipfile.ZipFile('day5.zip', 'w')
z.write('a.log') # a.log是當前目錄下的一個文件
z.write('data.data')
z.close()
# 解壓
z = zipfile.ZipFile('day5.zip', 'r')
z.extractall()
z.close()
import tarfile
# 壓縮
tar = tarfile.open('your.tar', 'w')
tar.add("/Users/xue/bbs/bbs2.zip", arcname="bbs2.zip")
tar.add("/Users/xue/bbs/cmdb.zip", arcname="cmdb.zip")
tar.close()
# 解壓
tar = zipfile.ZipFile('day5.zip', 'r')
tar.extractall() # 可設置解壓地址
tar.close()
json & pickle 模塊
用於序列化的兩個模塊,解決了不同平臺不同語言之間的數據交換,pickle相比於json,能夠處理更復雜的數據類型
json: 用於字符串和puyhon數據類型進行轉換
pickle: 用於python特有的類型和python的數據類型進行轉換
Json模塊提供了四個功能:dumps, dump, loads, load
pickle模塊提供了四個功能:dumps, dump, loads, load
import pickle
data={'k1': 123, 'k2': 'hello'}
p_str = pickle.dumps(data)
print(p_str)
with open('D:/result.pk', 'w') as fp:
pickle.dump(data, fp)
shelve模塊
是一個簡單的k, v將內存數據通過文件持久化的模塊,可以持久化任何pickle可支持的python數據格式
import shelve
d = shelve.open('shelve_test') # 打開一個文件
class Test(object):
def __init__(self, n):
self.n = n
t = Test(123)
t2 = Test(123334)
name = ['bob', 'xue', 'rain']
# 寫入
d["test"] = name # 持久化列表
d["t1"] = t # 持久化類
d["t2"] = t2
# 讀出
d.get("test")
d.get("t")
d.close()
xml處理模塊
xml是實現不同語言或程序之間進行數據交換的協議,跟json差不多,在json還沒出來的時候,大家用的就是xml,xml格式如下:
<?xml version="1.0" encoding="utf-8" ?>
<data>
<a name="a1">
<to>Tove</to>
<from updated="yes">hello</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</a>
<a name="a2">
<to>bbb</to>
<from updated="yes">hello</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</a>
</data>
遍歷xml、修改、刪除
# Author: Mr.Xue
# 2019.10.27
import xml.etree.ElementTree as ET
tree = ET.parse('xmltree.xml')
root = tree.getroot()
print(root.tag)
## 遍歷xml文檔
#for child in root:
#print(child.tag, child.attrib)
#for i in child:
#print(i.tag, i.text)
## 只遍歷from節點
#for node in root.iter('from'):
#print(node.tag, node.text)
## 修改
#for node in root.iter("from"):
#new_from = 'hello' # 字符串變量new_from
#node.text = new_from # 賦值,修改顯示信息
#node.set("updated", 'yes') # 加了個屬性
#tree.write('xmltree.xml')
# 刪除
for a in root.findall('a'):
to = a.find('to').text
if to == 'bbb':
root.remove(a)
tree.write('xmltree2.xml')
自己創建xml文件
# Author: Mr.Xue
# 2019.10.27
import xml.etree.ElementTree as ET
new_xml = ET.Element("name_list")
name = ET.SubElement(new_xml, 'name', attrib={"enrolled": 'yes'})
age = ET.SubElement(name, 'age', attrib={"checked": 'no'})
sex = ET.SubElement(name, 'sex')
age.text = '33'
name2 = ET.SubElement(new_xml, 'name', attrib={'enrolled': 'no'})
age = ET.SubElement(name2, 'age')
age.text = '18'
et = ET.ElementTree(new_xml) # 生成文檔對象
et.write('test.xml', encoding='utf-8', xml_declaration=True)
ET.dump(new_xml) # 打印生成的格式
result:
<?xml version='1.0' encoding='utf-8'?>
<name_list>
<name enrolled="yes">
<age checked="no">33</age>
<sex />
</name>
<name enrolled="no">
<age>18</age>
</name>
</name_list>
PyYAML模塊
Python也可以很容易的處理ymal文檔格式,只不過需要安裝一個模塊,參考文檔:http://pyyaml.org/wiki/PyYAMLDocumentation
ConfigParser模塊
用於生成和修改常見配置文檔,當前模塊的名稱在python3.x版本中變更爲configparser,常見文檔格式如下:
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
怎麼用python生成這樣一個文件呢?
# Author: Mr.Xue
# 2019.10.27
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9'}
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022'
topsecret["ForwardX11"] = 'no'
config["DEFAULT"]["ForwardX11"] = 'yes'
with open('example.ini', 'w') as configfile:
config.write(configfile)
讀、改、刪
# Author: Mr.Xue
# 2019.10.27
import configparser
conf = configparser.ConfigParser()
conf.read('example.ini')
#print(conf.sections())
#print(conf['bitbucket.org']["User"])
#print(conf.defaults())
# modify
sec = conf.remove_section('bitbucket.org')
conf.write(open('example.cfg', 'w'))
hashlib、hmac模塊
hashlib
用於加密的相關操作,3.x裏面hashlib替代了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 算法
# Author: Mr.Xue
# 2019.10.27
import hashlib
m = hashlib.md5()
m.update(b"hello")
print(m.digest()) #2進制格式hash
print(m.hexdigest()) #16進制格式hash
m.update(b"It's me")
#m.update("薩達打".encode(encoding='utf-8'))
print(m.hexdigest())
m2 = hashlib.md5()
m2.update(b"helloIt's me")
print(m2.hexdigest())
s = hashlib.sha1()
s.update(b"helloIt's me")
print(s.hexdigest())
hmac
散列消息鑑別碼,簡稱HMAC,是一種基於消息鑑別碼MAC(Message Authentication Code)的鑑別機制。使用HMAC時,消息通訊的雙方,通過驗證消息中加入的鑑別密鑰K來鑑別消息的真僞;它內部對我們創建 key 和 value 再進行處理然後再加密
一般用於網絡通信中消息加密,前提是雙方先要約定好key,就像接頭暗號一樣,然後消息發送把用key把消息加密,接收方用key + 消息明文再加密,拿加密後的值 跟 發送者的相對比是否相等,這樣就能驗證消息的真實性,及發送者的合法性了。
import hmac # 主要用於消息加密,速度比較快
#h = hmac.new(b'wueiqi') # key, value
#h.update(b'hellowo')
#h = hmac.new(b"wueiqi", b'hellowo')
h = hmac.new("天王蓋地虎".encode(encoding='utf-8'), '寶塔鎮河妖'.encode(encoding='utf-8'))
print(h.hexdigest())
正則表達式Re模塊
常用正則表達式符號
'.' 默認匹配除\n之外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行
'^' 匹配字符開頭
'$' 匹配字符結尾
'*' 匹配*號前的字符0次或多次,re.findall("ab*", "cabb3abcbbac"),結果爲['abb', 'ab', 'a']
'+' 匹配前一個字符1次或多次,re.findall("ab+", "ab+cd+abb+bba"),結果爲['ab', 'abb']
'?' 匹配?前面的字符1次或0次
'{m}' 匹配前一個字符m次
'{n,m}' 匹配前一個字符n到m次,re.findall("ab{1,3}", "abbabcabbcbbb"),結果爲['abb', 'ab', 'abb']
'|' 匹配|左或右的字符,re.search('abc|ABC', "ABCBabcCD").group(),結果爲'ABC'
'(...)' 分組匹配,re.search("(abc){2}a(123|456)c","abcabca456c").group(),結果abcabca456c
'\A' 只從字符串開頭匹配,如'^',re.search("\Aabc", "alexabc")是匹配不到的
'\Z' 匹配字符結尾,同'$'
'\d' 匹配數字0-9,只匹配一個
'\D' 匹配非數字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
'\s' 匹配空白字符、\t、\n、\r,re.search("\s+", "ab\tc1\n3").group() 結果爲'\t'
最常用的匹配語法
re.match 從頭開始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到列表中返回
re.splitall 以匹配到的字符當做列表分隔符
re.sub 匹配字符並替換
#example:
xue@xue-MacBookAir:~$ python3
Python 3.5.2 (default, Oct 8 2019, 13:06:37)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> re.match("^Chen", "ChenRonghua123")
<_sre.SRE_Match object; span=(0, 4), match='Chen'>
>>> res = re.match("^Chen", "ChenRonghua123")
>>> res.group()
'Chen'
>>> res = re.match("^Chen\d+", "Chen123Ronghua123")
>>> res.group()
'Chen123'
>>> re.search("R[a-z]+", "Chen123Ronghua123")
<_sre.SRE_Match object; span=(7, 14), match='Ronghua'>
>>> re.search("R[a-z]+", "Chen123Ronghua123Ronghua###")
<_sre.SRE_Match object; span=(7, 14), match='Ronghua'>
>>> re.search("a?", "alex")
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.search("a?", "aalex")
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.search("a?", "lex")
<_sre.SRE_Match object; span=(0, 0), match=''>
>>> re.search("[0-9]{3}", "a12l324ex")
<_sre.SRE_Match object; span=(4, 7), match='324'>
>>> re.search("[0-9]{1,3}", "a12l324ex")
<_sre.SRE_Match object; span=(1, 3), match='12'>
>>> re.findall("[0-9]{1,3}", "a12l324ex")
['12', '324']
>>> re.search("(abc){2}", "a12l324exabcabcabc")
<_sre.SRE_Match object; span=(9, 15), match='abcabc'>
>>> re.search("(abc){2}\|", "a12l324exabcabcabc|")
<_sre.SRE_Match object; span=(12, 19), match='abcabc|'>
>>> re.search("\A[0-9]+[a-z]\Z", "123435d")
<_sre.SRE_Match object; span=(0, 7), match='123435d'>
分組匹配
>>> re.search("(?P<id>[0-9]+)(?P<name>[A-Za-z]+)", "abcd1234efg567").groupdict()
{'id': '1234', 'name': 'efg'}
>>> re.split("[0-9]", "abc123de45gh")
['abc', '', '', 'de', '', 'gh']
>>> re.split("[0-9]+", "abc123de45gh")
['abc', 'de', 'gh']
>>> re.sub("[0-9]+", "|", "abc12de3f45GH")
'abc|de|f|GH'
>>> re.sub("[0-9]+", "|", "abc12de3f45GH", count=2)
'abc|de|f45GH'
>>> re.search(r"\\\\", r"12343\\5dd")
<_sre.SRE_Match object; span=(5, 7), match='\\\\'>
>>> re.search(r"\\", r"12343\5dd")
<_sre.SRE_Match object; span=(5, 6), match='\\'>
匹配模式:
re.I(re.IGNORECASE): 忽略大小寫
re.I(re.IGNORECASE): 忽略大小寫(括號內是完整寫法,下同)
M(MULTILINE): 多行模式,改變'^'和'$'的行爲(參見上圖)
S(DOTALL): 點任意匹配模式,改變'.'的行爲
>>> re.search("[a-z]+", "abcdE", flags=re.I)
<_sre.SRE_Match object; span=(0, 5), match='abcdE'>
logging模塊
參考:
https://www.cnblogs.com/alex3714/articles/5161349.html
paramiko模塊
該模塊基於SSH用於連接遠程服務器並執行相關操作
SSHClient
用於連接遠程服務器並執行基本命令
基於用戶名密碼連接:
import paramiko
# 創建SSH對象
ssh = paramiko.SSHClient()
# 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務器
ssh.connect(hostname='c1.salt.com', port=22, username='root', password='123')
# 執行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 獲取命令結果
res, err = stdout.read(), stderr.read()
s = res if res else err
print(s)
# 關閉連接
ssh.close()
# SSHClient 封裝 Transport
import paramiko
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='root', password='123')
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
print stdout.read()
transport.close()
基於公鑰密鑰連接:
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
# 創建SSH對象
ssh = paramiko.SSHClient()
# 允許連接不在know_hosts文件中的主機
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 連接服務器
ssh.connect(hostname='c1.salt.com', port=22, username='root', pkey=private_key)
# 執行命令
stdin, stdout, stderr = ssh.exec_command('df')
# 獲取命令結果
result = stdout.read()
# 關閉連接
ssh.close()
# SSHClient 封裝 Transport
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='root', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
transport.close()
#基於私鑰字符串進行連接
import paramiko
from io import StringIO
key_str = """-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAq7gLsqYArAFco02/55IgNg0r7NXOtEM3qXpb/dabJ5Uyky/8
NEHhFiQ7deHIRIuTW5Zb0kD6h6EBbVlUMBmwJrC2oSzySLU1w+ZNfH0PE6W6fans
H80whhuc/YgP+fjiO+VR/gFcqib8Rll5UfYzf5H8uuOnDeIXGCVgyHQSmt8if1+e
7hn1MVO1Lrm9Fco8ABI7dyv8/ZEwoSfh2C9rGYgA58LT1FkBRkOePbHD43xNfAYC
tfLvz6LErMnwdOW4sNMEWWAWv1fsTB35PAm5CazfKzmam9n5IQXhmUNcNvmaZtvP
c4f4g59mdsaWNtNaY96UjOfx83Om86gmdkKcnwIDAQABAoIBAQCnDBGFJuv8aA7A
ZkBLe+GN815JtOyye7lIS1n2I7En3oImoUWNaJEYwwJ8+LmjxMwDCtAkR0XwbvY+
c+nsKPEtkjb3sAu6I148RmwWsGncSRqUaJrljOypaW9dS+GO4Ujjz3/lw1lrxSUh
IqVc0E7kyRW8kP3QCaNBwArYteHreZFFp6XmtKMtXaEA3saJYILxaaXlYkoRi4k8
S2/K8aw3ZMR4tDCOfB4o47JaeiA/e185RK3A+mLn9xTDhTdZqTQpv17/YRPcgmwz
zu30fhVXQT/SuI0sO+bzCO4YGoEwoBX718AWhdLJFoFq1B7k2ZEzXTAtjEXQEWm6
01ndU/jhAasdfasdasdfasdfa3eraszxqwefasdfadasdffsFIfAsjQb4HdkmHuC
OeJrJOd+CYvdEeqJJNnF6AbHyYHIECkj0Qq1kEfLOEsqzd5nDbtkKBte6M1trbjl
HtJ2Yb8w6o/q/6Sbj7wf/cW3LIYEdeVCjScozVcQ9R83ea05J+QOAr4nAoGBAMaq
UzLJfLNWZ5Qosmir2oHStFlZpxspax/ln7DlWLW4wPB4YJalSVovF2Buo8hr8X65
lnPiE41M+G0Z7icEXiFyDBFDCtzx0x/RmaBokLathrFtI81UCx4gQPLaSVNMlvQA
539GsubSrO4LpHRNGg/weZ6EqQOXvHvkUkm2bDDJAoGATytFNxen6GtC0ZT3SRQM
WYfasdf3xbtuykmnluiofasd2sfmjnljkt7khghmghdasSDFGQfgaFoKfaawoYeH
C2XasVUsVviBn8kPSLSVBPX4JUfQmA6h8HsajeVahxN1U9e0nYJ0sYDQFUMTS2t8
RT57+WK/0ONwTWHdu+KnaJECgYEAid/ta8LQC3p82iNAZkpWlGDSD2yb/8rH8NQg
9tjEryFwrbMtfX9qn+8srx06B796U3OjifstjJQNmVI0qNlsJpQK8fPwVxRxbJS/
pMbNICrf3sUa4sZgDOFfkeuSlgACh4cVIozDXlR59Z8Y3CoiW0uObEgvMDIfenAj
98pl3ZkCgYEAj/UCSni0dwX4pnKNPm6LUgiS7QvIgM3H9piyt8aipQuzBi5LUKWw
DlQC4Zb73nHgdREtQYYXTu7p27Bl0Gizz1sW2eSgxFU8eTh+ucfVwOXKAXKU5SeI
+MbuBfUYQ4if2N/BXn47+/ecf3A4KgB37Le5SbLDddwCNxGlBzbpBa0=
-----END RSA PRIVATE KEY-----"""
private_key = paramiko.RSAKey(file_obj=StringIO(key_str))
transport = paramiko.Transport(('10.0.1.40', 22))
transport.connect(username='root', pkey=private_key)
ssh = paramiko.SSHClient()
ssh._transport = transport
stdin, stdout, stderr = ssh.exec_command('df')
result = stdout.read()
transport.close()
print(result)
SFTPClient
用於連接遠程服務器並執行上傳下載
基於用戶名密碼上傳下載
import paramiko
transport = paramiko.Transport(('hostname',22))
transport.connect(username='root',password='123')
sftp = paramiko.SFTPClient.from_transport(transport)
# 將location.py 上傳至服務器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 將remove_path 下載到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
基於公鑰密鑰上傳下載
import paramiko
private_key = paramiko.RSAKey.from_private_key_file('/home/auto/.ssh/id_rsa')
transport = paramiko.Transport(('hostname', 22))
transport.connect(username='root', pkey=private_key )
sftp = paramiko.SFTPClient.from_transport(transport)
# 將location.py 上傳至服務器 /tmp/test.py
sftp.put('/tmp/location.py', '/tmp/test.py')
# 將remove_path 下載到本地 local_path
sftp.get('remove_path', 'local_path')
transport.close()
補充
RSA:非對稱密鑰驗證
- 公鑰
- 私鑰
比如說:
10.0.0.31請求去連接10.0.0.41,那麼
私鑰放在31,公鑰放在41
需要先在31上生成鑰匙對,用命令ssh-keygen,默認保存在當前用戶的家目錄下
用more /root/.ssh/id_rsa.pub查看公鑰,拷貝到41去,用vim .ssh/authorized_keys打開需要粘貼的位置
除了這個方法,還可以用以下命令來拷貝公鑰,ssh-copy-id “-p52113 [email protected]”
ssh [email protected] -p53112這條命令是Linux中遠程登錄另一臺機器的命令
rwx rwx rwx
421
屬主屬組屬others
可讀可寫可執行