p4verify.sh #5

  • //
  • guest/
  • russell_jackson/
  • sdp/
  • Server/
  • Unix/
  • p4/
  • common/
  • bin/
  • p4verify.sh
  • View
  • Commits
  • Open Download .zip Download (12 KB)
#!/bin/bash
#==============================================================================
# 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
#------------------------------------------------------------------------------

#==============================================================================
# Declarations and Environment

export SDP_ENV=/p4/common/bin/p4_vars
export SDP_INSTANCE=${SDP_INSTANCE:-Unset}

export SDP_INSTANCE=${1:-$SDP_INSTANCE}
if [[ $SDP_INSTANCE == Undefined ]]; then
   echo "Instance parameter not supplied."
   echo "You must supply the Perforce instance as a parameter to this script."
   exit 1
fi

declare RecentChangesToVerify=${SDP_RECENT_CHANGES_TO_VERIFY:-2500}

declare StatusMessage="OK: All scanned depots verified OK."
declare -i VerifyOnlyRecentChanges=0
declare -i VerifyFailed=
declare -i ShowLog=0
declare -i ExitCode=0
declare RevRange=
declare VerifyCmd=
declare Log=Unset
declare Version=6.0.0
declare Threads=1

#==============================================================================
# Local Functions

# Micro-functions, one-liners used to avoid external dependencies.
function msg () { if [[ $Log != Unset ]]; then echo -e "$*" >> $Log; else echo -e "$*"; fi; }
function bail () { msg "\nError: ${1:-Unknown Error}"; exit ${2:-1}; }

function cmd ()
{ 
  echo === Running $* on $(date). >> $cmd_log 
  $* >> $cmd_log 2>&1
  status=$?
  if [ $status -ne 0 ]; then
    VerifyFailed = 1
  fi
}

#------------------------------------------------------------------------------
# Function: usage (required function)
#
# Input:
# $1 - style, either -h (for short form) or -man (for man-page like format).
# The default is -h.
#
# $2 - error message (optional).  Specify this if usage() is called due to
# user error, in which case the given message displayed first, followed by the
# standard usage message (short or long depending on $1).  If displaying an
# errror, usually $1 should be -h so that the longer usage message doesn't
# obsure the error message.
#
# Sample Usage:
# usage 
# usage -man
# usage -h "Incorrect command line usage."
#
# This last example generates a usage error message followed by the short
# '-h' usage summary.
#------------------------------------------------------------------------------
function usage
{
   declare style=${1:--h}
   declare errorMessage=${2:-Unset}

   if [[ $errorMessage != Unset ]]; then
      echo -e "\n\nUsage Error:\n\n$errorMessage\n\n" >&2
   fi

   echo "USAGE for p4verify.sh v$Version:

p4verify.sh [<instance>] [-recent]

   or

p4verify.sh -h|-man
"
   if [[ $style == -man ]]; then
      echo -e "DESCRIPTION:

	This script performs a 'p4 verify' of all submitted and shelved versioned
	files in depots of all types except 'remote' and 'archive' type depots.

	If run on a replica, it schedules archive failures for transfer to the
	replica.

OPTIONS:
<instance>
	Specify the SDP instances.  If not specified, the SDP_INSTANCE
	environment variable is used instead.  If the instance is not
	defined by a parameter and SDP_INSTANCE is not defined, p4verify.sh
	exists immediately with an error message.

 -recent
	Specify that only recent changelists should be verified.
	The \$SDP_RECENT_CHANGES_TO_VERIFY variable defines how many
	changelists are considered recent; the default is $RecentChangesToVerify.

	If the default is not appropriate for your site, add
	\"export SDP_RECENT_CHANGES_TO_VERIFY\" to /p4/common/config/p4_N.vars to
	change the default for an instance, or to /p4/common/bin/p4_vars to
	change it globally.  If unset, the default is $RecentChangesToVerify.

 -v     Show ouptput of verify attempts, which is suppressed by default.
	Setting SDP_SHOW_LOG=1 in the shell environment has the same
	effect as -v.

 -L <log>
	Specify the log file to use.  The default is /p4/N/logs/p4verify.log

 -D     Set extreme debugging verbosity.

-P #
	Specify the number of depots to verify in parallel.

HELP OPTIONS:
 -h	Display short help message
 -man	Display man-style help message

EXAMPLES:
	This script is typically called via cron with only the instance
	paramter as an argument, e.g.:
	p4verify.sh N

LOGGING:
	This script generates no output by default.  All (stdout and stderr) is
	logged to /p4/N/logs/p4verify.log.

	The exception is usage errors, which result an error being sent to
	stderr followed usage info on stdout, followed by an immediate exit.

	If the '-v' flag is used, the contents of the log are displayed to
	stdout at the end of processing.

EXIT CODES:
	An exit code of 0 indicates no errors were encounted attempting to
	perform verifications, AND that all verifications attempted
	reported no problems.

	A exit status of 1 indicates that verifications could not be
	attempted for some reason.

	A exit status of 2 indicates that verifications were successfully
	performed, but that problems such as BAD or MISSING files
	were detected, or else system limits prevented verification.
"
   fi

   exit 1
}

#------------------------------------------------------------------------------
# Function: get_verify_rev_range ($depot, $recentChanges)
#------------------------------------------------------------------------------
function get_verify_rev_range () {
   declare depot=${1:-}
   declare recentChangesToVerify=${2:-}
   declare nowChange=
   [[ -z "$depot" || -z "$recentChangesToVerify" ]] && return 0

   nowChange=$($P4 -ztag -F %change% changes -m 1 //$depot/...)
   thenChange=$($P4 -ztag -F %change% changes -m $recentChangesToVerify //$depot/... | tail -1)
   [[ -z "$nowChange" ]] && return 1
   [[ -z "$thenChange" ]] && return 1

   echo "@$thenChange,@$nowChange"

   return 0
}

#==============================================================================
# Command Line Processing
declare -i shiftArgs=0

set +u
while [[ $# -gt 0 ]]; do
   case $1 in
      (-h) usage -h;;
      (-man) usage -man;;
      (-recent) VerifyOnlyRecentChanges=1;;
      (-v) ShowLog=1;;
      (-L) Log=$2; shiftArgs=1;;
      (-D) set -x;; # Debug; use 'set -x' mode.
      (-P) Threads=$2; shiftArgs=1;;
      (-*) usage -h "Unknown command line option ($1).";;
      (*) export SDP_INSTANCE=$1;;
   esac

   # Shift (modify $#) the appropriate number of times.
   shift; while [[ $shiftArgs -gt 0 ]]; do
      [[ $# -eq 0 ]] && usage -h "Incorrect number of arguments."
      shiftArgs=$shiftArgs-1
      shift
   done
done
set -u

#==============================================================================
# Command Line Verification

[[ $SDP_INSTANCE == Unset ]] && \
   bail "The \$SDP_INSTANCE setting is not defined. It must be defined by doing:\n\n\tsource /p4/common/bin/p4_vars <instance>\n\nor by passing in the instance name as a parameter to this script.\n"

#==============================================================================
# Main Program

source $SDP_ENV $SDP_INSTANCE ||\
   bail "Failed to load SDP environment for instance $SDP_INSTANCE."

source $P4CBIN/backup_functions.sh ||\
   bail "Failed to load backup_functions.sh."

check_vars
set_vars
get_journalnum

[[ $Log == Unset ]] && Log=$LOGS/p4verify.log

# This is needed because everything in backup_functions.sh uses LOGFILE including the mail_log_file function.
LOGFILE=$Log
LOG=$LOGS/p4verify

rotate_log_file $LOGFILE ".gz"

msg "${0##*/} v$Version Starting verify at $(date +'%a %Y-%m-%d %H:%M:%S %Z')."

P4="$P4BIN -p $P4PORT -u $P4USER"
$P4CBIN/p4login

msg "If there are errors in this log, contact your local support team."

VerifyFailed=0

RevRange=

depots=() # Clear array
thread=0  # Set current threads to 0


# Build array depots of all of the depot names
for d in `$P4 -s depots|grep "^info: Depot " | cut -d" " -f3,5 | egrep -v 'archive$|remote$' | cut -d" " -f1 ` ; do
   depots+=( "$d" ) # Append depot to the array
done

# loop depots running the number of them in parraell that is specified by the command line
for d in "${depots[@]}"; do
  # Loop to see if we are over our thread count.  If so wait until we drop below it again
  while [ $thread -ge $Threads ]; do
    sleep 5
    #loop thread process id's and see if any have finished.
    spot=0
    for p in "${ids[@]}"; do
      running=$(ps cax | grep $p)
      if [ -n "$running" ]; then
        run[$spot]=$p
        spot=$((spot+1))
        ids=("${run[@]}")
      else
        thread=$((thread-1))
      fi
    done
  done

  # check the depot type as behaviour / flags differ
  depot_type=`$P4 depot -o $d | sed -n "s/^Type:[     ]*\(.*\)/\1/p"`

  if [[ $depot_type != "unload" ]]; then
    if [[ $VerifyOnlyRecentChanges -eq 1 ]]; then
      RevRange=$(get_verify_rev_range "$d" "$RecentChangesToVerify")
    fi

    if [[ "${P4REPLICA}" == "FALSE" || ${SHAREDDATA} == "TRUE" ]]; then
      VerifyCmd="$P4 -s verify -qz //$d/...$RevRange"
      cmd_log=$LOG-$d.log
      cmd $VerifyCmd & 
      ids[$thread]=$! # add the process ID into the array of running processes
      thread=$((thread+1))  #  add one to the thread count and start a new verify

      VerifyCmd="$P4 -s verify -qS //$d/..."        # cannot specify range with -S
      cmd_log=$LOG-$d-S.log
      cmd $VerifyCmd &
      ids[$thread]=$! # add the process ID into the array of running processes
      thread=$((thread+1))  #  add one to the thread count and start a new verify
    else
      VerifyCmd="$P4 -s verify -qz -t //$d/...$RevRange"
      cmd_log=$LOG-$d.log
      cmd $VerifyCmd &
      ids[$thread]=$! # add the process ID into the array of running processes
      thread=$((thread+1))  #  add one to the thread count and start a new verify

      VerifyCmd="$P4 -s verify -qS -t //$d/..."    # cannot specify range with -S
      cmd_log=$LOG-$d-S.log
      cmd $VerifyCmd &
      ids[$thread]=$! # add the process ID into the array of running processes
      thread=$((thread+1))  #  add one to the thread count and start a new verify
    fi
  else     # unload depot;  revision range not applicable
    if [[ "${P4REPLICA}" == "FALSE" || ${SHAREDDATA} == "TRUE" ]]; then
      VerifyCmd="$P4 -s verify -U -q //$d/..."
      cmd_log=$LOG-$d.log
      cmd $VerifyCmd &
      ids[$thread]=$! # add the process ID into the array of running processes
      thread=$((thread+1))  #  add one to the thread count and start a new verify
    else
      VerifyCmd="$P4 -s verify -U -q -t //$d/..."
      cmd_log=$LOG-$d.log
      cmd $VerifyCmd &
      ids[$thread]=$! # add the process ID into the array of running processes
      thread=$((thread+1))  #  add one to the thread count and start a new verify
    fi
  fi
done

# now that we have started all of them wait until all of our processes have finished before continuing.
while [ $thread -gt 0 ]; do
  sleep 5
  #loop thread process id's and see if any have finished.
  spot=0
  for p in "${ids[@]}"; do
  running=$(ps cax | grep $p)
  if [ -n "$running" ]; then
    run[$spot]=$p
    spot=$((spot+1))
  else
    thread=$((thread-1))
  fi
  ids=("${run[@]}")
  done
done

# now that the processes have finished combine all of the log file together
for d in "${depots[@]}"; do
   cat $LOG-$d.log >> "$Log"
   if [ -f $LOG-$d-S.log ]; then
     cat $LOG-$d-S.log >> "$Log"
     rm -f $LOG-$d-S.log
   fi
   rm -f $LOG-$d.log
done

if [[ $VerifyFailed -ne 0 ]]; then
   StatusMessage="Error: Verify attempt failed.  Review the log [$Log]."
   ExitCode=1
fi

if [[ $ExitCode -eq 0 ]]; then
   egrep '(BAD!|MISSING!|p4 help max)' $Log > /dev/null 2>&1
   if [[ $? -eq 0 ]]; then
      StatusMessage="Warning: Verify errors detected.  Review the log [$Log]."
      ExitCode=2
   fi
fi
 
msg "Completed verifications at $(date)."

if [[ $ExitCode -ne 0 ]]; then
   mail_log_file "$HOSTNAME $P4SERVER P4Verify Log ($StatusMessage)"
fi

[[ $ShowLog -eq 1 && -s $Log ]] && cat $Log

exit $ExitCode
# Change User Description Committed
#55 31318 Russell C. Jackson (Rusty) Changing to run -qt on all servers since the commit supports it now.
#54 30664 Russell C. Jackson (Rusty) Fixed bug in p4verify.sh
#53 29830 Russell C. Jackson (Rusty) Fixed bug where shelf verify output was being added to the log file for each depot.
#52 29425 Russell C. Jackson (Rusty) Fix logic on logging.
#51 29423 Russell C. Jackson (Rusty) Fix for log rotation.
#50 29412 Russell C. Jackson (Rusty) Filter errors into separate log to email
#49 29180 Russell C. Jackson (Rusty) Commented out Running verify to clean up the logs.
#48 28477 Russell C. Jackson (Rusty) Added --only MISSING to speed up verifies.
#47 28367 Russell C. Jackson (Rusty) Updates to improve verify speed even more.
#46 28321 Russell C. Jackson (Rusty) Added cat of shelf verfiy into overall verify log.
#45 28201 Russell C. Jackson (Rusty) Fixed some bugs with logging and with spaces in directory names.
#44 28072 Russell C. Jackson (Rusty) Added command to verify files in top level of depot.
#43 28068 Russell C. Jackson (Rusty) Modified the split size based on the number of files in the directory.
#42 28065 Russell C. Jackson (Rusty) Added sleep before deleting files to give all verify commands a chance to kick off.
#41 28059 Russell C. Jackson (Rusty) Added loop for deleting files since rm would fail if there are too many files for * to handle.
#40 28041 Russell C. Jackson (Rusty) Added the depot name to avoid removing files from another depot with the same directory name.
#39 28037 Russell C. Jackson (Rusty) Improved logic to keep parallel threads at the max the whole time.
#38 28031 Russell C. Jackson (Rusty) Reduced some repetition in the loop to speed p4verify.sh up.
#37 28027 Russell C. Jackson (Rusty) Changed split to 1000 to all for better parallelization.
#36 27945 Russell C. Jackson (Rusty) Redirect rm output to dev null to eliminate cron output.
#35 27941 Russell C. Jackson (Rusty) Lowered sleep time due to the smaller file sizes to verify.
#34 27939 Russell C. Jackson (Rusty) Added P4TMP to path to files
#33 27936 Russell C. Jackson (Rusty) Dropped the file split down to 5000 files per list in order to use the parallel option better.
#32 27910 Russell C. Jackson (Rusty) Removed debugging echo commands.
#31 27863 Russell C. Jackson (Rusty) Fixed logic error.
#30 27859 Russell C. Jackson (Rusty) Fixed typo and background of shelves.
#29 27855 Russell C. Jackson (Rusty) Moved shelf verify to separate log.
#28 27849 Russell C. Jackson (Rusty) Improved wait routine.
#27 27837 Russell C. Jackson (Rusty) Skipping verify on edge and edgerep servers.
#26 27833 Russell C. Jackson (Rusty) Added wait for last file verify to finish before removing files.
#25 27830 Russell C. Jackson (Rusty) MUCH improved parallel verify.
Each thread only verifies 100k files at a time, so you don't run the risk of running out of memory, and it reduces the length of time, thereby reducing timeouts as well.
#24 27793 Russell C. Jackson (Rusty) Added log messages for shelves and unload depot.
#23 27792 Russell C. Jackson (Rusty) Added modprobe dummy command
#22 27672 Russell C. Jackson (Rusty) Updated p4verify.sh to verify on directories so that it still uses parallel over a single large depot
#21 25924 Russell C. Jackson (Rusty) Moved LOGFILE set above get_journalnum to avoid echo of output.
#20 25058 Russell C. Jackson (Rusty) Added if statement to exclude search for MISSING on edge servers.
#19 24183 Russell C. Jackson (Rusty) Put quotes around the instance grep
#18 24052 Russell C. Jackson (Rusty) Added check for empty process variable to avoid grep error.
#17 24046 Russell C. Jackson (Rusty) Added check for the log files as well since we skip those on edge servers.
#16 23855 Russell C. Jackson (Rusty) Added missing echo commands.
#15 23804 Russell C. Jackson (Rusty) Fixed typo.
#14 23749 Russell C. Jackson (Rusty) Updated to skip spec depot on verify -S, and switched to use -F formatting.
#13 23681 Russell C. Jackson (Rusty) Added call to rsync_missing to the end of p4verify.sh
Renamed rsync_shelves.sh to rsync_missing.sh to be more accurate.
#12 23530 Russell C. Jackson (Rusty) Corrected version of p4verify.sh - Picks up the correct verify pids now.
#11 23524 Russell C. Jackson (Rusty) Corrected version of p4verify.sh - Picks up the correct verify pids now.
#10 23500 Russell C. Jackson (Rusty) Added a check to skip the verify of all depots on edge and edge replicas since they are normally run in cache mode.
#9 22982 Russell C. Jackson (Rusty) Added completed message.
#8 22981 Russell C. Jackson (Rusty) Made files writeable so they are easier to update once on the server.
#7 22916 Russell C. Jackson (Rusty) Fixed logic that was missing a running process.
#6 22908 Russell C. Jackson (Rusty) Fixed VerifyFailed setting.
#5 22905 Russell C. Jackson (Rusty) Fixed single thread logic.
#4 22869 Russell C. Jackson (Rusty) Updated to only send email on error.
#3 22835 Russell C. Jackson (Rusty) Replacing p4verify.sh with new version that support parallel.
#2 22814 Russell C. Jackson (Rusty) Added required functions to p4verify.sh
#1 22693 Russell C. Jackson (Rusty) Branched a Unix only version of the SDP.
Removed extra items to create a cleaner tree.
Moved a few items around to make more sense without Windows in the mix.
//guest/perforce_software/sdp/dev/Server/Unix/p4/common/bin/p4verify.sh
#22 22074 Russell C. Jackson (Rusty) Corrected the name of the variable.
Already reviewed with Tom.
#21 22066 Russell C. Jackson (Rusty) Added rotate for p4verify.log instead of just deleting the prior one.
#20 21233 Russell C. Jackson (Rusty) Review 21010 from Adrian commit.
#19 21007 adrian_waters Fix specification of depot path in get_verify_rev_range when -recent used
#18 20995 C. Thomas Tyler Style tweak; using double-square brakets rather than single-square
brackets.
#17 20994 adrian_waters Refactor around changes to support -recent arg - had broken code even where -recent not used because of unbounded variable ($d);  use of the -recent option also fails as 'verify -S' not valid for shelved files (only @= is supported) ;  stripping out archive,unload+remote depots also not working + get_verify_rev_range used depot name incorrectly in changes (eg, changed -m 1 depot/...
rather than //depot/...)

Raised  job000634 for changes.

Further aim is to modify script for depots with no shelved files does not result in an 'error' line being written to p4verify.log - it confuses clients - will do that as a separate change.
#16 20909 Russell C. Jackson (Rusty) Fixed missing LOGFILE variable issue.
#15 20879 Robert Cowham Fix typo in variable name.
#14 20868 C. Thomas Tyler Add '-recent' flag to p4verify.sh to verify only recent changes.

Usage info is added with '-h' and '-man' flags.

This change involved changing the command line parsing to accept
the <instance> positional parameter and '-recent' flag, as well
as standard '-v' and '-D' flags.

This change also should reduce memory requirement in cases where
there are a large number of verify errors.  This was done by
combining greps and tossing 'grep' output to /dev/null, using only
the grep exit code to determine if BAD/MISSING (etc.) appear in the
log.

Added a Version id.  (Need to avoid +k due to the way SDP files
move around from server to server).  This must be updated manually.
#13 20086 Russell C. Jackson (Rusty) Added -t to verify of shelves on a replica, and added verify of shelves on the master.
#12 20083 Russell C. Jackson (Rusty) Added missing echo of command into log file.
#11 19314 Russell C. Jackson (Rusty) Change p4verify.sh to use -S to verify shelves on a replica instead of printing the files
on the shelf.

Removed the HOST_IP settings from mkdirs and instance_vars since it causes problems in
a shared depotdata environment, and it was a temporary fix to work around a bug with
auth.id that is being fixed.
#10 19102 Russell C. Jackson (Rusty) Added check for SHAREDDATA to avoid using -t on a shared data volume replica.
Allows running verify on the replica instead of the master.
#9 16029 C. Thomas Tyler Routine merge to dev from main using:
p4 merge -b perforce_software-sdp-dev
#8 15778 C. Thomas Tyler Routine Merge Down to dev from main.
#7 13906 C. Thomas Tyler Normalized P4INSTANCE to SDP_INSTANCE to get Unix/Windows
implementations in sync.

Reasons:
1. Things that interact with SDP in both Unix and Windows
environments shoudn't have to account for this obscure
SDP difference between Unix and Windows.  (I came across
this doing CBD work).

2. The Windows and Unix scripts have different variable
names for defining the same concept, the SDP instance.
Unix uses P4INSTANCE, while Windows uses SDP_INSTANCE.

3. This instance tag, a data set identifier, is an SDP concept.
I prefer the SDP_INSTANCE name over P4INSTANCE, so I prpose
to normalize to SDP_INSTANCE.

4. The P4INSTANCE name makes it look like a setting that might be
recognized by the p4d itself, which it is not.  (There are other
such things such as P4SERVER that could perhaps be renamed as
a separate task; but I'm not sure we want to totally disallow
the P4 prefix for variable names. It looks too right to be wrong
in same cases, like P4BIN and P4DBIN.  That's a discussion for
another day, outside the scope of this task).

Meanwhile:
* Fixed a bug in the Windows 2013.3 upgrade script that
was referencing undefined P4INSTANCE, as the Windows
environment defined only SDP_INSTANCE.

* Had P4INSTANCE been removed completely, this change would
likely cause trouble for users doing updates for existing
SDP installations.  So, though it involves slight technical debt,
I opted to keep a redundant definition of P4INSTANCE
in p4_vars.template, with comments indicating SDP_INSTANCE should be
used in favor of P4INSTANCE, with a warning that P4INSTANCE
may go away in a future release.  This should avoid unnecessary
upgrade pain.

* In mkdirs.sh, the varialbe name was INSTANCE rather than
SDP_INSTANCE.  I changed that as well.  That required manual
change rather than sub/replace to avoid corrupting other similar
varialbe names (e.g.  MASTERINSTANCE).

This is a trivial change technically (a substitute/replace, plus
tweaks in p4_vars.template), but impacts many files.
#6 13586 C. Thomas Tyler Routine merge down from main -> dev.
Trivial merges, all resolved with 'p4 resolve -as.'
#5 12169 Russell C. Jackson (Rusty) Updated copyright date to 2015

 Updated shell scripts to require an instance parameter to eliminate the need
 for calling p4master_run.    Python and Perl still need it since you have to set the
environment for them to run in.

 Incorporated comments from reviewers. Left the . instead of source as that seems
more common in the field and has the same functionality.
#4 12028 C. Thomas Tyler Refreshed SDP dev branch, merging down from main.
#3 11485 Russell C. Jackson (Rusty) Brought over changes from RCJ sdp to properly handle Edge servers
 and to properly replicate shelves when replicating from Windows to Linux
#2 11476 Russell C. Jackson (Rusty) Fixed echo command to match the actual command run.
#1 10638 C. Thomas Tyler Populate perforce_software-sdp-dev.
//guest/perforce_software/sdp/main/Server/Unix/p4/common/bin/p4verify.sh
#1 10148 C. Thomas Tyler Promoted the Perforce Server Deployment Package to The Workshop.