610 likes | 778 Views
ITEC 400 More Perl and Unix/Linux Files. George Vaughan Franklin University. Topics. Perl Comparison and Conditional Operators String Manipulation Functions Subroutines Name Scope Scalar and List Context Subroutines with List and Scalar Context Modules Getopt Module “Here” Document
E N D
ITEC 400More Perl and Unix/Linux Files George Vaughan Franklin University
Topics • Perl • Comparison and Conditional Operators • String Manipulation Functions • Subroutines • Name Scope • Scalar and List Context • Subroutines with List and Scalar Context • Modules • Getopt Module • “Here” Document • Unix/Linux Files
Comparison Operator <=> and cmp • Useful with sort function • Return Value: • Returns -1 if left operand is less than right operand • Returns 0 if operands are equal • Returns 1 if left operand is greater than right operand. • For Numbers: <=> • example: if ( (1 <=> 3) == -1) { print “1 is less than 3\n”; }
Comparison Operator <=> and cmp • For Strings: cmp • example: if ( (“apple” cmp “cherry”) == -1) { print “apple is less than cherry\n”; }
Conditional Operator ?: • Returns different values depending condition. • Format: condition ? result1 : result2 • If condition is true, conditional operator returns result1 else if condition is false, conditional operator returns result2 • Example: $biggest = ($a > $b) ? $a : $b;
String Manipulation Functions • uc(string) : Convert all letters in string to upper case. • lc(string) : Convert all letters in string to lower case. • string =~ s/reg_expr/replacement/ : Replace the first substring that match the regular expression with the replacement substring. • string =~ s/reg_expr/replacement/g : Replace the all substrings that match the regular expression with the replacement substring.
0001 #!/usr/bin/perl 0002 0003 ########### 0004 # File: ex0400 0005 ########### 0006 0007 print "original string: ", 0008 $ARGV[0],"\n"; 0009 0010 print "upper case : ", 0011 uc($ARGV[0]),"\n"; 0012 0013 print "lower case : ", 0014 lc($ARGV[0]),"\n"; 0015 0016 $ARGV[0] =~ s/hot/cold/; 0017 print "substitution 1 : ", 0018 $ARGV[0],"\n"; 0019 0020 $ARGV[0] =~ s/i/I/g; 0021 print "substitution 2 : ", 0022 $ARGV[0],"\n"; Lines 7-8: print original string Lines 10-11: print string converted to uppercase. Lines 13-14: print string converted to lower case. Line 16: substitute the FIRST occurrence of hot to cold. Note that the binding operator “=~” causes the string in ARGV[0] to be modified. Line 20: substitute ALL occurrences of “i” to “I”. Note that the binding operator “=~” causes the string in ARGV[0] to be modified. Example: >ex0400 "It is hot in August" original string: It is hot in August upper case : IT IS HOT IN AUGUST lower case : it is hot in august substitution 1 : It is cold in August substitution 2 : It Is cold In August Example ex0400
Subroutines • Like many other languages, perl allows us define subroutines (similar to methods in Java). • In Perl, a subroutine can have an arbitrary number of arguments. • Arguments are NOT named. Rather, they are contained in an array named “@_” • Therefore, the first argument is in @_[0], the second in @_[1] and so on.
0001 #!/usr/bin/perl 0002 ##### 0003 # File ex0410 0004 #### 0005 0006 $area = areaOfRectangle(3, 4); 0007 print "Area = $area\n"; 0008 0009 sub areaOfRectangle { 0010 return($_[0] * $_[1]); 0011 } Line 6: invoke the function. Lines 9-11: function definition Line 10: calculate area of rectangle using first 2 arguments to function and return area. Example ex0410
Subroutines • In our previous example, we saw how to use function parameters in “@_” : 0009 sub areaOfRectangle { 0010 return($_[0] * $_[1]); 0011 } • If we chose to, we can make our subroutine more readable by setting a list of variables with meaningful names to the values of “@_” (see ex0420): 0009 sub areaOfRectangle { 0010 ($length, $width) = @_; 0011 return($length * $width); 0012 }
0001 #!/usr/bin/perl 0002 ##### 0003 # File ex0420 0004 #### 0005 0006 $area = areaOfRectangle(3, 4); 0007 print "Area = $area\n"; 0008 0009 sub areaOfRectangle { 0010 ($length, $width) = @_; 0011 return($length * $width); 0012 } Line 6: invoke the function. Lines 9-12: function definition Line 10: copy the subroutine parameters to variables with readable names. Line 11: calculate area of rectangle using first 2 arguments to function and return area. example ex0420
Name Scope • In general, variable names have global scope. • A variable defined in the calling function is visible in the called function.
0001 #!/usr/bin/perl 0002 ######### 0003 #File ex0430 0004 ######### 0005 0006 $apple = 4; 0007 mysub(); 0008 print '$apple = ', $apple, "\n"; 0009 0010 sub mysub { 0011 $apple = 5; 0012 } Line 6: set value of $apple to 4. Line 7: invoke “mysub()” Line 11: Change the value of $apple to 5 (the same variable defined on line 6) Line 8: Print value of $apple Example: >ex0430 $apple = 5 Example ex0430
Name Scope • In example ex0430, we saw that changing the value of $apple in the subroutine affected the value of $apple in the calling function - this is because $apple has global scope. • Sometimes a routine may want its variables to have local scope. • This can be achieved by prefixing the key word “my” in front of variable when it is declared or first defined: my $apple = 5;
0001 #!/usr/bin/perl 0002 ########## 0003 # File ex0440 0004 ########## 0005 0006 $apple = 4; 0007 mysub(); 0008 print '$apple = ', $apple, "\n"; 0009 0010 sub mysub { 0011 my $apple = 5; 0012 } Line 6: set value of $apple to 4. Line 7: invoke “mysub()” Line 11: Declare $apple to be local (using “my” keyword). Line 11: Change the value of $apple to 5 ($apple is now local to “mysub”) Line 8: Print value of $apple Example: >ex0440 $apple = 4 Example ex0440
Scalar and List Context • Scalar values: something that has a single value, like singular variable such as $myvar or a literal value such as 13. • List values: something that represents multiple values such as plural variables (like an array or hash) or a literal list such as (2, 9, 4, 170) • In Perl, operators and function can exhibit different behavior depending on whether the operand(s) are scalar or lists.
Scalar and List Context • Perl provides a set of functions to operate on lists: • reverse LIST: reverses elements in list • foreach LIST: loops through elements of list • print LIST: prints a list to standard out • sort LIST: sorts a list of elements • keys HASH_LIST: returns a list of keys from a hash • join (delimiter, LIST): returns a string with a delimiter (like a space, comma or colon or whatever) between each element in the list. • map {sub function} LIST: returns a list by applying the function in {} to each element in the list
0001 #!/usr/bin/perl 0002 ########### 0003 # File ex0450 0004 ########### 0005 0006 #Examples of ASCII sort 0007 @words = (yellow, blue, green, orange); 0008 @sortedWords = sort @words; 0009 print @sortedWords, "\n"; 0010 print join(' ', @sortedWords), "\n"; 0011 print join(', ', @sortedWords), "\n"; 0012 print join(', ', reverse @sortedWords), "\n"; 0013 0014 @upperWords = map {uc} @sortedWords; 0015 print join(', ', @upperWords), "\n"; 0016 0017 #Examples of numerical sort 0018 0019 @numbers = (13, 4, 7, 3); 0020 @sortedNumbers = sort { $a <=> $b } @numbers; 0021 print join(', ', @sortedNumbers), "\n"; Line 8: ASCII sort of words Line 9: print elements of @sortedWords as 1 long string Line 10: print elements of @sortedWords, each element separated by a space. Line 11: print elements of @sortedWords, each element separated by a comma and space. Line 12: print elements of @sortedWords, in REVERSE order, each element separated by a comma and space. Line 14: use map function to convert each character of each element in @upperWords to upper case. Line 20: NUMERICAL sort Example: >ex0450 bluegreenorangeyellow blue green orange yellow blue, green, orange, yellow yellow, orange, green, blue BLUE, GREEN, ORANGE, YELLOW 3, 4, 7, 13 Example ex0450
Subroutines with List and Scalar Context • We saw earlier that there are Perl functions that can return a scalar value if a scalar argument is used and a list value if a list argument is used. • We can design the same capability in our own functions. • In the next example, our function multiplies the argument by 2. • If a scalar argument is used, then a scalar value is returned. • If a list argument is used, then a list value is returned.
0001 #!/usr/bin/perl -w 0002 ############# 0003 # File ex0460 0004 ############ 0005 0006 print "scalar case: ", 0007 times2(4), "\n"; 0008 0009 print "list case: ", 0010 join(', ', times2 (3, 4, 5)), "\n"; 0011 0012 sub times2 { 0013 my @params = @_; 0014 for ($i=0; $i < scalar(@params); ++$i) { 0015 $params[$i] *= 2; 0016 } 0017 return wantarray ? @params : $params[0]; 0018 } Line 7: invoke times2() with a scalar argument. Line 10: invoke times2() with a list argument. Lines 14-16: multiple each element times 2. Line 17: The function “wantarray” is a Perl function to test if return value should be a scalar or list (depending on argument) Line 17: If result is to be a list, return @params, else return the scalar value $params[0] Example ex0460
Perl Modules • Useful Perl code can be packaged into a Module. • A module is a package of reusable subroutines and variables. • A module is imported with the ‘use’ command. • The book provides a description of the standard Perl modules in chapter 32. • There are many useful modules defined at the Comprehensive Perl Archive Network (CPAN) • http://www.cpan.org/
Getopt Module • The Getopt Module facilitates the processing of script options including: • options that take arguments. • options that do not take arguments. • The following statement loads in the Getopt Module: use Getopt::Std;
Getopt Module • The following statement is an example of option definitions: getopts("hvd:f:"); • options h and v do not take arguments • options d and f do take arguments (followed by colons) • Results are returned by variables with names like: $opt_v, $opt_f • value is Boolean if option takes no argument ($opt_v) • value is argument if option does take argument ($opt_f)
Here Document • The “Here” document is a construct that allows multiple lines of input to processed. • Very useful for generating HTML in a CGI script • Useful for outputting multiple lines of text, such as text used to describe the usage of a command. • There are 3 forms, Literal, Shell Expansion and Execution formats.
Here Document Literal format (label in single quotes): print << ‘MY_LABEL’; line 1 line 2 . . . line n MY_LABEL • Lines 1 through n are processed literally, no shell expansion.
Here Document • “Shell Expansion” format (label in double quotes): print << “MY_LABEL”; line 1 line 2 . . . line n MY_LABEL • Lines 1 through n are processed literally, except Shell variables are expanded and text in back quotes are executed.
Here Document • Execution format (label in back quotes): print << `MY_LABEL`; line 1 line 2 . . . line n MY_LABEL • Lines 1 through n are executed.
0001 #!/usr/bin/perl -w 0002 ########### 0003 # File ex0470 0004 ########### 0005 0006 $time=`date`; 0007 0008 print << 'LITERAL_EXAMPLE'; 0009 Literal line 1 0010 Literal line 2 $time 0011 Literal line 3 0012 LITERAL_EXAMPLE 0013 0014 print << "SHELL_EXP_EXAMPLE"; 0015 Expansion line 1 0016 Expansion line 2 $time 0017 Expansion line 3 0018 SHELL_EXP_EXAMPLE 0019 0020 print << `EXECUTION_EXAMPLE`; 0021 date 0022 ls | wc -l 0023 EXECUTION_EXAMPLE Line 6: Save current time in $time Lines 8-12: Literal “Here” document Line 10, notice that $time will not be expanded. Lines 14-18: “Here” document with shell expansion. Line 16: $time will be expanded Lines 20-23: “Here document that is executed. Example: >ex0470 Literal line 1 Literal line 2 $time Literal line 3 Expansion line 1 Expansion line 2 Sun Sep 26 13:19:54 EDT 2004 Expansion line 3 Sun Sep 26 13:19:54 EDT 2004 31 Example ex0470
Putting It All Together • Assume we want to write a script that can be used to evaluate file types. • We will use the Unix ‘file’ command (see manpage) • The file command evaluates the contents of a file and determines its type.
Putting It All Together • Furthermore, assume we want these capabilities: • If the user specifies no options, the script will evaluate the files in the current directory • If the user specifies the –f option with an argument (a filename), then only that file will be evaluated. • If the user specifies a directory with the –d option, then all the files in the specified directory are evaluated. • Furthermore, we should force –f and –d to be mutually exclusive.
0001: #!/usr/bin/perl 0002: 0003: use Getopt::Std; 0004: 0005: sub usage { 0006: print STDERR << "EOF"; 0007: usage: $0 [-h] [-f file] [-d dir] 0008: -h : this (help) message 0009: -d dir : scan directory specified 0010: by dir. If this option is 0011: not used, then the 0012: current directory. 0013: -f file : file to be analyzed. If 0014: this option is not used, 0015: then all files in 0016: directory scanned. 0017: EOF 0018: } 0019: Line 3: import the Getopt module Lines 5-18: Subroutine to print usage statement. Line 6-17: “Here” Document. This is a single print statement Example ex0480
0020: 0021: getopts("hd:f:") or usage() and exit; 0022: 0023: usage() and exit if $opt_h; 0024: 0025: $dir = $opt_d; 0026: $file = $opt_f; 0027: 0028: usage() and exit if ($file && $dir); 0029: 0030: if ($file) { 0031: print `file $file`; 0032: } 0033: elsif ($dir) { 0034: print `file $dir/*`; 0035: } 0036: else { 0037: print `file *`; 0038: } Line 21: Define and collect options. If invalid option specified, generate usage message and exit. Line 23: if use specified help option (-h), generate usage message and exit. Lines 25-26: Map option variables to reader friendly variables. Line 28: If user specified both file and directory option, this is an error – so generate usage message and exit. Lines 30-38: Do the real work… Example ex0480
Example ex0480 • The next several slides illustrate the use of options with ex0480 • Case 1 – no options: $ ex0480 ex0480: a /usr/bin/perl script text executable ex0480.num: ASCII English text. • Case 2 – user specifies file: $ex0480 -f /etc/passwd /etc/passwd: ASCII text
Example ex0480 • Case 3 – User specifies directory: $ ex0480 -d /etc/rc.d /etc/rc.d/init.d: directory /etc/rc.d/rc: Bourne-Again shell script text executable /etc/rc.d/rc0.d: directory /etc/rc.d/rc1.d: directory /etc/rc.d/rc2.d: directory /etc/rc.d/rc3.d: directory /etc/rc.d/rc4.d: directory /etc/rc.d/rc5.d: directory /etc/rc.d/rc6.d: directory /etc/rc.d/rc.local: Bourne shell script text executable /etc/rc.d/rc.sysinit: Bourne-Again shell script text executable
Example ex0480 • Remaining Cases - User either: • specifies help option (-h) • Specifies an illegal option (e.g. –z) • specifies both the directory and file options: usage: ex0480 [-h] [-f file] [-d dir] -h : this (help) message -d dir : scan directory specified by dir. If this option is not used, then the current directory. -f file : file to be analyzed. If this option is not used, then all files in directory scanned.
Process Manager (in Perl) • The next several slides illustrate the use of using Perl for writing a realistic script for System Administration. • Write a PERL script that will: • match process names given a basic regular expression (BRE). • The matched process will be presented to the user. • If more than one process matches the BRE then a numbered list of all matching processes is presented to the user. • The user then either selects a single process to kill or exits without killing the process.
Process Manager (in Perl) • For example, let’s say we want to kill a process that contains “sh”: $ ex0020_4.pl sh P# - USER PID STIME COMMAND 1 - root 9 Jan25 bdflush 2 - root 1795 Jan25 sshd 3 - root 2196 Jan25 ssh-agent 4 - root 2247 Jan25 bash 5 - root 2287 Jan25 sshd 6 - gvaughan 2289 Jan25 sshd 7 - gvaughan 2290 Jan25 bash 8 - root 2330 Jan25 sshd 9 - gvaughan 2332 Jan25 sshd 10 - gvaughan 2333 Jan25 bash 11 - root 2373 Jan25 sshd 12 - gvaughan 2375 Jan25 sshd 13 - gvaughan 2376 Jan25 bash 14 - root 2420 Jan25 sshd 15 - gvaughan 2422 Jan25 sshd 16 - gvaughan 2423 Jan25 bash Enter P# of process to kill or q to quit:
Process Manager (in Perl) • Or, let us assume we want to kill a process owned by “gvaughan”: $ ex0020_4.pl -u gvaughan sh P# - USER PID STIME COMMAND 1 - gvaughan 2289 Jan25 sshd 2 - gvaughan 2290 Jan25 bash 3 - gvaughan 2332 Jan25 sshd 4 - gvaughan 2333 Jan25 bash 5 - gvaughan 2375 Jan25 sshd 6 - gvaughan 2376 Jan25 bash 7 - gvaughan 2422 Jan25 sshd 8 - gvaughan 2423 Jan25 bash Enter P# of process to kill or q to quit:
Process Manager (in Perl) • Or, maybe we want to kill a process owned by gvaughan whose name matches “sleep” with signal KILL: $ ex0020_4.pl -s KILL -u gvaughan sleep P# - USER PID STIME COMMAND 1 - gvaughan 17272 00:25 sleep Enter P# of process to kill or q to quit: 1 kill -KILL 17272 • Or, we want to kill a process owned by gvaughan whose name matches “sleep” and without query: $ ex0020_4.pl -s KILL -u gvaughan -n sleep killing 17277 with signal KILL
Process Manager (in Perl) • What follows is the annotated source • The script is a little long – 88 lines long. Wouldn’t be surprised if a Perl guru could do it with a “one-liner” • Provides a good example of: • Option handling • Pattern matching
0001: #!/usr/bin/perl 0002: 0003: sub usage { 0004: print STDERR << "EOF"; 0005: usage: $0 -h [-n x] [-d y] process_name 0006: -h : this (help) message 0007: -n : disable confirmation 0008: -u user_name : only return those processes owned by user_name 0009: -s signal : send the given signal to the matching processes 0010: process_name : a BRE used to match currently active processes 0011: EOF 0012: } 0013: 0014: use Getopt::Std; 0015: getopts("hnu:s:") or usage() and exit; 0016: 0017: usage() and exit if $opt_h; 0018: 0019: $no_confirmation = $opt_n if $opt_n; Lines 3-12: usage subroutine with “here” document. Line 14: Include Getopts module Line 15: specify and collect options Line 19: Map to readable variable Example ex0490
0020: 0021: $user_name_arg = $opt_u if $opt_u; 0022: 0023: @legal_signals = split(" ", `kill -l`); 0024: $num_of_signals = scalar(@legal_signals); 0025: 0026: if ($opt_s) { 0027: for ($i=0; $i < $num_of_signals; ++$i) { 0028: if ($opt_s eq $legal_signals[$i]) { 0029: $signal = $opt_s; 0030: last; 0031: } 0032: } 0033: } 0034: else { 0035: $signal = "TERM"; 0036: } 0037: 0038: $signal or die "$opt_s is not a legal signal. See man page for kill"; Line 21: Map to readable variable Lines 23-24: Construct list of legal signals from “kill” command. Lines 26-33:If user specified a signal, make sure it is legal. Lines 34-36: If user did not specify a signal, default to TERM Line 38: If specified signal is illegal, terminate. Example ex0490
0039: 0040: $bre = $ARGV[$#ARGV]; 0041: 0042: open (PROCESS_LIST, "ps -e -o ruser,pid,stime,comm |") 0043: or die "cannot execute ps command"; 0044: 0045: if (! $no_confirmation ) { 0046: printf("%4s - %-15s %6s %8s %s\n", "P#", "USER", 0047: "PID", "STIME", "COMMAND"); 0048: } 0049: Line 40: Fetch “Basic Regular Expression” from command line (last value). Line 42-43: Open input pipe from ps command. Lines 45-48: If user did not choose “no_confirmation” then user wants confirmation. So, generate header for process list. Example ex0490
0050: for ($i=1; $line = <PROCESS_LIST>; ) { 0051: if ($line =~ /^ RUSER/) { 0052: next; 0053: } 0054: @fields = split(" ", $line); 0055: $user_name = $fields[0]; 0056: $pid = $fields[1]; 0057: $stime = $fields[2]; 0058: $command = $fields[3]; 0059: #print "command=*$command*, bre=*$bre*\n"; 0060: if (! $command) { 0061: next; 0062: } 0063: if (! ($command =~ /$bre/)) { 0064: next; 0065: } 0066: if ($user_name_arg && $user_name ne $user_name_arg) { 0067: next; 0068: } Line 50-70: Loop through all processes in process list. Lines 54-58: Fetch all meaningful fields from ps output. Line 59: Print statement for debugging Line 60: If command field is blank, skip to next process Line 63: If command doesn’t match BRE, skip to next process. Line 66: If user name is specified and process is not owned by user, skip to next process. Example ex0490
0069: if ( $no_confirmation ) { 0070: print "killing $pid with signal $signal\n"; 0071: system("kill -$signal $pid"); 0072: } 0073: else { 0074: $process_list[$i] = $pid; 0075: printf("%4d - %-15s %6d %8s %s\n", $i++, $user_name, 0076: $pid, $stime, $command); 0077: } 0078: } 0079: 0080: if ( (! $no_confirmation) && ($i > 1)) { 0081: print "Enter P# of process to kill or q to quit: "; 0082: $response = <STDIN>; 0083: chomp($response); 0084: if ($response =~ /^\d+$/) { 0085: print "kill -$signal $process_list[$response]\n"; 0086: system("kill -$signal $process_list[$response]"); 0087: } 0088: } Line 69: If user doesn’t want confirmation, don’t generate process list, just send a signal to process. Line 73: Otherwise, print process info on process list. Line 80-82: Let user pick process number from list. 84-87: If user entered a valid process number, then kill the associated process.45 Example ex0490
Unix/Linux Files • Directories • User and Group Names • File Related Commands • chmod • chgrp • ln • ln –s
Directories • root (‘/’): • All Unix file systems are represented by a directory tree with root (‘/’) at the top of the tree. • This is why the path returned by ‘pwd’ command always begins with ‘/’: $pwd /export/home/vaughang • home directory • defined in /etc/passwd • Executing the ‘cd’ command without arguments always returns you to your home directory.
User and Group IDs Group Name user name • ls –l drwx------ 3 vaughang faculty 512 Jan 3 21:07 backup drwxr-xr-x 2 vaughang faculty 512 Jan 3 20:13 bin lrwxrwxrwx 1 vaughang faculty 19 Jan 6 22:06 itec400 -> public_html/itec400 -rw-r--r-- 1 vaughang faculty 42 Jan 23 20:21 junk • User Names • defined in /etc/passwd • In the listing above, all files are owned by user gvaughan • Notice that we view directories as a type of file.
User and Group IDs drwxr-x--- 2 vaughang faculty 512 Jan 3 20:13 bin • Group Name • A group is a collection of one more User Names • Allows for assigning file permissions for entire groups of users. • In the file above, the group with privileges to this file is ‘faculty’. • Groups are defined in /etc/group. • A User Name may be a member of more than one group.
File Modes • File Modes determine who has permission to do what to a given file. • File modes can be viewed using ‘ls –l’ drwx------ 3 vaughang faculty 512 Jan 3 21:07 backup drwxr-xr-x 2 vaughang faculty 512 Jan 3 20:13 bin lrwxrwxrwx 1 vaughang faculty 19 Jan 6 22:06 itec400 -> public_html/itec400 -rw-r--r-- 1 vaughang faculty 42 Jan 23 20:21 junk • The first character in column 1 is file type. • The remainder of column 1 is the file mode. File Type File Mode