在 linux 上可以通過 dmidecode 或是 lshw 來獲取硬件信息,能夠方便的查看系統(tǒng)配置。但它們的輸出信息過多,解析起來有些麻煩,另外 lshw 對 usb 接口的網(wǎng)卡支持不好,顯示的信息不夠,所以在此整理下通過讀文件或是一些簡單命令來獲取硬件信息的方法。
DMI
一般情況下內(nèi)核默認加載了 dmi sysfs ,路徑是 /sys/class/dmi 。里面包含了 bios , board , product 等信息。
Bios
通過命令 ls -l /sys/class/dmi/id/bios_* 可以看到支持的 bios 字段,如下:
$ ls -l /sys/class/dmi/id/bios_*
-r--r--r-- 1 root root 4.0K 5月 8 17:18 /sys/class/dmi/id/bios_date
-r--r--r-- 1 root root 4.0K 5月 8 17:18 /sys/class/dmi/id/bios_vendor
-r--r--r-- 1 root root 4.0K 5月 8 17:18 /sys/class/dmi/id/bios_version
直接讀文件即可獲取對應(yīng)值。
Board
通過命令 ls -l /sys/class/dmi/id/board_* 可以看到支持的 board 字段,如下:
$ ls -l /sys/class/dmi/id/board_*
-r--r--r-- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/board_asset_tag
-r--r--r-- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/board_name
-r-------- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/board_serial
-r--r--r-- 1 root root 4.0K 5月 8 08:43 /sys/class/dmi/id/board_vendor
-r--r--r-- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/board_version
直接讀文件即可獲取對應(yīng)值,但有些文件需要 root 權(quán)限。
Product
通過命令 ls -l /sys/class/dmi/id/product_* 可以看到支持的 product 字段,如下:
$ ls -l /sys/class/dmi/id/product_*
-r--r--r-- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/product_family
-r--r--r-- 1 root root 4.0K 5月 8 08:43 /sys/class/dmi/id/product_name
-r-------- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/product_serial
-r--r--r-- 1 root root 4.0K 5月 8 17:12 /sys/class/dmi/id/product_sku
-r-------- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/product_uuid
-r--r--r-- 1 root root 4.0K 5月 8 08:45 /sys/class/dmi/id/product_version
直接讀文件即可獲取對應(yīng)值,但有些文件需要 root 權(quán)限。
其中 product_uuid 可作為機器的唯一 ID 。
CPU
通過讀取文件 /proc/cpuinfo 可獲取 cpu 的信息,一般 model name 字段為 cpu 名稱,如:
$ cat /proc/cpuinfo|grep 'model name'
model name : Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
model name : Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
model name : Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
model name : Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
但在龍芯,申威上可能不是這個字段,需要根據(jù)文件內(nèi)容確定。
Memory
通過讀取文件 /proc/meminfo 可獲取內(nèi)存總大小,字段是 MemTotal ,如:
$ cat /proc/meminfo |grep MemTotal
MemTotal: 7860064 kB
對于內(nèi)存廠商等信息還未找到獲取方法,待以后補全。
Disk
硬盤信息這里使用 lsblk 來獲取,通過指定它的參數(shù)來獲取,如:
$ lsblk -J -bno NAME,SERIAL,TYPE,SIZE,VENDOR,MODEL,MOUNTPOINT,UUID
{
"blockdevices": [
{"name": "sda", "serial": "TF0500WE0GAV0V", "type": "disk", "size": "500107862016", "vendor": "ATA ", "model": "HGST HTS725050A7", "mountpoint": null,
"children": [
{"name": "sda1", "serial": null, "type": "part", "size": "4294967296", "vendor": null, "model": null, "mountpoint": "/boot"},
{"name": "sda2", "serial": null, "type": "part", "size": "4294967296", "vendor": null, "model": null, "mountpoint": "[SWAP]"},
{"name": "sda3", "serial": null, "type": "part", "size": "1024", "vendor": null, "model": null, "mountpoint": null},
{"name": "sda5", "serial": null, "type": "part", "size": "107374182400", "vendor": null, "model": null, "mountpoint": "/Data"},
{"name": "sda6", "serial": null, "type": "part", "size": "64424509440", "vendor": null, "model": null, "mountpoint": "/"}
]
}
]
}
參數(shù)的含義通過 lsblk -h 命令查看。
只有 type 為 disk 時才表示為一塊硬盤,其它如 loop 則應(yīng)該過濾掉。 每塊硬盤中的 children 表示它下面的分區(qū),通過 mountpoint 可確定硬盤在此系統(tǒng)上的使用情況。
Network
這里是先獲取系統(tǒng)上的網(wǎng)絡(luò)接口,這包括了物理網(wǎng)卡和虛擬網(wǎng)卡(如 docker 創(chuàng)建的)。
所以要先過濾,過濾順序如下:
1. 按名字過濾
過濾掉 lo
2. 按驅(qū)動過濾
過濾掉驅(qū)動為 dummy, veth, vboxnet, vmnet, vmxnet, vmxnet2, vmxnet3 的網(wǎng)卡, 虛擬機中的
3. 按網(wǎng)卡類型過濾
過濾掉 bridge 類型的網(wǎng)卡
如果網(wǎng)卡接口同時存在于 /sys/class/net/ 和 /sys/devices/virtual/net/ 中,則需要過濾掉。
接下來分別給出網(wǎng)卡信息獲取的方法:
Interface Name
即是上面的目錄下的子目錄名
Mac Address
讀取文件 /sys/class/net/<iface name>/address 可得到
IP
通過調(diào)用 ioctl 來獲取指定 iface name 的 ip ,代碼大致如下:
char* get_ip_for_iface(char *iface)
{
int fd;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
fprintf(stderr, "open socket failed: %s", strerror(errno));
return;
}
// must init ifr
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ - 1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
char *c_addr = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
char *ip = calloc(strlen(c_addr)+1, sizeof(char));
memcpy(ip, c_addr, strlen(c_addr));
return ip;
}
ipv6 的暫未測試。
Model
網(wǎng)卡一般在 pci 接口上,但也有些實在 usb 接口上,要分別獲取。
不過都要先讀取文件 /sys/class/net/enp0s25/device/uevent ,然后分別處理。
-
pci
uevent內(nèi)容如:DRIVER=e1000e PCI_CLASS=20000 PCI_ID=8086:1502 PCI_SUBSYS_ID=17AA:21F3 PCI_SLOT_NAME=0000:00:19.0 MODALIAS=pci:v00008086d00001502sv000017AAsd000021F3bc02sc00i00取到其中的
PCI_SLOT_NAME,然后執(zhí)行lspci -k -s <PCI_SLOT_NAME>來獲取model信息,如:$ lspci -k -s 0000:00:19.0 00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (Lewisville) (rev 04) Subsystem: Lenovo 82579LM Gigabit Network Connection Kernel driver in use: e1000e Kernel modules: e1000e其中
Subsystem之后的即是model信息。 -
usb
uevent內(nèi)容如:DEVTYPE=usb_interface DRIVER=ath9k_htc PRODUCT=cf3/9271/108 TYPE=255/255/255 INTERFACE=255/0/0 MODALIAS=usb:v0CF3p9271d0108dcFFdscFFdpFFicFFisc00ip00in00取到其中的
PRODUCT,然后將/替換為:,然后執(zhí)行lsusb -d <product>來獲取model信息,如:# 可以不要最后的 '108' $ lsusb -d cf3:9271:108 Bus 001 Device 007: ID 0cf3:9271 Atheros Communications, Inc. AR9271 802.11n其中
Subsystem之后的即是model信息。
Bluetooth
在 /sys/class/bluetooth/ 下是藍牙設(shè)備,與 網(wǎng)卡 一樣,根據(jù) /sys/class/bluetooth/<hciX>/device/uevent 的內(nèi)容使用 lspci 或 lsusb 來獲取 model 信息。
如:
$ cat /sys/class/bluetooth/hci0/device/uevent
DEVTYPE=usb_interface
DRIVER=btusb
PRODUCT=a5c/21e6/112
TYPE=255/1/1
INTERFACE=255/1/1
MODALIAS=usb:v0A5Cp21E6d0112dcFFdsc01dp01icFFisc01ip01in00
這就是一個 usb 接口的設(shè)備,所以使用 lsusb 來獲取 model 信息,如:
$ lsusb -d a5c:21e6:112
Bus 001 Device 003: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad]
Graphic
顯卡信息在 /sys/class/drm/ 下,里面還包含了顯卡支持輸出接口,但只有 card+integer 組成的目錄才是顯卡的,如本機的信息:
$ ls /sys/class/drm/
card0@ card0-DP-1@ card0-DP-2@ card0-DP-3@ card0-HDMI-A-1@ card0-HDMI-A-2@ card0-HDMI-A-3@ card0-LVDS-1@ card0-VGA-1@ renderD128@ version
根據(jù)輸出可知只有一塊顯卡 card0 ,通過讀取文件 card0/device/uevent 獲取設(shè)備類型,然后同 網(wǎng)卡 一樣查詢 model 信息,如:
$ cat /sys/class/drm/card0/device/uevent
DRIVER=i915
PCI_CLASS=30000
PCI_ID=8086:0166
PCI_SUBSYS_ID=17AA:21FA
PCI_SLOT_NAME=0000:00:02.0
MODALIAS=pci:v00008086d00000166sv000017AAsd000021FAbc03sc00i00
$ lspci -k -s 0000:00:02.0
00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09)
Subsystem: Lenovo 3rd Gen Core processor Graphics Controller
Kernel driver in use: i915
Kernel modules: i915
另外 /sys/class/hwmon/ 和 /sys/class/graphics/ 下有當前使用中的顯卡設(shè)備,也是對應(yīng)子目錄下的 device/uevent 來獲取信息。
若無 device 目錄或是 device/uevent 中的內(nèi)容既沒有 pci 信息也沒有 usb 信息,則過濾掉,有就如下所示獲?。?/p>
hwmon
$ cat /sys/class/hwmon/hwmon2/device/uevent
DRIVER=nouveau
PCI_CLASS=30000
PCI_ID=10DE:0A75
PCI_SUBSYS_ID=17AA:3957
PCI_SLOT_NAME=0000:02:00.0
MODALIAS=pci:v000010DEd00000A75sv000017AAsd00003957bc03sc00i00
$ lspci -k -s 0000:02:00.0
02:00.0 VGA compatible controller: NVIDIA Corporation GT218M [GeForce 310M] (rev a2)
Subsystem: Lenovo GT218M [GeForce 310M]
Kernel driver in use: nouveau
Kernel modules: nouveau
graphics
$ cat /sys/class/graphics/fb0/device/uevent
DRIVER=i915
PCI_CLASS=30000
PCI_ID=8086:0166
PCI_SUBSYS_ID=17AA:21FA
PCI_SLOT_NAME=0000:00:02.0
MODALIAS=pci:v00008086d00000166sv000017AAsd000021FAbc03sc00i00
$ lspci -k -s 0000:00:02.0
00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics Controller (rev 09)
Subsystem: Lenovo 3rd Gen Core processor Graphics Controller
Kernel driver in use: i915
Kernel modules: i915
Display Monitor
顯示器的信息目前是從 edid 中獲取,先確定顯示器連接的顯卡端口,然后使用 edid-decode (需要安裝)解析其的 edid 文件,就可得到詳細信息。如本機是 card0-LVDS-1 :
$ cat /sys/class/drm/card0-LVDS-1/edid|edid-decode
Extracted contents:
header: 00 ff ff ff ff ff ff 00
serial number: 06 af 6c 10 00 00 00 00 00 14
version: 01 04
basic params: 90 1c 10 78 02
chroma info: 20 e5 92 55 54 92 28 25 50 54
established: 00 00 00
standard: 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
descriptor 1: 12 1b 56 58 50 00 19 30 30 20 36 00 15 9c 10 00 00 18
descriptor 2: 00 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 20
descriptor 3: 00 00 00 fe 00 41 55 4f 0a 20 20 20 20 20 20 20 20 20
descriptor 4: 00 00 00 fe 00 42 31 32 35 58 57 30 31 20 56 30 20 0a
extensions: 00
checksum: ec
Manufacturer: AUO Model 106c Serial Number 0
Made week 0 of 2010
EDID version: 1.4
Digital display
6 bits per primary color channel
Digital interface is not defined
Maximum image size: 28 cm x 16 cm
Gamma: 2.20
Supported color formats: RGB 4:4:4
First detailed timing is preferred timing
Established timings supported:
Standard timings supported:
Detailed mode: Clock 69.300 MHz, 277 mm x 156 mm
1366 1414 1446 1454 hborder 0
768 771 777 793 vborder 0
-hsync -vsync
Manufacturer-specified data, tag 15
ASCII string: AUO
ASCII string: B125XW01
Checksum: 0xec (valid)
EDID block does NOT conform to EDID 1.3!
Missing name descriptor
Missing monitor ranges
Detailed block string not properly terminated
Sound
聲卡設(shè)備在 /sys/class/sound 目錄下,目錄名一般是 card+integer 組成,如本機的信息:
$ ls /sys/class/sound/
card0@ controlC0@ hwC0D0@ hwC0D3@ pcmC0D0c@ pcmC0D0p@ pcmC0D3p@ pcmC0D7p@ pcmC0D8p@ timer@
就只有一塊聲卡 card0 ,通過讀取文件 card0/device/uevent 獲取設(shè)備類型,然后同 網(wǎng)卡 一樣查詢 model 信息,如:
$ cat /sys/class/sound/card0/device/uevent
DRIVER=snd_hda_intel
PCI_CLASS=40300
PCI_ID=8086:1E20
PCI_SUBSYS_ID=17AA:21FA
PCI_SLOT_NAME=0000:00:1b.0
MODALIAS=pci:v00008086d00001E20sv000017AAsd000021FAbc04sc03i00
$ lspci -k -s 0000:00:1b.0
00:1b.0 Audio device: Intel Corporation 7 Series/C216 Chipset Family High Definition Audio Controller (rev 04)
Subsystem: Lenovo 7 Series/C216 Chipset Family High Definition Audio Controller
Kernel driver in use: snd_hda_intel
Kernel modules: snd_hda_intel
Input/Output Device
輸入設(shè)備的信息可以從 /proc/bus/input/devices 文件中獲取,如:
I: Bus=0019 Vendor=0000 Product=0005 Version=0000
N: Name="Lid Switch"
P: Phys=PNP0C0D/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input0
U: Uniq=
H: Handlers=event0
B: PROP=0
B: EV=21
B: SW=1
I: Bus=0011 Vendor=0001 Product=0001 Version=ab54
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input3
U: Uniq=
H: Handlers=sysrq kbd event3 leds
B: PROP=0
B: EV=120013
B: KEY=10000 0 0 0 1000402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7
I: Bus=0011 Vendor=0002 Product=0007 Version=01b1
N: Name="SynPS/2 Synaptics TouchPad"
P: Phys=isa0060/serio1/input0
S: Sysfs=/devices/platform/i8042/serio1/input/input5
U: Uniq=
H: Handlers=mouse0 event5
B: PROP=5
B: EV=b
B: KEY=e520 10000 0 0 0 0
B: ABS=660800011000003
...
由于內(nèi)容太多,這里就只顯示部分內(nèi)容。
另外也可通過 xinput 命令獲取,如:
$ xinput
? Virtual core pointer id=2 [master pointer (3)]
? ? Virtual core XTEST pointer id=4 [slave pointer (2)]
? ? SynPS/2 Synaptics TouchPad id=11 [slave pointer (2)]
? ? TPPS/2 IBM TrackPoint id=12 [slave pointer (2)]
? Virtual core keyboard id=3 [master keyboard (2)]
? Virtual core XTEST keyboard id=5 [slave keyboard (3)]
? Power Button id=6 [slave keyboard (3)]
? Video Bus id=7 [slave keyboard (3)]
? Sleep Button id=8 [slave keyboard (3)]
? Integrated Camera: Integrated C id=9 [slave keyboard (3)]
? AT Translated Set 2 keyboard id=10 [slave keyboard (3)]
? ThinkPad Extra Buttons id=13 [slave keyboard (3)]
使用 xinput list-prop <device id> 可以查看設(shè)備的屬性。
Battery
電池信息可以從 /sys/class/power_supply/<name>/uevent 文件中獲取,電池的名稱一般以 BAT 開頭。如本機的信息:
$ cat /sys/class/power_supply/BAT0/uevent
POWER_SUPPLY_NAME=BAT0
POWER_SUPPLY_STATUS=Full
POWER_SUPPLY_PRESENT=1
POWER_SUPPLY_TECHNOLOGY=Li-ion
POWER_SUPPLY_CYCLE_COUNT=0
POWER_SUPPLY_VOLTAGE_MIN_DESIGN=11100000
POWER_SUPPLY_VOLTAGE_NOW=12226000
POWER_SUPPLY_POWER_NOW=0
POWER_SUPPLY_ENERGY_FULL_DESIGN=57720000
POWER_SUPPLY_ENERGY_FULL=48000000
POWER_SUPPLY_ENERGY_NOW=48000000
POWER_SUPPLY_CAPACITY=100
POWER_SUPPLY_CAPACITY_LEVEL=Full
POWER_SUPPLY_MODEL_NAME=45N1023
POWER_SUPPLY_MANUFACTURER=SANYO
POWER_SUPPLY_SERIAL_NUMBER=15921
Backlight
/sys/class/backlight/ 目錄下的是背光設(shè)備,如顯示屏,背光鍵盤等,可以更改文件內(nèi)容來調(diào)節(jié)這些設(shè)備的亮度。如:
$ ls /sys/class/backlight/intel_backlight/
actual_brightness bl_power brightness device@ max_brightness power/ subsystem@ type uevent
-
brightness
更改這個文件可以修改此設(shè)備的當前亮度
-
max_brightness
這個文件顯示的是此設(shè)備支持的最大亮度
另外背光設(shè)備 device 可能只想真實的顯卡設(shè)備,一般是子目錄中包含 video 的。
Camera
/sys/class/video4linux/ 下是攝像頭設(shè)備,不同子目錄中的設(shè)備可能是同一個,也是讀取 device/uevent 文件來選擇 lspci 或 lsusb 獲取設(shè)備信息,如:
$ cat /sys/class/video4linux/video0/device/uevent
DEVTYPE=usb_interface
DRIVER=uvcvideo
PRODUCT=5986/2d2/11
TYPE=239/2/1
INTERFACE=14/1/0
MODALIAS=usb:v5986p02D2d0011dcEFdsc02dp01ic0Eisc01ip00in00
$ lsusb -d 5986:2d2:11
Bus 001 Device 004: ID 5986:02d2 Acer, Inc
Printer
打印機應(yīng)該是在 /sys/class/printer 下,信息獲取方法應(yīng)該與上文一致,本人手中沒有打印機就不給出示例了。
Fingerprint
指紋的功能目前是由 libfprint 項目提供,調(diào)用其提供的接口來獲取。
如使用 qdbus 來獲?。?/p>
$ qdbus --system --literal net.reactivated.Fprint /net/reactivated/Fprint/Manager net.reactivated.Fprint.Manager.GetDevices
[Argument: ao {}]
輸出可知本機沒有指紋設(shè)備。
實現(xiàn)
這里用 Go 實現(xiàn)了 hardware ,見此: hardware