使用 shell 命令如何从命令中提取字段 (zdb)
using shell commands how to extract field from command (zdb)
我需要 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 }'
哪个returns:
12530249324826415927
将所有脚本放在一起看起来像这样:
#!/bin/sh
DISK=`gpart list | head -n 1 | awk -F ": " '{print }'`
GUID=`zdb | grep -A4 "children\[0" | grep guid | awk -F ": " '{print }'`
gpart recover ${DISK}
gpart resize -i 3 ${DISK}
zpool online -e zroot ${GUID}
zfs set readonly=off zroot/ROOT/default
这是有效的,但想知道是否有更好的方法来提取字段而无需过多管道,我在 [=35= 的原始 FreeBSD 设置上执行此操作] 是只读的,所以我无法安装 python、bash 等,我只能使用 /usr/bin
中的基本堆栈,如 cut、awk、sed 等
如果我能直接从像 zdb 这样的命令中获取值就好了,但由于还没有找到直接的方法,我需要做一些 shell 功夫。
有什么改进的技巧和建议吗?
您可以使用如下的独立 Awk
,
zdb | awk '/children\[0\]/{flag=1; next} flag && /guid:/{split([=10=],arr,":"); print arr[2]; flag=0}'
如果前导空格令人担忧想办法使用sub()
函数删除它作为sub(/^[[:space:]]/,"",arr[2])
作为
zdb | awk '/children\[0\]/{flag=1; next} flag && /guid:/{split([=11=],arr,":"); sub(/^[[:space:]]/,"",arr[2]); print arr[2]; flag=0}'
想法是识别模式 children[0]
,启用标志,下一个匹配 guid:
匹配 仅当设置标志时 。这避免了对带有 guid:
的行的处理被重复多次并跳过它们。当识别出第一个匹配项时,该标志将被重置。
永远不要使用反引号替换命令,使用更有效的方式 $(..)
我需要 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 }'
哪个returns:
12530249324826415927
将所有脚本放在一起看起来像这样:
#!/bin/sh
DISK=`gpart list | head -n 1 | awk -F ": " '{print }'`
GUID=`zdb | grep -A4 "children\[0" | grep guid | awk -F ": " '{print }'`
gpart recover ${DISK}
gpart resize -i 3 ${DISK}
zpool online -e zroot ${GUID}
zfs set readonly=off zroot/ROOT/default
这是有效的,但想知道是否有更好的方法来提取字段而无需过多管道,我在 [=35= 的原始 FreeBSD 设置上执行此操作] 是只读的,所以我无法安装 python、bash 等,我只能使用 /usr/bin
中的基本堆栈,如 cut、awk、sed 等
如果我能直接从像 zdb 这样的命令中获取值就好了,但由于还没有找到直接的方法,我需要做一些 shell 功夫。
有什么改进的技巧和建议吗?
您可以使用如下的独立 Awk
,
zdb | awk '/children\[0\]/{flag=1; next} flag && /guid:/{split([=10=],arr,":"); print arr[2]; flag=0}'
如果前导空格令人担忧想办法使用sub()
函数删除它作为sub(/^[[:space:]]/,"",arr[2])
作为
zdb | awk '/children\[0\]/{flag=1; next} flag && /guid:/{split([=11=],arr,":"); sub(/^[[:space:]]/,"",arr[2]); print arr[2]; flag=0}'
想法是识别模式 children[0]
,启用标志,下一个匹配 guid:
匹配 仅当设置标志时 。这避免了对带有 guid:
的行的处理被重复多次并跳过它们。当识别出第一个匹配项时,该标志将被重置。
永远不要使用反引号替换命令,使用更有效的方式 $(..)