Array compare bash script

Hello,

i have a script that should compare between ${ARRAY[@]}
that contains all fstab record like this :

>>echo ${ARRAY[@]}
/ /boot

between all mountpoints in my df that is stord in ${ARRAY2[@]}

>>echo ${ARRAY2[@]}
/ /boot /dev/shm /var/spool/asterisk/monitor

now i have this loop:

for i in ${ARRAY[@]}; do
	for j in ${ARRAY2[@]}; do
	if [[ $i != $j ]];then
		echo "fstab $i doesnt exsist in $j df"
		exit 
		fi
		done
	done

what happend now is that for exsample ${ARRAY[@]} try to compare first value "/" to all values in ${ARRAY2[@]} like this :

[ / != / ]]
[[ / != /boot ]]

and then the script fails - my point here is to find if i have records in fstab
that are not mounted on df

i want that when ${ARRAY[@]} found a match in ${ARRAY2[@]}
it will continue to next value and not try to match the first value to all ${ARRAY2[@]} values.

thanks

Hmm. Your problem is, I think, df output (a line) does not always exactly match fstab lines. The data needs to be reformatted. Before you compare.

So, your compare loop has problems trying to compare things. Can you please show us how you got values into ARRAY1 and ARRAY2 to begin with?

PS: awk can do what you want in a single line - find excluded stings from one array to another.

If the array elements are unique and in the same order then you only need one loop.
Example:

ARRAY=(/ /boot /var /usr) # fstab
ARRAY2=(/ /xboot /var) # df
max=${#ARRAY[@]}
max2=${#ARRAY2[@]}
i=0 j=0
while [ $i -lt $max ] || [ $j -lt $max2 ]
do
  if [[ "${ARRAY[$i]}" != "${ARRAY2[$j]}" ]]
  then
    if [[ "${ARRAY[$i]}" = "${ARRAY2[$((j+1))]}" ]]
    then
      echo "df ${ARRAY2[$j]} doesnt exist in fstab ${ARRAY[$i]}"
      j=$((j+1))
    elif [[ "${ARRAY[$((i+1))]}" = "${ARRAY2[$j]}" ]]
    then
      echo "fstab ${ARRAY[$i]} doesnt exist in df ${ARRAY2[$j]}"
      i=$((i+1))
    else
      echo "mismatch fstab ${ARRAY[$i]} and df ${ARRAY2[$j]}"
    fi
  fi
  i=$((i+1)) j=$((j+1))
done

i dont want to count on the same order i want it indevidualy to check
every val in Array compare to array2

this is the values:

ARRAY_FILES=$(df -Pk |awk '{print$6}' | grep -v Mounted | xargs)
ARRAY=($ARRAY_FILES)
FSTAB_ARRAY=$(cat /etc/fstab  | awk '{print$1,$2}' | sed '/^#.*/d'| grep -v "devpts\|sysfs\|proc" | awk '{print$2}' | grep ^/|xargs)
ARRAY2=($FSTAB_ARRAY)

---------- Post updated at 09:51 AM ---------- Previous update was at 09:49 AM ----------

Hey-
thanks but you script returns this :

different no of elements, let's find out
df /boot doesnt exist in fstab /dev/shm
mismatch fstab /boot and df /var/spool/asterisk/monitor

it compare the worng files as theres no order of how fstab presents and df

now, i have managed to make it work but like this :

echo ${ARRAY[@]} > $FILE

for i in  ${ARRAY2[@]} 
        do
        grep $i $FILE
        if [[ $? -ne 0 ]]
                then
                echo "$i is missing in df "
                exit    
                fi
        done

and$FILE containd df values

IFS includes a newline, so you do not need xargs to convert newline to a space character.
My script sample needs a sorted input.
For example

ARRAY2=($(df -Pk | awk '$6~/^[/]/{print$6}' | sort)) # df
ARRAY=($(awk '/^[^#]/ && $2~/[/]/ && $3!~/devpts|sysfs|proc/{print $2}' /etc/fstab | sort)) # fstab

BTW df does unneeded stat() and statfs(), a mount -v would be less overhead.

---------- Post updated at 10:17 ---------- Previous update was at 10:14 ----------

Please avoid unneeded cat! If you want to have /etc/fstab first in the line then do

ARRAY=($( </etc/fstab awk '/^[^#]/ && $2~/[/]/ && $3!~/devpts|sysfs|proc/{print $2}' | sort)) # fstab
1 Like

Thanks you the array worked and now ur loop also.
btw - the reason i dont compare it to mount -v is cause the system thinks that the nfs is mounted but its not and only throw df i can see it :

df :

df: `/var/spool/asterisk/monitor': Stale file handle
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        39G  9.0G   28G  25% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
/dev/sda1       283M   27M  242M  10% /boot
/dev/sda2 on / type ext4 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
/dev/sda1 on /boot type ext4 (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
192.168.223.22:/mnt/pbxarchive/PBXIL-Managment on /var/spool/asterisk/monitor type nfs (rw,vers=4,addr=192.168.223.22,clientaddr=192.168.11.100)

see that /var/spool/asterisk/monitor show like its mounted but its not also
the file looks like that :

d?????????? ? ?        ?           ?            ? monitor

and df output gives this error :

df: `/var/spool/asterisk/monitor': Stale file handle

thats why our last script that checked /proc/mounts didnt alerted us.

anyway- thank you so much for your time!

---------- Post updated at 08:03 AM ---------- Previous update was at 03:21 AM ----------

well if anyone will look it up
i have endded up doing this loop :

for i in $(</etc/fstab awk '/^[^#]/ && $2~/[/]/ && $3!~/devpts|sysfs|proc/{print $2}' | sort)
        do
        df 2> /dev/null |grep -w $i > /dev/null
                if [[ $? -ne 0 ]]
                        then
                        NOT_MOUNTED="$i $NOT_MOUNTED"
                        echo "$NOT_MOUNTED is NOT mounted!"
                        exit
                        fi
                done

Thnaks all

I have updated my post#3 - the original code did not report mismatches-only.
Your short script only checks in one direction.
You can run the df on the desired target only:

for i in ...
do
  if df "$i" 2>/dev/null >&2
  then
    ...
  fi
done

Or without stat() and statfs()

for i in ...
do
  if </etc/mtab awk -v fs="$i" '$2==fs {exit 1}'
  then
    ...
  fi
done

--
Regarding your error "Stale NFS handle" is correct, the printing of the many ???? on standard output is a Linux bug IMHO.
The server revoked its NFS share. Maybe it reshared with a new NFS handle. Try to remount it

umount /var/spool/asterisk/monitor
mount /var/spool/asterisk/monitor
1 Like