<<

To show some of the basic components of shell scripting, we are going to take a common task, creating a new user, and design a script to automate this process.

Original Script

Display commands to manually creating an account

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser # Purpose: To automate the creation of a user account # # : Created

# Edit system files ":" echo "smo1:x:1000:100:Scott1:/root/n321/home/smo1:/bin/bash" echo "shadow:" echo "smo1:*:::::::"

# Create home directories echo " -r /etc/skel /root/n321/home/smo1" echo "chown -R 1000:100 /root/n321/home/smo1" echo " -R go-rwx /root/n321/home/smo1"

# done

Revision 1

Write to temporary data files and directories. Never to live (production) areas when debugging scripts. Note: code segments that are in bold indicate changes from the previous example.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files

# Edit system files echo "smo1:x:1000:100:Scott1:/root/n321/home/smo1:/bin/bash" >> passwd echo "smo1:*:::::::" >> shadow

# Create home directories cp -r /etc/skel /root/n321/home/smo1 chown -R 1000:100 /root/n321/home/smo1 chmod -R go-rwx /root/n321/home/smo1

# done

Revision 2:

As scripts become complex, it is sometimes difficult to all the occurrences of hard coded data (i.e. names) when you need to a change. A way to minimize this is to create a number of global variables the beginning of the script for those items. You only need to make the change in one place.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files # Added global variables

# Account Variables

USERNAME=smo2 PASSWORD="*" UUID=1002 UGID=100 GCOS=Scott2 HOME=/root/n321/home/smo2 SHELL=/bin/bash

# File variables

PASSWD=passwd SHADOW=shadow SKEL=/etc/skel

# Edit system files echo "$USERNAME:x:$UUID:$UGID:$GCOS:$HOME:$SHELL" >> $PASSWD echo "$USERNAME:*:::::::" >> $SHADOW

# Create home directories cp -r $SKEL $HOME chown -R $UUID:$UGID $HOME chmod -R go-rwx $HOME

# done

Revision 3:

Thus far, we have hard coded user account information directly into the script. Unfortunately, every we need to create a new user, we would have to edit the script. A better approach would be to be able to include key pieces of information directly on the command line.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files # Added global variables # Added command line arguments

# Account Variables

USERNAME=$1 PASSWORD="*" UUID=$2 UGID=100 GCOS=$3 HOME=/root/n321/home/$USERNAME SHELL=/bin/bash

# File variables

PASSWD=passwd SHADOW=shadow SKEL=/etc/skel

# Edit system files echo "$USERNAME:x:$UUID:$UGID:$GCOS:$HOME:$SHELL" >> $PASSWD echo "$USERNAME:*:::::::" >> $SHADOW

# Create home directories cp -r $SKEL $HOME chown -R $UUID:$UGID $HOME chmod -R go-rwx $HOME

# done

Revision 4:

While script variables tend to be used as , sometimes it is helpful to treat them as integers so that we can basic mathematical operations on them (i.e. loop counters). It is also convenient to be able to set variables to the output of a command line.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files # Added global variables # Added command line arguments # Automatically generate UID

# Account Variables

USERNAME=$1 PASSWORD="*" UGID=100 GCOS=$2 HOME=/root/n321/home/$USERNAME SHELL=/bin/bash

# File variables

PASSWD=passwd SHADOW=shadow SKEL=/etc/skel

# Get new UID

LUID=` -1 $PASSWD | -d: -f3` UUID=` 1 + $LUID`

# Edit system files echo "$USERNAME:x:$UUID:$UGID:$GCOS:$HOME:$SHELL" >> $PASSWD echo "$USERNAME:*:::::::" >> $SHADOW

# Create home directories cp -r $SKEL $HOME chown -R $UUID:$UGID $HOME chmod -R go-rwx $HOME

# done

Revision 5:

Assuming we enter everything correctly, our script should create new user accounts. What happens if we make a mistake on the command line? Depending on what we , we could create a lot of problems. A way to minimize this is to add code to make sure there are no errors. This revision shows an initial example.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files # Added global variables # Added command line arguments # Automatically generate UID # Added some error checking

# Enough Arguments? if [ $# -ne 2 ] then echo "Usage: $0 " 1 else echo "Creating account for $2" fi

# Account Variables

USERNAME=$1 PASSWORD="*" UGID=100 GCOS=$2 HOME=/root/n321/home/$USERNAME SHELL=/bin/bash

# File variables

PASSWD=passwd SHADOW=shadow SKEL=/etc/skel

# Get new UID

LUID=`tail -1 $PASSWD | cut -d: -f3` UUID=`expr 1 + $LUID`

# Edit system files echo "$USERNAME:x:$UUID:$UGID:$GCOS:$HOME:$SHELL" >> $PASSWD echo "$USERNAME:*:::::::" >> $SHADOW

# Create home directories cp -r $SKEL $HOME chown -R $UUID:$UGID $HOME chmod -R go-rwx $HOME

# done

Revision 6:

Script output has already been addressed in the first version of our script but what if the script needs some information from the user running it that wasn’t provided on the command line. There needs to be a method to enable a user to enter it if prompted. In this revision, we had a new command line option, -v, that, if present, will prompt the user to verify that the new account should be created. Also introduced in this revision is code that allows us to different things based on a range of conditions.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser [-v] # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files # Added global variables # Added command line arguments # Automatically generate UID # Added some error checking # Add verification before creating account

# Enough Arguments? case $# in 2) USERNAME=$1 GCOS=$2 ;; 3) if [ $1 != "-v" ] then echo "Usage: $0 " exit 1 else echo -n "Are you sure? (Y|N): " read ANSWER if [ $ANSWER != "Y" -a $ANSWER != "y" ] then exit 3 fi

USERNAME=$2 GCOS=$3 fi ;; *) echo "Usage: $0 " exit 1 ;; esac

# Account Variables

PASSWORD="*" UGID=100 HOME=/root/n321/home/$USERNAME SHELL=/bin/bash

# File variables

PASSWD=passwd SHADOW=shadow SKEL=/etc/skel

# Get new UID

LUID=`tail -1 $PASSWD | cut -d: -f3` UUID=`expr 1 + $LUID`

# Edit system files echo "$USERNAME:x:$UUID:$UGID:$GCOS:$HOME:$SHELL" >> $PASSWD echo "$USERNAME:*:::::::" >> $SHADOW

# Create home directories cp -r $SKEL $HOME chown -R $UUID:$UGID $HOME chmod -R go-rwx $HOME

# done

Revision 7:

The final revision of our code provides a additional error checking if the script is run with the create user verification option. In the previous revision, the account is only created if Y or y is entered. If anything else is typed, it is assumed that it was the same as typing N or n. In this revision, we want to make sure that only or no responses are entered.

#!/bin/bash

# Author: N321 Class # Program: makeuser # Usage: makeuser [-v] # Purpose: To automate the creation of a user account # # History: Created # Wrote to local files # Added global variables # Added command line arguments # Automatically generate UID # Added some error checking # Add verification before creating account

# Enough Arguments? case $# in 2) USERNAME=$1 GCOS=$2 ;; 3) if [ $1 != "-v" ] then echo "Usage: $0 " exit 1 else while [ 1 ] do echo -n "Are you sure? (Y|N): " read ANSWER case $ANSWER in Y | y) break ;; N | n) exit 3 ;; *) ;; esac

done

USERNAME=$2 GCOS=$3 fi ;; *) echo "Usage: $0 " exit 1 ;; esac

# Account Variables

PASSWORD="*" UGID=100 HOME=/root/n321/home/$USERNAME SHELL=/bin/bash

# File variables

PASSWD=passwd SHADOW=shadow SKEL=/etc/skel

# Get new UID

LUID=`tail -1 $PASSWD | cut -d: -f3` UUID=`expr 1 + $LUID`

# Edit system files echo "$USERNAME:x:$UUID:$UGID:$GCOS:$HOME:$SHELL" >> $PASSWD echo "$USERNAME:*:::::::" >> $SHADOW

# Create home directories cp -r $SKEL $HOME chown -R $UUID:$UGID $HOME chmod -R go-rwx $HOME

# done

Now that we have a working makeuser script, we can create a second one called makeclass that will enable us to create a group of users at one time. This script will read a file and parse it line by line then pass the appropriate arguments to makeuser. The format of the input file is username:gcos.

Original Script:

We can pass the output of a command that can be used to feed a for loop.

#!/bin/bash

# Author: N321 Class # Program: makeclass # Usage: makeclass # Purpose: Create a group of users # # History: Created

USERFILE=$1 if [ $# -ne 1 ] then echo "Usage: $0 " exit 1 elif [ ! -f $USERFILE ] then echo "$USERFILE not found" exit 2 fi for NEWUSER in ` $USERFILE` do NEWUSERNAME=`echo $NEWUSER | cut -d: -f1` NEWGCOS=`echo $NEWUSER | cut -d: -f2`

./makeuser8 $NEWUSERNAME $NEWGCOS done

# done

Revision 1:

One problem with the original approach is that any spaces on a line will be seen as an item separator. While this is exactly what we want when parsing commands, it is not necessarily good when dealing with files. This revision includes a method to specifically read a file for input.

#!/bin/bash

# Author: N321 Class # Program: makeclass # Usage: makeclass # Purpose: Create a group of users # # History: Created

USERFILE=$1 if [ $# -ne 1 ] then echo "Usage: $0 " exit 1 elif [ ! -f $USERFILE ] then echo "$USERFILE not found" exit 2 fi while read NEWUSER do NEWUSERNAME=`echo $NEWUSER | cut -d: -f1` NEWGCOS=\"`echo $NEWUSER | cut -d: -f2`\"

./makeuser8 "$NEWUSERNAME \"$NEWGCOS\"" done < $USERFILE

# done