--------------------------------------------- Practice Unix/Linux Questions - Chapters 7-10 --------------------------------------------- -IAN! idallen@ncf.ca All scripts written must begin with a proper script header, including the correct interpreter, comments, and a proper PATH and umask. All scripts must work on both Linux (Linux Test Machine) and on AIX Unix. (The same script must work in both places without modification.) All prompts for user input must appear on the terminal, even if standard output is redirected. (Do not send prompts for input into the output file!) Test this! Where possible, commands should open their own files. (Do not use "cat" needlessly - read more on this point in the week4.txt notes.) Never let the shell expand glob patterns (wildcards) unexpectedly. Test this! Don't assume you can write temporary files into the current directory. Test this by changing directories to a directory into which you cannot write and running your script from there. Pay close attention to the names and locations of output files. Real scripts must check the error returns on the commands they use. You may disregard this requirement until after we discuss Chapter 11, at which point you must always check for errors. Not all of these scripts are equally difficult to write. Find the easy ones first! TimeSaver: Use filename completion in the shell to complete the names of these scripts when you want to test them or edit them. Don't keep typing the full path names of the scripts! Let your Shell do your typing for you! (0) Type in all the scripts in the parts of Chapter 10 that we study (starting with "whoson"). Add the correct script headers to the scripts. Test them to make sure that they work. (1) Write this executable script named "1_linux_finger.sh": Run "finger" to the Linux Test Machine (use the IP address) to show all logins, and delete from the display the logins that are by idallen. (The output must not contain idallen logins.) (2) Write this executable script named "2_aix_rusers.sh": Run the "rusers" command with a single argument that is the AIX Unix machine name (use the full domain name). Translate blanks to newlines. Delete the first line. Sort the remaining lines. Hints: - use "tail -n +2" (see the man page) - see the example "tr" commands in week4.txt notes The rusers command is probably not available on Floppix. (3) Write this executable script named "3_rhostmaker.sh": Create the file ".rhosts" in the HOME directory of the person running the script. The file must contain the host name of the machine on which the script is running. Make the permissions on the file exactly this: read for the owner of the file, nothing for anyone else. The script must work correctly no matter in which directory it is executed, no matter on which machine it is run. It must create the .rhosts file in the HOME directory of the person running the script; it must put the current machine name in the file. Hints: - the Unix "hostname" command will output the current host name - command substitution (Ch.10) will let you capture command output - one of the keyword variables (Ch.10) may be useful (4) Write this executable script named "4_pinger.sh": Prompt to read a host name from the script user and then read the host name. Send only 4 ping packets (a count of 4) to the host name supplied by the user. Display the exit status (return code) of the ping command. Have the script exit with that return status. Hints: - "man ping" in the Linux man pages (the AIX man page for ping is displayed far below the man page for "ntx_ping") - Chapter 10 Special Parameters (exit status) - on AIX, ping is not in /bin or /usr/bin; find where it is located and set the script PATH accordingly (5) Write this executable script named "5_nameservers.sh": Extract all lines containing the word "nameserver" from the system file /etc/resolv.conf and display them with line numbers. Hints: - "man cat" on Linux or AIX (6) Write this executable script named "6_secure_directories.sh": Remove group and other permissions on the current directory and on all subdirectories of the current directory that don't begin with periods (the non-hidden directories). Do not change any files. Hints: - echo */. (in the notes for Chapter 4 and Chapter 5) Note: This is tricky to do correctly if the current directory has *no* non-hidden subdirectories. You need control structures from Chapter 11 to handle that case. To keep this script simple, you may assume that there will always be at least one non-hidden subdirectory. (7) Write this executable script named "7_backgrounder.sh": Prompt to read a command name from the script user and then read the command name. Run the command that the user enters in the background. Hints: - "the read builtin" (Ch10) REMEMBER: Always test your scripts with input that contain blanks and other special characters. (8) Write this executable script named "8_standard_error.sh": Prompt to read a line from the script user and then read the line. Display one copy of the line on standard output. Display a second copy of the line on standard error with all the characters changed to UPPER CASE. (This last item will require some thought - you can't blindly copy anything you've seen to date.) Test your script as follows: $ ./8_standard_error.sh >out If you don't see a prompt, fix your script so that the prompt does not get redirected into the file "out". The prompt should be visible, even with standard output redirected into a file. (Advice: Prompts for input should always be visible, even if output is redirected. You never want the prompt to be redirected into the output file along with the script output!) Hints: - last page of "Redirecting Standard Error" (Ch10) - in a command pipeline, which command is the one that needs to have its standard output sent to standard error? (9) Write this executable script named "9_show_processes.sh": Prompt to read a text string from the script user and then read the text string. Look for that text string in the output of the "ps" command. Use both the "f" and "e" options to the "ps" command, so that "ps" outputs *all* the processes on the machine in a nice format. Your output will be only the lines from "ps" that contain the text string. Bonus: Fix the script so that it works even if the user enters a text string that starts with a dash. (Hint: the man page.) 10) Try all the script examples that use different command interpreters (e.g. #!/bin/cat) given in the chapter10.txt file. Also try these command interpreter lines and see what they do: #!/bin/wc #!/bin/cat -n #!/bin/sort -r #!/bin/grep # #!/bin/grep -v # Reminder: These first lines are interpreted by the Unix kernel only if the script is executable and you try to execute it. The lines are comment lines and are ignored by all Unix shells that read the file. 11) Write this executable script named "91_environment_variables.sh": Produce an output line similar to the following: The value of $HOME is: /thome/alleni for each of the shell variables: HOME, MAIL, PATH, and SHELL. The script will generate four lines of output, showing the name and current values of each of the four shell variables. Test the script by setting your MAIL variable to be an asterisk, exporting MAIL, then running your script. Your script must show the correct value - an asterisk. (Never let shell glob patterns expand unintentionally.) 12) Write this executable script named "92_UPPER_translator.sh": Prompt to read a line from the script user and then read the line. The script user should enter a line that contains two file names, separated by blanks. The script will place each file name into its own shell script variable. Translate all the characters from the first file to UPPER-CASE and put the result into the second file. (Translate the file contents, not the file names!) Your script doesn't have to handle the errors that might result if the user doesn't supply two names, or if s/he supplies more than two names, or if the input file doesn't exist, or if the output name is not writable. (You'll deal with all that in Chapter 11.) 13) Write this executable script named "93_host_finder.sh": Look for the name of the current host in the file /etc/hosts and print only the lines containing the current host name. The script must work on any machine and print the lines from /etc/hosts that match the current machine name. Hints: - the Unix "hostname" command will output the current host name - command substitution (Ch.10) will let you capture command output 14) Write this executable script named "94_make_email.sh": Generate and output the full user@domain.name email address of the person who runs this script on this machine. The script must work for any user and any machine in any domain. (Test it on AIX Unix and the Linux Test machine.) Hints: - see the new examples in the updated (on June 13) Chapter 10 notes related to Command Substitution - the "whoami" command outputs your user name - the file /etc/resolv.conf contains a line with the domain name - "cut -f 2" will extract the 2nd tab-delimited field of its input - command substitution (Ch.10) will let you capture command output Advanced Bonus: Some versions of /etc/resolv.conf have a "search" line instead of a "domain" line. Modify the script to find *either* line ("search" or "domain") and extract the second field (the domain name). (Hint: Look up the "-e" option. What if you used two "-e" options?) Double Advanced Bonus: Some versions of /etc/resolv.conf contain *both* a "search" *and* a "domain" line. Modify the script to work even if both lines are present. (Hint: You only want the first line you find, not both lines. What command will do that for you?) 15) Write this executable script named "95_PATH_lister.sh": Display all the directories in your PATH variable, one per line, line numbered. Hints: - translate colons into newlines see the example "tr" commands in week4.txt notes - "man cat" on Linux or AIX 16) Write this executable script named "96_script_history.sh": Look for and display lines containing the current name of this shell script being run that are contained in the file ".bash_history" in the HOME directory of the user running the script. The script must work no matter what the name of the shell script is. (Do not hard-code the name into the script! Use the correct shell positional parameter variable.) The HOME directory must be the HOME directory of the user running the script. If you test this on ACADAIX, the default shell is the Korn shell and it uses a file named ".sh_history" instead. You can link that file name to the name ".bash_history" for testing. (Or, you can simply type "bash" and bash will create its own history file for you to examine.) Hints: - one of the keyword variables (Ch.10) may be useful - one of the positional parameter variables (Ch.10) will be needed 17) Write this executable script named "97_backwards_args.sh": Display the number of arguments found on the command line. Next, display three of the arguments from the command line, one per line, in reverse order (last to first). The script doesn't need to detect or handle more or less than three arguments. Assume that the users of the script will always type exactly three and don't worry about errors that might occur if they do not. Warning: Make sure that shell glob characters do not expand when you display the arguments!! 18) Write this executable script named "98_sort_diff.sh": Display on the screen the strings that are the first and second command line arguments to the script. Take the first argument as a file name and sort it into a temporary file. Take the second argument as a file name and sort it into a different temporary file. Use the "diff" command to show the differences (if any) between the two sorted files. Remove the temporary files. (Put the temporary files under the /tmp directory.) The script should exit with the same return code as the "diff" command, whatever that is. The script doesn't need to detect or handle more or less than two command line arguments. Assume that the users of the script will always type exactly two and don't worry about errors that might occur if they do not. Don't worry about errors that might occur because of invalid, unreadable, or missing file names. (You'll learn how to do that in Chapter 11.) Warning: Make sure that shell glob characters do not expand when you process the arguments!! 19) Write this executable script named "99_pid_finder.sh": Look for the process ID number of the currently running script in the output of the "ps" command with the "f" option. Display the matching lines along with line numbers. Hints: - "man cat" on Linux or AIX Bonus: Find a way to display the first title/header line of "ps" before you display the matching lines. (Hint: - you might want to run "ps" twice in the same script.) 19) Write this executable script named "99_who_from.sh": Extract all the "From:" header lines from your mailbox and display them with line numbers. Hints: - "man cat" on Linux or AIX =================== Command syntax used =================== You probably need to use most of the variables, syntax, and commands listed below to write the above scripts; though, your scripts won't necessarily use them in the way that they are shown in the list below: $input & cat "$HOME/.bash_history" cat "$HOME/.rhosts" cat -b cat -n cat /etc/resolv.conf cat /tmp/temp1$$ /tmp/temp2$$ cut -f 2 echo "$#" "$$" "$?" echo "$(command one | command two | command three)" echo "$(grep 'pattern' file)" echo "$(hostname)" echo "$(whoami)" echo "$0" "$1" "$2" "$3" echo "$HOME" "$MAIL" "$PATH" "$SHELL" echo */. echo 1>&2 "something" exit "$status" finger @ip.ad.dr.ess grep -e "$input" grep -e 'pattern1' -e 'pattern2' grep -v head -1 ls /usr/sbin ping -c ps -ef read var1 var2 sort status="$?" tail -n +2 tr ' ' '\n' tr ':' '\n' tr 'a-z' 'A-Z' whereis ping