:從批量SSH到巡檢告警腳本)
講個在運維圈很常見的場景凌晨三點某臺機器磁盤告警你第一反應(yīng)不是查監(jiān)控平臺而是挨個 ssh 上去執(zhí)行df -h。我剛做運維那會兒手底下二十多臺服務(wù)器每次巡檢、發(fā)版本、看日志全靠人肉登錄一天下來一半時間都花在重復(fù)敲命令上。后來痛定思痛把所有能固化的操作都改成了 Python 自動化運維腳本才慢慢把這種“救火式運維”變成“躺平式巡檢”。這篇內(nèi)容不整虛的從 Python 環(huán)境怎么配、虛擬環(huán)境怎么建、常用庫怎么選到批量執(zhí)行命令、系統(tǒng)巡檢、定時任務(wù)全程按實際運維場景寫你拿到就能照著改。純 Shell 也能寫自動化但一旦碰到字符串處理、異常捕獲、多線程這種復(fù)雜邏輯Shell 寫起來特別難受Python 的優(yōu)勢就在這里。不管你是剛?cè)胄械男“走€是寫了多年 Shell 的老手只要想把“登錄服務(wù)器敲命令”變成“跑一條腳本出結(jié)果”這篇文章都值得花十分鐘看完。我會盡量把參數(shù)、坑、避雷方法都交代清楚。1. 環(huán)境準備Python版本、虛擬環(huán)境與安裝庫的那些坑1.1 版本選擇不是越新越好先聊版本。很多新手上來就裝最新版 Python然后照著老教程寫代碼結(jié)果庫裝不上或者 API 對不上。自動化運維場景下的 Python我建議直接用 3.10 或 3.8 這種穩(wěn)定到不能再穩(wěn)定的版本而不是追新。原因很簡單運維要的是可預(yù)測性生產(chǎn)環(huán)境跑著的腳本不會因為你手癢升級了一個大版本就自動適配。你本地跑得歡到了服務(wù)器上 Python 3.6 直接報語法錯誤這種事我見過太多次了。還有一條血淚教訓(xùn)系統(tǒng)自帶的 Python 不要動。尤其 CentOS 7 那批機器yum 依賴系統(tǒng)里的 Python 2.7你要是手賤把它升級或者替換了大概率 yum 直接廢掉到時候連包都裝不上。Ubuntu 22.04 自帶 Python 3.10裝上python3-venv和python3-pip就能用省事很多。在服務(wù)器上裝新 Python 時盡量用官方源碼編譯或者系統(tǒng)包管理器裝不要直接去覆蓋/usr/bin/python3。我的習(xí)慣是系統(tǒng)環(huán)境保持出廠狀態(tài)所有項目依賴都隔離走。1.2 venv虛擬環(huán)境運維腳本的隔離區(qū)提到隔離就繞不開venv。你可以把虛擬環(huán)境理解成給每個項目單獨分一個小房間不同的項目有不同的依賴版本互相不干擾。運維腳本雖然是腳本但依賴收斂同樣重要。你在一臺機器上給系統(tǒng) Python 裝了 paramiko下個月裝另一個工具不小心把 paramiko 升級了線上腳本可能就崩了。所以我固定操作是為運維項目單獨建一個 venv名字就叫ops裝什么都扔進去跑腳本也全都用這個環(huán)境里的 Python 解釋器。創(chuàng)建方式很簡單python3 -m venv ~/venvs/ops source ~/venvs/ops/bin/activate pip install paramiko psutil建好之后把當(dāng)前環(huán)境里的依賴導(dǎo)出成requirements.txt方便在別的機器上復(fù)現(xiàn)pip freeze requirements.txt這里有個細節(jié)在 crontab 或 systemd timer 里跑腳本時source activate不一定生效所以別依賴激活狀態(tài)直接寫 venv 里 Python 的絕對路徑比如~/venvs/ops/bin/python。關(guān)于這個坑后面第 5 章還會細說。1.3 pip安裝時報錯怎么破安裝庫最容易翻車的不是庫本身而是環(huán)境。“bash: pip: command not found” 這個報錯在新裝機的 Linux 上非常經(jīng)典。解決辦法不是找什么 get-pip.py 腳本而是先看系統(tǒng)包管理器里有沒有對應(yīng)的包Debian 系直接apt install python3-pipRHEL 系用yum install python3-pip。裝完之后我仍然建議只在 venv 里用 pip。另一個常見問題是權(quán)限。直接用sudo pip install xxx到系統(tǒng)目錄短期看著爽長期就是給自己埋雷。系統(tǒng)包管理器管理的 Python 包和 pip 裝的包經(jīng)常互相沖突升級一個庫可能帶崩另一個工具。我現(xiàn)在的原則很明確系統(tǒng) Python 只用于系統(tǒng)工具業(yè)務(wù)腳本一律進 venv。如果碰到編譯類安裝失敗比如error: command gcc failed with exit status 1通常是缺 Python 頭文件。Debian 系裝python3-devRHEL 系裝python3-devel裝完再重新 pip install 就好。這個問題在新版 paramiko 或 cryptography 編譯的時候特別容易觸發(fā)別慌先把頭文件補齊。至于 pip 下載慢那就配國內(nèi)鏡像源執(zhí)行一次就行pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/現(xiàn)在很多云主機在境內(nèi)不配鏡像的話裝個大一點的庫能等半天配置之后速度立刻就不一樣了。2. 入門庫速查先搞清楚你要處理什么場景2.1 標(biāo)準庫已經(jīng)能解決一半問題說到 Python 做自動化運維很多人第一反應(yīng)是裝這個庫裝那個庫但其實標(biāo)準庫已經(jīng)能解決一半以上的問題。比如shutil一個copytree就能把整個目錄連文件結(jié)構(gòu)復(fù)制過去比 Shell 里各種find、cp拼接要可靠得多。再比如glob掃描一批符合模式的日志文件幾行代碼就能做歷史日志歸檔。這些標(biāo)準庫不需要額外安裝正因為免費反而容易被忽略。還有一個被低估的是subprocess。想在 Python 里執(zhí)行外部命令、拿返回結(jié)果標(biāo)準做法是import subprocess result subprocess.run([df, -h], capture_outputTrue, textTrue) print(result.stdout)注意這里傳入的參數(shù)是一個列表而不是一整條字符串。用列表傳參可以避免很多 Shell 注入和轉(zhuǎn)義問題。有些教程為了省事直接寫shellTrue這在自動化場景里其實有風(fēng)險因為一旦命令里有不可信的外部輸入容易出問題。運維腳本里如果必須拼接命令我會先確認命令來源絕對可信否則盡量用列表形式。2.2 遠程操作三件套paramiko、fabric、netmiko遠程管理是自動化運維的重頭戲。如果只想寫個腳本連幾臺機器跑點命令paramiko是最直接的。它在底層實現(xiàn)了 SSH 協(xié)議給你封裝好 SSHClient 和 SFTP 兩個接口既可以執(zhí)行命令也能傳文件。fabric則在 paramiko 之上又包了一層任務(wù)和上下文管理適合做部署動作但坦白講fabric 的 API 變化比較快新老版本用法差異大新手容易對著老教程踩坑。netmiko是面向網(wǎng)絡(luò)設(shè)備的專門處理設(shè)備 CLI 的交互細節(jié)比如分頁符、命令回顯長度這類問題。你要維護一堆交換機路由器用 paramiko 裸連會很痛苦因為網(wǎng)絡(luò)設(shè)備經(jīng)常有分頁和交互提示符netmiko 把這些細節(jié)都處理好了。這幾個庫的定位差異我用一張表格列出來庫定位適用場景上手難度paramikoSSH 協(xié)議庫服務(wù)器批量命令、文件傳輸中fabric基于 paramiko 的任務(wù)封裝部署腳本、遠程批量執(zhí)行中netmiko網(wǎng)絡(luò)設(shè)備交互庫交換機路由器配置巡檢、批量下發(fā)低中ansible自動化引擎/框架配置管理、多主機編排偏高Ansible 其實不算庫它是一個獨立的自動化框架用 Python 寫的也支持插件擴展。如果你的環(huán)境允許免密 SSH寫 playbook 確實很爽但如果只是臨時處理幾臺機器Python 腳本反而更輕不用引入一套新的編排語法。2.3 系統(tǒng)信息采集不用再讀 /proc寫巡檢腳本時系統(tǒng)信息采集是最基礎(chǔ)的活兒。傳統(tǒng)做法是去讀/proc/loadavg、/proc/meminfo這些文件或者調(diào)free、df、uptime命令再解析輸出。不是不行就是麻煩而且不同系統(tǒng)輸出格式有差異。我后來的選擇是直接用psutil這個庫把所有系統(tǒng)指標(biāo)都封裝成了函數(shù)跨平臺表現(xiàn)一致。import psutil print(psutil.cpu_percent(interval1)) print(psutil.virtual_memory().percent) print(psutil.disk_usage(/).percent)psutil還能拿進程列表、網(wǎng)絡(luò)連接數(shù)做告警和排查非常順手。后面第 4 章的健康巡檢腳本我會基于它寫一個完整的例子。2.4 通知與調(diào)度的庫怎么選腳本跑完總要讓人知道結(jié)果。標(biāo)準庫里的logging負責(zé)把日志寫到文件smtplib負責(zé)發(fā)郵件。定時調(diào)用不推薦在 Python 進程里自己做除非是開發(fā)環(huán)境臨時用。生產(chǎn)環(huán)境直接用 crontab 或者 systemd timer 更穩(wěn)妥因為操作系統(tǒng)層面的調(diào)度不依賴你的腳本進程一直活著。進程內(nèi)調(diào)度方案像schedule、apscheduler更適合開發(fā)環(huán)境或 Windows 服務(wù)器上不方便配計劃任務(wù)的場景放到正式環(huán)境容易遇到進程被殺、時間漂移這些坑。3. 第一個實用腳本批量SSH執(zhí)行命令3.1 先拆需求再寫功能很多人一上來就寫代碼結(jié)果寫到一半發(fā)現(xiàn)沒想清楚要干嘛。批量執(zhí)行命令這個腳本核心需求其實就三條能連接一批服務(wù)器、能執(zhí)行指定命令、能把結(jié)果收集回來??此坪唵蔚欠诺蕉_機器上串行跑太慢并發(fā)太高又容易被服務(wù)器拒絕所以還得考慮并發(fā)度。基于這些我選了 paramiko 而不是直接用系統(tǒng)ssh命令原因就是 paramiko 的異常處理更可控你能區(qū)分是認證失敗、連接超時還是命令執(zhí)行失敗。3.2 一個可用的paramiko批量執(zhí)行腳本直接給一個能跑的版本假設(shè)你已經(jīng)有 SSH 密鑰服務(wù)器列表寫在代碼里。生產(chǎn)環(huán)境建議把列表挪到配置文件后面我會說怎么改。#!/usr/bin/env python3 import paramiko import logging from concurrent.futures import ThreadPoolExecutor HOSTS [ {host: 192.168.1.10, user: ops, key_filename: /home/user/.ssh/id_rsa}, {host: 192.168.1.11, user: ops, key_filename: /home/user/.ssh/id_rsa}, ] COMMANDS [hostname, uptime, df -h] logging.basicConfig( levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, filename/tmp/batch_run.log ) def run_on_host(item): ssh paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect( hostnameitem[host], usernameitem[user], key_filenameitem[key_filename], timeout10, banner_timeout10, auth_timeout10, ) for cmd in COMMANDS: stdin, stdout, stderr ssh.exec_command(cmd, timeout15) out stdout.read().decode(utf-8, errorsreplace) err stderr.read().decode(utf-8, errorsreplace) print(f$ {cmd}\n{out.strip()}) if err.strip(): logging.warning(f{item[host]} stderr: {err.strip()}) ssh.close() def main(): with ThreadPoolExecutor(max_workers5) as pool: list(pool.map(run_on_host, HOSTS)) if __name__ __main__: main()幾個關(guān)鍵點說一下。set_missing_host_key_policy(paramiko.AutoAddPolicy())的意思是自動接受首次連接的主機指紋這在批量環(huán)境里省事但在安全要求高的環(huán)境不建議這么干最好是預(yù)先把 known_hosts 配好。banner_timeout和auth_timeout用來防止某臺機器 SSH 握手階段卡死不設(shè)置的話腳本可能掛在某一臺上。3.3 并發(fā)數(shù)不是越大越好ThreadPoolExecutor 很好用把串行改成并發(fā)只需要加幾行。但max_workers別貪多我個人推薦 5 到 10 就夠了。你要管理的是幾十臺服務(wù)器5 個并發(fā)處理起來就是一分鐘以內(nèi)的事如果設(shè)成 50很多開源防火墻或者商用設(shè)備會直接把你的 IP 拉黑。記住自動化是給運維減負不是給安全設(shè)備送素材。3.4 擴展文件分發(fā)和收集執(zhí)行命令只是開始很多時候還要把安裝包分發(fā)到各臺機器或者把日志收集回來。這就要用 SFTP。ssh paramiko.SSHClient() # ... connect 同上 ... sftp ssh.open_sftp() sftp.put(/local/app.tar.gz, /tmp/app.tar.gz) sftp.get(/var/log/app.log, ./collect/192.168.1.10_app.log) sftp.close()這里容易踩的坑是遠程目錄權(quán)限或者目錄不存在。sftp.put不會自動創(chuàng)建遠程目錄你得先執(zhí)行mkdir -p或者用sftp.mkdir逐級建目錄。收集日志時更建議每臺機器建一個子目錄避免文件名沖突比如上面例子里的./collect/192.168.1.10_app.log。3.5 別把密碼硬編碼在腳本里很多初學(xué)者喜歡在腳本里寫password123456我強烈不建議。腳本會放在服務(wù)器上甚至?xí)粋鞯酱a倉庫里密碼一旦泄漏就是安全事故。更好的方案是優(yōu)先用 SSH 密鑰如果一定要用密碼就用getpass提示交互輸入或者從配置中心讀取。至少也要把密碼放在環(huán)境變量里而不是寫死在源碼中。4. 巡檢告警腳本從手動登錄到自動出報告4.1 巡檢指標(biāo)先設(shè)計好代碼才有意義在寫巡檢腳本之前先問自己一個問題你到底要關(guān)注哪些指標(biāo)我見過不少巡檢腳本輸出一大堆數(shù)字最后沒人看因為根本沒有重點。最基礎(chǔ)也最常用的指標(biāo)無非是這幾個指標(biāo)建議閾值說明CPU 使用率 80% 持續(xù) 5 分鐘長時間跑高需要關(guān)注系統(tǒng)負載 CPU 核心數(shù)負載過高說明隊列積壓內(nèi)存使用率 85%接近耗盡易觸發(fā) OOM磁盤使用率 90%再往上可能影響寫日志關(guān)鍵進程存活進程不存在告警服務(wù)掛了要第一時間知道關(guān)鍵端口監(jiān)聽端口不可達告警結(jié)合業(yè)務(wù)場景定義別把指標(biāo)定得太死不同業(yè)務(wù)不一樣。內(nèi)存 90% 對緩存類服務(wù)可能很正常磁盤 80% 對備份機器也可能就該清理了。閾值先按經(jīng)驗給一版跑一段時間再調(diào)。4.2 本機巡檢腳本實例下面這個腳本可以在單臺服務(wù)器上跑用來采集和判斷指標(biāo)命中閾值就輸出告警。實際使用時可以結(jié)合上一節(jié)提到的 paramiko把它推到遠程機器上執(zhí)行。#!/usr/bin/env python3 import os import time import psutil import socket HOST socket.gethostname() CPU_THRESHOLD 80 MEM_THRESHOLD 85 DISK_THRESHOLD 90 def check_cpu(): # 取三次采樣平均值避免瞬時峰值誤報 total 0.0 for _ in range(3): total psutil.cpu_percent(interval1) avg total / 3 if avg CPU_THRESHOLD: print(f[ALERT] {HOST} CPU usage {avg:.1f}% {CPU_THRESHOLD}%) return avg def check_memory(): mem psutil.virtual_memory() if mem.percent MEM_THRESHOLD: print(f[ALERT] {HOST} memory usage {mem.percent:.1f}% {MEM_THRESHOLD}%) return mem.percent def check_disk(): du psutil.disk_usage(/) if du.percent DISK_THRESHOLD: print(f[ALERT] {HOST} disk usage {du.percent:.1f}% {DISK_THRESHOLD}%) return du.percent if __name__ __main__: cpu check_cpu() mem check_memory() disk check_disk() print(f[INFO] {HOST} CPU{cpu:.1f}% MEM{mem:.1f}% DISK{disk:.1f}%)這里有個細節(jié)CPU 使用率采樣如果只取一次特別容易誤報。運維機器經(jīng)常有定時任務(wù)、日志壓縮這種瞬時尖峰所以我的做法是連續(xù)采樣三次取平均寧可慢幾秒也別半夜發(fā)騷擾告警。4.3 閾值判斷要連續(xù)采樣別被瞬時尖峰騙了關(guān)于“持續(xù)多久才算報警”也可以用一個更簡單的做法在內(nèi)存里維護一個計數(shù)連續(xù)三分鐘超過閾值才觸發(fā)告警。不要一個采樣點超標(biāo)就發(fā)郵件不然晚上你會被短信轟炸。說實話告警靈敏度寧低勿高等你的監(jiān)控系統(tǒng)每天發(fā)幾十條信息沒人看的時候真正的故障反而會被淹沒。4.4 定時任務(wù)crontab還是systemd timer巡檢腳本寫好了剩下的就是定時執(zhí)行。我最常用的是 crontab簡單直接。下面是典型的寫法*/5 * * * * /home/ops/venvs/ops/bin/python /home/ops/scripts/health_check.py /var/log/health_check.log 21這三處必須注意第一Python 解釋器寫絕對路徑不要寫python或者python3因為 cron 環(huán)境里的 PATH 很精簡可能找不到命令第二腳本也寫絕對路徑cron 的工作目錄不固定第三日志要重定向到文件否則腳本的輸出會被 cron 的郵件系統(tǒng)吞掉找都找不到。systemd timer 更規(guī)范能配置依賴、隨機啟動延遲但需要寫 service 和 timer 兩個單元文件對小規(guī)模腳本來說稍微重了一點。我一般是腳本少用 crontab腳本多了再上 systemd timer。4.5 用smtplib發(fā)告警郵件告警怎么通知出去最傳統(tǒng)也穩(wěn)定的方式是郵件。用 smtplib 封裝一個推送函數(shù)import smtplib from email.mime.text import MIMEText def send_alert(subject, content): smtp_server smtp.example.com smtp_port 465 user opsexample.com passwd your-smtp-auth-code msg MIMEText(content, plain, utf-8) msg[Subject] subject msg[From] user msg[To] ops-teamexample.com server smtplib.SMTP_SSL(smtp_server, smtp_port) server.login(user, passwd) server.sendmail(user, [ops-teamexample.com], msg.as_string()) server.quit()注意用戶名和密碼這里用的是 SMTP 授權(quán)碼不是郵箱登錄密碼。現(xiàn)在很多群機器人也有 Webhook 接口原理類似curl 一個 URL 就能推送相對郵件來說更實時。但團隊內(nèi)部協(xié)作郵件還是最通用的記錄留痕也方便。5. 常見問題與排查實錄5.1 “python命令不存在”或“pip找不到”這次熱搜里就有很多類似的報錯比如某個版本的pnpm不能被識別為 cmdlet 或者命令本質(zhì)都是同一個原因執(zhí)行文件的路徑不在 PATH 環(huán)境變量里。Python 也一樣Windows 上安裝時沒勾選“Add Python to PATH”就會出現(xiàn)python 不是內(nèi)部或外部命令。Linux 上則是沒裝對應(yīng)的包。解決辦法很簡單Windows 重新安裝一次并勾選 PATH或者在系統(tǒng)環(huán)境變量里手動加Linux 就是安裝python3-pip。排列組合如果python3存在但python不存在建個軟鏈即可。如果pip找不到優(yōu)先用python3 -m pip保證用對解釋器。如果多個 Python 版本混在一起pip 裝進了另一個版本用python3 -m pip install就不會錯。5.2 SSH連接失敗的各種原因批量連接最煩的就是某臺機器突然連不上。常見報錯和排查思路我整理成了速查表現(xiàn)象常見原因排查 / 解決Authentication failed用戶名密碼錯誤或密鑰對不上檢查用戶名確認密鑰是否在目標(biāo)機的 authorized_keys 中Bad permissions密鑰文件權(quán)限過寬chmod 600 ~/.ssh/id_rsaConnection refusedsshd 未啟動、端口被防火墻攔檢查 sshd 服務(wù)狀態(tài)確認遠程端口是否通Error reading SSH protocol banner握手超時或服務(wù)器響應(yīng)慢設(shè)置banner_timeout和auth_timeout別用默認值等太久No host key type configured舊設(shè)備算法不兼容檢查是否需要配置disabled_algorithmsConnection refused出現(xiàn)頻率很高我排查的順序是先 ping 看通不通再看端口再確認 sshd 是不是在監(jiān)聽。如果端口通但連不上大概率是防火墻的配置問題。5.3 exec_command卡住不返回paramiko 執(zhí)行命令時如果忘記讀stdout和stderr或者命令本身不退出腳本就會一直卡著。我的經(jīng)驗是每條命令都給timeout參數(shù)比如上面的例子寫成exec_command(cmd, timeout15)超時之后報錯退出。另外如果命令會產(chǎn)生大量輸出一定要及時讀取否則 SSH 通道的緩沖區(qū)滿了客戶端會阻塞住。還有一種情況是執(zhí)行交互式命令比如top這種要持續(xù)輸出的exec_command不適合要用invoke_shell來回寫交互但那個更復(fù)雜盡量別碰。5.4 中文亂碼與編碼問題腳本輸出中文亂碼十有八九是編碼沒統(tǒng)一。遠程服務(wù)器默認locale可能是POSIX或C輸出的中文會變成亂碼本地 Windows 控制臺默認 GBKPython 默認 UTF-8直接打印也容易串。我在代碼里讀取輸出時統(tǒng)一寫成decode(utf-8, errorsreplace)這樣即使個別字節(jié)不對也不會整個崩潰。另一個辦法是在命令前面加export LANGen_US.UTF-8;讓遠程命令的輸出盡量用 UTF-8 編碼。5.5 venv在cron里不生效這個問題坑了無數(shù)人。你在終端里試腳本一切正常但 crontab 跑起來就報ModuleNotFoundError。原因很簡單cron 的執(zhí)行環(huán)境非常干凈不會加載你的~/.bashrcvenv 也沒被激活。解決方法是不要靠 activate直接在 crontab 里寫 venv 的 Python 絕對路徑。同時依賴庫如果有變動要在 venv 里更新requirements.txt并且確認 cron 用的這個環(huán)境確實裝有所有依賴。5.6 不要亂動系統(tǒng)Python又得重復(fù)一次真的不要在系統(tǒng) Python 里全局 pip install。很多運維事故都是“順手”升級了一個包結(jié)果系統(tǒng)的某個工具依賴舊版本直接罷工。RHEL 系的 yum 依賴 Python 2.7 是經(jīng)典案例。所以所有業(yè)務(wù)腳本依賴一律進 venv系統(tǒng) Python 保持安裝時的狀態(tài)。這是自動化運維的基本衛(wèi)生習(xí)慣。6. 從腳本到工具幾條實踐經(jīng)驗寫到這里我把這些年做自動化運維腳本的個人體會講一講沒有大道理都是踩坑踩出來的。第一先小范圍驗證再全量執(zhí)行。不管是批量執(zhí)行命令還是分發(fā)文件先挑一臺測試機跑通確認沒有破壞性操作再放到生產(chǎn)批量里。我見過有人寫完腳本直接全量重啟服務(wù)結(jié)果腳本里少判斷了一個條件整批機器一起出問題那場面是真的慘。把HOSTS列表先改成一臺機器跑通了再放開。第二腳本要冪等能重復(fù)執(zhí)行。冪等這個詞聽上去高級其實很簡單同一個腳本跑一次和跑十次最終狀態(tài)應(yīng)該一致。比如分發(fā)文件之前先比較文件 hash合了就跳過創(chuàng)建用戶之前先判斷用戶是否存在。自動化運維最怕的就是腳本沒有防御性跑第二次就報錯或者更糟跑第二次把數(shù)據(jù)覆蓋了。第三日志比結(jié)果重要。任何腳本都應(yīng)該有自己的日志至少記錄什么時間、在哪臺機器上、執(zhí)行了什么命令、返回碼是多少。不要只依賴print用logging寫到固定文件方便事后回溯。運維行業(yè)的準則就是“執(zhí)行過的操作要有留痕”否則出了問題你就是那個背鍋的。第四參數(shù)化配置不要硬編碼。服務(wù)器列表、用戶名、閾值、路徑全部放到配置文件或環(huán)境變量里。不然每次加一臺機器都要改代碼改完還得擔(dān)心改錯。簡單做法是用argparse支持命令行傳參再復(fù)雜一點就引入 YAML 配置文件。腳本通用性高了后面接手的人會感謝你。第五別追求一步到位。一個腳本能解決一個問題就很好了后續(xù)需求可以慢慢加。比如批量執(zhí)行命令腳本先支持固定命令再支持傳參再支持文件分發(fā)再支持并發(fā)控制。慢慢迭代出來的工具才最貼合實際場景一上來就想寫個超級復(fù)雜的平臺大概率爛尾。自動化運維腳本的價值不在于代碼多花哨而在于把重復(fù)操作固化下來把容易出錯的人為判斷變成可重復(fù)的邏輯。我現(xiàn)在打開電腦很多操作已經(jīng)不需要再登錄服務(wù)器了前一天晚上把巡檢腳本跑完第二天早上看結(jié)果就行。這種幸福感就是靠這些不起眼的小腳本積累出來的。你也不妨從今天的第一行import paramiko開始。