diff --git a/pg_db_dump_file.sh b/pg_db_dump_file.sh index 24e2390..6920f61 100755 --- a/pg_db_dump_file.sh +++ b/pg_db_dump_file.sh @@ -11,7 +11,7 @@ set -e -u -o pipefail function usage () { cat <<- EOT - Usage: ${0##/*/} [-t] [-s] [-g] [-c] [-r|-a] [-k ] [-n] [-b ] [-i ] [-d [-d ...]] [-e [-e ...]] [-u ] [-h ] [-p ] [-l ] [-L ] + Usage: ${0##/*/} [-t] [-s] [-g] [-c] [-r] [-k ] [-n] [-b ] [-i ] [-d [-d ...]] [-e [-e ...]] [-u ] [-h ] [-p ] [-l ] [-L ] -t: test usage, no real backup is done -s: turn ON ssl mode, default mode is off @@ -28,7 +28,6 @@ function usage () -p : default port is '5432' -l : default password is empty -r: use redhat base paths instead of debian - -a: use amazon base paths instead of debian -L : where to put the dump log file, if not set tries to use PostgreSQL log folder EOT } @@ -67,12 +66,11 @@ _DB_PORT=5432; _EXCLUDE=''; # space separated list of database names _INCLUDE=''; # space seperated list of database names REDHAT=0; -AMAZON=0; # CONN_DB_HOST=''; ERROR=0; # set options -while getopts ":ctsgnk:b:i:d:e:u:h:p:l:L:ram" opt; do +while getopts ":ctsgnk:b:i:d:e:u:h:p:l:L:rm" opt; do # pre test for unfilled if [ "${opt}" = ":" ] || [[ "${OPTARG-}" =~ ${OPTARG_REGEX} ]]; then if [ "${opt}" = ":" ]; then @@ -204,10 +202,6 @@ while getopts ":ctsgnk:b:i:d:e:u:h:p:l:L:ram" opt; do r) REDHAT=1; ;; - # a|amazon) - a) - AMAZON=1; - ;; # L|logpath) L) if [ -z "${LOG_PATH}" ]; then @@ -234,11 +228,6 @@ if [ ${ERROR} -eq 1 ]; then exit 0; fi; -if [ "${REDHAT}" -eq 1 ] && [ "${AMAZON}" -eq 1 ]; then - echo "You cannot set the -a and -r flag at the same time"; - exit 0; -fi; - # if we have numeric keep and keep number is set to 0 abort if [ "${CLEAN_NUMBER}" -eq 1 ] && [ "${KEEP}" -lt 1 ]; then echo "If keep in numbers is on, keep must be at least 1 or higher"; @@ -264,13 +253,6 @@ if [ "${REDHAT}" -eq 1 ]; then if [ -z "${LOG_PATH}" ]; then LOG_PATH="/var/lib/pgsql/${DB_VERSION}/data/log/"; fi; -elif [ "${AMAZON}" -eq 1 ]; then - # only older 9.6 or before - PG_BASE_PATH="/usr/lib64/pgsql"; - # LOG PATH, will be attached to DB VERSION - if [ -z "${LOG_PATH}" ]; then - LOG_PATH="/var/lib/pgsql${DB_VERSION}/data/pg_log"; - fi; else # Debian base path PG_BASE_PATH="/usr/lib/postgresql/"; @@ -362,7 +344,18 @@ fi; # if we have an ident override set, set a different DUMP VERSION here than the automatic one if [ "${SET_IDENT}" -eq 1 ]; then - DUMP_DB_VERSION=$(pgv=$("${PG_PATH}/pg_dump" --version | grep "pg_dump" | cut -d " " -f 3); if [[ $(echo "${pgv}" | cut -d "." -f 1) -ge 10 ]]; then echo "${pgv}" | cut -d "." -f 1; else echo "${pgv}" | cut -d "." -f 1,2; fi ); + DUMP_DB_VERSION=$( + pgv=$( + "${PG_PATH}/pg_dump" --version | \ + grep "pg_dump" | \ + cut -d " " -f 3 + ); + if [[ $(echo "${pgv}" | cut -d "." -f 1) -ge 10 ]]; then + echo "${pgv}" | cut -d "." -f 1; + else + echo "${pgv}" | cut -d "." -f 1,2; + fi + ); else DUMP_DB_VERSION=${DB_VERSION}; fi; @@ -568,7 +561,10 @@ function clean_up TO_DELETE=$((count-KEEP)); echo "- Remove old backups for '${name}', found ${count}, will delete ${TO_DELETE}"; if [ ${TEST} -eq 0 ]; then - find "${BACKUPDIR}" -name "${name}${DB_TYPE}*.sql" -type f -printf "%Ts\t%p\n" | sort -nr | head -n ${TO_DELETE} | xargs rm; + find "${BACKUPDIR}" -name "${name}${DB_TYPE}*.sql" -type f -printf "%Ts\t%p\n" | \ + sort -n | \ + head -n ${TO_DELETE} | \ + xargs rm; else print "find \"${BACKUPDIR}\" -name \"${name}${DB_TYPE}*.sql\" -type f -printf \"%Ts\\t%p\\n\" | sort -nr | head -n ${TO_DELETE} | xargs rm"; fi; diff --git a/pg_drop_restore.sh b/pg_drop_restore.sh index e7a1e29..39ace8a 100755 --- a/pg_drop_restore.sh +++ b/pg_drop_restore.sh @@ -2,14 +2,14 @@ # Author: Clemens Schwaighofer # Description: -# Drop and restore one database +# Drop and restore one database from a dump created by created by pg_db_dump_file.sh function usage () { cat <<- EOT Restores a single database dump to a database - Usage: ${0##/*/} -o -d -f [-h ] [-p ] [-e ] [-i ] [-j ] [-s] [-r|-a] [-n] + Usage: ${0##/*/} -o -d -f [-h ] [-p ] [-e ] [-i ] [-j ] [-s] [-r] [-n] -o : The user who will be owner of the database to be restored -d : The database to restore the file to @@ -21,7 +21,6 @@ function usage () -j : Run how many jobs Parallel. If not set, 2 jobs are run parallel -s: Restore only schema, no data -r: use redhat base paths instead of debian - -a: use amazon base paths instead of debian -n: dry run, do not do anything, just test flow EOT } @@ -29,20 +28,21 @@ function usage () _port=5432 _host='local'; _encoding='UTF8'; -role=''; +# role=''; schema=''; NO_ASK=0; TEMPLATEDB='template0'; SCHEMA_ONLY=0; REDHAT=0; -AMAZON=0; DRY_RUN=0; BC='/usr/bin/bc'; PORT_REGEX="^[0-9]{4,5}$"; OPTARG_REGEX="^-"; MAX_JOBS=''; +PG_PARAMS=(); +PG_PARAM_ROLE=(); # if we have options, set them and then ignore anything below -while getopts ":o:d:h:f:p:e:i:j:raqnms" opt; do +while getopts ":o:d:h:f:p:e:i:j:rqnms" opt; do # pre test for unfilled if [ "${opt}" = ":" ] || [[ "${OPTARG-}" =~ ${OPTARG_REGEX} ]]; then if [ "${opt}" = ":" ]; then @@ -86,71 +86,80 @@ while getopts ":o:d:h:f:p:e:i:j:raqnms" opt; do esac fi; case $opt in - o|owner) + # o|owner) + o) if [ -z "$owner" ]; then owner=$OPTARG; # if not standard user we need to set restore role # so tables/etc get set to new user - role="--no-owner --role $owner"; + # role="--no-owner --role $owner"; + PG_PARAM_ROLE=("--no-owner" "--role" "$owner"); fi; ;; - d|database) + # d|database) + d) if [ -z "$database" ]; then database=$OPTARG; fi; ;; - e|encoding) + # e|encoding) + e) if [ -z "$encoding" ]; then encoding=$OPTARG; fi; ;; - f|file) + # f|file) + f) if [ -z "$file" ]; then file=$OPTARG; fi; ;; - h|hostname) + # h|hostname) + h) if [ -z "$_host" ]; then # if local it is socket if [ "$OPTARG" != "local" ]; then - host='-h '$OPTARG; - else - host=''; + PG_PARAMS+=("-h" "${OPTARG}"); fi; _host=$OPTARG; fi; ;; - p|port) + # p|port) + p) if [ -z "$port" ]; then - port='-p '$OPTARG; + PG_PARAMS+=("-p" "${OPTARG}"); _port=$OPTARG; fi; ;; - i|ident) + # i|ident) + i) if [ -z "$ident" ]; then ident=$OPTARG; fi; ;; - j|jobs) + # j|jobs) + j) MAX_JOBS=${OPTARG}; ;; - q|quiet) + # q|quiet) + q) NO_ASK=1; ;; - r|redhat) + # r|redhat) + r) REDHAT=1; ;; - a|amazon) - AMAZON=1; - ;; - n|dry-run) + # n|dry-run) + n) DRY_RUN=1; ;; - s|schema-only) + # s|schema-only) + s) SCHEMA_ONLY=1 schema='-s'; ;; - m|help) + # m|help) + m) usage; exit 0; ;; @@ -162,10 +171,10 @@ while getopts ":o:d:h:f:p:e:i:j:raqnms" opt; do esac; done; -if [ "$REDHAT" -eq 1 ] && [ "$AMAZON" -eq 1 ]; then - echo "You cannot set the -a and -r flag at the same time"; - exit 1; +if [ "${ERROR}" -eq 1 ]; then + exit 0; fi; + # check that the port is a valid number if ! [[ "$_port" =~ $PORT_REGEX ]]; then echo "The port needs to be a valid number: $_port"; @@ -174,16 +183,15 @@ fi; NUMBER_REGEX="^[0-9]{1,}$"; # find the max allowed jobs based on the cpu count # because setting more than this is not recommended -cpu=$(cat /proc/cpuinfo | grep processor | tail -n 1); -_max_jobs=$[ ${cpu##*: }+1 ] # +1 because cpu count starts with 0 +_max_jobs=$(nproc --all); # if the MAX_JOBS is not number or smaller 1 or greate _max_jobs -if [ ! -z "${MAX_JOBS}" ]; then +if [ -n "${MAX_JOBS}" ]; then # check that it is a valid number if ! [[ "$MAX_JOBS" =~ $NUMBER_REGEX ]]; then echo "Please enter a number for the -j option"; exit 1; fi; - if [ "${MAX_JOBS}" -lt 1 ] || [ "${MAX_JOBS}" -gt ${_max_jobs} ]; then + if [ "${MAX_JOBS}" -lt 1 ] || [ "${MAX_JOBS}" -gt "${_max_jobs}" ]; then echo "The value for the jobs option -j cannot be smaller than 1 or bigger than ${_max_jobs}"; exit 1; fi; @@ -208,22 +216,21 @@ fi; # PARAMS: timestamp in seconds or with milliseconds (nnnn.nnnn) # RETURN: formated string with human readable time (d/h/m/s) # CALL : var=$(convert_time $timestamp); -# DESC : converts a timestamp or a timestamp with float milliseconds -# to a human readable format +# DESC : converts a timestamp or a timestamp with float milliseconds to a human readable format # output is in days/hours/minutes/seconds function convert_time { timestamp=${1}; # round to four digits for ms - timestamp=$(printf "%1.4f" $timestamp); + timestamp=$(printf "%1.4f" "$timestamp"); # get the ms part and remove any leading 0 - ms=$(echo ${timestamp} | cut -d "." -f 2 | sed -e 's/^0*//'); - timestamp=$(echo ${timestamp} | cut -d "." -f 1); + ms=$(echo "${timestamp}" | cut -d "." -f 2 | sed -e 's/^0*//'); + timestamp=$(echo "${timestamp}" | cut -d "." -f 1); timegroups=(86400 3600 60 1); # day, hour, min, sec timenames=("d" "h" "m" "s"); # day, hour, min, sec output=( ); - time_string=; - for timeslice in ${timegroups[@]}; do + time_string=''; + for timeslice in "${timegroups[@]}"; do # floor for the division, push to output if [ ${BC_OK} -eq 1 ]; then output[${#output[*]}]=$(echo "${timestamp}/${timeslice}" | bc); @@ -235,15 +242,19 @@ function convert_time done; for ((i=0; i<${#output[@]}; i++)); do - if [ ${output[$i]} -gt 0 ] || [ ! -z "$time_string" ]; then - if [ ! -z "${time_string}" ]; then + if [ "${output[$i]}" -gt 0 ] || [ -n "$time_string" ]; then + if [ -n "${time_string}" ]; then time_string=${time_string}" "; fi; time_string=${time_string}${output[$i]}${timenames[$i]}; fi; done; - if [ ! -z ${ms} ] && [ ${ms} -gt 0 ];; then - time_string=${time_string}" "${ms}"ms"; + # milliseconds must be filled, but we also check that they are non "nan" string + # that can appear in the original value + if [ -n "${ms}" ] && [ "${ms}" != "nan" ]; then + if [ "${ms}" -gt 0 ]; then + time_string="${time_string} ${ms}ms"; + fi; fi; # just in case the time is 0 if [ -z "${time_string}" ]; then @@ -253,20 +264,20 @@ function convert_time } # for the auto find, we need to get only the filename, and therefore remove all path info -db_file=`basename $file`; +db_file=$(basename "$file"); # if file is set and exist, but no owner or database are given, use the file name data to get user & database -if [ -r "$file" ] && ( [ ! "$owner" ] || [ ! "$database" ] || [ ! "$encoding" ] ); then +if [ -r "$file" ] && { [ ! "$owner" ] || [ ! "$database" ] || [ ! "$encoding" ]; }; then # file name format is # ...-____