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}

相关推荐
流浪00116 分钟前
Linux系统篇34——信号(六):信号处理期间又来了怎么办?——sigaction、sa_mask、可重入函数与 volatile
linux·运维·面试·操作系统·信号处理·信号
学烹饪的小胡桃29 分钟前
资产设备管理系统 WGFIX 怎么设置https访问
linux·运维·服务器·网络·安全
Raspberry_Pi_官方账号1 小时前
在 Raspberry Pi 上构建一个数字主权的“第二大脑”
树莓派·syncthing·raspberrypi·logseq
邪修king1 小时前
Re:Linux系统篇(二十六):文件系统(二):Ext 文件系统底层详解:从 inode、块组到软硬链接,结合 Windows 讲透文件管理本质
android·java·linux
高亦真1 小时前
今天是学习嵌入式的第38天
linux·学习·算法
DYWorker0011 小时前
Linux驱动子系统:中断子系统 —— Consumer和Provider(005)
linux·驱动开发
草莓熊Lotso1 小时前
【Redis 进阶】主从复制深度解析:从配置落地到 PSYNC 同步原理
linux·开发语言·网络·数据库·redis·缓存·php
ShineWinsu2 小时前
对于Git:远程操作的超详细保姆级解析
linux·git·gitee·github·远程仓库·分布式版本控制系统·远程操作
小张成长计划..2 小时前
【Linux】21:进程间通信
linux
赵民勇3 小时前
systemd-sysusers命令详解
linux·运维