many solutions for a problem

One of the many things that I love about coding/scripting is that there are numerous solutions for the same problem. Whether that is using a different command to achieve the desired effect or for example using different loop formats (bash allows you to use C syntax for loops as well!).

I’ve been working on another script lately that has taken up some considerable amount of time. I am referencing a number of scripts to achieve my results, however I’ve either tried to simplify, improve or just make my version function better. Another aim is for it to be used by those with very little scripting knowledge and in limited amount of time tailor it to their own needs.

A big source of help has been reading Defensive BASH Programming by Kfir Lavi. I’ve been able to implement a number of elements from that article in my scripting and I believe it has meant that my scripts are improving.

Most of the easier and straight forward functions of the script have been completed. Some of the script has been tested and it’s working well, other parts I’ve just been tinkering away on and feel that it will probably be tested in a live environment when it is done and I will iron out the kinks.

Since the other day I’ve been trying to figure out the following line from the code:

read PART TYPE SIZE USED PRIO <<< $(swapon -s 2> /dev/null | tail -n 1 2>/dev/null) 2>/dev/null
if [ "${TYPE} != "partition" ]; then
  print_FAIL
  echo "Swap is not a partiton."
fi
if ! (( 256000 < ${SIZE} && ${SIZE} < 300000 )); then
  print_FAIL
  echo "Swap is not the correct size"
fi

Something similar was done to checking Logical Volumes/Virtual Groups and such. I knew read was a built in command within the bash shell that was used to take input from stdin, however I was not 100% sure how it was being utilized in this case.

A bit of research lead me to this article, which covered extensively how the read command actually works. I learnt from the article that the command actually assigns a value to each word, usually treating a word when white space is detected (although this can be changed using the -d delim option, which provides a new delimiter).

After some trial and error, I was able to play around with it and replicate what the script was doing. To a certain degree I felt other options were also available, as the previous day I resolved an issue of using awk to accomplish a similar result without requiring read.

Below is an example of achieving the same result, using a variety of methods. I know one is purely replacing the command with a variable, but it just shows that the same result can be completed. Here are a few examples of this – and I’m sure others could come up with a number of other solutions:

#!/bin/bash
function swap_variable_loop()
{
	printf "Testing SWAP with variable loop:\n"
	local readswap=$(swapon --noheadings)
	echo $readswap | while read NAME TYPE SIZE USED PRIO
	do
		echo "NAME: $NAME"
		echo "TYPE: $TYPE"
		echo "SIZE: $SIZE"
		echo "USED: $USED"
		echo "PRIO: $PRIO"
#		printf "${wordarray[@]}\n"
	done
}

function swap_loop()
{
	printf "Testing SWAP with loop:\n"
	swapon --noheadings | while read NAME TYPE SIZE USED PRIO
	do
		echo "NAME: $NAME"
		echo "TYPE: $TYPE"
		echo "SIZE: $SIZE"
		echo "USED: $USED"
		echo "PRIO: $PRIO"
	done
}

function swap_loop_array()
{
	printf "Testing SWAP with loop and array:\n"
	swapon --noheadings | while read -a swaparray
	do
		local n=0
		for i in NAME TYPE SIZE USED PRIO
		do
			echo $i":" ${swaparray[$n]}
			n=`expr $n + 1`
		done
	done
}

function swap_awk()
{
	printf "Testing SWAP with awk:\n"
	
	echo -n "NAME: " && swapon --noheadings | awk '{ print $1 }'
	echo -n "TYPE: " && swapon --noheadings | awk '{ print $2 }'
	echo -n "SIZE: " && swapon --noheadings | awk '{ print $3 }'
	echo -n "USED: " && swapon --noheadings | awk '{ print $4 }'
	echo -n "PRIO: " && swapon --noheadings | awk '{ print $5 }'
}

swap_variable_loop
swap_loop
swap_loop_array
swap_awk

And for the results:

Testing SWAP with variable loop:
NAME: /dev/dm-1
TYPE: partition
SIZE: 980M
USED: 580.8M
PRIO: -2

Testing SWAP with loop:
NAME: /dev/dm-1
TYPE: partition
SIZE: 980M
USED: 580.8M
PRIO: -2

Testing SWAP with loop and array:
NAME: /dev/dm-1
TYPE: partition
SIZE: 980M
USED: 580.8M
PRIO: -2

Testing SWAP with awk:
NAME: /dev/dm-1
TYPE: partition
SIZE: 980M
USED: 580.8M
PRIO: -2

With the above scripts, I have options to play with, whether I assign the result of the swapon command using read or I use awk to just grab the relevant bits to use in the function. Hope this article has been useful in better understanding how you can approach a problem from multiple angles and methods along with better understanding a few commands!

Leave a Reply

Your email address will not be published. Required fields are marked *