#!/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. | ||