bash: 如何使用数组创建另一个数组?

3
我正在尝试编写一个shell脚本,用作HDD温度警报任务的cron job。cron job必须执行以下操作:
  1. 验证现有的ATA设备(我正在使用camcontrol);
  2. 验证已识别设备的温度(我正在使用smartctl);
  3. 将ATA设备的温度与常量变量进行比较;
  4. 如果其中一个设备的温度高于常量变量,则脚本发送一封电子邮件,其中包含所有ATA设备的温度。
我的问题是如何使用第二个项目的结果来完成第三个项目...
我的实际代码是:
# Defines alert temperature
TEMP_MAX=30 #Graus celcius

# Create an array with devices
arrdiscs=($(camcontrol devlist | awk '{print substr($NF, 8, length($NF)-8)}'))

# Get the temperature of the devices
for i in "${arrdiscs[@]}"
do
  # Get temperatures
  TEMP="$(smartctl -A /dev/$i | egrep ^194 | awk '{print $10}')"
done

如果我使用以下代码,就可以输出设备名称和温度:

for i in "${arrdiscs[@]}"
do
  TEMP="$(smartctl -A /dev/$i | egrep ^194 | awk '{print $10}')"
  echo "[$i]: $TEMP"
done

我尝试了很多方法(和许多其他人一样):

for i in "${arrdiscs[@]}"
do
  TEMP="$(smartctl -A /dev/$i | egrep ^194 | awk '{print $10}')"
  echo "[$i]: $TEMP"
done

echo "ARRAY DISCOS: ${arrdiscs[*]}"
echo "TEMPERATURAS: ${TEMP[*]}"

以上代码正确输出了"arrdiscs",但"TEMP"打印为空。那么我该如何基于TEMP变量创建一个数组,以便我可以验证哪个温度高于TEMP_MAX?
根据Etan Reisner的建议进行了一些更改:
# Defines alert temperature
temp_max=20 #Graus celcius

# Monta array de discos do sistema
arrdiscs=($(camcontrol devlist | awk '{print substr($NF, 8, length($NF)-8)}'))
echo "${arrdiscs[@]}"

alertdiscs=()
for i in "${arrdiscs[@]}"
do
    temp=("$(smartctl -A "/dev/$i" | egrep ^194 | awk '{print $10}')")

    if [ -z "$temp" ]; then
      echo "\$temp is empty"
    else
      if [ $temp -gt $temp_max ]; then
          alertdiscs+=("[$i]: $temp")
          echo ${temp[@]}
      fi
    fi
done

if [ ${#alertdics[@]} -gt 0 ]; then
    echo "The following discs were too hot:"
    printf '%s\n' "${alertdiscs[@]}"
else
    echo "${alertdiscs[@]}"
fi

但是我得到的结果如下:
ada0 ada1 ada2 ada3 da0
33
31
32
30
$temp is empty
[ada0]: 33 [ada1]: 31 [ada2]: 32 [ada3]: 30

变量temp_max被设置为20,但是没有显示任何“以下光盘过热”消息... :(

你需要创建一个数组并添加元素,它不会神奇地出现。 - Karoly Horvath
哦!真的吗?我以为数组会出现在神的工作中!请不要发表没有任何讨论或解决问题的评论...如果你至少读了标题和所有文本,你可能就不会发表这样的评论了...谢谢...什么都没做... - Cadoso
1个回答

2

您可以像这样逐步创建数组:

temps=()
for i in "${arrdiscs[@]}"
do
    temps+=("$(smartctl -A "/dev/$i" | egrep ^194 | awk '{print $10}')")
done

echo "${temps[*]}"

话虽如此,我建议大多数温度仅在循环中保持本地,并将触发警报的温度(以及磁盘)存储在适合于在最后的消息中使用的数组中。

# Defines alert temperature
temp_max=30 #Graus celcius

alertdiscs=()
for i in "${arrdiscs[@]}"
do
    temp=("$(smartctl -A "/dev/$i" | egrep ^194 | awk '{print $10}')")
    if [ -n "$temp" ] && [ $temp -gt $temp_max ]; then
        alertdiscs+=("[$i]: $temp")
    fi
done

if [ ${#alertdiscs[@]} -gt 0 ]; then
    echo "The following discs were too hot:"
    printf '%s\n' "${alertdiscs[@]}"
fi

嗨,Etan!非常感谢!但是......如果我有任何未返回其温度的磁盘,我会收到错误消息:_[: -gt: unary operator expected_。我尝试过使用unset,但如果我有多个没有温度的设备,它就没用了。不能使用delete array[index],因为索引可能是依赖于运行脚本的系统的任何数字。我还尝试使用awk -Fsed,但没有成功......你能帮我解决这个问题吗? - Cadoso
那可能是在循环中发生的,而不是在循环后面。是的,我没有考虑到这一点。正在编辑。 - Etan Reisner
非常好!再次感谢!但是最后一个 if 没有起作用...我编辑了我的问题,加入了一些新代码和一些结果来帮助调试... - Cadoso
最后一个if检查中变量名有错别字。已经修复。 - Etan Reisner
非常感谢Etan Reisner!运行得非常好! - Cadoso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接