有没有办法让任何命令输出都可机读/友好?

有没有办法让任何命令输出都可机读/友好?

我面临的实际问题是:我想定期(比如说每天一次)对磁盘使用情况/可用磁盘进行采样。并将所有输出存储在数据库或类似数据库中。

我看到du使用空格来分隔值,但没有看到任何可以改变该格式的开关。

但一般的问题是:是否有一种常用的方法可以将任何命令输出转换为更适合机器阅读的版本(即 CSV、XML 等)?

答案1

首先,没有使用“du”换行符分隔值。每行都是一对大小 + 路径,以空格分隔。这相当机器可读 - 常见工具如awkcut可以轻松使用它。

例如,awk '{print $1}'获取第一列 - 如果您du -s仅使用获取总数,这会立即为您提供数字。

但一般来说,命令输出只是文本,并且文本的格式多种多样 - 因此不可能存在适用于每个程序的通用工具。

有些程序有内置选项来输出 CSV 或 JSON 或 YAML(或很少文本可以很容易地转换成 XML,但如果程序本身不能以机器可读的格式输出内容,您最终会使用各种文本处理工具(例如 awk、grep、perl、sed、cut)将其转换为可用的内容,并希望格式保持不变。

与您的具体问题相关,有两种方法可以获取磁盘使用情况:您可以将所有单个文件的大小相加(这很慢并且需要一些 I/O),或者您可以要求文件系统为您提供“可用空间”数字,已经追踪(因此速度非常快)。因此du,您应该使用 ,而不是df

  • “df” 的输出中确实有更多列;幸运的是,其中大多数(最后一列除外)或多或少保证不包含任何空格(至少对于本地磁盘而言),因此使用“awk”来获取正确的列也是可以的。

    avail=$(df -P / | awk 'NR == 2 {print $5}')
    

    ('df' 可以-P选择始终按照 POSIX 规定的特定顺序输出字段,即使默认顺序在系统之间可能有所不同。因此df -P,可用空间始终是第 5 个字段。)

  • Linux(GNU Coreutils)'df' 实际上有--output选项可以让它只输出您想要的列,但是其他变体中可能不提供此功能(例如 Busybox df):

    avail=$(df --output=Avail / | tail -1)
    
  • 还有其他工具可以查询文件系统的可用空间,例如findmnt --df在 Linux 上,它有类似的选项来输出单独的列以及隐藏标题的选项:

    avail=$(findmnt -b -n -o AVAIL /)
    

    它还可以输出 JSON,这很容易被机器读取(并且在 shell 中,jq可以使用该工具来处理它 - Python 或 Perl 当然有内置模块来将 JSON 解析为字典或数组):

    data=$(findmnt --json --df --bytes /)
    avail=$(jq -r ".filesystems[0].avail" <<< "$data")
    

另一种方法是旁路工具并直接执行其后台操作。例如,如果你使用 C 或类似语言编程,你不会运行任何这些工具来检查磁盘使用情况 - 调用所有这些程序使用 statfs() 系统调用,因此您实际上可以直接调用该statfs("/")函数。

例如,如果您用 Python 编写监控脚本,则无需担心任何输出解析 - 只需调用os.statvfs("/"),可用的块数就在.f_bavail

答案2

有一种方法可以将任何由空格分隔的输出转换为包含例如前两个字段的 CSV。

StackOverflow 帖子 在 csv 中的 du 输出后附加文本 提供以下 bash 函数:

sizeFolder(){
  du -h --max-depth=1 --block-size=1M $TMP_DIR | sort -hr | awk 'NR==FNR{a[NR]=$0; next} {print $1, $2, a[FNR]}' textfile -
}

相关内容