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}

相关推荐
yuxb73几秒前
Linux 文本处理与 Shell 编程笔记:正则表达式、sed、awk 与变量脚本
linux·笔记·正则表达式
刘一说12 分钟前
CentOS 系统 Java 开发测试环境搭建手册
java·linux·运维·服务器·centos
wdxylb6 小时前
云原生俱乐部-shell知识点归纳(1)
linux·云原生
飞雪20077 小时前
Alibaba Cloud Linux 3 在 Apple M 芯片 Mac 的 VMware Fusion 上部署的完整密码重置教程(二)
linux·macos·阿里云·vmware·虚拟机·aliyun·alibaba cloud
路溪非溪7 小时前
关于Linux内核中头文件问题相关总结
linux
Lovyk10 小时前
Linux 正则表达式
linux·运维
Fireworkitte10 小时前
Ubuntu、CentOS、AlmaLinux 9.5的 rc.local实现 开机启动
linux·ubuntu·centos
sword devil90011 小时前
ubuntu常见问题汇总
linux·ubuntu
ac.char11 小时前
在CentOS系统中查询已删除但仍占用磁盘空间的文件
linux·运维·centos
淮北也生橘1213 小时前
Linux的ALSA音频框架学习笔记
linux·笔记·学习