使用Python自動(dòng)執(zhí)行SSH和SCP任務(wù)

我最近幫助了一個(gè)朋友在100多個(gè)設(shè)備上刷新軟件虽缕。對(duì)于每個(gè)設(shè)備始藕,他都知道MAC地址,并具有通過(guò)ssh登錄的相應(yīng)密碼氮趋。他將此信息存儲(chǔ)在Excel工作表中伍派。他手動(dòng)閃爍的過(guò)程是

  1. 根據(jù)設(shè)備的MAC地址找出設(shè)備的IP地址。
  2. 使用IP地址和密碼SSH進(jìn)入設(shè)備剩胁。
  3. 通過(guò)SCP上載軟件安裝程序诉植。
  4. 執(zhí)行一些Shell命令以安裝軟件。

在一臺(tái)設(shè)備上手動(dòng)執(zhí)行此操作就可以了昵观,對(duì)于兩臺(tái)設(shè)備晾腔,您開(kāi)始考慮wtf舌稀,三臺(tái)設(shè)備之后,您就會(huì)想到WTF灼擂!在軟件中壁查,減少WTF始終是一個(gè)目標(biāo),因此我想也許我可以通過(guò)使用漂亮的Python腳本自動(dòng)化他的過(guò)程來(lái)為他提供幫助剔应。在本文中睡腿,我想向您展示最終的結(jié)果。

查找給定了MAC地址的IP地址

我們需要解決的第一件事是找出我們本地網(wǎng)絡(luò)內(nèi)部設(shè)備的IP地址领斥。為此嫉到,您的PC和設(shè)備都必須連接到同一網(wǎng)絡(luò)。給定一個(gè)IP地址月洛,您可以使用python模塊scapy(請(qǐng)注意何恶,我在本文的先前版本中使用了其他軟件包。但是嚼黔,這僅在我已經(jīng)連接到或?qū)α硪粋€(gè)設(shè)備執(zhí)行ping操作時(shí)才有效)哪個(gè)MAC地址使用IP细层。在代碼中,這看起來(lái)像

from scapy.layers.l2 import arping
def get_mac_and_ip(suffix: int) -> Tuple[str, str]:
    ip = f"192.168.1.{suffix}"
    ans, _ = arping(ip, timeout=.2, verbose=False)
    for s, r in ans.res:
        st="%19s,Ether.src% %ARP.psrc%"
        return tuple(r.sprintf(st).strip().split())

    return ("DONT", "CARE")
mac_to_ip = dict(get_mac_and_ip(suffix) for suffix in range(1, 256))

因此唬涧,我們只測(cè)試每個(gè)IP地址并存儲(chǔ)回送MAC地址的IP地址疫赎。使用scapy時(shí),您需要以root用戶身份執(zhí)行腳本碎节。太酷了捧搞,現(xiàn)在我們知道所有MAC地址到IP地址的連接。下一個(gè)問(wèn)題剩下三個(gè)狮荔。

建立SSH連接

下一個(gè)問(wèn)題是胎撇,我們?nèi)绾问褂肞ython建立SSH連接。有一個(gè)名為paramiko的簡(jiǎn)潔庫(kù)殖氏,使您可以非常簡(jiǎn)單地完成此操作晚树。從根本上講,您需要要連接的IP地址雅采,用戶名和密碼爵憎。代碼看起來(lái)像

import paramiko
# To allow connection without having to accept the host connection
# We need to use this policy. I've just pulled it here due to 
# mediums way of displaying code ...
policy = paramiko.client.AutoAddPolicy
# Iterate over all our found mac, ip connections and SSH into
# the clients
for mac, ip in mac_to_ip.items():
    # Assume that to be given
    pwd = mac_to_pwd[mac]
with paramiko.SSHClient() as client:
        client.set_missing_host_key_policy(policy)
        try:
            client.connect(ip, username='root', password=pwd)
        except paramiko.ssh_exception.NoValidConnectionsError:
            print("Connection failed")

現(xiàn)在,我們可以使用連接的客戶端執(zhí)行Shell命令婚瓜,您將很快看到它宝鼓。

通過(guò)SCP上傳數(shù)據(jù)

在執(zhí)行命令之前,我們需要將安裝程序上載到我們的設(shè)備巴刻。為此席函,我們利用庫(kù)SCP,該庫(kù)與paramiko完美配合冈涧。在下面的示例中茂附,假設(shè)我們已經(jīng)使用paramiko SSHClient建立了連接正蛙。

from scp import SCPClient 
import sys
def progress4(f, size, sent, p):
    prog = sent / size * 100.
    sys.stdout.write(f"({p[0]}:{p[1]}) {f}\'s progress: {prog}\r")
local_path = "/home/me/installer.tar.gz"
remote_path = "/home/root/inst/"
with SCPClient(client.get_transport(), progress4=progress4) as scp:
    scp.put(local_path, remote_path=remote_path)

progress4功能打印出的上傳進(jìn)度。對(duì)我來(lái)說(shuō)营曼,這有助于估算我仍然需要等待多長(zhǎng)時(shí)間而又不會(huì)變得急躁乒验,這可能會(huì)導(dǎo)致另一個(gè)WTF :)。現(xiàn)在我們快到了蒂阱,只剩一步了锻全。

通過(guò)SSH執(zhí)行Shell命令

現(xiàn)在,由于我們具有正在運(yùn)行的ssh連接并上傳了安裝程序录煤,因此我們只需解壓縮它并運(yùn)行它鳄厌。這可以通過(guò)我們可以使用SSH客戶端發(fā)送的shell命令輕松完成。在代碼中妈踊,這看起來(lái)像

def exec_blocking(cmd, client):
    print(f"Executing {cmd}")
    _, stdout_, stderr_ = client.exec_command(cmd)
    status = stdout_.channel.recv_exit_status()
    print(f"STATUS {status}")
    for line in stdout_.readlines():
        print(line)
    if status != 0:
        errors = "\n".join(list(stderr_.readlines))
        raise Exception(f"{cmd} failed with {errors}")
# Unpack the installer 
exec_blocking("tar xzvf /home/root/inst/installer.xzvf", client)
# Run the installer
exec_blocking("./installer/install.sh", client)

該命令將通過(guò)exec_command發(fā)送到設(shè)備了嚎。這是一個(gè)立即返回的非阻塞函數(shù)。要等到命令完成執(zhí)行廊营,您需要調(diào)用recv_exit_status()歪泳。這樣,您可以確保命令執(zhí)行成功與否露筒。

結(jié)論

將所有代碼段組合到一個(gè)腳本中呐伞,使我們可以使用單個(gè)命令在列表中所有設(shè)備上刷新/執(zhí)行命令。這為我們節(jié)省了很多時(shí)間和WTF :)

希望您學(xué)到了一些新知識(shí)慎式。感謝您的關(guān)注伶氢,并隨時(shí)與我聯(lián)系以提出問(wèn)題,意見(jiàn)或建議瘪吏。

翻譯自:https://medium.com/@simon.hawe/save-time-by-automating-ssh-and-scp-tasks-with-python-e149de606c7b

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鞍历,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子肪虎,更是在濱河造成了極大的恐慌,老刑警劉巖惧蛹,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扇救,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡香嗓,警方通過(guò)查閱死者的電腦和手機(jī)迅腔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)靠娱,“玉大人沧烈,你說(shuō)我怎么就攤上這事∠裨疲” “怎么了锌雀?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蚂夕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我腋逆,道長(zhǎng)婿牍,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任惩歉,我火速辦了婚禮等脂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撑蚌。我一直安慰自己上遥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布争涌。 她就那樣靜靜地躺著粉楚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪第煮。 梳的紋絲不亂的頭發(fā)上解幼,一...
    開(kāi)封第一講書(shū)人閱讀 51,231評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音包警,去河邊找鬼撵摆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛害晦,可吹牛的內(nèi)容都是我干的特铝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼壹瘟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鲫剿!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起稻轨,我...
    開(kāi)封第一講書(shū)人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灵莲,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后殴俱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體政冻,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躏精。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖苦锨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤舟舒,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布拉庶,位于F島的核電站,受9級(jí)特大地震影響魏蔗,放射性物質(zhì)發(fā)生泄漏砍的。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一莺治、第九天 我趴在偏房一處隱蔽的房頂上張望廓鞠。 院中可真熱鬧,春花似錦谣旁、人聲如沸床佳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)砌们。三九已至,卻和暖如春搁进,著一層夾襖步出監(jiān)牢的瞬間浪感,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工饼问, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留影兽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓莱革,卻偏偏與公主長(zhǎng)得像峻堰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盅视,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容