1.1 簡介
之前寫過一個服務(wù)器硬件信息抓取的腳本,雖然寫的不好,但是卻還被許多網(wǎng)友分享了?,F(xiàn)在回頭看看當(dāng)初的腳本,感覺像屎一樣,很慚愧。
人總是在成長嘛,不光是皺紋,還有體重,希望大家能體諒我當(dāng)年技術(shù)的不足。雖然我現(xiàn)在技術(shù)也不高,但相比之前要好一些。所以,下決心再重寫一遍。
如果您在此篇文章中有所收獲,那么我的辛苦就沒有白費。其實奉獻是一件很幸福的事兒,只要不賠錢。
1.2 結(jié)構(gòu)
之前寫的腳本只是想著把結(jié)果顯示出來,沒有深層次的構(gòu)思,所以擴展性差,可讀性差,適用性也差。今天痛定思痛,好好的從邏輯上想了想該怎么做。
我還大概畫了一張草圖,幫助理解:

沒錯,真的是畫的。
大概意思就是,我把硬件信息分成兩個模塊:
一個是客戶端的腳本,這個腳本負責(zé)采集數(shù)據(jù),并將采集的數(shù)據(jù)上傳;
另一個是服務(wù)端,負責(zé)接收傳來的數(shù)據(jù),并做數(shù)據(jù)處理,轉(zhuǎn)化為人類容易理解的數(shù)據(jù)(比如客戶端上傳了vendor id號 8086,那么服務(wù)端可翻譯成Intel)。
1.3 腳本
最早我是用shell寫的腳本,原因是用shell比較方便。
后來我使用python寫了一遍,原因是shell腳本做字符串處理太麻煩了,沒有python用著舒服。
最后我又用回了shell,原因是shell基本上不依賴系統(tǒng)環(huán)境,基本上所有的linux系統(tǒng)都支持bash shell,但是并不是每臺機器的python環(huán)境都一樣,雖然可以創(chuàng)建python虛擬環(huán)境,但是畢竟需要創(chuàng)建。
使用bash shell寫客戶端腳本,當(dāng)時也考慮過性能問題,其實完全沒必要。就好比你有一個地球,然后在這個地球上要放兩件東西,一個是西瓜,一個是桃子,所以沒必要糾結(jié)是西瓜大,還是桃子小。而且我主要的目的是實現(xiàn)功能。我不喜歡在吃泡面的時候,有人跟我談營養(yǎng)。
這里我為了編寫方便,將功能拆分成了多個,也便于理解。具體代碼含義以及目的,我在注釋上有寫。
1.3.1 獲取CPU信息
#!/bin/bash
#文件名: get_cpu_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "cpu_mhz": "1200.604",
# "numa_node0_cpus": "0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30",
# "cpu_min_mhz": "1200.0000",
# "l3_cache": "20480K",
# "l1d_cache": "32K",
# "core_per_socket": "8",
# "cpu_max_mhz": "3000.0000",
# "vendor_id": "GenuineIntel",
# "bogomips": "4199.74",
# "thread_per_core": "2",
# "l1i_cache": "32K",
# "cpus": "32",
# "byte_order": "LittleEndian",
# "numa_node1_cpus": "1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31",
# "cpu_family": "6",
# "numa_nodes": "2",
# "model_name": "Intel(R)Xeon(R)CPUE5-2620v4@2.10GHz",
# "op_modes": "32-bit,64-bit",
# "l2_cache": "256K",
# "architecture": "x86_64",
# "sockets": "2",
# "virtualization": "VT-x",
# "stepping": "1",
# "model": "79"
# }
#]
# 需要使用到的命令或工具是 lscpu
function get_cpu()
{
lscpu > /tmp/cpu.hw.info
declare -A cpu_info
# 獲取CPU的 architecture op_mode byte_order cpus
cpu_info[architecture]=$(cat /tmp/cpu.hw.info |grep '^Architecture:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[op_modes]=$(cat /tmp/cpu.hw.info |grep '^CPU op-mode(s):' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[byte_order]=$(cat /tmp/cpu.hw.info |grep '^Byte Order:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[cpus]=$(cat /tmp/cpu.hw.info |grep '^CPU(s):' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[sockets]=$(cat /tmp/cpu.hw.info |grep '^Socket(s):' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[core_per_socket]=$(cat /tmp/cpu.hw.info |grep 'Core(s) per socket:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[thread_per_core]=$(cat /tmp/cpu.hw.info |grep '^Thread(s) per core:'|awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[numa_nodes]=$(cat /tmp/cpu.hw.info |grep '^NUMA node(s):' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[vendor_id]=$(cat /tmp/cpu.hw.info |grep '^Vendor ID:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[cpu_family]=$(cat /tmp/cpu.hw.info |grep '^CPU family:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[model]=$(cat /tmp/cpu.hw.info |grep '^Model:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[model_name]=$(cat /tmp/cpu.hw.info |grep '^Model name:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[stepping]=$(cat /tmp/cpu.hw.info |grep '^Stepping:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[cpu_mhz]=$(cat /tmp/cpu.hw.info |grep '^CPU MHz:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[bogomips]=$(cat /tmp/cpu.hw.info |grep '^BogoMIPS:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[virtualization]=$(cat /tmp/cpu.hw.info |grep '^Virtualization:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[l1d_cache]=$(cat /tmp/cpu.hw.info |grep '^L1d cache:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[l1i_cache]=$(cat /tmp/cpu.hw.info |grep '^L1i cache:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[l2_cache]=$(cat /tmp/cpu.hw.info |grep '^L2 cache:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[l3_cache]=$(cat /tmp/cpu.hw.info |grep '^L3 cache:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[numa_node0_cpus]=$(cat /tmp/cpu.hw.info |grep '^NUMA node0 CPU(s):' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[numa_node1_cpus]=$(cat /tmp/cpu.hw.info |grep '^NUMA node1 CPU(s):' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[cpu_max_mhz]=$(cat /tmp/cpu.hw.info |grep '^CPU max MHz:' |awk -F ':' '{print $NF}' |tr -d ' ')
cpu_info[cpu_min_mhz]=$(cat /tmp/cpu.hw.info |grep '^CPU min MHz:' |awk -F ':' '{print $NF}' |tr -d ' ')
# 如果沒有獲取到 model_name,那么通過別的方法獲取一下
if [ -z "${cpu_info[model_name]}" ]; then
cpu_info[model_name]=$(cat /proc/cpuinfo |grep 'model name' |head -n 1|awk -F ':' '{print $NF}' |tr -d ' ')
fi
# 刪除產(chǎn)生的臨時文件
rm -f /tmp/cpu.hw.info
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!cpu_info[@]}
do
_temp_json="{\"$key\":\"${cpu_info[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json
return 0
}
# 獲取到所有cpu的信息
# 這里我用數(shù)據(jù)作為輸出格式,只是為了格式統(tǒng)一
function get_cpu_all()
{
local cpu_all_info="[]"
echo "[$(get_cpu)]"
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_cpu_all
#}
#
#main "$@"
1.3.2 獲取內(nèi)存信息
#!/bin/bash
#文件名: get_memory_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "set": "1",
# "maximum_voltage": "1.2V",
# "configured_voltage": "1.2V",
# "rank": "2",
# "asset_tag": "011850A0",
# "locator": "A1",
# "minimum_voltage": "1.2V",
# "form_factor": "DIMM",
# "speed": "2666MHz",
# "configured_clock_speed": "2400MHz",
# "manufacturer": "00AD063200AD",
# "total_width": "72bits",
# "bank_locator": "NotSpecified",
# "part_number": "HMA82GR7AFR8N-VK",
# "type_detail": "Synchronous",
# "data_width": "64bits",
# "serial_number": "2DEAAAAA",
# "size": "16384MB",
# "type": "DDR4"
# }
#]
# 需要使用到的命令或工具是 dmidecode csplit
# 獲取每個槽位的內(nèi)存信息
function get_memory()
{
local memory_info_file="$1"
declare -A memory_slot
# 獲取set maximum_voltage configured_voltage minimum_voltage total_width type_detail rank asset_tag
memory_slot[set]=$(cat $memory_info_file |grep 'Set:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[maximum_voltage]=$(cat $memory_info_file |grep 'Maximum Voltage:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[configured_voltage]=$(cat $memory_info_file |grep 'Configured Voltage:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[minimum_voltage]=$(cat $memory_info_file |grep 'Minimum Voltage:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[total_width]=$(cat $memory_info_file |grep 'Total Width:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[type_detail]=$(cat $memory_info_file |grep 'Type Detail:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[data_width]=$(cat $memory_info_file |grep 'Data Width:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[rank]=$(cat $memory_info_file |grep 'Rank:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[asset_tag]=$(cat $memory_info_file |grep 'Asset Tag:' |awk -F ':' '{print $NF}' |tr -d ' ')
# 獲取locator form_factor speed configured_clock_speed manufacturer bank_locator part_number serial_number size type
memory_slot[locator]=$(cat $memory_info_file |grep ' Locator:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[form_factor]=$(cat $memory_info_file |grep 'Form Factor:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[speed]=$(cat $memory_info_file |grep " Speed:" |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[configured_clock_speed]=$(cat $memory_info_file |grep 'Configured Clock Speed:'|awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[manufacturer]=$(cat $memory_info_file |grep 'Manufacturer:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[bank_locator]=$(cat $memory_info_file |grep 'Bank Locator:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[part_number]=$(cat $memory_info_file |grep 'Part Number:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[serial_number]=$(cat $memory_info_file |grep 'Serial Number:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[size]=$(cat $memory_info_file |grep 'Size:' |awk -F ':' '{print $NF}' |tr -d ' ')
memory_slot[type]=$(cat $memory_info_file |grep 'Type:' |awk -F ':' '{print $NF}' |tr -d ' ')
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!memory_slot[@]}
do
_temp_json="{\"$key\":\"${memory_slot[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json |jq .
return 0
}
# 將內(nèi)存槽位信息拆分成一條一條的,并且獲取到所有的內(nèi)存槽位信息
function get_memory_all()
{
local num=0
IFS_old=$IFS
IFS=$'\n'
rm -f /tmp/memory_info_*.hw.info
# 取到所有內(nèi)存槽位的信息并保存
dmidecode -t memory >/tmp/memory_info_all.hw.info
# 使用 csplit 進行分割
csplit /tmp/memory_info_all.hw.info /Memory\ Device/ -n3 -s {*} -f /tmp/memory_info_ -b "%d.hw.info"
#ls /tmp/memory_info_*.hw.info
# 刪除第一條信息和總信息
rm -f /tmp/memory_info_0.hw.info
rm -f /tmp/memory_info_all.hw.info
# 獲取每條內(nèi)存的信息
local memory_all_info="[]"
for i in $(ls /tmp/memory_info_*.hw.info)
do
#get_memory "$i"
local _temp="[$(get_memory "$i")]"
memory_all_info=$(echo $memory_all_info |jq ". + $_temp")
done
# 去掉沒插內(nèi)存的槽位信息
#echo $memory_all_info |jq 'map(select(.size != "NoModuleInstalled"))'
memory_all_info=$(echo $memory_all_info |jq 'map(select(.size != "NoModuleInstalled"))')
echo $memory_all_info
rm -f /tmp/memory_info_*.hw.info
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_memory_all
#}
#
#main "$@"
1.3.3 獲取硬盤信息
#!/bin/bash
#文件名: get_disk_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "compliance": "SPC-4",
# "transport_protocol": "SAS",
# "serial_number": "03GZ8AAA",
# "logical_block_size": "512bytes",
# "product": "HUC101860CSS200",
# "revision": "FU29",
# "local_time_is": "562019CST",
# "temperature_warning": "DisabledorNotSupported",
# "locator": "/dev/bus/0-dmegaraid,0",
# "lun_id": "0x5000cca02f3707fc",
# "smart_health_status": "OK",
# "device_type": "disk",
# "user_capacity": "600GB",
# "vendor": "HGST",
# "rotation_rate": "10000rpm",
# "form_factor": "2.5inches"
# }
#]
# 需要使用到的命令或工具是 smartctl ssacli (因為硬件發(fā)展比較快,建議將smartctl升級到最新,否則有些硬盤不能識別)
function get_disk()
{
#/dev/bus/0 -d megaraid,0
local slot="$*"
smartctl -iH $slot > /tmp/disk.hw.info
declare -A disk_slot
# 獲取硬盤的locator
disk_slot[locator]=$(echo "$slot" |tr -d ' ')
# 獲取硬盤的vendor product revision compliance serial_number
disk_slot[vendor]=$(cat /tmp/disk.hw.info |grep '^Vendor:' |awk -F ':' '{print $NF}' |awk '{print $1}')
disk_slot[product]=$(cat /tmp/disk.hw.info |grep '^Product:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[revision]=$(cat /tmp/disk.hw.info |grep '^Revision:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[compliance]=$(cat /tmp/disk.hw.info |grep '^Compliance:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[serial_number]=$(cat /tmp/disk.hw.info |grep '^Serial ' |awk -F ':' '{print $NF}' |tr -d ' ')
# 獲取硬盤的user_capacity(size) logical_block_size physical_block_size rotation_rate form_factor lun_id
disk_slot[user_capacity]=$(cat /tmp/disk.hw.info |grep '^User Capacity:' |egrep -o '\[.*\]' |tr -d '\[|\]| ')
disk_slot[rotation_rate]=$(cat /tmp/disk.hw.info |grep '^Rotation Rate:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[form_factor]=$(cat /tmp/disk.hw.info |grep '^Form Factor:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[lun_id]=$(cat /tmp/disk.hw.info |grep '^Logical Unit id:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[logical_block_size]=$(cat /tmp/disk.hw.info |grep '^Logical block size:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[physical_block_size]=$(cat /tmp/disk.hw.info |grep '^Sector Sizes:' |egrep -o ', [0-9].*physical' |sed s/physical//g |tr -d ' |,')
# 獲取硬盤的device_type transport_protocol local_time_is smart_health_status temperature_warning firmware_version
disk_slot[device_type]=$(cat /tmp/disk.hw.info |grep '^Device type:' |awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[transport_protocol]=$(cat /tmp/disk.hw.info |grep '^Transport protocol:' |egrep -o 'SAS|SAT')
disk_slot[local_time_is]=$(cat /tmp/disk.hw.info |grep '^Local Time is:' |awk -F 's:' '{print $NF}' |tr -d ' ')
disk_slot[smart_health_status]=$(cat /tmp/disk.hw.info |grep '^SMART Health Status:'|awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[temperature_warning]=$(cat /tmp/disk.hw.info |grep '^Temperature Warning:'|awk -F ':' '{print $NF}' |tr -d ' ')
disk_slot[firmware_version]=$(cat /tmp/disk.hw.info |grep '^Firmware Version:' |awk -F ':' '{print $NF}' |tr -d ' ')
# 比較麻煩的數(shù)據(jù)抓取信息,需要邏輯判斷一下
# 硬盤logical_block_size
if [ "${disk_slot[logical_block_size]}" == "" ]; then
disk_slot[logical_block_size]=$(cat /tmp/disk.hw.info |grep '^Sector Sizes:' |egrep -o '[0-9].*logical,' |sed s/logical//g |tr -d ' |,')
fi
# 硬盤的lun_id
if [ "${disk_slot[lun_id]}" == "" ]; then
disk_slot[lun_id]=$(cat /tmp/disk.hw.info |grep '^LU WWN Device Id:' |awk -F ':' '{print $NF}' |tr -d ' ')
fi
# 硬盤的型號
if [ "${disk_slot[product]}" == "" ]; then
disk_slot[product]=$(cat /tmp/disk.hw.info |grep '^Device Model:' |awk -F ':' '{print $NF}' |awk '{print $1}')
fi
# 硬盤的接口
if [ "${disk_slot[transport_protocol]}" == "" ]; then
disk_slot[transport_protocol]=$(cat /tmp/disk.hw.info |grep '^SATA Version is:' |grep -o 'SATA'|head -n1)
fi
# 硬盤健康狀態(tài)
if [ "${disk_slot[smart_health_status]}" == "" ]; then
disk_slot[smart_health_status]=$(cat /tmp/disk.hw.info |grep '^SMART overall-health self-assessment test result:' |awk -F ':' '{print $NF}' |tr -d ' ')
fi
# 刪除產(chǎn)生的臨時文件
rm -f /tmp/disk.hw.info
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!disk_slot[@]}
do
_temp_json="{\"$key\":\"${disk_slot[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json |jq .
return 0
}
# 獲取到所有硬盤的信息
function get_disk_all()
{
local disk_all_info="[]"
# 將硬盤信息存到文件中
# 因為陣列卡種類繁多,驅(qū)動類型也不一樣,導(dǎo)致了不通的機器使用smartctl查看信息的參數(shù)也不同
# 我這邊只列舉了常用的三種驅(qū)動類型,以及查看方法(megaraid_sas mpt3sas smartpqi)
local array_driver=$(lsmod |egrep '^(megaraid_sas|mpt3sas|smartpqi)' |awk '{print $1}')
if [ "$array_driver" == "megaraid_sas" ]; then
smartctl --scan-open |egrep 'megaraid' |grep -v '^#'|cut -d '#' -f1 >/tmp/disk1.hw.info
if [ $(cat /tmp/disk1.hw.info |wc -l) -eq 0 ]; then
smartctl --scan-open |egrep 'scsi' |grep -v '^#'|cut -d '#' -f1 >/tmp/disk1.hw.info
fi
elif [ "$array_driver" == "mpt3sas" ]; then
smartctl --scan-open |grep sat |grep -v '^#'|cut -d '#' -f1 >/tmp/disk1.hw.info
elif [ "$array_driver" == "smartpqi" ]; then
local disk_num=$(ssacli ctrl slot=0 pd all show |grep physicaldrive |awk '{print $2}' |wc -l)
for((i=0;i<$disk_num;i++)); do
echo "-d cciss,$i /dev/sda" >>/tmp/disk1.hw.info
done
else
>/tmp/disk1.hw.info
fi
# 循環(huán)讀取每塊硬盤的信息,并添加到數(shù)組中
while read Line
do
local _temp="[$(get_disk $Line)]"
disk_all_info=$(echo $disk_all_info |jq ". + $_temp")
done </tmp/disk1.hw.info
rm -f /tmp/disk1.hw.info
# 輸出結(jié)果
echo $disk_all_info
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_disk_all
#}
#
#main "$@"
1.3.4 獲取nvme信息
#!/bin/bash
#文件名: get_nvme_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "controller_id": "0",
# "ieee_out_identifier": "0x5cd2e4",
# "serial_number": "PHLE811300G82PAAAAA",
# "logical_block_size": "512",
# "product": "INTELSSDPE2KE020T7",
# "local_time_is": "FriAug3016:19:272019CST",
# "locator": "-dnvme/dev/nvme0",
# "smart_health_status": "PASSED",
# "user_capacity": "2.00TB",
# "vendor": "0x8086",
# "firmware_version": "QDV10170"
# }
#]
# 需要使用到的命令或工具是 smartctl (因為硬件發(fā)展比較快,建議將smartctl升級到最新,否則有些硬盤不能識別)
function get_nvme()
{
# -d nvme /dev/nvme0
local slot="$*"
smartctl -iH $slot > /tmp/nvme.hw.info
declare -A nvme_slot
# 獲取nvme硬盤的locator
nvme_slot[locator]=$(echo "$slot" |tr -d ' ')
# 獲取硬盤的vendor product serial_number firmware_version ieee_out_identifier user_capacity logical_block_size local_time_is smart_health_status controller_id
nvme_slot[vendor]=$(cat /tmp/nvme.hw.info |grep '^PCI Vendor' |awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[product]=$(cat /tmp/nvme.hw.info |grep '^Model Number:' |awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[serial_number]=$(cat /tmp/nvme.hw.info |grep '^Serial ' |awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[firmware_version]=$(cat /tmp/nvme.hw.info |grep '^Firmware Version:' |awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[ieee_out_identifier]=$(cat /tmp/nvme.hw.info |grep '^IEEE OUI Identifier:'|awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[user_capacity]=$(cat /tmp/nvme.hw.info |grep '^Namespace 1 Size/Capacity:'|egrep -o '\[.*\]' |tr -d '\[|\]| ')
nvme_slot[logical_block_size]=$(cat /tmp/nvme.hw.info |grep '^Namespace 1 Formatted LBA Size:'|awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[local_time_is]=$(cat /tmp/nvme.hw.info |grep '^Local Time is:' |awk -F 's:' '{print $NF}' |tr -d ' ')
nvme_slot[smart_health_status]=$(cat /tmp/nvme.hw.info |grep '^SMART overall-health'|awk -F ':' '{print $NF}' |tr -d ' ')
nvme_slot[controller_id]=$(cat /tmp/nvme.hw.info |grep '^Controller ID:' |awk -F ':' '{print $NF}' |tr -d ' ')
# 刪除產(chǎn)生的臨時文件
rm -f /tmp/nvme.hw.info
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!nvme_slot[@]}
do
_temp_json="{\"$key\":\"${nvme_slot[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json |jq .
return 0
}
# 獲取到所有nvme硬盤的信息
function get_nvme_all()
{
local nvme_all_info="[]"
# 獲取nvme盤符
ls /dev/nvme* 2>/dev/null|egrep -o nvme[0-9]+$ >/tmp/nvme1.hw.info
#cat /tmp/nvme1.hw.info
# 判斷是否存在nvme硬盤
if [ $(cat /tmp/nvme1.hw.info |wc -l) -eq 0 ]; then
echo $nvme_all_info
rm -f /tmp/nvme1.hw.info
return 0
fi
# 循環(huán)讀取每塊nvme硬盤的信息,并添加到數(shù)組中
while read Line
do
local _temp="[$(get_nvme "-d nvme /dev/$Line")]"
nvme_all_info=$(echo $nvme_all_info |jq ". + $_temp")
done </tmp/nvme1.hw.info
# 刪除臨時文件
rm -f /tmp/nvme1.hw.info
# 輸出結(jié)果
echo $nvme_all_info
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_nvme_all
#}
#
#main "$@"
1.3.5 獲取網(wǎng)卡信息
#!/bin/bash
#文件名: get_netcard_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "slot": "01:00.0",
# "name": "eth2",
# "pci_id_1": "8086:1521",
# "pci_id_2": "1028:1f9a",
# "supported_ports": "TP",
# "mac": "e4:43:4b:42:73:d8",
# "chassis": "",
# "link_detected": "0",
# "speed": "Unknown!",
# "port": ""
# }
#]
# 需要使用到的命令或工具是 lspci ethtool lldpcli
function get_netcard()
{
local slot="$1"
lspci -nn -vmm | egrep 'Ethernet controller' -A4 -B1 |grep "$slot" -A5 >/tmp/netcard.hw.info
declare -A netcard_port
# 獲取slot的id
netcard_port[slot]="$slot"
# 獲取網(wǎng)卡的pciid,分成兩個字段
local _temp1=$(cat /tmp/netcard.hw.info |grep "^Vendor:" |awk '{print $NF}' |tr -d '[|]')
local _temp2=$(cat /tmp/netcard.hw.info |grep "^Device:" |awk '{print $NF}' |tr -d '[|]')
netcard_port[pci_id_1]="$_temp1:$_temp2"
local _temp3=$(cat /tmp/netcard.hw.info |grep "^SVendor:" |awk '{print $NF}' |tr -d '[|]')
local _temp4=$(cat /tmp/netcard.hw.info |grep "^SDevice:" |awk '{print $NF}' |tr -d '[|]')
netcard_port[pci_id_2]="$_temp3:$_temp4"
# 獲取對應(yīng)的網(wǎng)口名稱,如果沒有(可能是驅(qū)動問題),則默認為空字符串
local _temp0=$(ls -l /sys/class/net/* |grep $slot |awk -F '/' '{print $NF}')
netcard_port[name]="$_temp0"
if [ -z "$_temp0" ]
then
netcard_port[supported_ports]=""
netcard_port[link_detected]=""
netcard_port[speed]=""
netcard_port[mac]=""
netcard_port[chassis]=""
netcard_port[port]=""
else
# 獲取ethtool工具輸出的信息
ethtool ${netcard_port[name]} >/tmp/netcard1.hw.info 2>/dev/null
local _temp5=$(cat /tmp/netcard1.hw.info |grep 'Supported ports:' |egrep -o '\[.*\]' |tr -d '[|]| ')
netcard_port[supported_ports]="$_temp5"
local _temp6=$(cat /tmp/netcard1.hw.info |grep 'Link detected:' |awk '{print $NF}')
netcard_port[link_detected]="$_temp6"
local _temp7=$(cat /tmp/netcard1.hw.info |grep 'Speed:' |awk '{print $NF}')
netcard_port[speed]="$_temp7"
# 獲取mac
local _temp8=$(cat /sys/class/net/${netcard_port[name]}/address 2>/dev/null)
netcard_port[mac]="$_temp8"
# 獲取交換機端信息,通過使用lldpcli
local _temp9=$(lldpcli show neighbors ports ${netcard_port[name]} summary -f json |jq .lldp.interface.${netcard_port[name]}.chassis |jq -r 'if . then . else "" end' |jq -r keys[0])
local _temp10=$(lldpcli show neighbors ports ${netcard_port[name]} summary -f json |jq .lldp.interface |jq -r "if . then .${netcard_port[name]}.port.id.value else \"\" end")
netcard_port[chassis]="$_temp9"
netcard_port[port]="$_temp10"
fi
# 刪除產(chǎn)生的臨時文件
rm -f /tmp/netcard.hw.info
rm -f /tmp/netcard1.hw.info
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!netcard_port[@]}
do
_temp_json="{\"$key\":\"${netcard_port[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json |jq .
return 0
}
function get_netcard_all()
{
local netcard_all_info="[]"
for i in $(lspci -nn -vmm | egrep 'Ethernet controller' -B1 |grep Slot |awk '{print $NF}')
do
local _temp="[$(get_netcard "$i")]"
netcard_all_info=$(echo $netcard_all_info |jq ". + $_temp")
done
echo $netcard_all_info
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_netcard_all
#}
#
#main "$@"
1.3.6 獲取raid卡信息
#!/bin/bash
#文件名: get_raidcard_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "pci_id": "1000:005f"
# }
#]
# 需要使用到的命令或工具是 lscpi
function get_raidcard()
{
declare -A raidcard_info
raidcard_info[pci_id]=$(lspci -nn |egrep 'LSI|SCSI' |egrep -o '\[[0-9a-z]{4}\:[0-9a-z]{4}\]' |tr -d '\[\]')
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!raidcard_info[@]}
do
_temp_json="{\"$key\":\"${raidcard_info[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json
return 0
}
# 獲取到所有raidcard的信息
# 這里我用數(shù)據(jù)作為輸出格式,只是為了格式統(tǒng)一
function get_raidcard_all()
{
local raidcard_all_info="[]"
echo "[$(get_raidcard)]"
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_raidcard_all
#}
#
#main "$@"
1.3.7 獲取基本信息
#!/bin/bash
#文件名: get_base_info.sh
#作者:liuxin
#更新時間: 20190830
# 我們生成的內(nèi)容是
#[
# {
# "hostname": "",
# "processor": "x86_64",
# "version": "NotSpecified",
# "hardware_platform": "x86_64",
# "machine": "x86_64",
# "operating_system": "GNU/Linux",
# "serial_number": "AAAAAA",
# "wake-up_type": "PowerSwitch",
# "kernel_name": "Linux",
# "uuid": "4C4C4544-0039-4610-8033-C4C04F4B4C32",
# "product_name": "PowerEdgeR630",
# "kernel_release": "3.10.0-862.14.4.el7.x86_64",
# "family": "NotSpecified",
# "manufacturer": "DellInc."
# }
#]
# 需要使用到的命令或工具是 dmidecode uname
function get_base()
{
dmidecode -t1 > /tmp/base.hw.info
declare -A base_info
# 獲取服務(wù)器的 manufacturer product_name version serial_number uuid wake-up_type family
base_info[manufacturer]=$(cat /tmp/base.hw.info |grep 'Manufacturer:' |awk -F ':' '{print $NF}' |tr -d ' ')
base_info[product_name]=$(cat /tmp/base.hw.info |grep 'Product Name:' |awk -F ':' '{print $NF}' |tr -d ' ')
base_info[version]=$(cat /tmp/base.hw.info |grep 'Version:' |awk -F ':' '{print $NF}' |tr -d ' ')
base_info[serial_number]=$(cat /tmp/base.hw.info |grep 'Serial Number:'|awk -F ':' '{print $NF}' |tr -d ' ')
base_info[uuid]=$(cat /tmp/base.hw.info |grep 'UUID:' |awk -F ':' '{print $NF}' |tr -d ' ')
base_info[wake-up_type]=$(cat /tmp/base.hw.info |grep 'Wake-up Type:' |awk -F ':' '{print $NF}' |tr -d ' ')
base_info[family]=$(cat /tmp/base.hw.info |grep 'Family:' |awk -F ':' '{print $NF}' |tr -d ' ')
# 獲取機器的系統(tǒng)信息 hostname kernel_name kernel_release machine processor hardware_platform operating_system
base_info[hostname]=$(uname -n)
base_info[kernel_name]=$(uname -s)
base_info[kernel_release]=$(uname -r)
base_info[machine]=$(uname -m)
base_info[processor]=$(uname -p)
base_info[hardware_platform]=$(uname -i)
base_info[operating_system]=$(uname -o)
# 獲取系統(tǒng)版本信息,這個比較麻煩,需要做幾次判斷
base_info[os]=""
if [ -f /etc/centos-release ]; then
base_info[os]="centos-"$(cat /etc/centos-release |egrep -o '[0-9]+(\.[0-9]+)+')
elif [ -n "$(grep -i red /etc/redhat-release)" ]; then
base_info[os]="redhat-"$(cat /etc/redhat-release |egrep -o '[0-9]+(\.[0-9]+)+')
elif [ -n "$(grep -i ubuntu /etc/issue)" ]; then
base_info[os]="ubuntu-"$(cat /etc/issue |egrep -o '[0-9]+(\.[0-9]+)+')
fi
# 刪除產(chǎn)生的臨時文件
rm -f /tmp/base.hw.info
# 將關(guān)聯(lián)數(shù)組轉(zhuǎn)化為json字符串輸出
local str_json="{}"
for key in ${!base_info[@]}
do
_temp_json="{\"$key\":\"${base_info[$key]}\"}"
str_json=$(jq -n "$str_json + $_temp_json")
done
echo $str_json
return 0
}
# 獲取到所有基礎(chǔ)的信息
# 這里我用數(shù)據(jù)作為輸出格式,只是為了格式統(tǒng)一
function get_base_all()
{
local base_all_info="[]"
echo "[$(get_base)]"
return 0
}
#------------------
## 入口函數(shù),也是主函數(shù)
#function main()
#{
# get_base_all
#}
#
#main "$@"
1.3.8 主函數(shù)
#!/bin/bash
#文件名: main.sh
#作者:liuxin
#更新時間: 20190903
#------------------
# 入口函數(shù),也是主函數(shù)
function main()
{
# 獲取當(dāng)前腳本所在路徑
local file_path=$(dirname $(readlink -f "$0"))
# 導(dǎo)入其它函數(shù)
source $file_path/scripts/get_base_info.sh
source $file_path/scripts/get_cpu_info.sh
source $file_path/scripts/get_disk_info.sh
source $file_path/scripts/get_memory_info.sh
source $file_path/scripts/get_netcard_info.sh
source $file_path/scripts/get_nvme_info.sh
source $file_path/scripts/get_raidcard_info.sh
# 獲取所有數(shù)據(jù)
all=$(jq -n "{base:$(get_base_all)} + {cpu:$(get_cpu_all)} + {disk:$(get_disk_all)} + {memory:$(get_memory_all)} + {netcard:$(get_netcard_all)} + {nvme:$(get_nvme_all)} + {raidcard:$(get_raidcard_all)}")
#echo $all
# 上傳抓取到的數(shù)據(jù)
curl -X POST http://192.168.1.30:5000/api_2_0/server_info -H 'Content-Type: application/json' -d "{\"data\":$all}"
return 0
}
main "$@"
1.4 主函數(shù)
主結(jié)構(gòu)
.
├── main.sh
└── scripts
├── get_base_info.sh
├── get_cpu_info.sh
├── get_disk_info.sh
├── get_memory_info.sh
├── get_netcard_info.sh
├── get_nvme_info.sh
└── get_raidcard_info.sh
1 directory, 8 files