Notes: Perl Lab 12

System Commands

  1. Overview
  2. backtics
  3. system()

  1. System Commands Overview

    In perl there are several ways of executing external system commands. Generally, it is better to avoid using external commands when there are perl functions that will provide the same or similar functionality. One of the problems of using external commands, is that they may change if the perl code is moved from one type of system to another. For example, some of the arguments to the unix command ls are different or unavailable when moving between Linux, FreeBSD and Solaris. If a script depends on the functionality of this external command, it will cease to operate or may provide incorrect information when run on a different system.

    Another possible problem is a degradation in performance of the script. There is considerable system overhead in executing a command which may become apparent depending on how frequently perl calls the command or how resource intensive the command itself may be.

    Still, there are many times when it is helpful to be able to acces external commands within a Perl program.

  2. backtics

    The simplest way to execute a system command is to enclose the command in backtics ``. The output from the command is returned and can be captured in a scalar or list variable. When the output is stored in a list variable, it will be stored such that each line of output will be assigned to an element of the list. In order to capture the individual elements of a single line in an array, the split command will need to be used.

    Example lab12_0.pl
     
    #!/usr/bin/perl -w
    
    # Name: Mark Tucker
    # Assignment: Lab12 Example 00
    # Description: Example of using backtics to execute a command
    #==========================================================================
    
    # capture the output of the finger command in a scalar variable
    $me = `finger $ENV{USER}`;
    print "Output is: $me\n";
    
    # print separator
    print "X" x 50 . "\n";
    
    # capture the output of the finger command in a list variable (array)
    chomp(@finger = `finger $ENV{USER}`);
    
    # Print the finger output to the screen
    foreach $i (@finger) {
        print "X: $i\n";
    }
    
    exit;
    # DONE
    
    

    When executed, the script above produces the following output:
     
    [mark@platypus PERL] ./lab12_0.pl
    Output is: Login: tuckerm                               Name: Mark Tucker
    Directory: /mnt/homes/tuckerm           Shell: /bin/tcsh
    Office: Staff, 20030601
    Last login Thu Apr 22 11:57 (GMT) on pts/8 from localhost
    No mail.
    No Plan.
    
    Login: mark                             Name: Mark Tucker
    Directory: /home/mark                   Shell: /bin/bash
    Office: vail 444a, x6328                Home Phone: go_away
    On since Mon Apr 26 11:42 (GMT) on :0 (messages off)
    On since Mon Apr 26 11:42 (GMT) on pts/0   1 hour 17 minutes idle
    On since Mon Apr 26 11:52 (GMT) on pts/1   4 seconds idle
    On since Mon Apr 26 13:42 (GMT) on pts/2   2 hours 57 minutes idle
    On since Mon Apr 26 17:47 (GMT) on pts/3
    On since Mon Apr 26 13:42 (GMT) on pts/4   1 hour 26 minutes idle
    On since Mon Apr 26 15:05 (GMT) on pts/5   3 hours 23 minutes idle
    On since Mon Apr 26 15:11 (GMT) on pts/6   5 minutes 56 seconds idle
    No mail.
    No Plan.
    
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    X: Login: tuckerm                               Name: Mark Tucker
    X: Directory: /mnt/homes/tuckerm        Shell: /bin/tcsh
    X: Office: Staff, 20030601
    X: Last login Thu Apr 22 11:57 (GMT) on pts/8 from localhost
    X: No mail.
    X: No Plan.
    X: 
    X: Login: mark                                  Name: Mark Tucker
    X: Directory: /home/mark                Shell: /bin/bash
    X: Office: vail 444a, x6328             Home Phone: go_away
    X: On since Mon Apr 26 11:42 (GMT) on :0 (messages off)
    X: On since Mon Apr 26 11:42 (GMT) on pts/0   1 hour 17 minutes idle
    X: On since Mon Apr 26 11:52 (GMT) on pts/1   4 seconds idle
    X: On since Mon Apr 26 13:42 (GMT) on pts/2   2 hours 57 minutes idle
    X: On since Mon Apr 26 17:47 (GMT) on pts/3
    X: On since Mon Apr 26 13:42 (GMT) on pts/4   1 hour 26 minutes idle
    X: On since Mon Apr 26 15:05 (GMT) on pts/5   3 hours 23 minutes idle
    X: On since Mon Apr 26 15:11 (GMT) on pts/6   5 minutes 56 seconds idle
    X: No mail.
    X: No Plan.
    [mark@platypus PERL] 
    

    Example lab12_1.pl
     
    #!/usr/bin/perl -w
    
    # Name: Mark Tucker
    # Assignment: Lab12 Example 01
    # Description: Example of using backtics to execute a command and split 
    #              the output.
    #==========================================================================
    
    # print the original output to the screen
    print `uptime`;
    
    # capture the output to an array
    @uptime = split(/\s+/, `uptime`);
    
    # print the array values to the screen individually
    foreach $k (@uptime) {
        print "Z: $k\n";
    }
    
    exit;
    # DONE
    
    

    When executed, the script above produces the following output:
     
    [mark@platypus PERL] ./lab11_1.pl  
     18:33:22  up 6 days, 18 min,  8 users,  load average: 0.07, 0.03, 0.00
    Z: 
    Z: 18:33:22
    Z: up
    Z: 6
    Z: days,
    Z: 18
    Z: min,
    Z: 8
    Z: users,
    Z: load
    Z: average:
    Z: 0.07,
    Z: 0.03,
    Z: 0.00
    [mark@platypus PERL] 
    

  3. system

    The system function also executes an external command but does not return the output from the command. This function is especially appropriate when the purpose of the perl program is to decide which command and arguments are to be executed and then execute the script created commandline. With system, the perl script will stop executing while the command itself is running and will resume once the command has terminated. The system function will return any value returned from the termination of the program. This value will also be stored in the perl built-in variable $?.

    Example lab12_2.pl
     
    #!/usr/bin/perl -w
    
    # Name: Mark Tucker
    # Assignment: Lab12 Example 00
    # Description: Example of using backtics to execute a command
    #==========================================================================
    
    # set command name
    $cmd = '/usr/bin/mozilla';
    
    # what is the url we want?
    if($ENV{HOSTNAME} =~ /^metlab/) {
        $url = 'http://apollo.lsc.vsc.edu';   # do class stuff
    }elsif($ENV{HOSTNAME} =~ /^annex/) {
        $url = 'http://www.weathertap.com/';  # get weather data
    }else{
        $url = 'http://www.unitedmedia.com/comics/dilbert/'; # read dilbert
    }
    
    # run the command
    $ret_val = system("$cmd $url");
    
    print "Done with Mozilla, $ret_val Exiting...\n";
    
    exit;
    # DONE
    
    

    When executed, the script above produces the following output:
     
    [mark@platypus PERL] ./lab11_1.pl
    Done with Mozilla, 2 Exiting...
    [mark@platypus PERL] 
    

    In the code example above, perl will launch the mozilla web browser with whatever arguments are stored the in the url.

    Another example of the system function is the "z-mount.pl" script which is used to mount campus z-drives under Linux.

    z-mount example.
     
    #!/usr/bin/perl -w
    
    # DESCRIPTION: This script requests the user's windows 
    # domain login information and then builds the appropriate arguments to the
    # smbmount command.  If successful, the command will mount the drive and then
    # report the success/failure state to the user.
    
    # AUTHOR:  Mark Tucker  05 Mar 2003
    
    # CHANGE HISTORY:
    #
    
    
    #=============================================================================
    
    #-------------
    # constant variables & paths
    #-------------
    $home = $ENV{HOME};
    $user = $ENV{USER};
    $mount_dir = '/mnt/z-drives';
    
    print "home is $home\nuser is $user\n";
    
    # get the user's domain login
    $ans = 0;
    while ($ans != 1 ) {
        print "\nPlease enter your LSC Domain username:\n";
        chomp($username = <STDIN>);
        print "You have entered \"$username\" is this correct? (Y/N)\n";
        chomp($resp = <STDIN>);
        if($resp !~ /^y/i) {
            print "Trying again... \n\n";
        }else{
            $ans = 1;
        }
          
    }
    
    $mount_pt = "$mount_dir/$user";
    mkdir( $mount_pt, 0770);
    
    # create symlink in the users home
    $link_name = "$home/z-drive";
    if( ! -l $link_name ) {
        symlink("$mount_dir/$user", "$link_name");
    }
    
    $command = "sudo /usr/bin/smbmount //alpha/$username $mount_pt -o username=$username,uid=$user,gid=$user,workgroup=LSC,rw";
    
    # debug output
    print "\n\ncommand:\n$command\n\n";
    
    # lets actually mount the file system now.
    system("$command");
    
    if($? == 0) {
        print "Z: drive for $user successfully mounted on \"$home/z-drive\".\n";
        sleep 2;
    }else{
        print "\n\nMount command failed.\n";
        sleep 9;
    }
    
    exit;
    # done
    
    

    When executed, the script above produces the following output:
     
    [mark@platypus PERL] /mnt/homes/00links/scripts/z-mount.pl
    [mark@platypus PERL] 
    


last updated: 18 Mar 2012 12:55