如何从hdparm输出的frozen行中提取not关键字?
嘿,我来帮你搞定这个问题!咱们先拆解下你当前脚本的问题,再给你靠谱的解决办法~
问题出在哪?
你的脚本有两个明显的问题:
- 语法小bug:
echo $is_frozen前面没加分号或者换行,shell会把它和前面的命令串在一起执行,这会导致异常(不过你说返回frozen,可能是输入时的格式问题,但这个必须先修正) - 逻辑不对:你用
awk '/frozen/ { print $1 }',意思是匹配包含frozen的行,然后打印该行的第一个字段,而不是frozen前面紧挨着的那个词,这当然拿不到not啦!
正确的提取方法
要精准拿到frozen前面的not,我们需要让awk找到frozen这个字段,然后输出它的前一个字段。这里有两种稳妥的写法:
写法一:通用遍历匹配(推荐)
这种方法会遍历行内的所有字段,不管frozen在哪个位置,都能找到它并输出前一个词:
for d in $(ls /sys/block); do # 屏蔽非SSD设备的hdparm报错,避免干扰输出 is_frozen=$(hdparm -I /dev/$d 2>/dev/null | awk '{for(i=1;i<=NF;i++){if($i=="frozen") print $(i-1)}}') echo "Device /dev/$d - Frozen status prefix: $is_frozen" done
NF是awk的内置变量,表示当前行的总字段数,遍历每个字段找到frozen后,$(i-1)就是它的前一个字段。- 加
2>/dev/null是为了忽略hdparm对非物理磁盘(比如loop设备、ramdisk)的报错信息,让输出更干净。
写法二:先匹配行再定位
如果你能确定frozen所在行的格式不会变,也可以先匹配包含frozen的行,再在该行内查找:
for d in $(ls /sys/block); do is_frozen=$(hdparm -I /dev/$d 2>/dev/null | awk '/frozen/ {for(i=1;i<=NF;i++){if($i=="frozen") print $(i-1)}}') echo "Device /dev/$d - Frozen status prefix: $is_frozen" done
其实和写法一逻辑一致,只是先缩小了处理的行范围,效率差不多,但写法一更通用,适配不同设备的输出差异。
快速测试技巧
你可以先单独针对某个SSD设备测试awk命令,验证是否能拿到not:
hdparm -I /dev/sda | awk '{for(i=1;i<=NF;i++){if($i=="frozen") print $(i-1)}}'
额外优化:只处理SSD设备
用ls /sys/block会拿到所有块设备,包括非SSD的,你可以通过rotational属性过滤出真正的SSD(SSD的rotational值为0,机械盘为1):
for d in $(ls /sys/block); do # 判断是否为SSD if [ $(cat /sys/block/$d/queue/rotational) -eq 0 ]; then is_frozen=$(hdparm -I /dev/$d 2>/dev/null | awk '{for(i=1;i<=NF;i++){if($i=="frozen") print $(i-1)}}') echo "SSD /dev/$d - Frozen status prefix: $is_frozen" fi done
内容的提问来源于stack exchange,提问作者Sandra Schlichting
相关产品推荐
相关产品推荐

