GO解析 - Linux 指令之 lsblk

版本

lsblk --version

lsblk from util-linux 2.38.1

代码

lsblkParser.go

go 复制代码
package utils

type LSBlkItem struct {
	Name       string // 名称
	Major      uint   // 主版本
	Minor      uint   // 此版本
	Removable  bool   // 可移除de
	Writable   bool   // 可写的
	Size       uint   // 大小字节
	Type       string // 类型, part是上一个磁盘的一部分,disk就是磁盘
	MountPoint string // 挂载点

	Parent *LSBlkItem // 父挂载点
}

type LSBlkParser struct {
}

lsblkParser_linux.go

go 复制代码
package utils

import (
	"errors"
	"os/exec"
	"strconv"
	"strings"
)

func (l *LSBlkParser) GetSizes(devNames []string) ([]LSBlkItem, error) {
	items, err := l.getItems()
	if nil != err {
		return nil, err
	}
	return items, err
}

func (l *LSBlkParser) getItems() ([]LSBlkItem, error) {
	/*
		-b 以字节显示磁盘大小
		-p 打印设备完整路径
	*/
	cmd := exec.Command("lsblk", "-b", "-p")
	bs, err := cmd.CombinedOutput()
	if nil != err {
		return nil, err
	}

	lines := strings.SplitN(string(bs), "\n", -1)
	var (
		isChild bool
		parent  *LSBlkItem
		items   = make([]LSBlkItem, 0)
	)
	for i, line := range lines {
		var item LSBlkItem
		if 0 == i || 0 >= len(line) {
			continue
		} // 第一行是标题行, 跳过
		item, isChild, err = l.getItem(line)
		if nil != err {
			return nil, err
		}
		if isChild {
			item.Parent = parent
		}
		items = append(items, item)
		if !isChild {
			parent = &items[len(items)-1]
		}
	}

	return items, err
}

func (l *LSBlkParser) getItem(line string) (item LSBlkItem, isChild bool, err error) {
	var (
		itemMinCnt = 6 // 字符串分解之后最少会有多少个
		//itemMaxCnt = 7
		currItemCnt = 0
	)
	/*
		NAME              MAJ:MIN RM        SIZE RO TYPE MOUNTPOINTS
		/dev/sda            8:0    1           0  0 disk
		/dev/sdb            8:16   1 31104958464  0 disk
		/dev/mmcblk0      179:0    0  7818182656  0 disk
		├─/dev/mmcblk0p1  179:1    0   536870912  0 part /boot/firmware
		└─/dev/mmcblk0p2  179:2    0  7277117440  0 part /
		/dev/mmcblk0boot0 179:32   0     4194304  1 disk
		/dev/mmcblk0boot1 179:64   0     4194304  1 disk
	*/
	strs := strings.Fields(line)
	currItemCnt = len(strs)
	if itemMinCnt > currItemCnt {
		return item, false, errors.New("item count not enough")
	}
	for i, str := range strs {
		switch i {
		case 0:
			if item.Name, err = l.getName(str); nil != err {
				return
			}
		case 1:
			if item.Major, item.Minor, err = l.getMajorMinor(str); nil != err {
				return
			}
		case 2:
			if item.Removable, err = l.getRemovable(str); nil != err {
				return
			}
		case 3:
			if item.Size, err = l.getSize(str); nil != err {
				return
			}
		case 4:
			if item.Writable, err = l.getWritable(str); nil != err {
				return
			}
		case 5:
			if item.Type, isChild, err = l.getType(str); nil != err {
				return
			}
		case 6:
			if item.MountPoint, err = l.getMountPoint(str); nil != err {
				return
			}
		}
	}

	return
}

func (l *LSBlkParser) getName(str string) (string, error) {
	for i := range str {
		if str[i] != '/' {
			continue
		}
		str = str[i:]
		return str, nil
	}

	return str, nil
}

func (l *LSBlkParser) getMajorMinor(str string) (major uint, minor uint, err error) {
	var temp uint64
	strs := strings.Split(str, ":") // 8:0
	for i := range strs {
		if temp, err = strconv.ParseUint(strs[i], 10, 32); nil != err {
			return
		}
		if 0 == i {
			major = uint(temp)
		} else if 1 == i {
			minor = uint(temp)
		} else {
			break
		}
	}
	return
}

func (l *LSBlkParser) getRemovable(str string) (bool, error) {
	temp, err := strconv.ParseUint(str, 10, 64)
	if nil != err {
		return false, err
	}
	if 0 == temp {
		return false, nil
	} else {
		return true, nil
	}
}

func (l *LSBlkParser) getSize(str string) (uint, error) {
	temp, err := strconv.ParseUint(str, 10, 64)
	if nil != err {
		return 0, err
	}
	return uint(temp), nil
}

func (l *LSBlkParser) getWritable(str string) (bool, error) {
	temp, err := strconv.ParseUint(str, 10, 64)
	if nil != err {
		return false, err
	}
	if 0 == temp {
		return true, nil
	} else {
		return false, nil
	}
}

func (l *LSBlkParser) getType(str string) (typ string, isChild bool, err error) {
	typ = str
	if 0 == strings.Compare(str, "disk") {
		isChild = false
	} else if 0 == strings.Compare(str, "part") {
		isChild = true
	}
	return
}

func (l *LSBlkParser) getMountPoint(str string) (string, error) {
	return str, nil
}

测试

main.go

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
	"pi_gpio_test/utils"
)

func main() {
	var lsblkParser utils.LSBlkParser

	items, err := lsblkParser.GetSizes([]string{
		"/dev/sda", "/dev/sdb",
	})
	if nil != err {
		fmt.Println(err)
		return
	}

	for _, item := range items {
		bs, err := json.Marshal(item)
		fmt.Println(string(bs), err)
	}
}

结果

{"Name":"/dev/sda","Major":8,"Minor":0,"Removable":true,"Writable":true,"Size":0,"Type":"disk","MountPoint":"","Parent":null}

{"Name":"/dev/mmcblk0","Major":179,"Minor":0,"Removable":false,"Writable":true,"Size":3523215360,"Type":"disk","MountPoint":"","Parent":null}

{"Name":"├─/dev/mmcblk0p1","Major":179,"Minor":1,"Removable":false,"Writable":true,"Size":536870912,"Type":"part","MountPoint":"/boot/firmware","Parent":{"Name":"/dev/mmcblk0","Major":179,"Minor":0,"Removable":false,"Writable":true,"Size":3523215360,"Type":"disk","MountPoint":"","Parent":null}}

{"Name":"└─/dev/mmcblk0p2","Major":179,"Minor":2,"Removable":false,"Writable":true,"Size":2982150144,"Type":"part","MountPoint":"/","Parent":{"Name":"/dev/mmcblk0","Major":179,"Minor":0,"Removable":false,"Writable":true,"Size":3523215360,"Type":"disk","MountPoint":"","Parent":null}}

{"Name":"/dev/mmcblk0boot0","Major":179,"Minor":32,"Removable":false,"Writable":false,"Size":4194304,"Type":"disk","MountPoint":"","Parent":null}

{"Name":"/dev/mmcblk0boot1","Major":179,"Minor":64,"Removable":false,"Writable":false,"Size":4194304,"Type":"disk","MountPoint":"","Parent":null}

相关推荐
码农君莫笑7 分钟前
Blazor项目中使用EF读写 SQLite 数据库
linux·数据库·sqlite·c#·.netcore·人机交互·visual studio
无为之士28 分钟前
Linux自动备份Mysql数据库
linux·数据库·mysql
Algorithm157644 分钟前
云原生相关的 Go 语言工程师技术路线(含博客网址导航)
开发语言·云原生·golang
岑梓铭44 分钟前
(CentOs系统虚拟机)Standalone模式下安装部署“基于Python编写”的Spark框架
linux·python·spark·centos
努力学习的小廉1 小时前
深入了解Linux —— make和makefile自动化构建工具
linux·服务器·自动化
MZWeiei1 小时前
Zookeeper基本命令解析
大数据·linux·运维·服务器·zookeeper
7yewh1 小时前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
小张认为的测试1 小时前
Linux性能监控命令_nmon 安装与使用以及生成分析Excel图表
linux·服务器·测试工具·自动化·php·excel·压力测试
打鱼又晒网1 小时前
linux网络套接字 | 深度解析守护进程 | 实现tcp服务守护进程化
linux·网络协议·计算机网络·tcp
良许Linux1 小时前
0.96寸OLED显示屏详解
linux·服务器·后端·互联网