run.lib #1

  • //
  • p4-sdp/
  • dev/
  • Server/
  • Unix/
  • p4/
  • common/
  • lib/
  • run.lib
  • View
  • Commits
  • Open Download .zip Download (9 KB)
# shellcheck disable=SC2148 disable=SC2034
declare Version=2.4.0
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
#------------------------------------------------------------------------------

#==============================================================================
# Library Functions.

#------------------------------------------------------------------------------
# Function: run
#
# Short: Run a command with optional description, honoring global $VERBOSITY
# and $NO_OP settings.  Simpler than runCmd().
#
# Input:
# $1 - cmd.  The command to run.  The command is displayed first
#      if $VERBOSITY > 3.
# $2 - desc.  Text description of command to run.
#      Optionally, the text string can be prefixed with 'N:', where N is
#      a one-digit integer, the minimum verbosity at which the description is to
#      be displayed.
#      Optionally, a series of text strings can be provided, delimited by '|',
#      allowing multiple descriptions to be provided, each with a different
#      minimum verbosity setting.
#      This parameter is optional.  If the N: prefix is omitted, it is
#      equivalent to "3:".  Sample values: "5:Cool command here:",
#      and "3:Regular verbosity message|4:Higher verbosity message."
#      and "This is a very|long description."
# $3 - honorNoOpFlag.  Pass in 1 to mean "Yes, honor the $NO_OP setting
#      and display (but don't run) commands if $NO_OP is set."  Otherwise
#      $NO_OP is ignored, and the command is always run.
#      This parameter is optional; the default value is 1.
# $4 - alwaysShowOutputFlag.  If set to 1, show output regardless of $VERBOSITY
#      value.  Otherwise, only show output if VERBOSITY > 4.
#      This parameter is optional; the default value is 0.
# $5 - grepString.  If set, this changes the exit code behavior.
#      If the specified string exists in the output, a 0 is returned, else 1.
#      Strings suitable for use with 'egrep' are allowed.
#
# Description:
#    Display an optional description of a command, and then run the
# command.  This is affected by $NO_OP and $VERBOSITY.  If $NO_OP is
# set, the command is shown, but not run, provided $honorNoOpFlag is 1.
# The description is not shown if $VERBOSITY < 3.
#
# The variables CMDLAST and CMDEXITCODE are set each time runCmd is called.
# CMDLAST contains the last command run. CMDEXITCODE contains its exit code.
#
# Output is shown if either $AlwaysShowOutputFlag is 1 or $VERBOSITY >= 4.
#------------------------------------------------------------------------------
function run () {
   dbg "CALL: run ($*)"
   local cmd=${1:-}
   local desc=${2:-}
   local -i honorNoOpFlag=${3:-1}
   local -i alwaysShowOutputFlag=${4:-0}
   local grepString=${5:-}
   local cmdScript=
   local cmdOut=
   local -i grepExit

   CMDLAST=$cmd
   CMDEXITCODE=0

   if [[ -n "$desc" ]]; then
      # Descriptions intended to be multi-line contain a '|' char.
      # Each entry may contain an optional 'N:' prefix where N is the
      # verbosity level at or above which the message is displayed.
      echo "$desc" | tr '|' '\n' | while read -r text; do
         if [[ $text =~ ^[0-9]+: ]]; then
            descVerbosity=${text%%:*}
            text=${text#$descVerbosity:}
            if [[ $VERBOSITY -ge $descVerbosity ]]; then
               echo -e "$text"
            fi
         else
            msg "$desc"
         fi
      done
   fi

   if [[ $honorNoOpFlag -eq 1 && $NO_OP -eq 1 ]]; then
      msg "NO-OP: Would run: \"$cmd\"\n"
   else
      msg "Running: \"$cmd\"."
      cmdScript="$(mktemp -t run.XXXXXX).cmd.sh"
      cmdOut="${cmdScript%.cmd.sh}.out"


      echo -e "#!/bin/bash\n$cmd\n" > "$cmdScript"
      chmod +x "$cmdScript"
      $cmdScript > "$cmdOut" 2>&1
      CMDEXITCODE=$?

      if [[ -n "$grepString" ]]; then
         # shellcheck disable=SC2196
         egrep "$grepString" "$cmdOut" > /dev/null 2>&1
         grepExit=$?
         CMDEXITCODE="$grepExit"
      fi

      if [[ $alwaysShowOutputFlag -eq 1 ]]; then
         cat "$cmdOut"
      else
         [[ $VERBOSITY -gt 3 ]] && cat "$cmdOut"
      fi

      # Be clean and tidy.
      /bin/rm -f "$cmdScript" "$cmdOut"

      # If a grep was requested, return the exit code from the egrep,
      # otherwise return the exit code of the command executed.  In
      # any case, $CMDEXITCODE contains the exit code of the command.
      if [[ -n "$grepString" ]]; then
         return $grepExit
      else
         return $CMDEXITCODE
      fi
   fi

   return 0
}

#------------------------------------------------------------------------------
# Function: rrun
#
# Short: Run a command with on a remote host optional description, honoring
# $VERBOSITY and $NO_OP settings.  Simpler than runRemoteCmd().
#
# Input:
# $1 - host.  The remote host to run the command on.
# $2 - cmd.  The command to run.  The command is displayed first
#      if $VERBOSITY > 3.
# $3 - desc.  Text description of command to run.
#      Optionally, the text string can be prefixed with 'N:', where N is
#      a one-digit integer, the minimum verbosity at which the description is to
#      be displayed.
#      Optionally, a series of text strings can be provided, delimited by '|',
#      allowing multiple descriptions to be provided, each with a different
#      minimum verbosity setting.
#      This parameter is optional.  If the N: prefix is omitted, it is
#      equivalent to "3:".  Sample values: "5:Cool command here:"
# $4 - honorNoOpFlag.  Pass in 1 to mean "Yes, honor the $NO_OP setting
#      and display (but don't run) commands if $NO_OP is set."  Otherwise
#      $NO_OP is ignored, and the command is always run.
#      This parameter is optional; the default value is 1.
# $5 - alwaysShowOutputFlag.  If set to 1, show output regardless of $VERBOSITY
#      value.  Otherwise, only show output if VERBOSITY > 4.
#      This parameter is optional; the default value is 0.
# $6 - grepString.  If set, this changes the exit code behavior.
#      If the specified string exists in the output, a 0 is returned, else 1.
#      Strings suitable for use with 'egrep' are allowed.
#
# Description:
#    Display an optional description of a command, and then run the
# command.  This is affected by $NO_OP and $VERBOSITY.  If $NO_OP is
# set, the command is shown, but not run, provided $honorNoOpFlag is 1.
# The description is not shown if $VERBOSITY < 3.
#
# The variables RCMDLAST and RCMDEXITCODE are set each time runCmd is called.
# RCMDLAST contains the last command run. RCMDEXITCODE contains its exit code.
#
# Output is shown if either $AlwaysShowOutputFlag is 1 or $VERBOSITY >= 4.
#------------------------------------------------------------------------------
function rrun () {
   dbg "CALL: rrun ($*)"
   local host=${1:-Unset}
   local cmd=${2:-Unset}
   local desc=${3:-}
   local -i honorNoOpFlag=${4:-1}
   local -i alwaysShowOutputFlag=${5:-0}
   local grepString=${6:-}
   local rCmdScript=
   local rCmdOut=
   local -i grepExit

   RCMDLAST="$cmd"
   RCMDEXITCODE=0

   if [[ -n "$desc" ]]; then
      echo "$desc" | tr '|' '\n' | while read -r text; do
         if [[ $text =~ ^[0-9]+: ]]; then
            descVerbosity=${text%%:*}
            text=${text#$descVerbosity:}
            if [[ $VERBOSITY -ge $descVerbosity ]]; then
               echo -e "$text"
            fi
         else
            msg "$desc"
         fi
      done
   fi

   if [[ $honorNoOpFlag -eq 1 && $NO_OP -eq 1 ]]; then
      msg "NO-OP: Would run: \"$cmd\" on host $host.\n"
   else
      msg "Running: \"$cmd\" on host $host."

      rCmdScript="$(mktemp -t rrun.XXXXXX).cmd.sh"
      rCmdOut="${rCmdScript%.cmd.sh}.out"

      echo -e "#!/bin/bash\n$cmd\n" > "$rCmdScript"
      chmod +wx "$rCmdScript"
      if ! scp -pq "$rCmdScript" "$host:${P4TMP:-/tmp}/."; then
         RCMDEXITCODE=-1
         errmsg "rrun(): Failed to copy temp command script to $host."
         return 1
      fi

      ssh -q -n "$host" "$rCmdScript" > "$rCmdOut" 2>&1
      RCMDEXITCODE=$?

      if [[ -n "$grepString" ]]; then
         # shellcheck disable=SC2196
         egrep "$grepString" "$rCmdOut" > /dev/null 2>&1
         grepExit=$?
         RCMDEXITCODE="$grepExit"
      fi

      if [[ $alwaysShowOutputFlag -eq 1 ]]; then
         cat "$rCmdOut"
      else
         [[ $VERBOSITY -gt 3 ]] && cat "$rCmdOut"
      fi

      # Be clean and tidy.
      /bin/rm -f "$rCmdScript" "$rCmdOut"

      # If a grep was requested, return the exit code from the egrep,
      # otherwise return the exit code of the command remotely executed.
      # In any case, $RCMDEXITCODE contains the exit code of the command.
      if [[ -n "$grepString" ]]; then
         return $grepExit
      else
         return $RCMDEXITCODE
      fi
   fi

   return 0
}
# Change User Description Committed
#1 31860 C. Thomas Tyler Importing coding standard updates from shelf in legacy structure.