About This Site
LectureNotes Week 08
LectureNotes Week 09
High School Computer Clubs Project
===================================== COMP 151 - Lecture Notes ===================================== ------------------------------------------------------- PROGRAMS AND COMMANDS: How does Bash execute commands? ------------------------------------------------------- A "program" is a file that is "executable", and preferably marked as executable. Almost every Linux command is such a program. The only exceptions are Bash built-in commands. You can see a list of builtin commands by using the builtin command "help": $ help The commands listed at the output of "help" command are natively recognized by Bash. For any other command, Bash does the following: (1) Check the environment variable called PATH. This tells Bash in which directories it should look for programs. The "env" builtin command will tell you the value of PATH (along other environment variables). A typical PATH is as follows: PATH=/sbin:/bin:/usr/sbin:/usr/bin which contains four directories. (2) For each directory in PATH, Bash checks if that directory contains a file that has the same name with the command. If there is, and the user has the right to execute the file, it is executed. If user does not have the execute right, Bash tells you that "access is denied". (3) If none of the directories contain such a file, Bash tells you that "command not found". You can interrogate where does Bash find the program, using "which" builtin command, as follows: $ which cat /bin/cat The output reports that the program "cat" is found under /bin directory. On the other hand: $ which links /usr/bin/links If you go and check the file, you will see that it is indeed executable: $ ls -l /bin/cat -rwxr-xr-x 1 root root 16504 Jul 16 2004 /bin/cat Although the file is owned by root (the super administrator of any Linux system), every user has the right to execute it, thus execution is allowed. How does Bash know how to execute a program. There are dozens of programming languages and Bash have no idea about any of them! When Bash needs to run(execute) a program (i.e. a file that is executable), it first checks the type of the file. We can do this ourselves using the "file" command: $ file /bin/cat /bin/cat: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.0, dynamically linked (uses shared libs), stripped This is cryptic! But briefly it tells us that the file is directly "executable" on the Intel CPU. This is a binary file which is written in the language that the hardware (CPU) can directly understand. In fact if you try to look at the file, Bash will warn you as follows: $ less /bin/cat "/bin/cat" may be a binary file. See it anyway? There is a second group of programs. An example is "base-config", which is used to configure a Debian GNU/Linux system at the beginning: $ which base-config /usr/sbin/base-config $file /usr/sbin/base-config /usr/sbin/base-config: Bourne shell script text executable This is different from /bin/cat. It is also executable, but not directly by the hardware. It is written in Bash language. So in fact it is a readable text file. Let's see a few lines from the file using "head" command, which shows first 10 lines of a file: $ head /usr/sbin/base-config #!/bin/sh # This program handles debian's second stage install -- after installing # the base system and rebooting, the inittab runs this program. set -e DI_DB=/var/log/debian-installer/cdebconf/questions.dat LIBDIR=/usr/lib/base-config MENUDIR=$LIBDIR/menu TEXTDOMAIN=base-config All Bash cares here is the first line which contains "#!/bin/sh". The "#!" in the first line of an executable file is called "the interpreter line". It is a special sign for Bash and it tells Bash the name of a program that knows how to interpret(run) the commands in this file. In our example it is the program "/bin/sh". Bash will run this program and give the name of base-config to it as a parameter. So in fact, running "base-config" command is same as running "/bin/sh /usr/sbin/base-config". But this convenience helps us, the users, not to worry about typing long commands and needing to know all that. However we can use this ability to create our own little programs without actually knowing how to program! NOTE: /bin/sh is indeed a link to bash. This is a common convenience in GNU/Linux systems for which many alternative shells (like Ash, Corn shell, Z Shell, etc.) are available. /bin/sh is always a link to default system shell. ------------------------------------ GROUPING COMMANDS INTO BASH PROGRAM: ------------------------------------ Let's first create a directory to put our own programs. "programs" directory under our home would be a convenient place for this: $ cd # to go to our home firectory $ mkdir programs # to create the directory As the next step let's create the program file, say "myfirstprog", using some text editor, such as "pico" $ pico programs/myfirstprog Now let's put the following line into our file: echo "Hello. I am a Bash program" echo "but a very simple one" At this point our file contains a single Bash command. The "echo" command is simply for writing (echoing) a text to the screen. Note that this file is not yet a program, for several reasons: (1)we have not marked it as executable, (2) we did not put and "interpreter line" so that Bash will know how to run the program, and (3) it is not in the PATH. However we can run our program by explicitly calling the interpreter as follows: $ bash programs/myfirstprog Hello. I am a Bash program but a very simple one This is inconvenient if we want someone else to use our program since they will need to know which interpreter to use, or if we ourselves need to type this long command every time to run it. So let's turn it into a real program by doing the following: $ chmod +x programs/myfirstprog now we can run the program by directly calling it: $ programs/myfirstprog Hello. I am a Bash program but a very simple one Note that Bash did not need an interpreter line! Since our program contains Bash commands, it works without an interpreter line. Bash simply assumes that any executable file that is not a binary (such as /bin/cat above) is one that contains Bash commands. Thus we can skip worrying about the interpreter line for Bash programs. However if we want to be able to run the program by simply calling its name ("myfirstprog"), we have to change the PATH, as follows: $ PATH=$PATH:~/programs We have to stop for a moment to understand this weird looking command, because it uses something called "variable" in the Bash environment. What we did above is to set the value of PATH variable to something new. The equal sign, "=", is used for this assignment: variable=new-value-for-variable So in fact, we could use a command as follows to set the PATH to a new value so that it will include the "programs" directory under our home (remember that the tilde, "~", is a shortcut for our home: $ PATH=/bin:/sbin:/usr/bin:/usr/sbin:~/programs The command above would give us what we want, but it is possible that our system had some other directories included in the PATH. What we wanted was to add ~/programs to PATH. The first command does exactly that: it takes the current value of PATH ( the $PATH) and appends ~/programs to it by using the column, ":", as seperator. When Bash sees something prefixed by a dollar sign, "$", it will expand it to its value. For example, the following command will print the value of PATH: $ echo "The Path is --> $PATH" After setting the PATH appropriately, we can now call our program by directly mentioning its name: $ myfirstprog Hello. I am a Bash program but a very simple one --------- EXERCISE: --------- Write a program that uses an interpreter line so that it will count the words in itself! You can use the wordcount program, "wc", as interpreter. SOLUTION: #!/usr/bin/wc Please count me! ------------------------------------ PASSING PARAMETERS TO BASH PROGRAMS: ------------------------------------ Bash is a very rich language which offers a variety of expansions in addition to the variable expansion we have mentioned above. But for the purposes of this course, we are only interested in passing simple parameters to our Bash programs so that we can have basic control on how they work. When Bash executes a program, the parameters given on the command line are made available to the program with names 0,1,2,..., etc. Variable number zero is the name of the program itselfi and variables 1,2,... are the actual parameters that come after the name of program. As an example, let's create a second program called "mysecondprog", in programs directory and put the following commands into it: #!/bin/sh echo "Hello. I am a Bash program" echo " my name is: $0 " echo " my first parameter is : $1 " echo " my second parameter is: $2 " (We have said that first line, the "interpreter line", is unnecessary for Bash programs, but it is a good habit to put it anyway!) Let us turn this file into a program as we did before by making it executable: $ chmod +x ~/programs/mysecondprog Now let's run it as follows (I assume that you have set the PATH variable accordingly): $ mysecondprog Hello. I am a Bash program my name is: mysecondprog my first parameter is : my second parameter is: Since there were no command line parameters, the values of $1 and $2 are empty. Let's try to run our program with some parameters: $ mysecondprog abc 123 xyz Hello. I am a Bash program my name is: mysecondprog my first parameter is : abc my second parameter is: 123 Our little progam is "programmed" to use only the first and second parameters, so the third one does not show up. There is a way to know the number of parameters but it is beyond the scope of our course here. In addition to command line parameters, a program can read additional values from the user using "read" command, as in the following example: #!/bin/sh echo "Please enter a filename to wordcount:" read x wc $x --------- EXERCISES: --------- (1) Write a bash program which takes a URL as its first parameter, dumps its text only version using "links -dump" and counts the lines, words ,letters in it using wc. SOLUTION: #!/bin/bash echo "Please wait while I am downloading $1" links $1 | wc echo "bye"
Last Updated : 2008-11-27 09:26:24