CIS 191: Linux and Unix Class 3 September 23rd, 2015.

download CIS 191: Linux and Unix Class 3 September 23rd, 2015.

If you can't read please download the document

description

Outline Review of Last Week Branching Constructs Loop Constructs More Shell Scripting Constructs

Transcript of CIS 191: Linux and Unix Class 3 September 23rd, 2015.

CIS 191: Linux and Unix Class 3 September 23rd, 2015 Just for fun Try typing yes I like fan noise (and kill it unless you really like fan noise) Also try telnet towel.blinkenlights.nl (and kill it when class starts by first pressing ctrl-] and then type quit) Outline Review of Last Week Branching Constructs Loop Constructs More Shell Scripting Constructs Change Permissions Syntax: absolute: chmod 777 file relative: chmod o-r file 777 -> > rwx | rwx | rwx 724 -> ? 724 -> > rwx | _w_ |r_ _ Directory permissions: r: list contents w: add/append files x: enter directory Shell Constructs in Brief | - Pipes, 2> - Redirections $( ), ` ` - Command Substitution ;, &&, || - Command Lists & - Run in background Variables var=str assigns the text str to the variable var $var is replaced with the text stored in var echo $var prints the text in var Variables that have not been set are replaced with the empty string Kind of like the null value in Java So, echo $notset will print a blank line From last class: $ question=whoami $ $($question) Note on notation From this point forward, single line shell interactions will still be preceded by a $, as before. Input to the shell and resulting output will be on consecutive lines Longer pieces of shell scripting will be written in consolas, but not preceded by a $. Output will be displayed separately Filename Completion Recall Wildcards * will match any string of text (except for hidden files) ? will match any single character (again, except hidden files) Some new stuff [chars] matches any character enclosed [a-z] matches the range of characters from a to z {list} is expanded to a space-delimited term once for each item in the list Recall the scp command from homework 1 So, twenty-{one,two,three,four} is expanded to twenty-one twenty-two twenty-three twenty-four Expansions Save Keystrokes A simple way to list all files for i in *; do echo $i is a file done From now on, expect to see this * notation instead of $(ls). So, to copy all CIS191 lecture notes to their own directory, just do $ mkdir CIS191 && cp cis191* CIS191 Quiz Outline Review of Last Week Branching Constructs Loop Constructs More Shell Scripting Constructs The If Statement Syntax if command then commands elif command then commands else commands fi xkcd.com/17 An If and test example! if [ $SHELL = /bin/bash ] then echo You are using bash else echo Your shell is not /bin/bash fi test A simple test binary which is often found with if. Built in comparison logics; exit with 0 if true, 1 if false Often, well see test run via its alias, the [ ] operator This is usually a shell command, not a program (fyi) Note that all the following commands can be run by typing [ my arguments ] or test my arguments Its really just a matter of style Id recommend using the square braces in an if statement for syntactic sugar A couple more test notes When you use bracket syntax, you have to write the notation exactly as we showed it here! [-e file] IS NOT THE SAME as [ -e file ] You must have the space separating the brackets and other text! Also, to reiterate, the brackets are just an alias for the test command. To test for file existence, you could also type test e file If and Test example hours=$(date +%H) if [ $hours lt 12 ] then echo It is before noon. fi Test Conditions (Strings) [ $str1 = $str2 ] => success if str1 is equal to str2 [ $str1 != $str2 ] => success if str1 is not equal to str2 [ -z $str ] => success if the string empty (null) [ -n $str ] => success if the string is nonempty (not null) compare strings in alphabetical order, but need to be escaped: [ $str1 \ success if str1 is less than str2 (alpha) [ $str2 \> $str2 ] => success if str1 is greater than str2 Test Conditions (numbers) The following convert the strings m and n to numbers before doing tests on them [ $m eq $n ] => success if m is equal to n [ $m ne $n ] => success if m is not equal to n [ $m lt $n ] => success if m is less than n [ $m le $n ] => success if m is less than or equal to n [ $m gt $n ] => success if m is greater than n [ $m ge $n ] => success if m is greater than or equal to n Or use success if filename names a file for which the current user has read permissions [ -o filename ] => success if filename names a file which the current user owns There are other options as well Checking write/execute permissions, filetype, etc See test(1) man page for more details man test How do we define true and false? In bash, true is a success code And false is an error code A success code is always 0 And anything else is an error Some standard exit codes 0 normal (true) 1 catchall for any general error 2 wrong usage 126 file is not executable 127 file not found 128 program killed by ^C An example of using error codes Good for reporting errors if rm file; then echo Removal worked. else echo Removal failed. fi If diff edition #!/bin/sh #Say $1 is the username if diff $1/homework reference-answer; then response=Incorrect answer! else response=Correct answer! fi echo $response >> $1/grade.txt If: grep edition Our old friend grep returns success or failure too #!/bin/sh # Assume $1 is the username if grep pants myfile.txt; then echo Your file contains pants! else echo Clothe your file please. fi We can inline these statements with ; Equivalently (and this holds similarly for for loops and other like constructs) $ if [ $SHELL = /bin/bash ]; then echo You are using bash; else echo Your shell is not /bin/bash; fi This is bad form when writing your scripts to save and distribute or execute later or submit for a homework assignment! But it can be useful when writing a one liner in the command line (and you are not intending to save it) Outline Review of Last Week Branching Constructs Loop Constructs More Shell Scripting Constructs For: A foreach construct Use for loops to repeat an iteration over a set of values The general form is as follows: for i in list do commands done i is set to each of the items in list, in turn commands is a list of commands to execute For: example for i in yellow red blue do echo $i fish done The results are yellow fish red fish blue fish For example for i in optimus; do echo $i: prime done Internal Field Separator (IFS) This is how the shell knows how to split a string of text into a list which can be iterated through Make sure not to change this globally Why might this be a bad idea? Change IFS locally only Good for iterating through a comma-separated line, or a line separated by semicolons (etc) Save old value of IFS $ OLDIFS=$IFS $ IFS=, $ IFS=$OLDIFS Useful: Debug Mode You can run any script with $ bash x script.sh to enter debug mode This will show each command being run (after substitutions and aliases, and in a loop iteration If, For, and Test: Better Together!! What does this do? for i in $(ls) do if [ -d $i ] echo $i is a directory fi done If, For, and Test: Better Together!! What does this do? for i in $(ls) do if [ -d $i ] echo $i is a directory fi done It lists directories, but not other types of files (and adds some flavor text to boot) While Another way to Loop! The while loop repeats an action while a condition is true Sound familiar? while condition do commands done Until do until a condition is satisfied The until loop repeats an action until a condition is satisfied until condition do commands done Wait until a minute is finished while [ $(date +%S) != 00 ]; do sleep 1 done echo A new minute just started. or, equivalently until [ $(date +%S) == 00 ]; do sleep 1 done echo A new minute just started. read User input This command allows you to get user input for your scripts $ read x hey there $ echo $x hey there $ read x y hey there $ echo $x and $y hey and there While + read You can use the read function in conjunction with a while loop for short hand (read returns a status code) read returns success if it gets input, and gives an error code if it receives an EOF (^D) on a blank line. while read x do echo You input ${x}. done So, to exit a while read loop We have a couple of options We can kill the program ^C, ^\ We can give read a zero-length string ^D (EOF) on an empty line Why wont just pressing enter work? We can break out of the loop programmatically on some input break and continue Basically the exact same functionality as in standard curly brace languages (c, java) break If this command is encountered, then the script will exit the innermost loop continue If this command is encountered, then the loop will stop execution of the loop body and skip to the next iteration of the loop In example while read x; do if [ $x == 'quit' ]; then break elif [ $x == 'skip' ]; then continue fi echo You entered ${x}. done Redirection and while read loops Consider the following while read line; do echo $line done < myfile.txt Leveraging reads break on newline Since read breaks on the newline, we can pipe the contents of any file we like into the while-read loops standard input This provides a very convenient way to loop through the lines in a file Outline Review of Last Week Branching Constructs Loop Constructs More Shell Scripting Constructs Arithmetic in Bash As we discussed, the shell primarily operates on strings But if youve ever programmed anything ever, then you know that sometimes arithmetic is necessary In bash, arithmetic is placed inside $(( )). For example $ echo The UID after yours is $(($UID + 1)) $ echo Six times nine is $((6 * 9)) Arithmetic Example Suppose you wanted to count the subdirectories using bash arithmetic count=0 for i in *; do if [ -d $i ]; then count=$(($count + 1)) fi done echo There are $count subdirectories. Bash and floating point arithmetic Bash doesnt do floating point arithmetic Just does typical integer truncation if an expression would evaluate to a decimal point Curly Braces for Dereferencing variables $ foo=herp $ echo ${foo} herp Considered to be good practice in all cases Didnt go into this last class for clarity Also useful to expand variables when we want to append text to them without any whitespace $ echo ${foo}derp herpderp Bash arrays Its possible to define arrays in bash, too! Though they are more like maps or dictionaries than arrays $ myarr[1]=first $ myarr[2]=second $ myarr[me]=ohmy Dereferencing arrays requires { } Unlike other variables, dereferencing an array requires the use of curly braces! $ echo ${myarr[1]} first $ echo ${myarr[1]}not${myarr[2]} firstnotsecond $ echo me${myarr[me]} meohmy $ echo $myarr[me] ohmy[me] (what?? remember to use curly braces!) Arrays are not backwards compatible! Its important to note that POSIX compliant scripts should not make use of the array notation! Older interpreters such as sh and dash do not support arrays or the array syntax In general, if you are using arrays, you should consider writing the script in another language Including them for completion more than as advice Script Arguments Your scripts can accept CLI arguments too! $1 is the first parameter to a script $2 is the second parameter to a script and so on and so on $0 is the name of the script (the filename) is the list of arguments (as a bash array) $* is also the list of arguments (as a space delimited string) $# is the number of arguments passed to the script shift operator for arguments Calling shift in a bash script will pop the first argument off the argument list, making $1=$2, $2=$3, and so on Another way to iterate through all input arguments! while [ $1 ]; do stuff shift done Shell Functions You can place code that needs to be repeated in a function (just like in other programming languages) Shell functions can be though of like sub-scripts If you define a function in the current shell environment, then the shell will tab complete the function for you! name () { commands } Shell Functions Can also be written in one line (like anything else in bash) $ name() { commands; } Arguments to functions are retrieved the same way they are to scripts So, $1 is the first argument, $# is the number of arguments What does this do? $ :() {: | :&}; : Kaboom! $ () {: | :&}; : Well, : is a valid name in bash so its basically just a function name. Lets try replacing it with bomb. $ bomb() {bomb | bomb&}; bomb Does this make things any clearer? Breakdown This statement defines a function, :, which runs itself in the background twice Then we call that function This is the canonical bash fork bomb Dont run this on Eniac. Theyll know it was you. Dont run it on your own computer either. Youll need to restart it (or the virtual machine).