Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash: how to use an array to create another array?

Tags:

arrays

bash

shell

I'm trying to make a shell script to use as an HDD temperature alert job with cron. The cron job must make these things:

  1. Verify the existing ATA devices (I'm using camcontrol);
  2. Verify the temperature of the devices identified (I'm using smartctl);
  3. Compare the temperatures of the ATA devices with a constant variable;
  4. If one of the devices temperature is highter than the constant variable, the script sends an email with the temperature of all ATA devices.

My problem is how to use the results of item 2 to accomplish the item 3...

My actual code is:

# 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

I can echo the devices names and the temperatures if I use:

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

I tried (and many others ways):

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[*]}"

The above code print the "arrdiscs" correctly but the "TEMP" prints null.

So... How can I create an array based on the TEMP variable so I can verify wich temperature is highter then TEMP_MAX?

Made some changes as suggested by 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

But I got the result as follow:

ada0 ada1 ada2 ada3 da0
33
31
32
30
$temp is empty
[ada0]: 33 [ada1]: 31 [ada2]: 32 [ada3]: 30

The variable temp_max was set to 20, but no "The following discs were too hot:" message displayed... :(

like image 420
Cadoso Avatar asked Feb 02 '26 19:02

Cadoso


1 Answers

You can create an array piecemeal like this:

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

echo "${temps[*]}"

That being said I would probably suggest keeping most of the temperatures local to the loop and only storing the alert-worthy temperatures (and disks) in an array suitable for use in the message at the end.

# 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
like image 52
Etan Reisner Avatar answered Feb 05 '26 10:02

Etan Reisner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!