隨著現代系統日益複雜,系統管理員需要自動化工具來提升效率。Python 作為一種易讀易用的物件導向程式語言,非常適合開發系統管理應用程式。本文將聚焦於 Python 在網路管理、網頁伺服器和網頁應用程式管理、資料函式庫系統管理和系統監控四大領域的應用。我們預設讀者具備系統管理經驗和 Python 基礎知識,並將提供在 Fedora 系統上的操作說明,讀者需自行調整至對應的 Linux 發行版。本文範例根據 Python 2.7 版本,讀者在 Python 3 環境下需確認函式庫的相容性。

使用Python進行系統管理自動化

前言

系統管理員的角色隨著時間的推移有了顯著的變化。單一工程師所支援的系統數量不斷增加,使得手工開發每個安裝變得不切實際,因此需要盡可能地自動化許多工。不同組織的系統結構各不相同,因此係統管理員必須能夠建立自己的管理工具。歷史上,最受歡迎的程式語言是UNIX shell和Perl,它們很好地完成了任務,但現代系統的複雜性需要新的工具,而Python正是其中之一。

為何選擇Python

Python是一種適合開發大規模應用程式的物件導向程式語言。其語法和結構使其非常易於閱讀,以至於有時被稱為“可執行的偽程式碼”。Python直譯器允許互動式執行,因此在某些情況下,管理員可以使用它代替標準的UNIX shell。儘管Python主要是一種物件導向語言,但它很容易被採用於程式式和函式式程式設計風格。因此,Python非常適合作為實作系統管理應用程式的新語言。許多Linux系統工具已經用Python編寫,例如Yum套件管理器和Anaconda Linux安裝程式。

本文的前提條件

本文主要探討使用Python程式語言解決特定的系統管理任務。我們將關注四個不同的系統管理領域:網路管理、網頁伺服器和網頁應用程式管理、資料函式庫系統管理和系統監控。雖然我們將詳細解釋本文中使用的大多數技術,但請記住,本文的主要目標是展示Python函式庫的實際應用,以解決特定的問題。因此,我們假設讀者是一位經驗豐富的系統管理員,能夠自行查詢額外的資訊,並根據特定的系統和環境調整解決方案。

準備工作

在討論範例時,讀者將被要求安裝額外的套件和函式庫。在大多數情況下,我們將提供在Fedora系統上執行這些任務的命令和說明,但讀者應該準備好將這些說明調整到所使用的Linux發行版。大多數範例也可在最近的OS X版本(10.10.X)上執行,只需稍作修改。

Python基礎知識

版本要求

本文中的所有範例均假設使用Python版本2.7。這主要是由範例中使用的函式庫所決定的。有些函式庫已經移植到Python 3,但有些尚未移植。因此,如果需要執行Python 3,請確保檢查所需的函式庫是否支援Python 3。

程式碼例項與解析

以下是一個簡單的Python程式碼範例,用於檢查網站是否可用:

import requests

def check_website(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            print(f"網站 {url} 可用")
        else:
            print(f"網站 {url} 不可用,狀態碼:{response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"檢查網站 {url} 時發生錯誤:{e}")

# 使用範例
check_website("http://www.example.com")

內容解密:

  1. 匯入必要的函式庫:我們首先匯入requests函式庫,它用於傳送HTTP請求。
  2. 定義檢查網站的函式check_website函式接受一個URL作為引數,並嘗試使用requests.get方法存取該網站。
  3. 處理HTTP回應:如果請求成功(狀態碼200),則列印網站可用的訊息。否則,列印網站不可用的訊息及狀態碼。
  4. 錯誤處理:如果在請求過程中發生任何異常,則捕捉該異常並列印錯誤訊息。
  5. 範例使用:最後,我們呼叫check_website函式並傳入一個範例URL來示範其用法。

這個範例展示瞭如何使用Python和requests函式庫來檢查網站的可用性。這是一個簡單但實用的系統管理任務自動化的例子。

本文結構概述

本文共包含14章,每章針對特定問題進行探討。部分範例橫跨多章,但每章均專注於特定導向的分析與解決方案。

章節組織架構

本文的章節按照問題型別進行分組:

  • 第1至4章專注於網路管理議題
  • 第5至7章探討Apache網頁伺服器與網頁應用管理
  • 第8至11章著重於監控與統計計算
  • 第12與13章關注資料函式倉管理問題

章節共通模式

每章均遵循相同的結構:

  1. 明確定義問題陳述
  2. 蒐集需求並進行設計規劃
  3. 進入實作階段

技術與Python函式庫整合

每章聚焦於一或多項技術,以及提供該技術介面的Python函式庫。例如:

  • SNMP協定
  • 應用程式外掛架構
  • 雲端運算概念

各章節內容摘要

第1章:使用SNMP讀取和收集效能資料

本章介紹SNMP基本原理、資料結構,並探討相關Python函式庫。同時,討論了用於儲存統計資料的迴圈資料函式庫(RRD),以及使用Jinja2範本框架生成網頁。

第2章:使用SOAP API管理裝置

探討SOAP API結構及相關Python函式庫,並介紹基本的日誌功能。本文第二版新增了使用REST API管理負載平衡裝置的範例。

第3章:建立IP位址管理網頁應用程式

本章利用Django框架開發網頁應用程式,用於管理已分配的IP位址與位址範圍。內容涵蓋Django應用程式結構、設定組態及URL結構,並介紹如何使用Apache網頁伺服器佈署Django應用程式。

第4章:整合IP位址應用程式與DHCP

本章擴充套件前一章內容,實作DHCP位址範圍支援,並介紹進階Django程式設計技巧,如自訂回應MIME型別及處理AJAX請求。第二版新增了使用OMAPI協定管理動態DHCP租約的功能。

第5章:維護Apache設定檔中的虛擬主機清單

本章開發另一個Django應用程式,專注於自訂Django管理介面。透過建立Apache設定管理應用程式,學習如何擴充套件預設的管理介面。

第6章:收集與呈現Apache日誌檔案的統計資料

本章目標是建立解析與分析Apache日誌檔案的應用程式。採用外掛式應用程式設計,介紹物件與類別型別探索功能,以及動態模組載入。第二版新增了根據收集資料的視覺化技術。

第7章:對應用程式日誌檔案執行複雜搜尋與報告

本章探討複雜、多行日誌條目的解析方法,並介紹開源日誌檔案解析工具Exctractor的功能。

第8章:為Nagios開發網頁可用性檢查指令碼

本章為Nagios建立兩個檢查網頁功能的指令碼,並介紹使用Beautiful Soup HTML解析函式庫提取網頁資訊的方法。

第9章:管理與監控子系統

本章開始為期三章的監控系統開發系列。首先介紹分散式應用程式設計原理,包括資料函式庫設計原則(如資料正規化)及使用RPC呼叫實作網路服務間的通訊機制。

第10章:遠端監控代理程式

本章實作遠端監控代理元件,並介紹如何使用ConfigParser模組將應用程式與其組態設定解耦。

第11章:統計資料收集與報告

本章完成監控系列的最後一部分,介紹如何對收集到的效能資料進行基本統計分析。使用NumPy進行計算,並利用matplotlib建立圖表。同時,學習如何判斷效能讀數是否在正常範圍內及計算該範圍的邊界。

第12章:分散式訊息處理系統

第二版新增的章節,介紹如何將分散式管理系統轉換為使用Celery遠端任務執行框架。

第13章:自動化MySQL資料函式庫效能調校

本章示範如何取得MySQL資料函式庫組態變數及內部狀態指標,並建立應用程式根據這些資料提出效能改進建議。

第14章:利用Amazon EC2/S3作為資料倉儲解決方案

本章示範如何利用Amazon Elastic Compute Cloud(EC2)將非經常性運算任務解除安裝至雲端。並建立應用程式自動建立資料函式庫伺服器,用於傳輸資料進行進一步分析。這個範例可用作建立隨需資料倉儲解決方案的基礎。

使用 SNMP 讀取和收集效能資料

大多數連線到網路的裝置都會使用 SNMP(簡易網路管理通訊協定)回報其狀態。此通訊協定主要用於管理和監控網路連線的硬體裝置,但某些應用程式也會透過此通訊協定公開其統計資料。在本章中,我們將探討如何從 Python 應用程式中存取這些資訊。我們將使用 RRDTool(一款廣為人知且流行的應用程式和函式庫,用於儲存和繪製效能資料)將取得的資料儲存在 RRD(輪替資料函式庫)中。最後,我們將研究 Jinja2 樣板系統,並用它來為我們的應用程式產生簡單的網頁。

應用程式需求與設計

系統監控是一個非常廣泛的主題,通常涵蓋許多不同的領域。一個完整的監控系統相當複雜,通常由多個元件共同組成。在本章中,我們不會開發一個完整、獨立的系統,而是會探討典型監控系統中的兩個重要領域:資訊收集和表示。在本章中,我們將實作一個使用 SNMP 通訊協定查詢裝置的系統,然後使用 RRDTool 函式庫儲存資料,該函式庫也用於產生圖形以進行視覺化資料表示。所有這些都使用 Jinja2 樣板函式庫整合到簡單的網頁中。我們將在深入本章的過程中更詳細地探討每個元件。

指定需求

在開始設計我們的應用程式之前,我們需要提出一些對系統的需求。首先,我們需要了解我們期望系統提供的功能。這將有助於我們建立一個有效的(並且希望是容易實作的)系統設計。在本章中,我們將建立一個使用 SNMP 通訊協定監控網路連線裝置(如網路交換器和路由器)的系統。因此,第一個需求是系統能夠使用 SNMP 查詢任何裝置。

從裝置收集的資訊需要儲存起來以供將來的參考和分析。讓我們對這些資訊的使用做一些假設。首先,我們不需要無限期地儲存它(我將在第 9-11 章中討論永久資訊儲存)。這意味著資訊只會儲存一段預先定義的時間,一旦它變得過時,就會被刪除。這是我們的第二個需求:資訊需要在「過期」後被刪除。

其次,資訊需要以能夠產生圖形的方式儲存。我們不會將它用於其他任何事情,因此資料儲存應該針對資料表示任務進行最佳化。

最後,我們需要產生圖形,並在易於存取的網頁上呈現這些資訊。資訊需要僅按裝置名稱進行結構化。例如,如果我們正在監控多個裝置的 CPU 和網路介面利用率,則此資訊需要在單一頁面上呈現。我們不需要在多個時間尺度上呈現此資訊;預設情況下,圖形應顯示過去 24 小時的效能指標。

高層設計規格

現在我們對系統的功能有了一些想法,讓我們建立一個簡單的設計,這將作為開發階段的。基本方法是我們之前指定的每個需求都應該由一個或多個設計決策來涵蓋。

第一個需求是我們需要監控網路連線的裝置,並且需要使用 SNMP。這意味著我們必須使用適當的 Python 函式庫來處理 SNMP 物件。SNMP 模組不包含在預設的 Python 安裝中,因此我們需要使用外部模組。我建議使用 PySNMP 函式庫(可在 http://pysnmp.sourceforge.net/ 上取得),該函式庫在大多數流行的 Linux 發行版上都很容易取得。


#### 內容解密:
# 上述提到使用 PySNMP 函式庫,這是一個用於處理 SNMP 物件的 Python 函式庫。
# 使用 PySNMP 的好處包括能夠輕鬆查詢網路裝置並檢索效能資料。
# 這裡強調了選擇合適的 Python 函式庫對於實作 SNMP 功能的重要性。

資料儲存引擎的最佳人選是 RRDTool(可在 http://oss.oetiker.ch/rrdtool/ 上取得)。輪替資料函式庫意味著資料函式庫的結構使得每個「表格」都有有限的長度,一旦達到限制,最舊的條目就會被丟棄。事實上,它們並不是被丟棄;新的條目只是被寫入它們的位置。

RRDTool 函式庫提供了兩種不同的功能:資料函式庫服務和圖形產生工具包。Python 中沒有對 RRD 資料函式庫的原生支援,但有一個外部函式庫可用於提供與 RRDTool 函式庫的介面。


#### 內容解密:
# RRDTool 被選為資料儲存引擎,因為它適合儲存時間序列資料並生成圖形。
# 使用 RRDTool 可以有效地管理和查詢大量效能資料。
# 這裡強調了 RRDTool 在儲存和表示效能資料方面的優勢。

最後,為了產生網頁,我們將使用 Jinja2 樣板函式庫(可在 http://jinja.pocoo.org 或 GitHub 上取得:https://github.com/mitsuhiko/jinja2),它允許我們建立複雜的樣板並將設計和開發任務分離。


#### 內容解密:
# Jinja2 被選為樣板引擎,用於生成網頁並使內容與呈現邏輯分離。
# 使用 Jinja2 可以建立靈活且可重複使用的範本,從而簡化了網頁生成的過程。
# 這裡強調了 Jinja2 在網頁生成和範本設計方面的優勢。

SNMP 簡介

SNMP(簡易網路管理通訊協定)是一種根據 UDP 的通訊協定,主要用於管理網路連線的裝置,如路由器、交換器、電腦、印表機、視訊攝影機等。某些應用程式也允許透過 SNMP 通訊協定存取內部計數器。

SNMP 不僅允許您從裝置讀取效能統計資料,還可以傳送控制訊息以指示裝置執行某些操作——例如,您可以使用 SNMP 命令遠端重新啟動路由器。

此圖示展示了 SNMP 管理系統與受管理的裝置之間的關係,以及 SNMP 代理在其中扮演的角色。

圖示解說:

  • 管理系統負責管理所有裝置。
  • 受管理的裝置是所有由管理系統管理的裝置。
  • SNMP 代理是在每個受管理的裝置上執行的應用程式,與管理系統互動。

#### 內容解密:
# 上述 Plantuml 圖表展示了 SNMP 系統中的三個主要元件之間的關係。
# 管理系統負責監控和管理受管理的裝置,而 SNMP 代理則是執行在受管理的裝置上,與管理系統進行互動。
# 這裡強調了理解 SNMP 系統架構對於實作有效的網路管理的重要性。

使用SNMP讀取和收集效能資料

SNMP(簡單網路管理通訊協定)是一種通用協定,用於管理和監控網路裝置。它定義了七個基本命令,其中最重要的是getget bulkresponse。管理系統使用前兩個命令查詢代理,而代理則使用response回應。

管理資訊函式庫(MIB)

管理系統如何知道要查詢什麼資訊?SNMP協定並未定義交換此資訊的方法,因此管理系統無法直接查詢代理以取得可用變數的清單。為解決此問題,使用了管理資訊函式庫(MIB)。每個裝置都有一個相關聯的MIB,描述該系統上管理資料的結構。MIB按層次順序列出受管裝置上可用的所有物件識別碼(OID)。

OID樹

OID代表物件樹中的一個節點,包含從樹頂節點到當前OID的所有節點的數字識別碼。這些節點ID由IANA(網際網路號碼分配機構)分配和監管。組織可以申請OID節點,並負責管理所分配節點下的OID結構。

以下是一個OID樹的部分結構範例:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Python系統管理自動化實務

package "Python 應用架構" {
    package "應用層" {
        component [主程式] as main
        component [模組/套件] as modules
        component [設定檔] as config
    }

    package "框架層" {
        component [Web 框架] as web
        component [ORM] as orm
        component [非同步處理] as async
    }

    package "資料層" {
        database [資料庫] as db
        component [快取] as cache
        component [檔案系統] as fs
    }
}

main --> modules : 匯入模組
main --> config : 載入設定
modules --> web : HTTP 處理
web --> orm : 資料操作
orm --> db : 持久化
web --> cache : 快取查詢
web --> async : 背景任務
async --> fs : 檔案處理

note right of web
  Flask / FastAPI / Django
end note

@enduml

此圖示展示了OID樹的基本結構。

系統SNMP變數節點

大多數裝置的基本資訊可在系統SNMP變數OID節點子樹下取得。該節點包含多個額外的OID節點,如表1-1所示。

表1-1:系統SNMP OID

OID字串OID名稱描述
1.3.6.1.2.1.1.1sysDescr包含系統或裝置簡短描述的字串,通常包含硬體型別和作業系統詳細資訊。
1.3.6.1.2.1.1.2sysObjectID包含廠商特定裝置OID節點的字串。
1.3.6.1.2.1.1.3sysUpTime表示系統初始化以來時間的數字,以百分之一秒為單位。
1.3.6.1.2.1.1.4sysContact包含負責此係統的聯絡人資訊的任意字串。
1.3.6.1.2.1.1.5sysName已分配給系統的名稱,通常包含完整網域名稱。
1.3.6.1.2.1.1.6sysLocation描述系統實體位置的字串。
1.3.6.1.2.1.1.7sysServices表示此係統提供的服務的數字,是OSI協定的點陣圖表示。

介面SNMP變數節點

基本介面統計資訊可從介面SNMP變數OID節點子樹下取得。介面變數的OID為1.3.6.1.2.1.2,包含兩個子節點:

  • ifNumber(1.3.6.1.2.1.2.1):包含網路介面總數的OID值。
  • ifTable(1.3.6.1.2.1.2.2):包含所有介面條目的OID節點,每個條目代表一個特定的介面。

表1-2:ifEntry子節點

OID字串OID名稱描述
1.3.6.1.2.1.2.2.1.XifEntry包含特定介面詳細資訊的條目,X代表不同的欄位,如ifIndex、ifDescr等。

程式碼範例:使用SNMP取得系統資訊

以下是一個使用Python和PySNMP函式庫來查詢系統SNMP變數的範例:

from pysnmp.hlapi import getCmd, SnmpEngine, CommunityData, UdpTransportTarget, ContextData, ObjectType, ObjectIdentity

# 設定SNMP引數
snmp_engine = SnmpEngine()
community_data = CommunityData('public')
udp_transport_target = UdpTransportTarget(('192.168.X.X', 161))
context_data = ContextData()

# 定義要查詢的OID
oid_sys_descr = ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'))
oid_sys_name = ObjectType(ObjectIdentity('1.3.6.1.2.1.1.5.0'))

# 傳送SNMP請求
result = getCmd(snmp_engine, community_data, udp_transport_target, context_data, oid_sys_descr, oid_sys_name)

# 處理結果
for response in result:
    for binding in response[0]:
        print('%s = %s' % (binding.prettyPrint().split('=')[0], binding.prettyPrint().split('=')[1]))

內容解密:

此程式碼首先匯入必要的PySNMP模組,然後設定SNMP引擎、社群資料、UDP傳輸目標和上下文資料。接著定義了要查詢的OID,包括系統描述和系統名稱。使用getCmd函式傳送SNMP請求,並處理傳回的結果,最終列印出查詢到的值。

這個範例展示瞭如何使用SNMP來收集網路裝置的基本資訊,包括系統描述和名稱等。