【问题标题】:using shell commands how to extract field from command (zdb)使用 shell 命令如何从命令中提取字段 (zdb)
【发布时间】:2017-10-12 15:34:44
【问题描述】:

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

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 设置中执行此操作,其中 root/zpool 是只读的,所以我无法安装 python、bash 等,我只能使用 /usr/bin 中的基本堆栈,如 cut、awk、sed 等。

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

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

【问题讨论】:

    标签: shell awk freebsd zfs


    【解决方案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: 的行不止一次重复并跳过它们。当识别出第一个匹配项时,该标志会被重置。

    并且永远不要使用反引号进行命令替换,使用$(..) 使用更有效的方式

    【讨论】:

    • 使用split($0,arr,": ") 分割的好坏如何注意: 后面的空格,这个想法是避免子并删除空格?
    • @nbari:这是个好主意!
    猜你喜欢
    • 2023-03-13
    • 2021-01-03
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2022-08-14
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    相关资源
    最近更新 更多