run.lib #1

  • //
  • guest/
  • perforce_software/
  • sdp/
  • main/
  • Server/
  • Unix/
  • p4/
  • common/
  • lib/
  • run.lib
  • View
  • Commits
  • Open Download .zip Download (9 KB)
# shellcheck shell=bash

#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
#------------------------------------------------------------------------------

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

#------------------------------------------------------------------------------
# Function: run
#
# Short: Run a command with optional description, honoring $VERBOSITY
# and $NoOp 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 $NoOp setting
#      and display (but don't run) commands if $NoOp is set."  Otherwise
#      $NoOp 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 $NoOp and $VERBOSITY.  If $NoOp 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=$P4U_TMPDIR/cmd.sh
   local cmdOut=$P4U_TMPDIR/script.out
   local -i grepExit

   # shellcheck disable=SC2034
   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 && $NoOp -eq 1 ]]; then
      msg "NO-OP: Would run: \"$cmd\"\n"
   else
      vmsg "Running: \"$cmd\"."

      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 $NoOp 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 $NoOp setting
#      and display (but don't run) commands if $NoOp is set."  Otherwise
#      $NoOp 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 $NoOp and $VERBOSITY.  If $NoOp 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="${P4TMP:-/tmp}/rcmd.$$.${RANDOM}${RANDOM}.sh"
   local rCmdOut=$P4U_TMPDIR/rcmd.out
   local -i grepExit

   # shellcheck disable=SC2034
   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 && $NoOp -eq 1 ]]; then
      vmsg "NO-OP: Would run: \"$cmd\" on host $host.\n"
   else
      vmsg "Running: \"$cmd\" on host $host."

      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 32135 C. Thomas Tyler Released SDP 2025.1.32133 (2025/10/29).
Copy Up using 'p4 copy -r -b perforce_software-sdp-dev'.
//guest/perforce_software/sdp/dev/Server/Unix/p4/common/lib/run.lib
#1 32044 C. Thomas Tyler Slow Refactoring: "Moving" log_functions.sh from bin to lib directory,
and changing to .lib extension per coming SDP Coding Standard for bash.

The "slow refactoring" means for this change, the original log_functions.sh
will remain in the bin directory, and a new logging.lib file will be added
in the lib directory.  The removal of the file in bin will occur separately.
This is intended to balance allowing progress while preventing potential
disruption to customers who may have supplemental automation relying on the
current names.

New libs: ps.lib, logging.lib, run.lib

We may also allow legacy exceptions since customer-side custom scripts may
have dependencies on backup_functions.sh and other *.sh libraries in the bin
directory.

Unrelated minor fixes in p4verify.sh.