From Fedora Project Wiki

The purpose of this page is to provide an easily readable document than the transcript of the Classroom session given on this subject. The example this document works with is about adding a new user, or users, to a machine, and some common customizations around this process.

A very simple shell script

The following has been added to a file, via vi, emacs, gedit, or the reader's preferred text editor. For the purposes of the example, assume the file used is useradd-wrapper.sh

useradd frank
echo mypassword | passwd --stdin frank

At it's simplest, a shell script is a series of commands to execute. You may not have seen passwd's --stdin option before, it allows the passwd command to take the target password to assign to a user over stdin or through an input redirection operator like a |. So in the example above, a user named frank is added to the system, then has an initial password set to mypassword.

Invoking a shell script

There are several ways that we can execute the above script. We could:

bash useradd-wrapper.sh

Using this method, we're invoking the bash shell and using it to execute the commands stored in the useradd-wrapper.sh script.

Another alternative, which is more popular, is to make the script executable and using the script name as the "command" to use on the shell commandline. So something like:

chmod a+x useradd-wrapper.sh

in order to make the file executable and

./useradd-wrapper.sh

to execute the instructions stored within the script.

The last alternative I'll bring up is running the script without the ./ at the beginning of the command. The problem is that usually the current directory (.) is not included on the PATH variable, which is the list of directories in which to search for executables. Fedora, however, includes a directory in each user's home directory on their default PATH built at login. ~user/bin, or in other words, in the user's home, the subdirectory bin/ is included by default. Our example uses useradd and other commands which are run as root, so for our example, we could move the useradd-wrapper.sh script to the /root/bin directory. If the file has already been made executable with the previously mentioned chmod command, we would now invoke the script as simply:

useradd-wrapper.sh

Some simple enhancements (#!, Comments, and Positional Parameters)

Lets make some quick enhancements to our script.

#!/bin/bash

useradd $1
echo mypassword | passwd --stdin $1

# Invocation ./myscript.sh frank

The first change is the addition of the #!/bin/bash line. The significance of the #! line is that it indicates what interpreter, or language, to use when executing the commands in this script. If you've worked with perl, python, or another shell script language, you've likely seen a line like this. The issue that this fixes is that a bash script will be invoked, even if the shell running the script from the command line is different. The #! should be the first line in the script. Additional lines that begin with # will be interpreted as comments. We see a comment line as the last line in this script.

The other major change to our simple script has been the addition of a variable to replace the username we want to work with. Variables for our use within the script are created upon execution. We'll see a few of these as the document progresses, but above we're using $1. $1 represents the first argument passed to the shell script from the command line, so as the comment as the bottom of the file suggests, our command line would now include the script to execute and the user we wish to add and set the password for. Other positional parameters of note. $0 stores the name of the script called, $2 the second argument passed, $3 the third argument, ...

Quoted Execution

Next we're going to execute a command from our script who's output we wish to store, rather than display.

#!/bin/bash

useradd $1

password=`mkpasswd`

echo $password | passwd --stdin $1

# Invocation ./myscript.sh frank