IBM Books

Administration Guide


Appendix A. Example of a saved command script

The following example of a saved command script is stored in $HOME/dcem/scripts. A system administrator can easily modify the script that was saved by changing the options (for example, groups, security, fan out levels) in the declared variables at the top of the script. The rest of the script functions will build a new execution environment based on the changes that the administrator makes.

#!/usr/bin/perl -w 
######################################################################### 
# 
# Licensed Materials - Property of IBM 
# 
# (C) COPYRIGHT International Business Machines Corp. 1994,2001 
# All Rights Reserved 
# 
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
# 
######################################################################### 
 
######################################################################### 
# 
# Example perl file - 
# Run via: 
#   perl <this-perl-script.pl>  [-debug] [-non_interactive] 
# E.g. 
#   perl listusers.pl 
#   perl listusers.pl -debug 
#   perl listusers.pl -non_interactive 
# 
# Author : Generated by Distributed Command Execution Manager 
# 
######################################################################### 
 
######################################################################### 
# perl information 
# 
######################################################################### 
 
$| = 1;           # Flush output buffer 
require 5.003;    # need this version of Perl or newer 
use English;      # use English names, not cryptic ones 
use FileHandle;   # use FileHandles instead of open(),close() 
use Carp;         # get standard error / warning messages 
use strict;       # force disciplined use of variables 
 
######################################################################### 
# GLOBAL VARIABLES AND CONSTANTS 
# 
######################################################################### 
 
my ($TRUE)                                 = "TRUE"; 
my ($FALSE)                                = "FALSE"; 
 
# ----------------------------------------------------------------------- 
# Command Environment Variables 
# ----------------------------------------------------------------------- 
 
my (@HOSTS)                                = ('b905em17.austin.ibm.com'); 
my (@GROUPS)                               = ('Group1','Group2'); 
 
# ----------------------------------------------------------------------- 
# Command Specification 
# ----------------------------------------------------------------------- 
 
my ($CMD_SPECIFICATION)=<<'END_CMD_SPECIFICATION' 
ls -l; whoami; pwd; ls -l 
END_CMD_SPECIFICATION 
; 
 
# ----------------------------------------------------------------------- 
# Script options and user default settings 
# NOTE: You must add any new options to 
# the OPTION_FLAGS array. 
# ----------------------------------------------------------------------- 
 
my ($DEBUG_FLAG)               = "-debug"; 
my ($LAUNCH_GUI_FLAG)          = "-gui"; 
my ($FORMAT_OUTPUT_FLAG)       = "-format_output"; 
my ($PROMPT_USER_FLAG)         = "-non_interactive"; 
my (@OPTION_FLAGS)             = ($DEBUG_FLAG, 
                                  $LAUNCH_GUI_FLAG, 
                                  $FORMAT_OUTPUT_FLAG, 
                                  $PROMPT_USER_FLAG); 
 
my ($DEBUG)                    = $FALSE; 
my ($LAUNCH_GUI)               = $FALSE; 
my ($FORMAT_OUTPUT)            = $FALSE; 
my ($PROMPT_USER)              = $TRUE; 
 
# ----------------------------------------------------------------------- 
# Csm Distributed Services 
# ----------------------------------------------------------------------- 
 
my ($DISTRIB_SERVICE)                      = "/opt/csm/bin/dsh"; 
my ($DISTRIB_POST_PROCESSING_COMMAND)      = "/opt/csm/bin/dshbak"; 
my ($DISTRIB_DEFAULT_REMOTE_SHELL)         = "rsh"; 
 
# ----------------------------------------------------------------------- 
#      Dsh Options 
# ----------------------------------------------------------------------- 
 
my ($DISTRIB_HOST_OPTION)                  = "-n"; 
my ($DISTRIB_GROUP_OPTION)                 = "-N"; 
my ($DISTRIB_FANOUT_OPTION)                = "-f"; 
my ($DISTRIB_STREAMING_OPTION)             = "-s"; 
my ($DISTRIB_VERIFY_HOSTS_OPTION)          = "-v"; 
my ($DISTRIB_USER_OPTION)                  = "-l"; 
my ($DISTRIB_REMOTE_SHELL_OPTIONS_OPTION)  = "-o"; 
my ($DISTRIB_REMOTE_SHELL_PATH_OPTION)     = "-r"; 
 
# ----------------------------------------------------------------------- 
# Additional Csm Command Environment Variables 
# ----------------------------------------------------------------------- 
 
my ($FANOUT)                                = 64; 
my ($STREAMING)                             = $TRUE; 
my ($VERIFY_HOSTS)                          = $FALSE; 
my ($USER)                                  = "root"; 
my ($REMOTE_SHELL_OPTIONS)                  = ""; 
my ($REMOTE_SHELL)                          = "rsh"; 
my ($COMMAND_PATH)                          = '$PATH'; 
 
# ----------------------------------------------------------------------- 
 
######################################################################### 
# Sub Functions 
######################################################################### 
 
######################################################################### 
# This sub-function displays the string passed to it. 
# This sub-function should be used only for debug messages. 
# 
# @param the messages string to be displayed 
# 
######################################################################### 
 
sub debug_message ($) 
{ 
    if ($DEBUG eq $TRUE) 
    { 
        display_message (@_); 
    } 
} 
 
######################################################################### 
# This sub-function displays the string passed to it. 
# This sub-function should be used to convey information to 
# users 
# 
# @param the messages string to be displayed 
# 
######################################################################### 
 
sub display_message ($) 
{ 
    my ($str) = @_; 
    print "$str"; 
} 
 
######################################################################### 
# This sub-function executes the command. 
# 
######################################################################### 
 
sub run_distributed_command_line () 
{ 
    debug_message ("Enter sub-function run_distributed_command()...\n"); 
 
    my (@execution_string); 
    my ($line) = ""; 
 
    # Get the arguments 
 
    # construct the execution string based on the parameters 
    @execution_string = build_execution_string(); 
 
    # run the command 
    debug_message ("Running the command: @execution_string \n\n"); 
 
    my (@output); 
    my ($current_pid) = fork; 
    if ($current_pid == 0) { 
        @output = exec (@execution_string); 
    } 
    elsif ($current_pid) { 
        debug_message("In parent process, before wait.\n"); 
        my ($child_pid) = wait; 
        debug_message("In parent process, after wait. Child pid was $child_pid.\n"); 
    } 
    else { 
        die "fork error: $!\n"; 
    } 
 
    foreach $line (@output) 
    { 
        display_message ($line); 
    } 
 
    debug_message ("\nLeave sub-function run_distributed_command().\n"); 
    return (@output); 
} 
 
######################################################################### 
# This sub-function invokes the 
# Distributed Command Execution Manager GUI 
# 
######################################################################### 
 
sub run_distributed_command_gui () 
{ 
    debug_message ("Enter sub-function run_distributed_command_gui()...\n"); 
 
    my ($cmd_name) = $0; 
    $cmd_name =~ s/\.pl$//; 
    debug_message( "Command name to load is $cmd_name\n"); 
 
    `/opt/csm/dcem/bin/dcem -command $cmd_name`; 
 
    debug_message ("Leave sub-function run_distributed_command_gui().\n"); 
} 
 
######################################################################### 
# This sub-function gets the path to the selected remote shell. 
# 
#-- This is generated by the printBuildCommandLineFunction() method 
######################################################################### 
 
sub get_remote_shell_path () 
{ 
    debug_message ("Enter sub-function get_remote_shell_path()..."); 
 
    my ($execution_string) = "ksh -c \"which $REMOTE_SHELL\""; 
    my ($line); 
 
    # run the command 
    debug_message ("Running the which $REMOTE_SHELL command: $execution_string \n\n"); 
 
    my (@output) = `$execution_string`; 
 
    $line = $output[0]; 
    my (@splitLine) = split(' ', $line); 
    my ($path) = $splitLine[0]; 
 
    if ($line =~ /$REMOTE_SHELL$/) 
    { 
        debug_message ("Found remote shell path $path\n"); 
        return $path; 
    } 
    else 
    { 
        display_message ("The remote shell $REMOTE_SHELL was not found. Dsh will use the 
        default $DISTRIB_DEFAULT_REMOTE_SHELL remote shell when executing this command.\n"); 
        return ""; 
    } 
} 
 
######################################################################### 
# This sub-function contructs the complete execution string. 
# 
######################################################################### 
 
sub build_execution_string () 
{ 
    debug_message ("Enter sub-function build_execution_string()...\n"); 
 
    my ($i) = 0; 
    my ($cmd_path) = ""; 
    my (@execution_string); 
 
    $execution_string[$i] = $DISTRIB_SERVICE; 
    $execution_string[++$i] = $DISTRIB_FANOUT_OPTION; 
    $execution_string[++$i] = $FANOUT; 
    debug_message ("Execution string is: @execution_string\n"); 
 
    if (($STREAMING eq $TRUE) && ($FORMAT_OUTPUT eq $FALSE)) 
    { 
        $execution_string[++$i] = $DISTRIB_STREAMING_OPTION; 
        debug_message ("Execution string is: @execution_string\n"); 
    } 
 
    $execution_string[++$i] = $DISTRIB_USER_OPTION; 
    $execution_string[++$i] = $USER; 
    debug_message ("Execution string is: @execution_string\n"); 
 
    if ($REMOTE_SHELL ne $DISTRIB_DEFAULT_REMOTE_SHELL) 
    { 
        my ($remote_shell_path) = get_remote_shell_path(); 
        if ($remote_shell_path ne "") 
        { 
            $execution_string[++$i] = $DISTRIB_REMOTE_SHELL_PATH_OPTION; 
            $execution_string[++$i] = $remote_shell_path; 
            debug_message ("Execution string is: @execution_string\n"); 
 
            $execution_string[++$i] = $DISTRIB_REMOTE_SHELL_OPTIONS_OPTION; 
            $execution_string[++$i] = $REMOTE_SHELL_OPTIONS; 
            debug_message ("Execution string is: @execution_string\n"); 
        } 
    } 
    elsif ($REMOTE_SHELL_OPTIONS ne "") 
    { 
        $execution_string[++$i] = $DISTRIB_REMOTE_SHELL_OPTIONS_OPTION; 
        $execution_string[++$i] = $REMOTE_SHELL_OPTIONS; 
        debug_message ("Execution string is: @execution_string\n"); 
    } 
 
    if (@GROUPS) 
    { 
        $execution_string[++$i] = $DISTRIB_GROUP_OPTION; 
        $execution_string[++$i] = join(",", @GROUPS); 
        debug_message ("Execution string is: @execution_string\n"); 
    } 
 
    if ($VERIFY_HOSTS eq $TRUE) 
    { 
        $execution_string[++$i] = $DISTRIB_VERIFY_HOSTS_OPTION; 
        debug_message ("Execution string is: @execution_string\n"); 
    } 
 
    if (@HOSTS) 
    { 
        $execution_string[++$i] = $DISTRIB_HOST_OPTION; 
        $execution_string[++$i] = join(",", @HOSTS); 
        debug_message ("Execution string is: @execution_string\n"); 
    } 
 
    if ($COMMAND_PATH ne '') 
    { 
        $cmd_path = "export PATH=$COMMAND_PATH;"; 
        debug_message ("Command path string is: $cmd_path\n"); 
    } 
 
    $execution_string[++$i] = join(" ", $cmd_path, $CMD_SPECIFICATION); 
    debug_message ("Execution string is: @execution_string\n"); 
 
    if ($FORMAT_OUTPUT eq $TRUE) 
    { 
        $execution_string[++$i] = join("", " | ", $DISTRIB_POST_PROCESSING_COMMAND); 
        debug_message ("Execution string is: @execution_string\n"); 
    } 
 
    debug_message ("Leave sub-function build_execution_string().\n"); 
    return (@execution_string); 
} 
 
######################################################################### 
# This sub-function asks the user whether the program should 
# continue or not. 
# 
# @param cmd_spec - the command specification 
# @param hosts    - the host machines to run the command on 
# @param groups   - the groups to run the command on 
# 
######################################################################### 
 
sub confirm_command_execution ($$$) 
{ 
    debug_message ("Enter sub-function confirm_command_execution()...\n"); 
 
    my ($cmd_spec, $hosts_ref, $groups_ref) = @_; 
    my (@hosts) = @$hosts_ref; 
    my (@groups) = @$groups_ref; 
    my ($host); 
    my ($group); 
    my ($reply) = ""; 
 
    display_message("The command \"$cmd_spec\" "); 
 
    if ((scalar(@hosts) == 0) && (scalar(@groups) == 0)) 
    { 
        display_message("has no targets specified.\n"); 
        return($FALSE); 
    } 
 
    display_message ("is about to be executed on the following "); 
 
    if (scalar(@hosts)) 
    { 
        display_message( "hosts:\n\t"); 
 
        foreach $host (@hosts) 
        { 
            display_message ("$host "); 
        } 
        display_message ("\n"); 
 
        if (scalar(@groups)) 
        { 
            display_message ("and "); 
        } 
    } 
 
    if (scalar(@groups)) 
    { 
        display_message ("groups:\n\t"); 
 
        foreach $group (@groups) 
        { 
            display_message ("$group "); 
        } 
        display_message ("\n"); 
    } 
 
    while (defined($reply) && $reply !~ /[yYnN]/ ) 
    { 
        display_message ("Do you wish to continue (y/n)?: "); 
        $reply = <STDIN>; 
        chop ($reply); 
    } 
 
    debug_message ("Leave sub-function confirm_command_execution().\n"); 
 
    # Check the reply to determine whether to continue 
    if ($reply =~ /[yY]/) 
    { 
        return($TRUE); 
    } 
    else 
    { 
        return ($FALSE); 
    } 
} 
 
######################################################################### 
# This sub-function exits the program with an appropriate 
# exit code. 
# 
# @param 
# 
######################################################################### 
 
sub exit_program ($$) 
{ 
    debug_message ("Enter sub-function exit_program()...\n"); 
 
    my ($msg, $exit_code) = @_; 
 
    display_message ($msg); 
 
    debug_message ("Leave sub-function exit_program().\n"); 
    debug_message ("Exiting program with exit_code: $exit_code\n"); 
    exit ($exit_code); 
} 
 
######################################################################### 
# This sub-function display the usage message for this command 
# 
# @param 
# 
######################################################################### 
 
sub usage ($) 
{ 
    debug_message ("Enter sub-function usage()...\n"); 
 
    my ($bad_option) = @_; 
    display_message ($bad_option); 
 
    display_message ("Usage: perl $0 [$DEBUG_FLAG] [$PROMPT_USER_FLAG]\n\n"); 
 
    display_message (" $DEBUG_FLAG\t\t\t- displays debug messages\n"); 
    display_message (" $PROMPT_USER_FLAG\t- does not prompt user for input\n"); 
 
    exit_program("", 1); 
 
    debug_message ("Leave sub-function usage().\n"); 
} 
 
######################################################################### 
# This function logs entries into a file whose name is 
# provided as the imput argument. 
# 
# @param - log file name 
# 
######################################################################### 
 
sub generate_log_entries 
{ 
    debug_message ("Enter sub-function generate_log_entries()...\n"); 
    `/opt/csm/dcem/bin/dLogMgr -s \"@_\"`; 
 
    debug_message ("Leave sub-function generate_log_entries().\n"); 
} 
 
######################################################################### 
# This function mails status reports after the command is 
# executed 
# 
# @param - email addresses 
# 
######################################################################### 
 
sub mail_report ($) 
{ 
    debug_message ("Enter sub-function mail_report()...\n"); 
 
    debug_message ("Leave sub-function mail_report().\n"); 
} 
 
######################################################################### 
# This sub-function check all the options, in the 
# @ARGV array. 
# Flags are assumed to begin with a '-' (dash or minus sign). 
# 
######################################################################### 
 
sub check_options () 
{ 
    debug_message ("Enter sub-function check _options ()...\n"); 
 
    my ($CMD_OPTION) = ""; 
    my ($TMP_CMD_OPTION) = ""; 
    my ($OPTION_FLAG) = ""; 
 
    foreach $CMD_OPTION (@ARGV) 
    { 
        $TMP_CMD_OPTION = ""; 
 
        # Check for incomplete and/or ambigous options 
        foreach $OPTION_FLAG (@OPTION_FLAGS) 
        { 
            if (index ($OPTION_FLAG, $CMD_OPTION) ==  0) 
            { 
                if ($TMP_CMD_OPTION eq "") 
                { 
                    $TMP_CMD_OPTION = $OPTION_FLAG; 
                } 
                else 
                { 
                    $TMP_CMD_OPTION = "AMBIGUOUS"; #ambiguous 
                    last; 
                } 
            } 
        } 
 
        if ($TMP_CMD_OPTION eq $PROMPT_USER_FLAG) 
        { 
            debug_message ("Setting PROMPT_USER to FALSE.\n"); 
            $PROMPT_USER = $FALSE; 
        } 
        elsif ($TMP_CMD_OPTION eq $LAUNCH_GUI_FLAG) 
        { 
            debug_message ("Setting LAUNCH_GUI to TRUE.\n"); 
            $LAUNCH_GUI = $TRUE; 
        } 
        elsif ($TMP_CMD_OPTION eq $FORMAT_OUTPUT_FLAG) 
        { 
            debug_message ("Setting FORMAT_OUTPUT to TRUE.\n"); 
            $FORMAT_OUTPUT = $TRUE; 
        } 
        elsif ($TMP_CMD_OPTION eq $DEBUG_FLAG) 
        { 
            $DEBUG = $TRUE; 
            debug_message ("Setting DEBUG to TRUE.\n"); 
        } 
        elsif ($TMP_CMD_OPTION eq "AMBIGUOUS") 
        { 
            usage ("Ambiguous option: $CMD_OPTION\n\n"); 
        } 
        else 
        { 
            usage ("Error! Bad option: $CMD_OPTION\n\n"); 
        } 
    } 
 
    debug_message ("Leave sub-function check _options ().\n"); 
} 
 
######################################################################### 
# This sub-function invokes all other subfunctions and is 
# responsible for executing the command. 
# 
######################################################################### 
 
sub main_driver () 
{ 
    # Check if any command line arguments have been passed in 
    check_options (); 
 
    debug_message ("Enter function main_driver()...\n"); 
 
    my ($host) =""; 
    my ($group) =""; 
    my ($continue_program) = "TRUE"; 
    my ($error_code) = 0; 
 
    debug_message ("hosts:\n"); 
    foreach $host (@HOSTS) 
    { 
        debug_message ("\t$host\n"); 
    } 
 
    debug_message ("groups:\n"); 
    foreach $group (@GROUPS) 
    { 
        debug_message ("\t$group\n"); 
    } 
 
    # What about the GUI option........ 
    if ($LAUNCH_GUI eq $TRUE) 
    { 
        display_message ("Launching GUI...\n"); 
 
        run_distributed_command_gui(); 
 
        exit_program ("", 0 ); 
    } 
 
    debug_message ("User prompt setting is: $PROMPT_USER\n"); 
 
    if ($PROMPT_USER eq $TRUE) 
    { 
        $continue_program = confirm_command_execution ($CMD_SPECIFICATION, 
                            \@HOSTS, \@GROUPS); 
        if ($continue_program eq $FALSE) 
        { 
            my ($exit_msg) = "Program exited without executing command.\n"; 
            exit_program ($exit_msg, 1 ); 
        } 
    } 
 
    # After all the GUI and PROMPT options have been processed, 
    # we are now ready to run the script 
    my (@results) = run_distributed_command_line (); 
    if (-e "/opt/csm/dcem/bin/dLogMgr") 
    { 
        generate_log_entries(@results); 
    } 
 
    debug_message ("Leave function main_driver().\n"); 
} 
 
######################################################################### 
# This the start of the script. 
# 
######################################################################### 
 
main_driver (); 
 
0;  # return 0 (no error from this script) 
 
######################################################################### 
#----------------- This is the END of the Script -------------- 
# 
######################################################################### 
 


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]