Basics of Writing a Linux Script

A shell script is an executable file that contains commands. Shell scripts are typically used for system admin tasks involving a set of multiple pre-existing commands that are run in a specific order. Often the results of one command are passed to another, chaining multiple commands into one single step. A shell script may choose to use one set of commands over another depending on whether a certain condition is met. Finally, a shell script may repeat commands or blocks of commands a specified number of times, or until a certain condition is met.

The first line of a shell script is special; it is used to specify the shell that the script should be under. This line should begin with a pound sign followed by an exclamation mark, #!. To indicate the shell, we then give the full path to the shell. When the Linux kernel sees the first two characters of a file are #!, it will look on the rest of the line for the full pathname of the interpreter to use to run the program. We will be using the bash shell, which is located at /bin/bash.

We can use the echo command to display basic text message. By default, the echo command does not require quotes to delineate the string. However, it is a good idea to use quotes to delineate the text string if single quotes will be used in the string in order to make sure they appear properly in the output.

Let’s make our very first script, and call it hello_world.sh. This script will contain the classic Hello World program.

#!/bin/bash

echo “Hello World!”

Note that the #! at the beginning of a file is sometimes referred to as a shebang.

Before we run the script, we need to make the script executable. To make the script executable, we enter the command chmod +x followed by the name of the script. Thus, to make our new script executable, we enter the command chmod +x hello_world.sh on the command line. To run the shell, we enter ./hello_world.sh at the command line. Prefixing the name of the shell script with ./ is necessary if the script is not in a folder that is indicated in the $PATH variable.

Let’s create a new script and call it echo_test.sh. The script should contain the following code:

#!/bin/bash

echo “Mirab, with sails unfurled.”
echo “Shaka, when the walls fell.”

We then enter chmod +x echo_test.sh on the command line to make the script executable. To execute the shell, we enter ./echo_test.sh. Note that each echo command produces output on a new line. To suppress the trailing newline, we use the -n command option for echo. A third script, echo_test2.sh, makes use of this feature.
#!/bin/bash

echo -n “Greetings, ”
echo “Professor Falken.”

A shell script is processed in the order in which the commands appear in the script. For the most part, each command ought to be listed on separate lines. All of the commands that we can use in the shell command line can be put into a shell script.

For example, the orientation.sh script below quickly lists out some basic information about the current shell session.

#!/bin/bash

echo -n “username: ”
whoami
echo -n “hostname: ”
hostname
echo -n “date: ”
date
echo “terminal: ”
tty

Comments begin with the hash symbol and continue until the end of the line. The shell ignores comments. For a typical script, we ought to at least include the name of the program, a short description of what the command does, and the author of the script.
#!/bin/bash

# current_dir.sh
# Al Jensen
# Prints working directory

echo -n “Working Directory: ”
pwd

Shell scripts can also make use of the printf command for outputting to the terminal. The printf command behaves in a similar manner to the C printf function; it takes a format string that contains a mix of literal characters and conversion specifiers, and also supports the newline and tab escape sequences – \n and \t, respectively.
#!/bin/bash

# print_test.sh
# Al Jensen
# illustrate the printf command

# %s specifier is for strings
printf “%s\n” “Are we having fun yet?”

# %d specifier is for decimals
printf “The secret of life is %d” 42

The Linux Terminal Environment

Log in as a nonroot user; this is an ordinary system user without administrative privileges. The terminal console will display the time of our last login, and then we will find ourselves at the shell prompt, indicated by the dollar sign.

To logout, we enter the command logout. We can then log in again as root, the administrative superuser. The terminal console will display the last time the root superuser logged in, and then display the shell prompt. Note that since we are logged in as root, the last character of the shell prompt is a hash mark instead of a dollar sign.

Again, we log out using the logout command.

The next command we will learn is the substitute user command; this command follows the form su and then the same of the user we wish to be.

To log in as root, we simply issue the su command without adding a username to the end. Typically, it’s best to add a hyphen to the end of the su command when switching to root, and between the su command and the username when we are switching to a different user. By adding a hyphen, we start the user’s session as a login shell. Note that when logging in as a regular user from root it is not necessary to enter a password.

The Bourne-Again shell, known as the bash shell, is an improved version of the original Unix shell developed in the 1970s. The bash shell is usually the default, and it is the shell we have been using so far. We enter commands at the shell’s prompt. As we have seen, the standard user prompt begins with a dollar sign, and the root superuser’s shell prompt begins with a hashtag.

Behind the dollar sign or hastag symbol, we can see that the bash shell displays additional information. By default, we are shown our username, followed by the @ symbol and the hostname of the system we are on. Additionally, we can verify who we are by entering the whoami command.

Each user has a home directory, which is where their personal files are stored. By default, when we open a terminal window as a user we being in our home directory. The home directory for all ordinary users are by default stored together in the /home directory.

To find out what directory we are in, we can use the print working directory command, pwd. We can use the pwd command to find where we are in the filesystem at any given time.

Note in the example above that when we logged in as root and entered the pwd command the system told us that we weren’t in the /home directory at all. The home directory of the root user is intentionally kept spearate from the home directories of regular users.

As an example, if we enter the su command to switch to root, and we do not place a hyphen after su, we will find we are still in the home directory of the original user.

When we switched users, we did not start a new login shell, since we ommitted the hyphen. If we began issuing commands right away as the root superuser, we could inadvertently alter the files and directories of a regular user. For this reason, it is generally a good idea to issue the command su – rather than su.

 

Sending Messages on the IBM i

An impromptu message is not predefined and is not stored in a message file. An impromptu message can be sent from one user to another; these messages may have no preset reply value. The message can be informational or for inquiry. We can send an impromptu message using the Send Message command, SNDMSG. The SNDMSG command only works with messages whose text is included within the MSG parameter of the command.

To send a message to a user, we use the TOUSR parameter. We can enter a specific user profile name or a special value; the special values that are allowed for this parameter are *SYSOPR, *ALLACT, and *REQUESTER. The *SYSOPR special value indicates the system operator’s message queue. The *ALLACT special value indicates all currently signed-on user profiles’ message queues. The *REQUESTER special value indicates the user profile currently running this interactive job.

The SNDMSG command allows us to send a message to the system operator without necessarily knowing the name of the user profile or message queue. All we need to do is specify TOUSR(*SYSOPR). We can also specify TOUSR(*ALLCT) if we want to broadcast a message to all users currently signed on. For example, we could issue the command SNDMSG MSG(‘Pizza in the break room!’) TOUSR(*ALLACT) to alert everyone that there is pizza in the break room. Finally, we can even send a message to ourselves by specifying TOUSR(*REQUESTER).

Note that we can enter the command DSPMSG to view messages sent to us.

To broadcast a message to all active user profiles, we would issue the command SNDMSG MSG(‘All active users will receive this message.’) TOUSR(*ALLACT). To send a message to the system operator, we issue the command SNDMSG MSG(‘This goes to the system operator’s message queue.’) TOUSR(*SYSOPR). Finally, to send a message to ourselves, for example as a reminder of things to do the next day, we can enter the command SNDMSG MSG(‘Bring donuts tomorrow.’) TOUSR(*REQUESTER).

As an alternative to sending the message to a user, we can send the message to a message queue using the TOMSGQ parameter. The disadvantage to using the TOMSGQ parameter is that we must know the name of the message queue assigned to the user; although, by default the message queue and the user name are the same. The advantage to using the TOMSGQ parameter is that we can send the same message to multiple specific users. The TOMSGQ parameter can accept a list of up to 50 values. As an example, we could issue the command SNDMSG MSG(‘The meeting time has been changed to Friday.’) TOMSGQ(ADALOV CBAB) to send a message to the ADALOV and CBAB users.

Be aware that the TOMSGQ and TOUSR parameters are mutually exclusive.

We can use the SNDMSG command to send an inquiry message. An inquiry message is a type of message we can send when we want the recipient to acknowledge and respond to the message. To send an inquiry message, we use the MSGTYPE parameter with the *INQ special value. The MSGTYPE parameter defaults to *INFO, which means the message is just informational. For example, to send an inquiry message to the security officer, we would issue the command SNDMSG MSG(‘Why is a raven like a writing desk?’) TOUSR(QSECOFR) TYPE(*INQ). Note that the MSGTYPE(*INQ) is invalid if TOUSR(*ALLACT) is specified or if TOMSGQ contains multiple values.

If the MSGTYPE(*INQ) is specified, we can identify a message queue to receive the reply with the RPYMSGQ parameter. The default value of the RPYMSGQ parameter is *WRKSTN. If *WRKSTN is used, the reply is sent back to the workstation message queue associated with the interactive job that sent the message, unless the job is a batch job, in which case the reply is sent to the QSYSOPR message queue.

As messages are not displayed the moment they are received, there can be a delay of indeterminate length between the time we send a message and the time the recipient actually reads it. If the message is urgent, we can send a break message. To send a break message, we use the Send Break Message command, SNDBRKMSG. Unless the message queue has been altered with a program to handle break messages, the message interrupts the interactive job of the recipient.

The Send Break Message command, SNDBRKMSG, delivers messages only to a workstation message queue. The SNDBRKMSG command has two required parameters, MSG and TOMSGQ. To send a break message to all active workstations, we issue the command SNDBRKMSG MSG(‘Photons be free!’) TOMSGQ(*ALLWS). The *ALLWS special value used here indicates all work station message queues.

We can prompt for the SNDBRKMSG command by entering the command on the prompt and then pressing F4. We will then have to type the message text and identify who should receive the message.

Please note that the Send Program Message, SNDPGMMSG, and the Send User Message, SNDUSRMSG, commands can be used only from within a CL program.