【问题标题】:Get amount of free disk space using Go使用 Go 获取可用磁盘空间量
【发布时间】:2013-12-05 04:31:00
【问题描述】:

基本上我想要df -h 的输出,其中包括可用空间和卷的总大小。该解决方案需要在 Windows、Linux 和 Mac 上运行,并使用 Go 编写。

我查看了 ossyscall Go 文档,但没有找到任何东西。在 Windows 上,即使是命令行实用程序也很笨拙 (dir C:\) 或需要提升权限 (fsutil volume diskfree C:\)。当然有一种方法可以做到这一点,我还没有找到......

更新:
根据 nemo 的回答和邀请,我提供了一个 cross-platform Go package 来执行此操作。

【问题讨论】:

  • 我所拥有的只是你可以使用cgo 降级到C:编写freespace_windows.go 和freespace_{linux,bsd}.go,然后使用GetDiskFreeSpacestatvfs 来获取可用空间。

标签: go diskspace


【解决方案1】:

在 POSIX 系统上,您可以使用 sys.unix.Statfs
以字节为单位打印当前工作目录的可用空间示例:

import "golang.org/x/sys/unix"
import "os"

var stat unix.Statfs_t

wd, err := os.Getwd()

unix.Statfs(wd, &stat)

// Available blocks * size per block = available space in bytes
fmt.Println(stat.Bavail * uint64(stat.Bsize))

对于 Windows,您还需要走系统调用路线。示例(source,已更新以匹配 new sys/windows package):

import "golang.org/x/sys/windows"

h := windows.MustLoadDLL("kernel32.dll")
c := h.MustFindProc("GetDiskFreeSpaceExW")

var freeBytes int64

_, _, err := c.Call(uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(wd))),
    uintptr(unsafe.Pointer(&freeBytes)), nil, nil)

随意编写一个提供跨平台功能的包。 关于如何实现跨平台的东西,请参阅build tool help page

【讨论】:

  • 感谢您的详细帖子。我已经更新了我的问题,以包含指向我的包的链接。
  • @bantl23 Bavail 是非特权用户可用的块数。 Bfree 只是空闲块的总数。
  • "在 POSIX 系统上,您可以使用 syscall.Statfs" 不幸的是,这不是 POSIX 兼容的系统调用。符合 POSIX 的调用是“statvfs”。 Statfs 提供了关于不同 *NIX 操作系统的不同信息。为什么 Go 开发者选择实现不符合 POSIX 的版本,我无法理解。
  • 来自包文档:“已弃用:此包已被锁定。调用者应改用 golang.org/x/sys 存储库中的相应包。golang.org/pkg/syscall/#Statfs
  • @BrettHolman 非常正确,更新了答案
【解决方案2】:

Minio 有一个包 (GoDoc) 来显示跨平台的磁盘使用情况,并且似乎维护得很好:

import (
        "github.com/minio/minio/pkg/disk"
        humanize "github.com/dustin/go-humanize"
)

func printUsage(path string) error {
        di, err := disk.GetInfo(path)
        if err != nil {
            return err
        }
        percentage := (float64(di.Total-di.Free)/float64(di.Total))*100
        fmt.Printf("%s of %s disk space used (%0.2f%%)\n", 
            humanize.Bytes(di.Total-di.Free), 
            humanize.Bytes(di.Total), 
            percentage,
        )
}

【讨论】:

  • 这段代码实际上是提供来自du -h输出的数据,例如目录使用而不是请求的df -h 命令提供磁盘使用。不管怎样,这可能是使用 minio 包的一个很好的例子。
【解决方案3】:

这是我基于github.com/shirou/gopsutil 库的df -h 命令版本

package main

import (
    "fmt"

    human "github.com/dustin/go-humanize"
    "github.com/shirou/gopsutil/disk"
)

func main() {
    formatter := "%-14s %7s %7s %7s %4s %s\n"
    fmt.Printf(formatter, "Filesystem", "Size", "Used", "Avail", "Use%", "Mounted on")

    parts, _ := disk.Partitions(true)
    for _, p := range parts {
        device := p.Mountpoint
        s, _ := disk.Usage(device)

        if s.Total == 0 {
            continue
        }

        percent := fmt.Sprintf("%2.f%%", s.UsedPercent)

        fmt.Printf(formatter,
            s.Fstype,
            human.Bytes(s.Total),
            human.Bytes(s.Used),
            human.Bytes(s.Free),
            percent,
            p.Mountpoint,
        )
    }
}

【讨论】:

  • 这在 Windows 10 和 MacOS 11.3 上运行良好。谢谢。
猜你喜欢
  • 2019-12-12
  • 2010-11-26
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多