使用shell命令如何从命令中提取字段(zdb)

时间:2017-05-13 11:25:10

标签: shell awk freebsd zfs

我需要expand/resize a ZFS磁盘,但为此,我需要从children[0] guid的输出中提取zdb,当前输出如下所示:

root@:/ # zdb
zroot:
    version: 5000
    name: 'zroot'
    state: 0
    txg: 448
    pool_guid: 14102710366601156377
    hostid: 1798585735
    hostname: ''
    com.delphix:has_per_vdev_zaps
    vdev_children: 1
    vdev_tree:
        type: 'root'
        id: 0
        guid: 14102710366601156377
        create_txg: 4
        children[0]:
            type: 'disk'
            id: 0
            guid: 12530249324826415927
            path: '/dev/gpt/disk0'
            whole_disk: 1
            metaslab_array: 38
            metaslab_shift: 24
            ashift: 12
            asize: 1066926080
            is_log: 0
            create_txg: 4
            com.delphix:vdev_zap_leaf: 36
            com.delphix:vdev_zap_top: 37
    features_for_read:
        com.delphix:hole_birth
        com.delphix:embedded_data

为了自动执行此过程并将所有步骤放在shell脚本中,我提出了这个:

zdb | grep -A4 "children\[0" | grep guid | awk -F ": " '{print $2}'

返回:

12530249324826415927 

将所有脚本放在一起看起来像这样:

#!/bin/sh

DISK=`gpart list | head -n 1 | awk -F ": " '{print $2}'`
GUID=`zdb | grep -A4 "children\[0" | grep guid | awk -F ": " '{print $2}'`

gpart recover ${DISK}
gpart resize -i 3 ${DISK}
zpool online -e zroot ${GUID}
zfs set readonly=off zroot/ROOT/default

这是有效的,但是想知道是否有更好的方法来提取字段而不需要管道太多,我在原始FreeBSD设置中执行此操作,其中读取了根/ zpool-只有这样我才能安装python,bash等,我必须只使用/usr/bin中的基本堆栈,如cut,awk,sed等。

如果我可以直接从像zdb这样的命令中获取值,那会很好但是由于没有找到直接的方法,我需要做一些shell功夫。

有任何提示,建议改进吗?

1 个答案:

答案 0 :(得分:1)

您可以使用下面的独立Awk

zdb | awk '/children\[0\]/{flag=1; next} flag && /guid:/{split($0,arr,":"); print arr[2]; flag=0}'

如果某个领先的空格令人担心某种程度使用sub()函数将其删除为sub(/^[[:space:]]/,"",arr[2])

zdb | awk '/children\[0\]/{flag=1; next} flag && /guid:/{split($0,arr,":"); sub(/^[[:space:]]/,"",arr[2]); print arr[2]; flag=0}'

想法是识别模式children[0],启用标记,并且当设置标志时,下一个匹配的guid:仅匹配 。这样可以避免处理guid:行重复多次并跳过它们。识别出第一个匹配时,该标志将被重置。

并且不要使用反向标记进行命令替换,使用$(..)

更高效的方式