#!/bin/bash #------------------------------------------------------------------------------ # Copyright (c) Perforce Software, Inc., 2007-2014. All rights reserved # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1 Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE # SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. #------------------------------------------------------------------------------ # Common functions used in all backup scripts. check_vars () { if [ -z "$P4INSTANCE" -o -z "$P4HOME" -o -z "$P4PORT" -o -z "$P4ROOT" -o -z "$P4JOURNAL" -o -z "$P4BIN" -o -z "$P4DBIN" -o -z "$P4TICKETS" -o -z "$KEEPCKPS" -o -z "$KEEPLOGS" -o -z "$CHECKPOINTS" -o -z "$LOGS" ]; then echo "Use p4master_run when calling this script." echo "Required external variable not set. Abort!" exit 1 fi } set_vars () { RC=/etc/init.d/p4d_${P4INSTANCE}_init [ -f "$RC" ] || RC=/p4/$P4INSTANCE/bin/p4d_${P4INSTANCE}_init LOGFILE=$LOGS/checkpoint.log OFFLINE_DB=${P4HOME}/offline_db P4SERVER=p4_${P4INSTANCE} SAVEDIR=${P4ROOT}/save EDGESERVER=0 if [ -f ${P4ROOT}/server.id ]; then SERVERNAME=`cat ${P4ROOT}/server.id` $P4BIN -u $P4USER -p $P4PORT server -o $SERVERNAME | grep ^Services | grep "edge-server" > /dev/null if [ `echo $?` -eq 0 ]; then EDGESERVER=1 fi fi } log () { echo -n `date` 2>&1 >> "$LOGFILE" echo " $prog: $@" 2>&1 >> "$LOGFILE" } die () { # send mail and exit # mail the error (with more helpful subject line than cron) log "$@" echo "$0: $@" | $MAIL -s "$HOSTNAME $P4SERVER checkpoint failed" $MAILTO exit 1 } checkdir () { local dir=$1 [ -w $dir ] && return if [ "$check" = 1 ] # --check, run interactively. just tell user. then echo "$0: $dir is not writable!" dirs_ok=false else die "$0: $dir is not writable. Abort!" fi } check_dirs () { # Check that key dirs are writable dirs_ok=true for dir in $OFFLINE_DB $CHECKPOINTS $LOGS; do checkdir $dir # aborts on failure. done } check_disk_space () { # Add the results of df -h or df -m to the log file. log "Checking disk space..." $P4BIN diskspace >> "$LOGFILE" 2>&1 } get_journalnum () { # get the current journal and checkpoint serial numbers. JOURNALNUM=`$P4BIN -u $P4USER -p $P4PORT counter journal 2>> $LOGFILE` || \ die "Cannot get the checkpoint number. Abort!" # If we are on an edge server, the journal has already rotated, so we have to decrement the value # so that we replay the correct journal file and create the correct checkpoint number on the # edge server. if [ $EDGESERVER -eq 1 ]; then JOURNALNUM=$(($JOURNALNUM - 1)) fi CHECKPOINTNUM=$(($JOURNALNUM + 1)) } get_offline_journal_num () { # Get the journal number of the offline database OFFLINEJNLNUM=`$P4DBIN -r $OFFLINE_DB -jd - db.counters | grep '@journal@' | cut -d "@" -f 8 2>> $LOGFILE` || \ die "Cannot get the offline journal number. Abort!" log "Offline journal number is: $OFFLINEJNLNUM" } replay_journals_to_offline_db () { log "Replay any unreplayed journals to the offline database" for (( j=$OFFLINEJNLNUM; $j <= (($JOURNALNUM-1)); j++ )); do log "Replay journal ${P4SERVER}.jnl.${OFFLINEJNLNUM} to offline db." # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $OFFLINE_DB -J off -jr ${CHECKPOINTS}/${P4SERVER}.jnl.${j}; } \ >> "$LOGFILE" 2>&1 || { die "Offline journal replay failed. Abort!"; } done } remove_old_checkpoints_and_journals () { if [ $KEEPCKPS -eq 0 ]; then log "Skipping cleanup of old checkpoints because KEEPCKPS is set to 0." elif [ $(($JOURNALNUM-$KEEPCKPS)) -gt 7 ]; then log "Deleting obsolete checkpoints and journals. Keeping latest $KEEPCKPS per KEEPCKPS setting in p4_vars." # Remove selected checkpoint and journal files based on # journal counter, regardless of whether compressed or not. for (( j=0; $j <= (($JOURNALNUM-$KEEPCKPS)); j++ )); do I_CKPFILE=${CHECKPOINTS}/${P4SERVER}.ckp.$j I_JNLFILE=${CHECKPOINTS}/${P4SERVER}.jnl.$j if [ -f "$I_CKPFILE" ]; then log "rm -f $I_CKPFILE" rm -f "$I_CKPFILE" fi if [ -f "${I_CKPFILE}.md5" ]; then log "rm -f ${I_CKPFILE}.md5" rm -f "${I_CKPFILE}.md5" fi if [ -f "$I_JNLFILE" ]; then log "rm -f $I_JNLFILE" rm -f "$I_JNLFILE" fi I_CKPFILE=${CHECKPOINTS}/${P4SERVER}.ckp.$j.gz I_JNLFILE=${CHECKPOINTS}/${P4SERVER}.jnl.$j.gz if [ -f "$I_CKPFILE" ]; then log "rm -f $I_CKPFILE" rm -f "$I_CKPFILE" fi if [ -f "${I_CKPFILE}.md5" ]; then log "rm -f ${I_CKPFILE}.md5" rm -f "${I_CKPFILE}.md5" fi if [ -f "$I_JNLFILE" ]; then log "rm -f $I_JNLFILE" rm -f "$I_JNLFILE" fi done else log "No old checkpoints and journals need to be deleted." fi } stop_p4d () { log "Shutting down the p4 server" $RC stop >> "$LOGFILE" 2>&1 COUNTER=`ps -ef | grep -i $P4DBIN | grep -v grep | wc -l` while [ $COUNTER != "0" ] do sleep 5 COUNTER=`ps -ef | grep -i $P4DBIN | grep -v grep | wc -l` done log "p4 stop finished -- p4 should be down now." } start_p4d () { log "Starting the p4 server" $RC start >> "$LOGFILE" 2>&1 sleep 1 # Give it a second to start up # Confirm that it started - success below means it did if $P4BIN -u $P4USER -p $P4PORT info >/dev/null 2>&1 ; then log "Server restarted successfully - p4 should be back up now." else log "Error: Server does not appear to have started." fi } truncate_journal () { [[ -f ${CHECKPOINTS}/${P4SERVER}.ckp.${CHECKPOINTNUM}.gz ]] && die "Checkpoint ${CHECKPOINTS}/${P4SERVER}.ckp.${CHECKPOINTNUM}.gz already exists, check the backup process." if [ $EDGESERVER -eq 0 ]; then [[ -f ${CHECKPOINTS}/${P4SERVER}.jnl.${JOURNALNUM} ]] && die "Jounrnal ${CHECKPOINTS}/${P4SERVER}.jnl.${JOURNALNUM} already exists, check the backup process." log "Truncating journal..." # 'p4d -jj' does a copy-then-delete, instead of a simple mv. # during 'p4d -jj' the perforce server will hang the responses to clients. # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $P4ROOT -J $P4JOURNAL -jj ${CHECKPOINTS}/${P4SERVER}; } \ >> "$LOGFILE" 2>&1 || \ { start_p4d; die "Journal rotation failed. Abort!"; } fi } replay_journal_to_offline_db () { log "Replay journal to offline db." # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $OFFLINE_DB -J off -jr ${CHECKPOINTS}/${P4SERVER}.jnl.${JOURNALNUM}; } \ >> "$LOGFILE" 2>&1 || \ { die "Journal replay failed. Abort!"; } } replay_active_journal_to_offline_db () { log "Replay active journal to offline db." # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $OFFLINE_DB -J off -jr ${P4JOURNAL}; } \ >> "$LOGFILE" 2>&1 || \ { die "Active Journal replay failed. Abort!"; } } dump_checkpoint () { log "Dump out new checkpoint from db files in $ROOTDIR." # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $ROOTDIR -jd -z ${CHECKPOINTS}/${P4SERVER}.ckp.${CHECKPOINTNUM}.gz; } \ >> "$LOGFILE" 2>&1 || \ { die "ERROR - New checkpoint dump failed!"; } } recreate_offline_db_files () { log "Recreate offline db files for quick recovery process." rm -f ${OFFLINE_DB}/db.* >> "$LOGFILE" # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $OFFLINE_DB -J off -jr -z ${CHECKPOINTS}/${P4SERVER}.ckp.${CHECKPOINTNUM}.gz; } \ >> "$LOGFILE" 2>&1 || \ { log "ERROR - Restore of checkpoint to $OFFLINE_DB failed!"; } } recreate_weekly_offline_db_files () { log "Recreate offline db files for quick recovery process." rm -f ${OFFLINE_DB}/db.* >> "$LOGFILE" # curly braces are necessary to capture the output of 'time' { time $P4DBIN -r $OFFLINE_DB -J off -jr -z ${CHECKPOINTS}/${P4SERVER}.ckp.${JOURNALNUM}.gz; } \ >> "$LOGFILE" 2>&1 || \ { die "ERROR - Restore of checkpoint to $OFFLINE_DB failed!"; } } # At the start of each run for live_checkpoint.sh, daily_backup.sh, and # weekly_backup.sh, before *any* logging activity occurs, rotate the logs # from the most recent prior run, always named "checkpoint.log" or "log". rotate_last_run_logs () { # Rotate prior checkpoint.log [[ -f "$LOGFILE" ]] && mv -f "$LOGFILE" "$LOGFILE.$JOURNALNUM" # Rotate prior server log. if [ -f "$LOGS/log" ]; then mv -f "$LOGS/log" "$LOGS/log.$JOURNALNUM" >> $LOGFILE 2>&1 cd "$LOGS" gzip "log.$JOURNALNUM" >> $LOGFILE 2>&1 cd - > /dev/null fi # Rotate prior broker log. if [ -f "$LOGS/p4broker.log" ]; then mv -f "$LOGS/p4broker.log" "$LOGS/p4broker.log.$JOURNALNUM" >> $LOGFILE 2>&1 cd "$LOGS" gzip "p4broker.log.$JOURNALNUM" >> $LOGFILE 2>&1 cd - > /dev/null fi # Rotate prior audit log. if [ -f "$LOGS/audit.log" ]; then mv -f "$LOGS/audit.log" "$LOGS/audit.log.$JOURNALNUM" >> $LOGFILE 2>&1 cd "$LOGS" gzip "audit.log.$JOURNALNUM" >> $LOGFILE 2>&1 cd - > /dev/null fi } remove_old_logs () { # Remove old Checkpoint Logs # Use KEEPCKPS rather than KEEPLOGS, so we keep the same number # of checkpoint logs as we keep checkpoints. # Avoid automatically removing #'s 1-7 in any case. if [ $KEEPCKPS -eq 0 ]; then log "Skipping cleanup of old checkpoint logs because KEEPCKPS is set to 0." elif [ $(($JOURNALNUM-$KEEPCKPS)) -gt 7 ]; then log "Deleting old checkpoint logs. Keeping latest $KEEPCKPS, per KEEPCKPS setting in p4_vars." for (( j=0; $j <= (($JOURNALNUM-$KEEPCKPS)); j++ )); do I_LOGFILE="$LOGS/checkpoint.log.$j" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi done else log "No old checkpoint logs need to be deleted." fi if [ $KEEPLOGS -eq 0 ]; then log "Skipping cleanup of old server logs because KEEPLOGS is set to 0." elif [ $(($JOURNALNUM-$KEEPLOGS)) -gt 7 ]; then log "Deleting old server logs. Keeping latest $KEEPLOGS, per KEEPLOGS setting in p4_vars." for (( j=0; $j <= (($JOURNALNUM-$KEEPLOGS)); j++ )); do I_LOGFILE="$LOGS/log.$j" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi I_LOGFILE="$LOGS/log.$j.gz" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi done for (( j=0; $j <= (($JOURNALNUM-$KEEPLOGS)); j++ )); do I_LOGFILE="$LOGS/p4broker.log.$j" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi I_LOGFILE="$LOGS/p4broker.log.$j.gz" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi done for (( j=8; $j <= (($JOURNALNUM-$KEEPLOGS)); j++ )); do I_LOGFILE="$LOGS/audit.log.$j" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi I_LOGFILE="$LOGS/audit.log.$j.gz" if [ -f "$I_LOGFILE" ]; then log "rm -f $I_LOGFILE" rm -f "$I_LOGFILE" fi done else log "No old server logs need to be deleted." fi }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 15789 | alan_petersen | Merging latest revision | ||
#2 | 15465 | alan_petersen | Merging using sdp_alan_petersen | ||
#1 | 10151 | alan_petersen |
Populate //guest/alan_petersen/sdp/... from //guest/perforce_software/sdp/.... |
||
//guest/perforce_software/sdp/main/Server/Unix/p4/common/bin/backup_functions.sh | |||||
#1 | 10148 | C. Thomas Tyler | Promoted the Perforce Server Deployment Package to The Workshop. |