golang index out of range

2017-01-10 10:02:15来源:作者:QuanTalk人点击

项目中需要计算Linux上的 disk usage。个人在查阅相关资料后决定使用bash的 df命令, 通过解析df的输出来更方便地获取 disk usage。第一版代码如下:

import( "fmt" "strconv" "strings" "os/exec" "log")func main() { out, _ := exec.Command("df").Output() ret, err := parseDfOutput(string(out)) if err != nil { log.Println(err) } fmt.Println(ret)}func parseDfOutput(out string) (float64, error) { outlines := strings.Split(out, "/n") l := len(outlines) var total, used float64 = 0, 0 for _, line := range outlines[1:l-1] { parsedLine := strings.Fields(line) t, err := strconv.ParseFloat(parsedLine[1], 64) if err != nil { return 0, err } u, err := strconv.ParseFloat(parsedLine[2], 64) if err != nil { return 0, err } total += t used += u } return used/total, nil }

代码在centos 7.2上面运行没有任何问题。但是运行在 docker alpine image后却报错:

/go/src/dftest # go run main.go panic: runtime error: index out of rangegoroutine 1 [running]: panic(0x500060, 0xc82000a070) /usr/local/go/src/runtime/panic.go:481 +0x3e6main.parseDfOutput(0xc820098000, 0x43d, 0xe00, 0xe00, 0x0, 0x0) /go/src/dftest/main.go:40 +0x321main.GetDiskUsageInfo(0xc820010118) /go/src/dftest/main.go:24 +0x212main.main() /go/src/dftest/main.go:12 +0x39exit status 2

关键是这句 index out of range数组越界了。我在 alpine中执行 df结果:

/go/src/dftest # dfFilesystem 1K-blocks Used Available Use% Mounted on /dev/mapper/docker-253:3-805329214-d52e8766f0fdd9a7dd12a7c05f2f26b31e8d58a3785a0045af8164bfca26a091 10474496 327704 10146792 3% /tmpfs 3954476 0 3954476 0% /dev tmpfs 3954476 0 3954476 0% /sys/fs/cgroup /dev/mapper/centos-var 209612800 22256172 187356628 11% /etc/resolv.conf/dev/mapper/centos-var 209612800 22256172 187356628 11% /etc/hostname/dev/mapper/centos-var 209612800 22256172 187356628 11% /etc/hostsshm 65536 0 65536 0% /dev/shm /dev/mapper/centos-home 733644800 17485984 716158816 2% /go/src/dftesttmpfs 3954476 0 3954476 0% /proc/kcore tmpfs 3954476 0 3954476 0% /proc/timer_list tmpfs 3954476 0 3954476 0% /proc/timer_stats tmpfs 3954476 0 3954476 0% /proc/sched_debug

再修改代码逐行数据df的结果后发现,如果文件系统的映射路径过长,像:

/dev/mapper/docker-253:3-805329214-d52e8766f0fdd9a7dd12a7c05f2f26b31e8d58a3785a0045af8164bfca26a091 /dev/mapper/centos-var

在linux上显示的时候一个表格无法显示,就会默认加上 /n来实现更优雅的显示效果。所以

outlines := strings.Split(out, "/n")

这行代码会产生比预计多很多的行数,导致后面解析时数组越界。

查看 df使用信息后加上个flag -P就好了。即:

out, _ := exec.Command("df").Output() --> out, _ := exec.Command("df", "-P").Output()

完整的代码如下:

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台