run.lib #1

  • //
  • guest/
  • tom_tyler/
  • sw/
  • main/
  • SSO_Cutover/
  • run.lib
  • View
  • Commits
  • Open Download .zip Download (7 KB)
# shellcheck shell=bash disable=SC2148 disable=SC2034
#==============================================================================
# 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 $NoOp
# settings.
#
# Input:
# $1 - cmd.  The command to run.  The command is displayed before executing.
# $2 - desc.  Optional text description displayed before the command runs.
#      A '|' character splits the description across multiple lines.  Each
#      line may be prefixed with 'N:' (single digit) to display that line only
#      when $Debug >= N.  Without an 'N:' prefix the line is always displayed.
#      Examples: "Starting backup."
#               "1:Verbose detail shown only at debug level 1+."
#               "First line.|Second line."
#               "0:Always shown.|2:Debug-only detail."
# $3 - honorNoOpFlag.  Pass 1 to honor the $NoOp setting (display but don't
#      run the command when $NoOp is set).  Pass 0 to always run.
#      Default: 1.
# $4 - alwaysShowOutputFlag.  Pass 1 to show command output regardless of
#      $Debug level.  Otherwise output is shown only when $Debug >= 1.
#      Default: 0.
# $5 - grepString.  If set, changes the return code: returns 0 if the string
#      is found in the output, 1 otherwise.  Supports egrep patterns.
#
# Sets library output variables CMDLAST (last command run) and CMDEXITCODE
# (its exit code) on each call.
#------------------------------------------------------------------------------
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
      echo "$desc" | tr '|' '\n' | while read -r text; do
         if [[ $text =~ ^[0-9]+: ]]; then
            local descVerbosity=${text%%:*}
            text=${text#"$descVerbosity:"}
            [[ "$Debug" -ge "$descVerbosity" ]] && msg "$text"
         else
            msg "$text"
         fi
      done
   fi

   if [[ "$honorNoOpFlag" -eq 1 && "$NoOp" -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
         [[ "$Debug" -ge 1 ]] && 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 on a remote host, honoring $Debug and $NoOp settings.
#
# Input:
# $1 - host.  The remote host to run the command on.
# $2 - cmd.  The command to run.  The command is displayed before executing.
# $3 - desc.  Optional text description displayed before the command runs.
#      Supports the same '|' line-splitting and 'N:' verbosity-prefix syntax
#      as the desc parameter of run().
# $4 - honorNoOpFlag.  Pass 1 to honor the $NoOp setting (display but don't
#      run the command when $NoOp is set).  Pass 0 to always run.
#      Default: 1.
# $5 - alwaysShowOutputFlag.  Pass 1 to show command output regardless of
#      $Debug level.  Otherwise output is shown only when $Debug >= 1.
#      Default: 0.
# $6 - grepString.  If set, changes the return code: returns 0 if the string
#      is found in the output, 1 otherwise.  Supports egrep patterns.
#
# Sets library output variables RCMDLAST (last command run) and RCMDEXITCODE
# (its exit code) on each call.
#------------------------------------------------------------------------------
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
            local descVerbosity=${text%%:*}
            text=${text#"$descVerbosity:"}
            [[ "$Debug" -ge "$descVerbosity" ]] && msg "$text"
         else
            msg "$text"
         fi
      done
   fi

   if [[ "$honorNoOpFlag" -eq 1 && "$NoOp" -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"
      # Compute the path the script will have on the remote host after scp.
      local remoteScript="${P4TMP:-/tmp}/$(basename "$rCmdScript")"

      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" "$remoteScript" > "$rCmdOut" 2>&1
      RCMDEXITCODE=$?

      # Clean up the remote temp file.
      ssh -q -n "$host" "rm -f '$remoteScript'" 2>/dev/null

      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
         [[ "$Debug" -ge 1 ]] && 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 32665 C. Thomas Tyler Updated latest updates from after QA testing was completed and validation in a live environment.