/ shell

Bash Positional Parameters

Hello everyone! It's been too long.

I have had a script in the works for a long time to assist me with KVM builds. I started very small, just rerunning the script in my shell anytime I needed to fire up a virtual machine. Later on, I moved onto using a Kickstart file with my script. As time progressed, I was able to setup an FTP and Apache server to host my Kickstart file. This was immediately beneficial because I could use multiple KVM hosts to read from a Kickstart file.

There were a few problems with this setup. One, I had to edit two or three separate files. I had to change the virt-install script, the storage script if the VM had additional storage, and I had to change the Kickstart file. So, I set about automating this task.

Here is the original file:

sudo virt-install --name testbench \
--ram 2048 \
--disk path=./testbench,size=60 \
--vcpus 2 \
--os-type linux --os-variant generic \
--network bridge=br0 \
--graphics none --console pty,target_type=serial \
--location '' \
--extra-args 'console=ttyS0,115200n8 serial' \
-x ks=

Alright, so, line by line, what does this do?

sudo virt-install --name testbench \ launches virt-install as the superuser and names the virtual machine. From the man page:


VIRT-INSTALL(1)                                                                   Virtual Machine Manager                                                                   VIRT-INSTALL(1)

virt-install - provision new virtual machines

virt-install [OPTION]...

virt-install is a command line tool for creating new KVM, Xen, or Linux container guests using the "libvirt" hypervisor management library.  See the EXAMPLES section at the end of
this document to quickly get started.


The actual entry is much more verbose, and I encourage you to take a gander to see all of the features virt-install offers. However, from the above we see that virt-install is a command line tool for creating virtual machines in the KVM, Xen, or libvirt hypervisor. Great

The next several lines are spent allocating the RAM (in MBs), the path of the virtual disk and size (in GBs), and how many virtual CPUs are allocated to the virtual machine.

Next, we have the OS type and variant, neither of which have an impact on the performance or configuration, but if you're using virt-manager it will make recommendations based on those settings. This is more of an identifying component rather than any functional purpose.

Finally, we have the networking, location, and extra arguments. I recommend creating a bridge interface (as does KVM's virt-manager) before building a VM. The location of the image is stored on an Apache server in this example. Rather than use a regular ISO image or CD-ROM image, I extracted the contents of the ISO to an Apache server. Again, the use case is for multiple KVM hosts. The extra arguments are for outputting the installation through the console session rather than connect via VNC, and the location of the Kickstart file. The graphics are done through the tty "serial" connection, which enables the installation to be viewed and interfaced with on the console.

Phew, still with me? Good! Because now we get to the exciting part!

I decided to expound upon this script by asking for user input. See the script here:

Mark II


echo "_______________"
echo "VM Installation"
echo "_______________"

echo "Enter the name of the VM:" read vm

echo "Enter the amount of RAM in MB:"
read ram

echo "Enter the name of the storage drive:"
read hd

echo "How large did you want the disk (in GB)?"
read hd_size

echo "Enter the number of CPU cores:"
read num_cpu

echo "Building VM"

sudo virt-install --name $vm \
		  --ram $ram \
		  --disk path=./$hd,size=$hd_size \
		  --vcpus $num_cpu \
		  --os-type linux --os-variant generic \
		  --network bridge=br0 \
		  --graphics none --console pty,target_type=serial \
		  --location '/home/chris/CentOS-7-x86_64-Minimal-1810.iso' \
		  --extra-args 'console=ttyS0,115200n8 serial' -x ks=

Here we have standard output and input being used to capture user input to assign the values to variables and apply the values upon execution of virt-install.

I received some solid advice from Kyle, which some of you might remember from our Cloud Engineering episode.

Chris: Look, I changed my script, isn't it so much more awesome now?

Kyle: Using STDIN for parameters? Okay, you can go blaspheme somewhere else.

Ah, such a talented, cultured man with wisdom beyond his years.

I get it, it's very n00bish. User input is maybe two or three lessons after "Hello World"


Time to get back to the drawing board.

I dug around and read about about positional parameters and tried a few things. However, I decided the best approach would be using getopts. The man page is pretty well done, with two key factors:

The getopts utility shall retrieve options and option-arguments from a list of parameters.


When the option requires an option-argument, the getopts utility shall place it in the shell variable OPTARG.  If no option was found, or if the option that was found does not have an option-argument, OPTARG shall be unset.

So, required parameters are going to be assigned to $OPTARG.

It took some trial and error, but here is the current state:

Mark III


# vm_installer - A script that automates a KVM installation using CentOS 7 and kickstart in /var/ftp/pub/ks.cfg

        echo "usage: vm-inst.sh [-n VM name ] [-r RAM] [-c vcpus] [-d hard drive name] [-g hd size in GB] | [-h]"

# Main

while getopts ":n:r:c:d:g:" arg; do
        case ${arg} in
                n )             vm=${OPTARG}      ;;
                r )             ram=${OPTARG}     ;;
                c )             num_cpu=$OPTARG   ;;
                d )             hd=$OPTARG        ;;
                g )             hd_size=$OPTARG   ;;
                \?)             info 
                                exit                  ;;
shift $((OPTIND -1))

echo "Building VM"

sudo virt-install --name $vm \
                  --ram $ram \
                  --disk path=./$hd,size=$hd_size \
                  --vcpus $num_cpu \
                  --os-type linux --os-variant generic \
                  --network bridge=br0 \
                  --graphics none --console pty,target_type=serial \
                  --location '/home/chris/isos/CentOS-7-x86_64-Minimal-1810.iso' \
                  --extra-args 'console=ttyS0,115200n8 serial' -x ks=

An info function to display the usage of the script in case something is entered incorrectly. I planned an interactive mode, for those that needed/wanted STDIN, but settled on this for now as it is fully functional. It is a work in progress, as I progress through my script ninja training I'm sure I'll fine tune and optimize it.

I hope you guys enjoyed this!

Bash Positional Parameters
Share this