自從筆者接觸Rust程式語言以來,大大小小的程式都是使用Rust程式語言來進行開發。在Web伺服器管理方面,由於伺服器環境已經不再需要安裝PHP、Node.js、Python等網站相關套件,因此也沒有一個好用的、可在本機或是遠端偵測伺服器狀態的工具能夠使用,索性就自己用Rust程式語言來開發一個追求效能,並針對Linux伺服器來運行的探針──M Prober(MagicLen Prober)。



M Prober的目標有以下幾項:

  • 輕量:一個輕量、可以獨立運行的探針是很重要的。試想一下,我們什麼時候會需要用到探針?當然就是想要查看現在系統環境的硬體配置或是找出導致伺服器在當下處理請求時變慢的原因嘛!但如果為了查看系統狀態還要安裝一堆有的沒的套件,甚至還要用一堆程式腳本來讓探針常駐在系統中來監看系統狀態,豈不是本末倒置?所以M Prober是一個單檔可獨立執行的程式,可以隨時取得、隨時移除。
  • 效能:M Prober幾乎只會透過/proc/sys這兩個存在於記憶體上的虛擬檔案系統來取得系統資訊,並不會去額外呼叫Linux環境中的任何shell指令。如果資料來源有不足的部份,會直接透過libc來取得。
  • 整合:不像Linux作業系統提供的那些常用指令工具,一種只能針對一個或是少數幾個方面的系統資訊進行查看。M Prober可以用來取得主機名稱、Linux核心名稱、已開機時間(uptime)、系統RTC時間、CPU、記憶體、網路和硬碟(或分割區、邏輯捲軸)等的資訊。(未來會再新增行程查看功能)
  • 無暫存:M Prober所取得的資料完全不會被暫存下來,非常乾淨,使用者不需煩惱刪掉M Prober的執行檔後還有剩餘的垃圾要處理。
  • 完善的命令列介面(CLI):M Prober提供完善的命令列介面,可以在使用者需要使用探針功能時,取代掉零散又不統一的Linux內建指令。
  • 易部署的HTTP服務:除了命令列介面之外,M Prober也可以當作一個Web應用程式來使用,它有自帶的HTTP服務器,可讓使用者直接在網頁上監視系統資源,並且提供以JSON格式來回傳資料的HTTP API。
  • 低系統需求:已確認的最低可正常運行M Prober的Linux核心版本為3.10
  • 無多國語言:無多國語言?不錯,查看系統資訊最重要的是數據,多國語言支援根本沒用,徒增使用的難度罷了。

GitHub:

安裝和解除安裝M Prober

透過Cargo

如果系統環境中有安裝「Cargo」的話,可以直接使用以下指令來下載「M Prober」的原始碼專案,並進行編譯安裝。

cargo install mprober

若要解除安裝,執行以下這個指令即可:

cargo uninstall mprober

透過GitHub(適用於x86和x86_64架構)

執行以下指令,將最新的M Prober執行檔從GitHub上下載下來,並移動到/usr/local/bin目錄中。

curl -fL "$(curl -fsS https://api.github.com/repos/magiclen/m-prober/releases/latest | sed -r -n 's/.*"browser_download_url": *"(.*\/mprober_'$(uname -m)')".*/\1/p')" -O && sudo mv mprober_$(uname -m) /usr/local/bin/mprober && sudo chmod +x /usr/local/bin/mprober

若要解除安裝,執行以下這個指令即可:

sudo rm /usr/local/bin/mprober

使用M Prober

命令列介面

取得主機名稱
mprober hostname

除了hostname這個子命令外,還可以使用hhostnameservername

m-prober

取得Linux核心版本
mprober kernel

除了kernel這個子命令外,還可以使用kllinux

m-prober

取得已開機時間(uptime)
mprober uptime

除了uptime這個子命令外,還可以使用uuputimeut

m-prober

可以加上-m參數再接上毫秒數來持續監看。

取得RTC(Real-Time Clock)時間
mprober time

除了time這個子命令外,還可以使用tsystimestimestutcutctimertcrtctimedate

m-prober

可以加上-m參數再接上毫秒數來持續監看。

顯示負載和CPU狀態
mprober cpu

除了cpu這個子命令外,還可以使用ccpuscorecoresloadprocessorprocessors

m-prober

可以加上-m參數再接上毫秒數來持續監看。

顯示記憶體狀態
mprober memory

除了memory這個子命令外,還可以使用mmemffreememoriesswapramdramddrcachebufferbuffersbufbuff

m-prober

進度條顏色的部份,紅色是已使用的記憶體量、黃色是快取量、藍色是緩衝量。可以加上-m參數再接上毫秒數來持續監看。

顯示網路狀態
mprober network

除了network這個子命令外,還可以使用nnetnetworksbandwidthtraffic

m-prober

可以加上-m參數再接上毫秒數來持續監看。

顯示硬碟狀態
mprober volume

除了volume這個子命令外,還可以使用vstoragevolumesddiskdisksblkblockblocksmountmountsssdhddtraffic

m-prober

可以加上-m參數再接上毫秒數來持續監看。

顏色模式

MPROBER_LIGHTMPROBER_FORCE_PLAIN環境變數可以用來控制M Prober預設的終端機輸出配色。如下圖:

m-prober

效能測試

以下指令可以用來測試目前系統環境的CPU、記憶體和硬碟效能:

mprober benchmark

除了benchmark這個子命令外,還可以使用bbenchperformance

也可以加上額外的--disable-xxx或是--enable-xxx等參數來控制要跑哪些效能測試。

m-prober

Web(HTTP)

啟動M Prober伺服器
mprober web

除了web這個子命令外,還可以使用wserverhttp

一旦啟動了M Prober伺服器,就可以用網頁瀏覽器(如Firefox、Chrome等)開啟http://0.0.0.0:8000,來監看系統。

m-prober

如果要更改監聽的連接埠,可以加上-p參數,再接上連接埠號碼。如果要更改監看系統的偵測間隔時間,可以加上-m參數,再接上秒數,有效的秒數範圍是1 ~ 15

HTTP API
GET /api/hostname
{
    "code": 0,
    "data": "magiclen-linux"
}
GET /api/kernel
{
    "code": 0,
    "data": "4.15.0-48-generic"
}
GET /api/uptime
{
    "code": 0,
    "data": 31694
}

資料的單位是

GET /api/time
{
    "code": 0,
    "data": {
        "date": "2019-05-03",
        "time": "12:43:14"
    }
}

這時間是RTC時間。

GET /api/cpu
{
    "code": 0,
    "data": {
        "cpus": [
            {
                "cores": 4,
                "mhz": [
                    2571.96,
                    2688.208,
                    2604.095,
                    2700.238,
                    2700.034,
                    2699.908,
                    2700.329,
                    2699.986
                ],
                "model_name": "Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz",
                "threads": 8
            }
        ],
        "load_average": {
            "fifteen": 1.02,
            "five": 0.83,
            "one": 0.61
        }
    }
}
GET /api/cpu-detect
{
    "code": 0,
    "data": {
        "cpus": [
            {
                "cores": 4,
                "mhz": [
                    1808.254,
                    1787.732,
                    1430.044,
                    1845.768,
                    1751.993,
                    1751.121,
                    1769.048,
                    1663.091
                ],
                "model_name": "Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz",
                "threads": 8
            }
        ],
        "cpus_stat": [
            0.08386009270965024,
            0.09152542372881356,
            0.10472972972972971,
            0.11295681063122924,
            0.06418918918918919,
            0.09364548494983276,
            0.06397306397306397,
            0.053691275167785234,
            0.0821917808219178
        ],
        "load_average": {
            "fifteen": 1.02,
            "five": 0.84,
            "one": 0.74
        }
    }
}

cpus_stat欄位的第一個值(也就是索引0的值)為該顆CPU每個邏輯核心的使用率的平均值。其餘的數值分別為每個邏輯核心的使用率。

GET /api/momery
{
    "code": 0,
    "data": {
        "memory": {
            "available": 22659469312,
            "buffers": 10412032,
            "cache": 19094446080,
            "free": 4154060800,
            "shared": 119246848,
            "total": 33633140736,
            "used": 10374221824
        },
        "swap": {
            "cache": 385024,
            "free": 4082888704,
            "total": 4094685184,
            "used": 11411456
        }
    }
}

數值的單位是位元組

GET /api/network-detect
{
    "code": 0,
    "data": [
        {
            "download_rate": 0.0,
            "download_total": 55713769,
            "interface": "lo",
            "upload_rate": 0.0,
            "upload_total": 55713769
        },
        {
            "download_rate": 702.0,
            "download_total": 7461474545,
            "interface": "enp0s20f0u4",
            "upload_rate": 1280.6666666666667,
            "upload_total": 331829069
        }
    ]
}

總和(total)的單位是位元組,速率(rate)的單位是位元組/秒

GET /api/volume
{
    "code": 0,
    "data": [
        {
            "device": "sda2",
            "mount_points": [
                "/",
                "/var/lib/docker/btrfs"
            ],
            "read_total": 7612149760,
            "size": 249809600512,
            "used": 70506823680,
            "write_total": 12919939072
        },
        {
            "device": "sdb1",
            "mount_points": [
                "/storage"
            ],
            "read_total": 7080878080,
            "size": 239938535424,
            "used": 218200993792,
            "write_total": 21799934464
        },
        {
            "device": "sdc2",
            "mount_points": [
                "/home"
            ],
            "read_total": 27511930880,
            "size": 496011051008,
            "used": 370128474112,
            "write_total": 56615944192
        }
    ]
}

總和(total)的單位是位元組

GET /api/volume
{
    "code": 0,
    "data": [
        {
            "device": "sda2",
            "mount_points": [
                "/",
                "/var/lib/docker/btrfs"
            ],
            "read_rate": 0.0,
            "read_total": 7612149760,
            "size": 249809600512,
            "used": 70506823680,
            "write_rate": 0.0,
            "write_total": 12928978944
        },
        {
            "device": "sdb1",
            "mount_points": [
                "/storage"
            ],
            "read_rate": 0.0,
            "read_total": 7080878080,
            "size": 239938535424,
            "used": 218200993792,
            "write_rate": 0.0,
            "write_total": 21799934464
        },
        {
            "device": "sdc2",
            "mount_points": [
                "/home"
            ],
            "read_rate": 0.0,
            "read_total": 27511934976,
            "size": 496011051008,
            "used": 370131861504,
            "write_rate": 4965717.333333333,
            "write_total": 56771334144
        }
    ]
}

總和(total)的單位是位元組。速率(rate)的單位是位元組/秒

GET /api/all
{
    "code": 0,
    "data": {
        "cpus": [
            {
                "cores": 4,
                "mhz": [
                    1200.121,
                    1200.272,
                    1200.12,
                    1200.055,
                    1200.098,
                    1200.034,
                    1200.014,
                    1200.124
                ],
                "model_name": "Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz",
                "threads": 8
            }
        ],
        "cpus_stat": [
            0.04951741502308015,
            0.043333333333333335,
            0.030405405405405407,
            0.05743243243243243,
            0.056666666666666664,
            0.04983388704318937,
            0.05387205387205387,
            0.05405405405405406,
            0.05067567567567568
        ],
        "hostname": "magiclen-linux",
        "kernel": "4.15.0-48-generic",
        "load_average": {
            "fifteen": 0.8,
            "five": 0.53,
            "one": 0.28
        },
        "memory": {
            "available": 22578839552,
            "buffers": 10412032,
            "cache": 19104878592,
            "free": 4062957568,
            "shared": 119230464,
            "total": 33633140736,
            "used": 10454892544
        },
        "network": [
            {
                "download_rate": 0.0,
                "download_total": 55798721,
                "interface": "lo",
                "upload_rate": 0.0,
                "upload_total": 55798721
            },
            {
                "download_rate": 9.333333333333334,
                "download_total": 7463048290,
                "interface": "enp0s20f0u4",
                "upload_rate": 28.666666666666668,
                "upload_total": 333465932
            }
        ],
        "rtc_time": {
            "date": "2019-05-03",
            "time": "12:54:34"
        },
        "swap": {
            "cache": 385024,
            "free": 4082888704,
            "total": 4094685184,
            "used": 11411456
        },
        "uptime": 32437,
        "volumes": [
            {
                "device": "sda2",
                "mount_points": [
                    "/",
                    "/var/lib/docker/btrfs"
                ],
                "read_rate": 0.0,
                "read_total": 7612149760,
                "size": 249809600512,
                "used": 70506831872,
                "write_rate": 0.0,
                "write_total": 12939075584
            },
            {
                "device": "sdb1",
                "mount_points": [
                    "/storage"
                ],
                "read_rate": 0.0,
                "read_total": 7080878080,
                "size": 239938535424,
                "used": 218200993792,
                "write_rate": 0.0,
                "write_total": 21799934464
            },
            {
                "device": "sdc2",
                "mount_points": [
                    "/home"
                ],
                "read_rate": 0.0,
                "read_total": 27521441792,
                "size": 496011051008,
                "used": 370118373376,
                "write_rate": 744106.6666666666,
                "write_total": 56883159040
            }
        ]
    }
}
授權(Authorization)

如果我們需要將M Prober的HTTP API暴露在網際網路上的話。為了避免HTTP API都可被任何人使用,我們可以啟用M Prober自帶的簡易授權機制。

當我們在使用命令列介面啟動M Prober的HTTP服務的時候,可以加入-a參數,再接上要同意使用的授權金鑰(隨便自訂一個別人猜不太到的字串即可)。如此一來,每個HTTP API在被呼叫的時候,HTTP請求中都必須要使用Authorization這個標頭欄位來存入同樣的授權金鑰,否則API就無法正確被調用。

此外,我們可能也會需要禁用網頁系統監看功能,但依然保留HTTP API。如果確定要這樣的話,只需在啟動HTTP服務的時候,於指令中加入--only-api參數。