------------------------ Week 7 Notes for DAT2330 ------------------------ -Ian! D. Allen - idallen@idallen.ca Remember - knowing how to find out an answer is more important than memorizing the answer. Learn to fish! RTFM! (Read The Fine Manual) ------ Review ------ In Week 6 (week06notes.txt): You used the gzip and bzip2 commands to compress/uncompress files. You understand the difference between a compressed and uncompressed tar file. You understand Unix file and directory permissions. You know what "r" and "x" permissions mean for a directory. You can express permissions in octal form (e.g. 077, 022, etc.). In lab, you decoded a tar-format archive and assembled a JPEG image. You know the difference between a .bash_profile and .bashrc file. You can understand and write the Syntax section of a Unix man page. You know how to put a command pipeline in the background and do job control. ------------------ This Week (Week 7) ------------------ You had your midterm test sheets returned to you and your questions answered about the midterm test. You were reminded about the Announcements and Discussion news groups, where questions are answered regarding course material. * A Few Questions: - Does the command name used on a command line affect the number of arguments passed by the shell? Answer: NO - Does the presence of redirection on a command line affect the number of arguments passed by the shell? Answer: NO * Unix Password File Format - Running Linux: "The passwd file" p.141 - look in section 5 of the manual for file formats: $ man passwd <= man page for passwd command (manual section 1) $ man 5 passwd <= specify manual section 5 (file formats) - each line in the password file contains seven fields, separated by colons - to extract a field from passwd, specify colon as a delimiter to cut or awk: $ cut -d: -f1 /etc/passwd $ awk -F: '{print $1}' /etc/passwd * Unix Processes - each process has its own current directory, PATH, and umask - changing any of these in a process will not affect other processes; however, these values are passed on to new child processes at the time the child processes are created (which can cause problems) * Shell Script header - because PATH and umask are inherited by child processes, a bad PATH or bad umask can cause a shell script to fail - bad PATH will cause commands in a shell script to not be found - bad umask (e.g. umask 777) will cause script to create unreadable files - therefore: all shell scripts need to set PATH and umask at the start: #!/bin/sh -u # set standard search path and friendly umask PATH=/bin:/usr/bin ; export PATH umask 022 date >out wc out rm out Review: shell_script_execution.txt - How a Shell Script is "Executed" All shell scripts must (1) have a #! line, (2) set PATH, (3) set umask Note! umask is a command, not a variable! PATH is a variable. * Shell Variables - use variables to hold constants (like you use #define in C) - use a variable to hold a temporary file name: tmp="/tmp/$USER.$$" - reduce maintenance: how many edits needed to change a constant? - export variables if you want them to be passed on to child processes PATH=/bin:/usr/bin ; export PATH Read notes: shell_variables.txt - Shell Variables you should know (including $* and $@) $TERM $HOME $PATH $SHELL $USER $$ $# $0 $1 $2 ... $? $* $@ DOUBLE QUOTE ALL VARIABLES to protect contents from unwanted shell GLOBbing. Double quotes permit the shell to expand the variables; but, they stop GLOB meta-characters from being expanded. Quoted strings are always one single argument, except for "$@" special case. Special case "$@" (double quoted) expands to be multiple double-quoted args. * Shell order of processing - shell does expansions in a strict order: 1) expand aliases (we don't cover aliases in DAT2330) 2) locate and remove redirection from command line 3) expand variables once 4) expand GLOB patterns (wildcards) once dollar signs inside variables don't expand a second time: $ x=x ; y='$x' ; echo $y $x GLOB characters inside GLOB expansion don't expand a second time: $ touch 'a * *' b c ; echo a* a * * GLOB characters inside variables **DO** expand (unless double-quoted): $ x='*' ; echo $x *** Double-quote all your variables! *** *** Double-quote all your variables!! *** *** Double-quote all your variables!!! *** $ touch a b c d $ msg="*** happy birthday ***" $ echo $msg <== missing quotes! a b c d happy birthday a b c d <== WRONG! WRONG! WRONG! $ echo "$msg" <== correct use of quotes *** happy birthday *** <== correct output * Command Substitution - Command Substitution is similar to variable substitution; but, it is the output of the given Unix command that is substituted - syntax: $( any Unix command goes between parentheses ) - *all* the standard output of the command(s) between parentheses is captured - typical use is to assign command output to a shell variable: $ users=$( who | wc -l ) $ echo "Number of users logged in: $users" $ words=$( wc -w &2 "$0: This appears on standard error" - you can interpret the syntax 1>&2 as meaning: "take unit 1 (stdout) and send it to the same place as unit 2 (stderr)" - echo 1>&2 will make standard output of echo appear on standard error - only use 1>&2 for *error messages* ! - don't redirect *all* echo output to stderr - ordinary script output should still appear on stdout (don't use 1>&2) * Getting input into shell scripts Read notes: shell_read.txt - Reading stdin into shell variables * Shell Script structure (9 parts) Read notes: script_style.txt Shell Script Programming Conventions and Style script_checklist.txt Shell Script Checklist - a list of things to verify * Using write and mesg - inter-terminal communication - "write" reads stdin and writes it onto the tty of another user - this is one-way communication; to have a two-way conversation, each person must "write" to the other - "mesg" turns on/off permission for people to write on your tty $ echo hello | write alleni99 $ write alleni99 hello ^D New commands: write mesg