Hands-on 1: The UNIX® Time-Sharing System

This hands-on assignment is due at the beginning of class on recitation 4. Before attempting this hands-on, you should read The UNIX® Time-Sharing System, which is also assigned for this recitation.

Warmup

If necessary, you may want to briefly re-read sections 5.2 and 6.2-6.4 of the paper to refresh yourself on the concepts of pipes and I/O redirection.

Note: Although the examples shown below are from the MIT server UNIX® workstations, it should be possible to do this assignment on any standard UNIX® system.

We'll start off with an extremely simple example that most of you are probably familiar with already:

MIT server% cd /bin

MIT server% ls -1 | more

Here, we are first changing into the /bin directory, which contains many of the executable commands for the system. The command ls -1 gives us a listing of all the files in the current directory with one file per line. (Note that -1 is the numeral "one", not the letter "L".) We then pipe the output from ls to the command more, which displays the results one page at a time. (Press the space bar to show the next page.) You can refer to the manual pages for ls and more to see more details and options for each command. Manual pages let you read information about various commands on UNIX® systems; to use them, run

MIT server% man command

where command is the command you are interested in. If you are unfamiliar with manual pages, you may want to try running

MIT server% man man

for information on the man command itself. Keep in mind that the manual pages for basic commands vary from system to system (much as the commands themselves do).

Now, try this:

MIT server% cd /bin

MIT server% ls -1 | grep p | more

This runs the same ls -1 command, but only lists the executable files which happen to contain the letter "p" somewhere in their names.

The point here is to observe that you can chain together multiple commands using the pipe character ( | ), and the output from each command will be passed to the input of the next, in left-to-right order. This allows you to treat any command that uses standard input and output as a primitive from which you can build more complex and useful commands.

Building Blocks

Now, we'd like you to figure out on your own how to solve some problems by chaining different commands together.

If you aren't already familiar with these commands, you may want to briefly skim through their man pages to familiarize yourself with what they do. You will probably need to use some of the options for the different commands in order to solve these problems.

Here are the commands you may find useful:

cat
fmt
grep
head
ls
ps
sort
tail
top
wc
yes (*)

(*) On some MIT server machines, the yes command isn't available. However, if you are doing this assignment on the MIT server you can use the command gyes, which is functionally equivalent. gyes is located in the "gnu" locker, so before you can use it you need to add the locker. You can do so with the following command:

MIT server% add gnu

(If you are curious about the MIT server's locker system, you can run man lockers for more information. The command whichlocker can be used to determine which locker contains a given command. The whichlocker command itself resides in the "outland" locker.)

Once you have added the gnu locker, you can use gyes instead of yes. Some MIT server machines seem to lack the manual pages for both yes and gyes (hereafter referred to just as yes). In case the man pages are missing on the machine you are using, here is a brief description of what yes does. yes is very simple; it just outputs a string repeatedly until killed. It takes either one or zero arguments; if you give it a string as an argument it will output that string until it is killed (you can kill a process by pressing control-c). If you give it no arguments, it will output the string "y" until it is killed, which explains why it is named yes.

Questions

For each of the outputs listed below, find one sequence of commands connected by pipes that produces the output. For each problem, turn in the command sequence that you used to generate the requested output. (Do not turn in the output itself.)

  1. A listing of all processes that you are currently running on the MIT server machine you are using, sorted by the command name in reverse alphabetical order (i.e. a process running zwgc should be listed before a process running acroread). The output should consist only of the processes you are running, and nothing else (i.e. if you are running 6 processes, the output should only have 6 lines).

  2. The number of words in the file /usr/dict/words (*) which do not contain the letters a, b, c, d, e or f.
    [* Note: On some UNIX®/Linux® systems, the dictionary has the filename /usr/share/dict/words]

  3. A 5x5 matrix of entries of alternating Y and N. It should look like this:

    Y N Y N Y
    N Y N Y N
    Y N Y N Y
    N Y N Y N
    Y N Y N Y

  4. A "long" listing of the largest 5 files in the /etc directory whose name contains the string ".conf", sorted by decreasing file size.
    Now we'd like to explore something slightly different, having to do with file redirection as discussed in section 6.2-6.4 of the paper. The authors explain that the following two commands are functionally equivalent (except that you have to remove the temp file afterwards in the second case):

    MIT server% ls | head -1
    MIT server% ls > temp; head -1 < temp

  5. Try the above commands in a few different directories. What happens if you try both of the commands in the /etc directory on the MIT server? How else can the second command not produce the same output as the first? Can you think of any negative side effects that the second construction might cause for the user? You might want to think about the commands you used to solve the first four questions and consider their behavior.
    The UNIX® paper authors explain in section 6.3 that a user can type two commands together in parenthesis separated by a semicolon, and redirect the output to a file. The file will then contain the concatenation of the two commands. The example from the paper is roughly:

    MIT server% (date ; ls) > temp1 &

    Note that this example uses the & operator to run the process asynchronously. That is, the shell will accept and run another command without waiting for the first to finish. The authors also mention that one can use the & operator multiple times on one line. For example, we can do almost the same thing:

    MIT server% (date & ls) > temp2 &

    See if you can figure out for yourself what exactly the difference is between using ";" and "&" in the examples above.
    As a final exercise, let's explore this for ourselves. First, we will write a very simple variation on the "yes" program that you encountered earlier on in this assignment. To do so, we will use the "command file" functionality described in section 6.4 of the paper. Most people call these command files "shell scripts", since they are essentially simple scripts that are executed by the shell.
    First, start up a copy of emacs editing a new file called "myyes".

    MIT server% emacs myyes &

    Now, enter the following lines into your file:

    #!/bin/sh

    echo y
    sleep 1
    echo n

    Save the file and exit emacs. If you don't already know what the echo and sleep commands do, look them up in the man pages. Lastly, make the file executable by running the following command:

    MIT server% chmod a+rx myyes

    Now let's try running the following two commands:

    MIT server% (./myyes ; ./myyes) > temp3

    MIT server% (./myyes & ./myyes) > temp4

  6. Lastly, compare the two temp files. Based on your understanding of file I/O in UNIX®, what is going on here, and why? Is this different from what you would expect? (If there is more than one difference between the two files, it is the ordering of the letters y and n that we are interested in).

    File system Links

    A link is an entry in the file system that refers or points to another object in the filesystem. UNIX® provides the ln command to create links. Let's experiment with links, firstly lets create a file:

    MIT server% emacs linkExperiment

    Type some text in the file, save it and close emacs. Now, run the following two commands:

    MIT server% ln linkExperiment link1

    MIT server% ln -s linkExperiment link2

  7. Look at the output of ls -lai, what are the similarities and differences between the link files? Try removing the linkExperiment file (rm linkExperiment) and editing link1 and link2. What happens? Why?

    Links can create some unexpected behavior:

    MIT server% pwd
    /afs/server.mit.edu/user/m/i/migfer/6.033/handson1/linkexample/home
    MIT server% ls -la
    total 16
    drwx------ 2 migfer mit 2048 Feb 2 09:08 .
    drwx------ 4 migfer mit 2048 Feb 2 08:58 ..
    lrwxr-xr-x 1 migfer mit 15 Feb 2 09:08 bob -> ../tree/one/bob
    lrwxr-xr-x 1 migfer mit 15 Feb 2 09:08 joe -> ../tree/one/joe
    lrwxr-xr-x 1 migfer mit 15 Feb 2 09:08 rob -> ../tree/two/rob
    lrwxr-xr-x 1 migfer mit 15 Feb 2 09:08 tom -> ../tree/two/tom

    MIT server% cd bob
    MIT server% cd ../rob
    ../rob: No such file or directory.
    MIT server% pwd
    /afs/server.mit.edu/user/m/i/migfer/6.033/handson1/linkexample/tree/one/bob


  8. What behavior would be "The Right Thing"? What would be required for this behavior to be possible?

  9. How long did this assignment take you to complete?