This document provides an introduction to scripting in Unix/Linux systems. It discusses how to begin writing shell scripts using Bash, including specifying the shell interpreter and making scripts executable. It also covers using commands, arguments, and variables in scripts to perform tasks and pass information. Loops and functions allow creating more complex scripts to automate repetitive tasks.
This document provides an introduction to scripting in Unix/Linux systems. It discusses how to begin writing shell scripts using Bash, including specifying the shell interpreter and making scripts executable. It also covers using commands, arguments, and variables in scripts to perform tasks and pass information. Loops and functions allow creating more complex scripts to automate repetitive tasks.
This document provides an introduction to scripting in Unix/Linux systems. It discusses how to begin writing shell scripts using Bash, including specifying the shell interpreter and making scripts executable. It also covers using commands, arguments, and variables in scripts to perform tasks and pass information. Loops and functions allow creating more complex scripts to automate repetitive tasks.
This document provides an introduction to scripting in Unix/Linux systems. It discusses how to begin writing shell scripts using Bash, including specifying the shell interpreter and making scripts executable. It also covers using commands, arguments, and variables in scripts to perform tasks and pass information. Loops and functions allow creating more complex scripts to automate repetitive tasks.
Download as PPTX, PDF, TXT or read online from Scribd
Download as pptx, pdf, or txt
You are on page 1of 52
3.
Scripting
CS362 Unix System Administration
CS362 - Unix System Administration
Outline § Introduction § Beginning a shell script § Using commands § Using arguments § Using variables § Using conditional expressions § Using loops § Using functions § Setting the script’s exit value Introduction • A script is a program written in an interpreted language, typically associated with a shell or a compiled program. • In Linux, many scripts are shell scripts, which are associated with Bash or another shell. (If you’re familiar with batch files in Windows, scripts serve a similar purpose.) • You can write shell scripts to help automate tedious, repetitive tasks or to perform new and complex tasks. • Scripts perform many of Linux’s startup functions, so mastering scripting will help you manage the startup process. • This session covers Bash shell scripts, beginning with the task of creating a new script file. We then describe several important scripting features that help you to perform progressively more complex scripting tasks. Beginning a shell script • Shell scripts are plain-text files, so you create them in text editors such as vi, nano, or pico. • A shell script begins with a line that identifies the shell that’s used to run it, such as the following: #!/bin/bash • The first two characters are a special code that tells the Linux kernel that this is a script and to use the rest of the line as a pathname to the program that’s to interpret the script. • This line is sometimes called the shebang, hashbang, hashpling, or pound bang line. • Shell scripting languages use a hash mark (#) as a comment character, so the script utility ignores this line, although the kernel doesn’t. • On most systems, /bin/sh a symbolic link that points to /bin/ bash, but it can point to another shell. • Specifying the script as using /bin/sh guarantees that any Linux system will have a shell program to run the script. • However, if the script uses any features specific to a particular shell, you should specify that shell instead—for instance, use /bin/bash or /bin/tcsh instead of /bin/sh. • This session describes Bash shell scripts. Simple Bash scripts can run in other shells, but more-complex scripts are more likely to be shell-specific. • When you’re done writing the shell script, you should modify it so that it’s executable. • You do this with the chmod command • Use the a+x option to add execute permissions for all users. • For instance, to make a file called my-script executable, you should issue the following command: chmod a+x my-script • You’ll then be able to execute the script by typing its name, possibly preceded by ./ to tell Linux to run the script in the current directory rather than searching the current path. • If you fail to make the script executable, you can still run the script by running the shell program followed by the script name (as in bash my-script), but it’s generally better to make the script executable. • If the script is one you run regularly, you may want to move it to a location on your path, such as /usr/local/bin. • When you do that, you won’t have to type the complete path or move to the script’s directory to execute it; you can just type my-script. The first bash program • First create the script using nano: nano helloworld • Type the following inside it: #!/bin/bash echo “Hello World” • The first line tells Linux to use the bash interpreter to run this script. The second line tells Linux to print the string. • Save the file and exit nano • Then, make the script executable: sudo chmod a+x helloworld • Execute the script ./helloworld Using Commands • One of the most basic features of shell scripts is the ability to run commands. • You can use both commands that are built into the shell and external commands —that is, you can run other programs as commands. • Most of the commands that you type in a shell prompt are external commands; they’re programs located in /bin, /usr/bin, and other directories on your path. • You can run such programs, as well as internal commands, by including their names in the script. You can also specify parameters to such programs in a script. • For instance, suppose that you want a script that launches two gnome-terminal windows and the Firefox web browser program. • The following script accomplishes this goal: #!/bin/bash /usr/bin/gnome-terminal& /usr/bin/gnome-terminal& /usr/bin/firefox& • Aside from the first line that identifies it as a script, the script looks just like the commands that you might type to accomplish the task manually, except for one fact: the script lists the complete paths to each program. • If a script produces a No such file or directory error for a command, typing which command, where command is the offending command, should help you locate it. • Each program-launch line in script ends in an ampersand (&). This character tells the shell to go on to the next line without waiting for the first to finish. • If you omit the ampersands in the script, the first gnome-terminal will open but the second won’t open until the first is closed. Likewise, firefox won’t start until the second gnome-terminal terminates. • Although launching several programs from one script can save time in startup scripts and some other situations, scripts are also frequently used to run a series of programs that manipulate data in some way. • Such scripts typically do not include the ampersands at the ends of the commands because one command must run after another or may even rely on output from the first. • Normal File-Manipulation Commands • The file manipulation commands, such as ls, mv, cp, and rm, are often used in scripts. • You can use these commands to help automate repetitive file maintenance tasks. • grep: it locates files that contain the string you specify, or displays the lines that contain those strings in a single file. • find: searches for patterns based on filenames, ownership, and similar characteristics. • cut: this command extracts text from fields in a file. • sed: provides many of the capabilities of a conventional text editor • echo: provide a message to the user • mail: used to send email from within a script Exercises • Write a shell script that displays the date and who’s logged on • Write a shell script that lists the files in /var/log Using Arguments • Variables can help you expand the utility of scripts. • A variable is a placeholder in a script for a value that will be determined when the script runs. • Variables’ values can be passed as parameters to a script, generated internally to a script, or extracted from a script’s environment. • An environment is a set of variables that any program can access. The environment includes things like the current directory and the search path for running programs. • Variables that are passed to the script are frequently called parameters or arguments. • They’re represented in the script by a dollar sign ($) followed by a number from 0 • up—$0 stands for the name of the script, $1 is the first parameter to the script, $2 is the second parameter, and so on. • For instance, let’s say you had a shell script named myscript that contained the following: #!/bin/bash # Script to echo out command-line arguments echo "The title of the script is $0.” echo "The first argument is $1, the second is $2." • The following shows what would happen if you ran that command with foo and bar as arguments: ./myscript foo bar The title of the sript is myscript. The first argument is foo, the second is bar. Using Variables • Just running individual commands from the shell script is useful, but this has its limitations. Often, you’ll want to incorporate other data in your shell commands to process information. • You can do this by using variables. Variables allow you to temporarily store information within the shell script for use with other commands in the script. • Environment Variables: track specific system information, such as the name of the system, the name of the user logged in to the system, the user’s system ID (called UID), the default home directory of the user, and the search path used by the shell to find programs. • User variables: script allows you to set and use your own variables within the script. Setting variables allows you to temporarily store data and use it throughout the script, making the shell script more like a real computer program. • User variables can be any text string of up to 20 letters, digits, or an underscore character. • User variables are case sensitive, so the variable Var1 is different from the variable var1. This little rule often gets novice script programmers in trouble. • Values are assigned to user variables using an equal sign. • Just like system variables, user variables can be referenced using the dollar sign($). • No spaces can appear between the variable, the equal sign, and the value. Here are a few examples of assigning values to user variables: var1=10 var2=-57 var3=testing var4=”still more testing” • The shell programming language does not type-cast its variables. This means that a variable can hold number data or character data. count=0 count=Sunday • When assigning character data containing spaces or special characters, the data must be enclosed in either single or double quotes. • Using double quotes to show a string of characters will allow any variables in the quotes to be resolved. var=“test string” newvar=“Value of var is $var” echo $newvar • Output: Value of var is test string • Using single quotes to show a string of characters will not allow variable resolution var=’test string’ newvar=’Value of var is $var’ echo $newvar • • Output: Value of var is $var • One of the most useful features of shell scripts is the ability to extract information from the output of a command and assign it to a variable. • After you assign the output to a variable, you can use that value anywhere in your script. • This comes in handy when processing data in your scripts. • The backtick character (`) • The $() format • Be careful with the backtick character; it is not the normal single quotation mark character you are used to using for strings. It appear on the same key as the tilde (∼) on most keyboards. • Command substitution allows you to assign the output of a shell command to a variable. • You must either surround the entire command line command with two backtick characters or use the $() format: testing=`date` testing=$(date) • The shell runs the command within the command substitution characters and assigns the output to the variable testing. • Notice that there are no spaces between the assignment equal sign and the command substitution character. • Here’s an example of creating a variable using the output from a normal shell command: #!/bin/bash testing=$(date) echo “The date and time are: ” $testing • Let us consider another example which checks to see if the computer’s router is up with the help of the ping utility. This script uses two variables. • The first is $ip, which is extracted from the output of route using the grep, tr, and cut commands. The second variable, $ping, simply points to the ping program. • Create the following script with the name routercheck #!/bin/bash ip=`route -n | grep UG | tr -s " " | cut -f 2 -d " "` ping="/usr/bin/ping" echo "Checking to see if $ip is up..." $ping -c 5 $ip • The result should be the message Checking to see if the computer’s default gateway system is up and the output from the ping command, which should attempt to send five packets to the router. • If the router is up and configured to respond to pings, you’ll see five return packets and summary information. • In addition to assigning variables with the assignment operator (=), you can read variables from standard input by using read. • The read command accepts input either from standard input (such as from the keyboard) or from another file descriptor. After receiving the input, the read command places the data into a variable. • Here’s the read command at its simplest: #!/bin/bash # testing the read command echo -n "Enter your name: " read name echo "Hello $name, welcome to Unix Administration Class" Exercise 1. Copy the /usr/bin directory listing to a log file and capture the current date and use it to create a unique filename. 2. Write a shell script that displays user name, home directory, shell, and path of the current logged in user. Exercise • Copy the /usr/bin directory listing to a log file and capture the current date and use it to create a unique filename. #!/bin/bash # copy the /usr/bin directory listing to a log file today=$(date +%y%m%d) ls –l /usr/bin > log.$today • The today variable is assigned the output of a formatted date command. This is a common technique used to extract date information for log filenames. The +%y %m%d format instructs the date command to display the date as a two-digit year, month, and day: Using Conditional Expressions • Scripting languages support several types of conditional expressions. • These enable a script to perform one of several actions contingent on a particular condition—typically the value of a variable. • One common command that uses conditional expressions is if, which allows the system to take one of two actions depending on whether a certain condition is true. • The if keyword’s conditional expression appears in brackets after the if keyword and can take many forms. • Conditionals may be combined together with the logical and (&&) or logical or (||) operators. • When conditionals are combined with &&, both sides of the operator must be true for the condition as a whole to be true. • When || is used, if either side of the operator is true, the condition as a whole is true. • Syntax: if [ command/expression ]; then command/statements elif [ command/expression ]; then command/statements else command/statements fi • The elif (else if) and else sections are optional • Put spaces after [ and before ], and around the operators and operands. • fi (if backward) marks the end of the if block • The bash shell if statement runs the command/expression defined on the if line. • If the exit status of the command is zero (the command completed successfully) or the expression is true, the commands listed under the then section are executed. • If the exit status of the command is non-zero or the expression is false, then commands aren’t executed, and the bash shell moves on to the next command in the script. • An expression can be: String comparison, Numeric comparison, File operators and Logical operators and it is represented by [expression]: • String Comparisons: = compare if two strings are equal != compare if two strings are not equal -n evaluate if string length is greater than zero -z evaluate if string length is equal to zero • Examples: [ s1 = s2 ] (true if s1 same as s2, else false) [ s1 != s2 ] (true if s1 not same as s2, else false) [ s1 ] (true if s1 is not empty, else false) [ -n s1 ] (true if s1 has a length greater than 0, else false) [ -z s2 ] (true if s2 has a length of 0, otherwise false) • Number Comparisons: -eq compare if two numbers are equal -ge compare if one number is greater than or equal to a number -le compare if one number is less than or equal to a number -ne compare if two numbers are not equal -gt compare if one number is greater than another number -lt compare if one number is less than another number • Examples: [ n1 -eq n2 ] (true if n1 same as n2, else false) [ n1 -ge n2 ] (true if n1 greater then or equal to n2, else false) [ n1 -le n2 ] (true if n1 less then or equal to n2, else false) [ n1 -ne n2 ] (true if n1 is not same as n2, else false) [ n1 -gt n2 ] (true if n1 greater than n2, else false) [ n1 -lt n2 ] (true if n1 less then n2, else false) • File Operators: -d check if path given is a directory -f check if path given is a file -e check if file name exists -r check if read permission is set for file or directory -s check if a file has a length greater than 0 -w check if write permission is set for a file or directory -x check if execute permission is set for a file or directory • Examples: [ -d fname ] (true if fname is a directory, otherwise false) [ -f fname ] (true if fname is a file, otherwise false) [ -e fname ] (true if fname exists, otherwise false) [ -s fname ] (true if fname length is greater then 0, else false) [ -r fname ] (true if fname has the read permission, else false) [ -w fname ] (true if fname has the write permission, else false) [ -x fname ] (true if fname has the execute permission, else false) • Logical Operators: ! negate (NOT) a logical expression -a logically AND two logical expressions -o logically OR two logical expressions && logically AND two logical expressions || logically OR two logical expressions • Compound Testing: [ condition1 ] && [ condition2 ] [ condition1 ] || [ condition2 ] • Examples: #!/bin/bash echo -n "Enter a number 1 < x < 10: " read num if [ “$num” -gt 1 ] && [ “$num” -lt 10 ]; then echo “$num*$num=$(($num*$num))” else echo “Wrong insertion !” fi Exercise • Write a shell script which: • accepts a file name • checks if file exists • if file exists, copy the file to the same name + .bak + the current date (if the backup file already exists ask if the user want to replace it). • When done you should have the original file and one with a .bak at the end. • Write a shell script that accepts mark out of 100 from the user, calculates letter grade based on the given scale and displays the grade to the user; [90 - 100] A [80 - 89] B+ [70 - 79] B [60 - 69] C+ [50 - 59] C [40 - 49] D [0 - 39] F Using Conditional Expressions • What do you do if more than two outcomes are possible—for instance, if a user may provide any one of four possible inputs? You can nest several if/then/else clauses, but this gets awkward quickly. • A cleaner approach is to use case: case word in pattern1) command(s);; pattern2) command(s);; ... esac • For a case statement, a word is likely to be a variable, and each pattern is a possible value of that variable. • The patterns can be expanded much like filenames, using the same wildcards and expansion rules (* to stand for any string, for instance). You can match an arbitrary number of patterns in this way. • Each set of commands must end with a double semicolon (;;), and the case statement as a whole ends in the string esac (case backward). • Upon execution, bash executes the commands associated with the first pattern to match the word. • Execution then jumps to the line following the esac statement; any intervening commands don’t execute. • If no patterns match the word, no code within the case statement executes. • If you want to have a default condition, use * as the final pattern; this pattern matches any word, so its commands will execute if no other pattern matches. • case statement example #!/bin/bash echo -n “Enter a number 1 < x < 5: ” read x case $x in 1) echo “Value of x is 1.”;; 2) echo “Value of x is 2.”;; 3) echo “Value of x is 3.”;; 4) echo “Value of x is 4.”;; 0 | 5) echo “wrong number.”;; *) echo “Unrecognized value.”;; esac Using Loops • Conditional expressions are sometimes used in loops. • Loops are structures that tell the script to perform the same task repeatedly until a particular condition is met (or until some condition is no longer met). • The for loop is used when you are looping through a range of variables for var in list do commands/statements done • Statements are executed with var set to each value in the list. • For instance, the next example shows a loop that plays all the .wav audio files in a directory. #!/bin/bash for d in `ls *.wav`; do aplay $d done • The for loop as used here executes once for every item in the list generated by ls *.wav. • Each of those items (filenames) is assigned in turn to the $d variable and so is passed to the aplay command. • For instance, the next example shows a loop that all the kefle ketemas in Addis: #!/bin/bash for KK in Arada Gulele Kolefe Bole Yeka do echo “The next region is $KK” done • Each time the for loop iterates through the list of values provided, it assigns the $KK variable the next value in the list. • The $KK variable can be used just like any other script variable within the for command statements. • An alternative form of the for loop is the c-style for loop. • The bash C-style for loop share a common heritage with the C programming language. • It is characterized by a three-parameter loop control expression; consisting of an initializer (EXP1), a loop-test or condition (EXP2), and a counting expression (EXP3). The syntax is as follows: for (( EXP1; EXP2; EXP3 )) do commands/statements done • The following example displays a message 5 times. #!/bin/bash # Display message 5 times for ((i = 0 ; i < 5 ; i++)) do echo "Welcome $i times." done • Another type of loop is the while loop, which executes for as long as its condition is true. The basic form of this loop type is as follows: while [ condition ] do commands/statements done • The until loop is similar in form, but it continues execution for as long as its condition is false—that is, until the condition becomes true. until [ condition ] do commands/statements done • The following example demonstrates while loop #!/bin/bash # while loop test var1=5 while [ $var1 -gt 0 ] do echo "$var1" var1=$[ $var1 - 1 ] done • The following example demonstrates until loop #!/bin/bash # using the until loop var1=100 until [ $var1 -eq 0 ] do echo $var1 var1=$[ $var1 - 25 ] done Using Functions • A function is a part of a script that performs a specific subtask and that can be called by name from other parts of the script. • Placing parentheses after the function name and enclosing the lines that make up the function within curly braces is how functions are defined: myfn() { commands } • The keyword function may optionally precede the function name. function myfn { commands } • In either event, the function is called by name as if it were an ordinary internal or external command. • Functions are useful in helping to create modular scripts. • For instance, if your script needs to perform half a dozen distinct computations, you can place each computation in a function and then call them all in sequence. • The next example demonstrates the use of functions in a simple program that copies a file but aborts with an error message if the target file already exists. • This script accepts a target and a destination filename and must pass those filenames to the functions. #/bin/bash #using functions doit(){ cp $1 $2 } check(){ if [ -e $2 ] then echo "Target file exists! Exiting!" exit fi } check $1 $2 doit $1 $2 • If you enter the example and call it safercp, you can use it like this, assuming that the file original.txt exists and dest.txt does not: ./safercp original.txt dest.txt ./safercp original.txt dest.txt Target file exists! Exiting! • The first run of the script succeeds because dest.txt doesn’t exist. On the second run, though, the destination file does exist, so the script terminates with the error message. • Note that the functions don’t run directly and in the order in which they appear in the script. They run only when called in the main body of the script—which in Lithe script consists of just two lines, each corresponding to one function call, at the very end of the script. Setting the Script’s Exit Value • Ordinarily, a script’s return value is the same as the last command the script called; that is, the script returns $?. • You can control the exit value, however, or exit from the script at any point, by using the exit command. • Used without any options, exit causes immediate termination of the script, with the usual exit value of $?. • This can be useful in error handling or in aborting an ongoing operation for any reason—if the script detects an error or if the user selects an option to terminate, you can call exit to quit. • If you pass a numeric value between 0 and 255 to exit, the script terminates and returns the specified value as the script’s own exit value. • Ordinarily, a script’s return value is the same as the last command the script called; that is, the script returns $?. • You can use this feature to signal errors to other scripts that might call your own script. • You may have to include extra code to keep track of the causes of abnormal termination, though. • For instance, you might set aside a variable (say, $termcause) to hold the cause of the script’s termination. • Set it to 0 at the start of the script and then, if the script detects a problem that will cause termination, reset $termcause to some non-0 value. • You can use any numeric codes you like; (there’s no set meaning for such codes.) • On exit, be sure to pass $termcause to exit: exit $termcause Code Description 0 Successful completion of the command 1 General unknown error 2 Misuse of shell command 126 The command can’t execute 127 Command not found 128 Invalid exit argument 128+x Fatal error with Linux signal x 130 Command terminated with Ctrl+C 255 Exit status out of range