LABORATORY
THREE
OBJECTIVES
1. Unix / Linux Shell Commands and Usage
2. Basic Shell Script Programming
3. Processing Exit Status
4. Web Pages Publishing
Unix / Linux Shell Commands and Usage
As a recap, here is a list of common Unix / Linux shell commands used with processes.
Command Usage
ps ps -elf
bg bg
fg fg %2
jobs jobs
time time a.out uptime uptime
top top
Description
Show the processes in the computer
Move a stopped foreground job to background
Move background job number 2 to foreground
Show the list of background jobs
Show the total execution time of a program and its share of CPU time
Show the current workload of the computer, e.g., number of users
Show CPU and resource utilization of computer with a list of active processes
kill | kill %2 | Terminate a background job |
Sometimes, users will try to customize their Linux system to look like whatever system they are familiar with, by changing the meaning of commands or create new commands. Recall that this is achieved via the use of alias, e.g., make ls behave like what you like by setting an alias for the command, alias ls=’ls –l’, or use the more familiar command dir instead of the ls command, via alias dir=ls.
If you want to define many aliases at the same time, you may put them into a “batch” file and execute it (like .bat file in MS-DOS). Then you do not need to type in the alias commands every time you login to the system. Just place all your aliases into a file, e.g., myalias. You can then execute this file containing useful aliases by typing source myalias. You are encouraged to create your own alias file to customize your Linux. Note that you can also execute the script created in Lab 2, i.e. allLab2, via the source command, i.e., source allLab2. The file does not need to be changed to executable via chmod if source command is used.
Many Unix / Linux functions are defined based on system variables, which are called shell variables. Here, PS1 is a shell variable that directs Linux shell to display its content as the (primary) prompt. There are two types of shell variables, namely, global variables and local variables in bash and csh. A global variable is called an environment variable. An environment variable can be created via the export command in bash, converting a local variable into a global variable. Once created, the environment variable can be accessed and modified (using =) in the regular manner. You can also remove the environment variable by the unexport command. You would need to use the command setenv instead of set to modify an environment variable in csh.
If you use the departmental file system, you will almost always see drwx------ for any directory and -rwx------ for any file. Only the write privilege can be set currently for the owner. Thus, performing chmod 644orchmod 600orchmod 777willnothavecreatedanychange.Ifyouperformchmod 000, you could get –r-x------ for a file. Changes in local desktop files would not affect the file system.
Shell Scripts
The First Shell Script
Try to run the following first shell script program in bash, call it first.sh. Just type the script name to execute it, after setting it to be executable:
chmod 700 first.sh
Note that you may need to make some changes to the program text before it can be executed, if you merely copy it from the pdf file. Watch out for difference in quotation symbols and for ^M characters when you make the copy, before you try to run it. This normally happens when files are moved across from Windows system to Unix / Linux systems. Each text line in a Windows file ends with ^M and ^L (called <CR><LF> or Carriage-Return and LineFeed), but the line in a Unix / Linux file ends with just ^L (i.e. <LF>). So there is an extra ^M in the view of Unix / Linux when a file created under Windows is moved or copied over. This is one major reason that a seemingly correct shell script program cannot run properly on the actual machine from our past experience. You can use the command dos2unix available on most Unix / Linux systems to perform the removal of those ^M characters for file first.sh:
dos2unix first.sh
The dos2unix command is not available in Mac OS/X, but you can still do the same trick using the following approach, by creating a new file called first2.sh:
tr –d ’\r’ < first.sh > first2.sh
#!/bin/bash
echo Hello $USER, time is $(date)
# $(date) allows the COMMAND/PROGRAM date to be executed and replacing the output echo -n ”You must be ”
# -n keeps output on the same line and we need a space at the end
whoami
# whoami is a command/program
echo Your home is $HOME
# HOME is a variable
echo Your calendar for this month is:
cal # cal is a program
echo Friends on this computer $(hostname) are:
who # who and hostname are programs
echo ”Thanks for coming. See you soon!!”
Basic Shell Script Programming
Try out the shell script programs covered in the lecture and follow through the statements / commands to understand how they work. Try the programs using different inputs. Note that the symbol * is a wildcard character that leads to the matching of filenames, etc.
[ -d $f ]; then
echo $f is a directory
[ -f $f -a -x $f ]; then
echo $f is a plain executable file
[ ! -w $f ]; then
echo $f could not be modified
Processing Exit Status (Optional)
After a command or program terminates, it would return an exit status back to the shell or the parent process. The exit status is a number between 0 and 255. By convention, an exit status of 0 means that the process execution is successful. If the exit status is non-zero, it means that the execution has failed in some way with an error, in much the same way that 404 means Page Not Found in http access.
There is a special shell variable $? in bash that will store the exit status of the command or process just executed. After a command is executed, this special status variable $? is set to the exit status of the command. Try the following command execution, and observe the outputs. However, note that the exit status for a chain of commands with I/O redirection or pipe could be hard to interpret.
$ ps
$ echo $?
0
$ abc
bash: abc: Command not found... $ echo $?
127
$ echo $?
0
Note that if you do have a program with the name abc and if the program executes correctly, the exit status would be 0 for your case above. However, if your program abc does not execute correctly, there would be a non-zero status, depending on the nature of the error and the arrangement of your program. For segmentation fault error, the exit status is 139. An arithmetic error gives an exit status of 136. Try the following program lab3A.c with inputs of 2 and 0. There will be errors in both executions. Try to
check the exit status with echo // lab 3A
#include <stdio.h>
int main() {
int n, m, ans, *ans2;
$? to verify the error code resulted due to bad inputs.
m = 5;
printf("Please enter a number\n");
scanf("%d",&n); // try non-zero and zero
ans = m / n;
printf("Dividing %d by %d yields %d\n",m,n,ans); *ans2 = m / n; // why is there a problem here? printf("Dividing %d by %d yields %d\n",m,n,*ans2); printf("Program terminates\n");
}
You have the freedom to decide on the exit status of a program. If you consider that your program does not terminate successfully, you could return some specific number. The exit status of a process is determined by the argument inside the exit() system call. It is an integer between 0 and 255, but some programmers also choose to return -1 inside the exit() system call. A return value of -1 from the exit() system call is equivalent to a value of 255. This is because the exit status is just a byte (unsigned). Thus, an exit status of 256 is the same as 0, i.e. correct execution. Try lab3B.c below with different inputs and check the exit status.
// lab 3B
#include <stdio.h> #include <stdlib.h>
int main(int argc, char *argv[]) { // isprime.c implementation int n, prime, i;
n = atoi(argv[1]);
printf("Your number is %d\n",n); // should comment out for usage in key.sh prime = 1;
for (i = 2; i <= n/2; i++)
if (n % i == 0) prime = 0;
if (prime) {
printf("Your number %d is prime\n",n); // should comment out for usage in key.sh
exit(0);
} else {
printf("Your number %d is not prime\n",n); // should comment out for usage in key.sh exit(1);
0 ]; then
echo "Your chosen public key $3 is bad"
exit 3 fi
echo "File $4 does not exist, will stop"
exit 4 fi
if [ -f $5 ]; then
echo "File $5 exist, will stop" exit 5
fi
./toencrypt $N $3 < $4 > $5 # toencrypt encrypts file using key E with modulo N echo Encrypted $4 into $5
In shell scripts, the exit status from commands could be exploited when executing a chain of commands to make the script more efficient. Commands in a command list in a script are executed in a short-circuit manner. This brings in efficiency in programming and execution, but also brings in confusion and could be error-prone for ordinary programmers. Short-circuit execution means that the execution of a combined conditional statement will not be executed to the end, but will stop once the truth value, i.e. TRUE or FALSE can be determined upon partial execution.
- · first-command && second-command
Here, the second command is not executed if the first command does not execute correctly (i.e., the return status is non-zero). The successful execution of the second command does not change the fact that this conditional evaluates to FALSE. - · first-command || second-command
Here, the second command is not executed if the first command executes correctly (i.e., the return status is zero). The potential unsuccessful execution of the second command does not change the fact that this conditional evaluates to TRUE.
You must be careful and beware of the difference of a success in exit status (0 = success, thus 0 || 1 = 0 meaning success) and a TRUE in normal expressions in if-conditionals (non-zero = true, thus 1 || 0 = 1 meaning true) when evaluated. This is opposite to normal programming logic, where 0 means FALSE.
Publishing Web Pages via Unix / Linux
|
|
with web tools into a zip file and place it under Unix/Linux. For your information, Unix/Linux people often use the tar command to archive files. Finally, you can extract the files from the zip file and set the appropriate protection mode for files and directories. |
Laboratory Exercise
Script programs are useful for text processing involving many files. For instance, each subject may be associated with a file containing the students taking the subject and perhaps with assessment grades. Given a collection of such subject files, it is not difficult to find out the academic performance of a particular student and generate a transcript for that student.
Write a bash shell script called transcript to search through a list of subject files and generate the transcript for one or more given students in the argument list. The first part of the argument list indicates the subject files to be used. This is followed by a special marker “student”. Then a list of student ID follows. Each subject file starts with a line of 4 entries: the word “Subject”, the subject code, the academic year and the semester that the subject is/was offered. Each of the subsequent lines contains the ID of a student and the grade. For subjects in the current semester, there is no grade for the students. To facilitate the checking of students, there is a special file called student.dat. Each line of this file contains the ID of a student and the name. For simplicity, there are only two semesters in each academic year. You can assume that there is no error in the information contained in all the files.
For instance, the program can be run like:
transcript COMP101121S2.dat COMP241122S1.dat student 1234
Here, COMP101121S2.dat and COMP241122S1.dat are the names of subject files, and 1234 is the ID of the student whose transcript is to be generated. The two lists are separated by the special marker “student”. The use of wildcard character “*” can also be used in the list of subject files. However, it would not be used in the list of student ID. Typical file contents are shown below:
Filename Content
student.dat | 1223 bob 1224 kevin 1225 stuart 1226 otto 1234 john 1235 mary 1236 peter 1237 david 1238 alice |
COMP101121S2.dat | Subject COMP1011 2021 2 1223 F 1236 A |
COMP101122S1.dat | Subject COMP1011 2022 1 1223 B 1238 C+ |
COMP241122S1.dat | Subject COMP2411 2022 1 1223 C+ 1236 A |
COMP243222S2.dat | Subject COMP2432 2022 2 1223 1237 |
Shell Scripts Page 11 Sample outputs (formatting is not important):
transcript COMP101121S2.dat COMP241122S1.dat student 1234
transcript COMP* student 1236 1234 1223
Transcript for 1234 john COMP1011 2021 Sem 2 B COMP2411 2022 Sem 1 B- GPA for 2 subjects 2.85
Transcript for 1236 peter
COMP1011 2021 Sem 2 A
COMP2411 2022 Sem 1 A
COMP2432 2022 Sem 2
GPA for 2 subjects 4.00
Transcript for 1234 john COMP1011 2021 Sem 2 B COMP2411 2022 Sem 1 B- GPA for 2 subjects 2.85
Transcript for 1223 bob
COMP1011 2021 Sem 2 F
COMP1011 2022 Sem 1 B
COMP2411 2022 Sem 1 C+
COMP2432 2022 Sem 2
GPA for 2 subjects 2.65
Remember that your program is supposed to work on any correct datasets. As a result, you should not hardcode the subject file names in your script program. It is not required that you use the real data set for program development and testing. It would be easier if you use a small dataset for development and initial program testing.