CSE 390A, Summer 2013 Assignment 4: Basic Shell Scripting Due Tuesday, July 23, 2013, 9:00 AM This assignment focuses on Bash shell scripting at an introductory level. Electronically turn in FOUR files: .plan, .bash_profile, mantra.sh, and filestats.sh as described in this document. To receive credit, your .bash_profile and .plan should also be present in your home directory. Task 1: .plan file (on attu) A file named .plan can be placed into your home directory to tell other users of the system about you. In this file you can write any text you like, and the text will be displayed to other users when they use the finger command on you. Set up a .plan file for yourself on attu that contains the following contents, you also need to turn this file in. At least one sentence about yourself (can be real or made up) A cow message as would be output from the ~meganca/390/cowsay or ~meganca/390/cowthink programs One other piece of ASCII art, or a short message in large text Want more cows in your plan? Check out: http://www.sunnyspot.org/asciiart/gallery/cow.html Test your .plan file by running finger on yourself. Turn in this file as part of your assignment submission, but part of this task is also making sure that the file can be seen by other students successfully when they use the finger command. The file must have read permissions for all users. Ask a classmate to try this command on you to see whether they see your .plan. In grading we will check whether you have a .plan file by running finger on each student. Task 2: Login script, .bash_profile (on attu) As we have discussed in class, .bash_profile is a script that runs every time you log in to a Bash shell. For this part of this assignment, you should create a .bash_profile file in your home directory that performs the following operations. You also need to turn this file in. 1. Create an alias so that when you type attu, you will connect to attu.cs.washington.edu with SSH. (This alias isn't very useful if you're testing on attu itself, but set it up anyway.) Set up a similar alias so that when you type dante, you will connect via SSH to dante.u.washington.edu. 2. Set it so that when you try to delete a file or overwrite a file during a move/copy operation, the user is prompted for confirmation first. (Hint: Set each of the three operations described to run in its “interactive mode”.) 3. (Self-Discovery) Lists which of your friends are online and what they are doing. Before adding this command to your .bash_profile, define a file named buddylist.txt in your home directory whose contents are the CSE user names of two or more of your friends in the department, one per line. The file can have as many lines as you like so long as it is at least two. If you would like, you may use meganca and your own username. Now add a command to your .bash_profile script to display which of your buddies are logged in to the system and what they're doing, sorted by user name. For example, if your buddylist.txt contains: stepp meganca ln Then a possible output from this command of your .bash_profile might be: ln ln ln stepp stepp pts/5 pts/6 pts/8 pts/3 pts/10 :pts/6:S.1 207.108.209.70 :pts/6:S.0 67.160.45.86 67.160.45.86 21:09 20:33 20:33 00:10 00:20 2:20m 2:15m 2:15m 7:46 8:34 0.34s 0.06s 11.23s 0.02s 0.02s 0.28s 0.02s 0.08s 0.04s 0.00s vim poisson.ml screen bash ./getml.sh banner ^_^ cowsay (Hint: You can get this to work using commands we've already seen, but you will need to read the man pages.) Note that your command should work regardless of the number of user names in buddylist.txt. You should not assume that buddylist.txt contains exactly 3 names as shown above, etc. 1 of 3 In class we discussed several ways to get information about who is currently logged on. Your first step should be to figure out which of these methods gives you the exact format shown above. The lecture 3 slides will be useful. Once you have found the correct command to call, there are several ways to call the command using the contents of buddylist.txt. If you use xargs in your solution you will want to give it an argument that sets the max number of arguments it sends to the command in question to be one (look at the man page for that command, it says it takes a single user as a parameter, not multiple users). You can also answer the problem without using xargs at all. Don’t forget to sort your results by username. Overall you will find it useful to search through man pages for useful options. Inside of man you can type /keyword and hit return to find the first occurrence of keyword in the man page. Typing n will find the next occurrence. Q will quit out of a man page. Recall that you can test the functionality of your .bash_profile by writing the following command in the shell: source .bash_profile 4. (Self-Discovery) Use the mesg command to set whether or not you want to be able to be contacted by commands such as write and wall. Either setting (yes or no) is fine; but explicitly set one or the other. 5. Set the user's prompt to consist of the current username, shortened host name, and working directory, with separators between each. For example, if user bob is logged into host attu3.cs.washington.edu and is in directory /usr/bin, the prompt would be: bob@attu3:/usr/bin$ Use appropriate commands and/or environment variables to discover each piece of info (Who is the current user? What host are they on?) to insert into the prompt. A tricky part is inserting the current directory; you can't do this by just running the pwd command, because it won't update each time the user changes to a new directory. Instead, insert the special symbol \w into your prompt text to tell Bash to put the working directory into the prompt. 6. At the end of the file, output this message to the user as he/she logs in. For user bob, the message might be: Hello, bob! Your shell is /bin/bash. The current time is 01:43 PM, Monday April 26, 2012. To be clear, you are not supposed to literally output bob and exactly that shell, and date/time shown above. You are to use appropriate commands to discover the current user's username and shell (there are shells other than bash that someone could be running) and to display the current time in the format shown. Read the man pages about displaying the current date/time with an appropriate "+FORMAT" parameter. For example, to show a date such as 04/26, you could write: date "+%m/%d" (Self-Discovery) If you want an optional extra challenge worth 0.001 points of extra credit, change the first output line above to print the user's real name rather than username. Hello, Hank Levy! To do this, you would need to perform a lookup on the person's real name based on their username. You can do this by examining the contents of the /etc/passwd file for the given username. There should be a line like this: bob:x:1000:1000:Hank Levy,,,:/home/bob:/bin/bash Notice that the various information about the user is separated by colon : characters. The cut command can chop a line into fields based on a delimiter and select only certain field(s) to output. You can use it twice: once to separate the tokens by colons, and a second time to remove commas after the name. You may assume that the format of these lines always contains the same number of colon-separated tokens in the same order. 2 of 3 Shell scripts Put a comment header atop each of your script files indicating your name, course, etc. and a description of the program. Each of your two scripts should also have a proper #! heading so that it can be used as an executable file. For reference, our mantra.sh is 26 lines (14 "substantive" lines in the CSE 142 Indenter tool) and our filestats.sh is 21 lines (13 "substantive"). You don't need to match these totals exactly or be close to them; they are just a ballpark. Task 2: Shell script, mantra.sh For this exercise, write a shell script file mantra.sh that accepts two command-line arguments: a string for a message to print, and a number of times to print it. The script should print the message that many times, surrounded by a box of stars. For example, if the user runs your script in the following way: ./mantra.sh "All work and no play makes Jack a dull boy" 5 Then the script should produce the following output to the shell: ********************************************** * All work and no play makes Jack a dull boy * * All work and no play makes Jack a dull boy * * All work and no play makes Jack a dull boy * * All work and no play makes Jack a dull boy * * All work and no play makes Jack a dull boy * ********************************************** Notice that you can pass a multi-word message by putting it in quotes. (Bash handles that for you.) You may assume that the user will pass 2 parameters and that their values will be reasonable; the message will be nonempty and shorter in length than the width of your terminal, and the number of times will be a valid integer greater than 0. Hint: Perhaps the trickiest part of this script is getting the lines of stars above and below the message to be exactly the right length to surround the messages. You can use an appropriate command to find out the length of the message and surrounding stars, then print a star this many times above/below. Use echo and ` ` backticks to combine commands. Use the diff command to check that your output EXACTLY matches the output listed on the homework web page!! Task 3: Shell script, filestats.sh For this exercise, write a shell script file filestats.sh that accepts an arbitrary number of file names as command-line arguments and prints information about each of the files: • number of lines in the file • number of blank lines in the file, and percentage of blank lines out of the total lines • number of characters and words in the file, and approximate number of characters per word (computed as the truncated integer division of total characters divided by total words) The web site file hw4.tar.gz contains some test files. If you decompress it to the current directory and then run: ./filestats.sh Jack.java lyrics.dat Then your script should produce EXACTLY the following output to the shell: Jack.java: lines: 13 blank: 3 (23%) chars: 369 in 44 word(s) (8 char/word) lyrics.dat: lines: 27 blank: 2 (7%) chars: 873 in 180 word(s) (4 char/word) Note that the shell expands command-line arguments containing wildcards before your script runs. For example, if your directory has files file1.txt , file2.txt and file3.txt and you run filestats.sh *.txt, the $@ array doesn't contain the string "*.txt". Instead it will contain three elements: "file1.txt" , "file2.txt", and "file3.txt". You may assume that each file listed as a command-line argument will be readable by your script. You may also assume that no file will be empty (0 lines, 0 characters). But a file might contain 0 blank lines or might be arbitrarily large/small. If no arguments are passed to your script, it should produce no output. Hint: It can be tricky to figure out the number of blank lines in a file. You can see which lines of a file are non-blank by using the grep command and looking for lines that match the pattern "." (a dot). This doesn't literally look for a period character; a dot represents any character in general. (We'll learn more about this when we cover "regular expressions.") Use the diff command to check that your output EXACTLY matches the output listed on the homework web page!! 3 of 3