diff --git a/client/CHANGELOG.md b/client/CHANGELOG.md new file mode 100644 index 0000000..7311efb --- /dev/null +++ b/client/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added + +### Changed + +* Use --dump-dir instead of --backup-dir to supress dump-server-state warning + +### Deprecated + +### Removed + +### Fixed + +* Make start_time and stop_time compatible with OpenBSD + +### Security + +## [22.03] + +Split client and server parts of the project diff --git a/zzz_evobackup b/client/zzz_evobackup similarity index 74% rename from zzz_evobackup rename to client/zzz_evobackup index ee47aa6..92b34a9 100755 --- a/zzz_evobackup +++ b/client/zzz_evobackup @@ -20,6 +20,8 @@ set -u ##### Configuration ################################################### +VERSION="22.03" + # email adress for notifications MAIL=jdoe@example.com @@ -38,18 +40,23 @@ LOCAL_BACKUP_DIR="/home/backup" # You can set "linux" or "bsd" manually or let it choose automatically SYSTEM=$(uname | tr '[:upper:]' '[:lower:]') -# Store pid and logs in a file named after this program's name -PROGNAME=$(basename $0) +# Store pid in a file named after this program's name +PROGNAME=$(basename "$0") PIDFILE="/var/run/${PROGNAME}.pid" -LOGFILE="/var/log/${PROGNAME}.log" + +# Customize the log path if you have multiple scripts and with separate logs +LOGFILE="/var/log/evobackup.log" # Enable/Disable tasks LOCAL_TASKS=${LOCAL_TASKS:-1} SYNC_TASKS=${SYNC_TASKS:-1} +HOSTNAME=$(hostname) + ##### SETUP AND FUNCTIONS ############################################# -BEGINNING=$(/bin/date +"%d-%m-%Y ; %H:%M") +START_EPOCH=$(/bin/date +%s) +DATE_FORMAT="%Y-%m-%d %H:%M:%S" # shellcheck disable=SC2174 mkdir -p -m 700 ${LOCAL_BACKUP_DIR} @@ -84,6 +91,7 @@ test_server() { else # SSH connection failed new_error=$(printf "Failed to connect to \`%s' within %s seconds" "${item}" "${SSH_CONNECT_TIMEOUT}") + log "${new_error}" SERVERS_SSH_ERRORS=$(printf "%s\\n%s" "${SERVERS_SSH_ERRORS}" "${new_error}" | sed -e '/^$/d') return 1 @@ -97,17 +105,16 @@ pick_server() { if [ "${increment}" -ge "${list_length}" ]; then # We've reached the end of the list new_error="No more server available" + log "${new_error}" SERVERS_SSH_ERRORS=$(printf "%s\\n%s" "${SERVERS_SSH_ERRORS}" "${new_error}" | sed -e '/^$/d') # Log errors to stderr printf "%s\\n" "${SERVERS_SSH_ERRORS}" >&2 - # Log errors to logfile - printf "%s\\n" "${SERVERS_SSH_ERRORS}" >> $LOGFILE return 1 fi # Extract the day of month, without leading 0 (which would give an octal based number) - today=$(date +%e) + today=$(/bin/date +%e) # A salt is useful to randomize the starting point in the list # but stay identical each time it's called for a server (based on hostname). salt=$(hostname | cksum | cut -d' ' -f1) @@ -119,6 +126,15 @@ pick_server() { echo "${SERVERS}" | cut -d' ' -f${field} } +log() { + msg="${1:-$(cat /dev/stdin)}" + pid=$$ + printf "[%s] %s[%s]: %s\\n" \ + "$(/bin/date +"${DATE_FORMAT}")" "${PROGNAME}" "${pid}" "${msg}" \ + >> "${LOGFILE}" +} + +log "START GLOBAL - VERSION=${VERSION} LOCAL_TASKS=${LOCAL_TASKS} SYNC_TASKS=${SYNC_TASKS}" ## Verify other evobackup process and kill if needed if [ -e "${PIDFILE}" ]; then @@ -133,16 +149,18 @@ if [ -e "${PIDFILE}" ]; then kill -9 "${pid}" printf "%s is still running (PID %s). Process has been killed" "$0" "${pid}\\n" >&2 else - rm -f ${PIDFILE} + rm -f "${PIDFILE}" fi fi -echo "$$" > ${PIDFILE} +echo "$$" > "${PIDFILE}" # shellcheck disable=SC2064 trap "rm -f ${PIDFILE}" EXIT ##### LOCAL BACKUP #################################################### if [ "${LOCAL_TASKS}" = "1" ]; then + log "START LOCAL_TASKS" + # You can comment or uncomment sections below to customize the backup ## OpenLDAP : example with slapcat @@ -173,6 +191,9 @@ if [ "${LOCAL_TASKS}" = "1" ]; then # mkdir -p -m 700 ${LOCAL_BACKUP_DIR}/mysql/ # pt-show-grants --flush --no-header > ${LOCAL_BACKUP_DIR}/mysql/all_grants.sql + # Dump all variables + # mysql -A -e"SHOW GLOBAL VARIABLES;" > ${LOCAL_BACKUP_DIR}/MySQLCurrentSettings.txt + ## example with SQL dump (schema only, no data) for each databases # mkdir -p -m 700 ${LOCAL_BACKUP_DIR}/mysql/ # for i in $(mysql --defaults-extra-file=/etc/mysql/debian.cnf -P 3306 -e 'show databases' -s --skip-column-names \ @@ -210,9 +231,9 @@ if [ "${LOCAL_TASKS}" = "1" ]; then ## PostgreSQL ## Purge previous dumps - # rm ${LOCAL_BACKUP_DIR}/pg.*.gz - # rm ${LOCAL_BACKUP_DIR}/pg-backup.tar - # rm ${LOCAL_BACKUP_DIR}/postgresql/* + # rm -rf ${LOCAL_BACKUP_DIR}/pg.*.gz + # rm -rf ${LOCAL_BACKUP_DIR}/pg-backup.tar + # rm -rf ${LOCAL_BACKUP_DIR}/postgresql/* ## example with pg_dumpall (warning: you need space in ~postgres) # su - postgres -c "pg_dumpall > ~/pg.dump.bak" # mv ~postgres/pg.dump.bak ${LOCAL_BACKUP_DIR}/ @@ -283,7 +304,7 @@ if [ "${LOCAL_TASKS}" = "1" ]; then # for snapshot in $(curl -s -XGET "localhost:9200/_snapshot/snaprepo/_all?pretty=true" | grep -Eo 'snapshot_[0-9]{4}-[0-9]{2}-[0-9]{2}' | head -n -10); do # curl -s -XDELETE "localhost:9200/_snapshot/snaprepo/${snapshot}" | grep -v -Fx '{"acknowledged":true}' # done - # date=$(date +%F) + # date=$(/bin/date +%F) # curl -s -XPUT "localhost:9200/_snapshot/snaprepo/snapshot_${date}?wait_for_completion=true" -o /tmp/es_snapshot_${date}.log ## RabbitMQ @@ -295,104 +316,126 @@ if [ "${LOCAL_TASKS}" = "1" ]; then #megacli -CfgSave -f ${LOCAL_BACKUP_DIR}/megacli_conf.dump -a0 >/dev/null - ## Dump system and kernel versions - uname -a > ${LOCAL_BACKUP_DIR}/uname - ## Dump network routes with mtr and traceroute (warning: could be long with aggressive firewalls) for addr in 8.8.8.8 www.evolix.fr travaux.evolix.net; do mtr -r ${addr} > ${LOCAL_BACKUP_DIR}/mtr-${addr} traceroute -n ${addr} > ${LOCAL_BACKUP_DIR}/traceroute-${addr} 2>&1 done - ## Dump process with ps - ps auwwx >${LOCAL_BACKUP_DIR}/ps.out + server_state_dir="${LOCAL_BACKUP_DIR}/server-state" + + dump_server_state_bin=$(command -v dump-server-state) if [ "${SYSTEM}" = "linux" ]; then - ## Dump network connections with ss - ss -taupen > ${LOCAL_BACKUP_DIR}/netstat.out + if [ -n "${dump_server_state_bin}" ]; then + ${dump_server_state_bin} --all --force --dump-dir "${server_state_dir}" + else + mkdir -p "${server_state_dir}" - ## List Debian packages - dpkg -l > ${LOCAL_BACKUP_DIR}/packages - dpkg --get-selections > ${LOCAL_BACKUP_DIR}/packages.getselections - apt-cache dumpavail > ${LOCAL_BACKUP_DIR}/packages.available + ## Dump system and kernel versions + uname -a > ${server_state_dir}/uname.txt - ## Dump MBR / table partitions - disks=$(lsblk -l | grep disk | grep -v -E '(drbd|fd[0-9]+)' | awk '{print $1}') - for disk in ${disks}; do - dd if="/dev/${disk}" of="${LOCAL_BACKUP_DIR}/MBR-${disk}" bs=512 count=1 2>&1 | grep -Ev "(records in|records out|512 bytes)" - fdisk -l "/dev/${disk}" > "${LOCAL_BACKUP_DIR}/partitions-${disk}" 2>&1 - done - cat ${LOCAL_BACKUP_DIR}/partitions-* > ${LOCAL_BACKUP_DIR}/partitions + ## Dump process with ps + ps auwwx > ${server_state_dir}/ps.txt - ## Dump iptables - if [ -x /sbin/iptables ]; then - { /sbin/iptables -L -n -v; /sbin/iptables -t filter -L -n -v; } > ${LOCAL_BACKUP_DIR}/iptables.txt - fi + ## Dump network connections with ss + ss -taupen > ${server_state_dir}/netstat.txt - ## Dump findmnt(8) output - FINDMNT_BIN=$(command -v findmnt) - if [ -x "${FINDMNT_BIN}" ]; then - ${FINDMNT_BIN} > ${LOCAL_BACKUP_DIR}/findmnt.txt + ## List Debian packages + dpkg -l > ${server_state_dir}/packages + dpkg --get-selections > ${server_state_dir}/packages.getselections + apt-cache dumpavail > ${server_state_dir}/packages.available + + ## Dump iptables + if [ -x /sbin/iptables ]; then + { /sbin/iptables -L -n -v; /sbin/iptables -t filter -L -n -v; } > ${server_state_dir}/iptables.txt + fi + + ## Dump findmnt(8) output + FINDMNT_BIN=$(command -v findmnt) + if [ -x "${FINDMNT_BIN}" ]; then + ${FINDMNT_BIN} > ${server_state_dir}/findmnt.txt + fi + + ## Dump MBR / table partitions + disks=$(lsblk -l | grep disk | grep -v -E '(drbd|fd[0-9]+)' | awk '{print $1}') + for disk in ${disks}; do + dd if="/dev/${disk}" of="${server_state_dir}/MBR-${disk}" bs=512 count=1 2>&1 | grep -Ev "(records in|records out|512 bytes)" + fdisk -l "/dev/${disk}" > "${server_state_dir}/partitions-${disk}" 2>&1 + done + cat ${server_state_dir}/partitions-* > ${server_state_dir}/partitions fi else - ## Dump network connections with fstat - fstat | head -1 > ${LOCAL_BACKUP_DIR}/netstat.out - fstat | grep internet >> ${LOCAL_BACKUP_DIR}/netstat.out + if [ -n "${dump_server_state_bin}" ]; then + ${dump_server_state_bin} --all --force --backup-dir "${server_state_dir}" + else + mkdir -p "${server_state_dir}" - ## List OpenBSD packages - pkg_info -m > ${LOCAL_BACKUP_DIR}/packages + ## Dump system and kernel versions + uname -a > ${server_state_dir}/uname - ## Dump MBR / table partitions - disklabel sd0 > ${LOCAL_BACKUP_DIR}/partitions + ## Dump process with ps + ps auwwx > ${server_state_dir}/ps.out - ## Dump pf infos - pfctl -sa > ${LOCAL_BACKUP_DIR}/pfctl-sa.txt + ## Dump network connections with fstat + fstat | head -1 > ${server_state_dir}/netstat.out + fstat | grep internet >> ${server_state_dir}/netstat.out + ## List OpenBSD packages + pkg_info -m > ${server_state_dir}/packages + + ## Dump MBR / table partitions + disklabel sd0 > ${server_state_dir}/partitions + + ## Dump pf infos + pfctl -sa > ${server_state_dir}/pfctl-sa.txt + fi fi ## Dump rights - #getfacl -R /var > ${LOCAL_BACKUP_DIR}/rights-var.txt - #getfacl -R /etc > ${LOCAL_BACKUP_DIR}/rights-etc.txt - #getfacl -R /usr > ${LOCAL_BACKUP_DIR}/rights-usr.txt - #getfacl -R /home > ${LOCAL_BACKUP_DIR}/rights-home.txt + #getfacl -R /var > ${server_state_dir}/rights-var.txt + #getfacl -R /etc > ${server_state_dir}/rights-etc.txt + #getfacl -R /usr > ${server_state_dir}/rights-usr.txt + #getfacl -R /home > ${server_state_dir}/rights-home.txt + log "STOP LOCAL_TASKS" fi ##### REMOTE BACKUP ################################################### -n=0 -server="" -if [ "${SERVERS_FALLBACK}" = "1" ]; then - # We try to find a suitable server - while :; do - server=$(pick_server "${n}") - test $? = 0 || exit 2 - - if test_server "${server}"; then - break - else - server="" - n=$(( n + 1 )) - fi - done -else - # we force the server - server=$(pick_server "${n}") -fi - -SSH_SERVER=$(echo "${server}" | cut -d':' -f1) -SSH_PORT=$(echo "${server}" | cut -d':' -f2) - -HOSTNAME=$(hostname) - -if [ "${SYSTEM}" = "linux" ]; then - rep="/bin /boot /lib /opt /sbin /usr" -else - rep="/bsd /bin /sbin /usr" -fi - if [ "${SYNC_TASKS}" = "1" ]; then + n=0 + server="" + if [ "${SERVERS_FALLBACK}" = "1" ]; then + # We try to find a suitable server + while :; do + server=$(pick_server "${n}") + test $? = 0 || exit 2 + + if test_server "${server}"; then + break + else + server="" + n=$(( n + 1 )) + fi + done + else + # we force the server + server=$(pick_server "${n}") + fi + + SSH_SERVER=$(echo "${server}" | cut -d':' -f1) + SSH_PORT=$(echo "${server}" | cut -d':' -f2) + + if [ "${SYSTEM}" = "linux" ]; then + rep="/bin /boot /lib /opt /sbin /usr" + else + rep="/bsd /bin /sbin /usr" + fi + + log "START SYNC_TASKS - server=${server}" + # /!\ DO NOT USE COMMENTS in the rsync command /!\ # It breaks the command and destroys data, simply remove (or add) lines. @@ -425,13 +468,13 @@ if [ "${SYNC_TASKS}" = "1" ]; then --exclude "/var/lib/postgresql" \ --exclude "/var/lib/sympa" \ --exclude "/var/lock" \ - --exclude "/var/log" \ - --exclude "/var/log/evobackup*" \ --exclude "/var/run" \ --exclude "/var/spool/postfix" \ --exclude "/var/spool/smtpd" \ --exclude "/var/spool/squid" \ --exclude "/var/state" \ + --exclude "/var/tmp" \ + --exclude "lxc/*/rootfs/tmp" \ --exclude "lxc/*/rootfs/usr/doc" \ --exclude "lxc/*/rootfs/usr/obj" \ --exclude "lxc/*/rootfs/usr/share/doc" \ @@ -444,6 +487,7 @@ if [ "${SYNC_TASKS}" = "1" ]; then --exclude "lxc/*/rootfs/var/log" \ --exclude "lxc/*/rootfs/var/run" \ --exclude "lxc/*/rootfs/var/state" \ + --exclude "lxc/*/rootfs/var/tmp" \ --exclude "/home/mysqltmp" \ ${rep} \ /etc \ @@ -453,20 +497,24 @@ if [ "${SYNC_TASKS}" = "1" ]; then -e "${RSH_COMMAND}" \ "root@${SSH_SERVER}:/var/backup/" \ | tail -30 >> $LOGFILE + + log "STOP SYNC_TASKS - server=${server}" fi ##### REPORTING ####################################################### -END=$(/bin/date +"%d-%m-%Y ; %H:%M") +STOP_EPOCH=$(/bin/date +%s) -printf "EvoBackup - %s - START %s ON %s (LOCAL_TASKS=%s SYNC_TASKS=%s)\\n" \ - "${HOSTNAME}" "${BEGINNING}" "${SSH_SERVER}" "${LOCAL_TASKS}" "${SYNC_TASKS}" \ - >> $LOGFILE +if [ "${SYSTEM}" = "openbsd" ]; then + start_time=$(/bin/date -f "%s" -j "${START_EPOCH}" +"${DATE_FORMAT}") + stop_time=$(/bin/date -f "%s" -j "${STOP_EPOCH}" +"${DATE_FORMAT}") +else + start_time=$(/bin/date --date="@${START_EPOCH}" +"${DATE_FORMAT}") + stop_time=$(/bin/date --date="@${STOP_EPOCH}" +"${DATE_FORMAT}") +fi +duration=$(( STOP_EPOCH - START_EPOCH )) -printf "EvoBackup - %s - STOP %s ON %s (LOCAL_TASKS=%s SYNC_TASKS=%s)\\n" \ - "${HOSTNAME}" "${END}" "${SSH_SERVER}" "${LOCAL_TASKS}" "${SYNC_TASKS}" \ - >> $LOGFILE +log "STOP GLOBAL - start='${start_time}' stop='${stop_time}' duration=${duration}s" -tail -10 $LOGFILE | \ - mail -s "[info] EvoBackup - Client ${HOSTNAME}" \ - ${MAIL} +tail -20 "${LOGFILE}" \ + | mail -s "[info] EvoBackup - Client ${HOSTNAME}" ${MAIL} diff --git a/.gitignore b/server/.gitignore similarity index 100% rename from .gitignore rename to server/.gitignore diff --git a/CHANGELOG.md b/server/CHANGELOG.md similarity index 94% rename from CHANGELOG.md rename to server/CHANGELOG.md index 144f9c3..80f6568 100644 --- a/CHANGELOG.md +++ b/server/CHANGELOG.md @@ -6,10 +6,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added - -### Changed - ### Deprecated ### Removed @@ -18,6 +14,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security +## [22.04] - 2022-04-20 + +### Added + +* Run the test suite on Bullseye (ext4/btrfs) in addition of Stretch and Buster (ext4/btrfs) +* Tell sed to follow symlinks +* Add a header in `bkctld status` output and improved columns width. +* bkctld-check-setup: compatibility with minifirewall 22.03+ + +### Changed + +* change versioning pattern + ## [2.12.0] - 2021-11-02 ### Changed diff --git a/LICENSE b/server/LICENSE similarity index 100% rename from LICENSE rename to server/LICENSE diff --git a/README.md b/server/README.md similarity index 100% rename from README.md rename to server/README.md diff --git a/Vagrantfile b/server/Vagrantfile similarity index 92% rename from Vagrantfile rename to server/Vagrantfile index 9791669..796fc2b 100644 --- a/Vagrantfile +++ b/server/Vagrantfile @@ -28,8 +28,8 @@ DEBIAN_FRONTEND=noninteractive apt-get -yq install openssh-server btrfs-progs rs SCRIPT $pre_part = <