diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8fe4fa --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.project diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..3e9f6c9 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Jens Berthold + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README b/README deleted file mode 100644 index 8292524..0000000 --- a/README +++ /dev/null @@ -1,7 +0,0 @@ -============================================================= - This is the repository for all scripts from ZabbixZone Blog - http://zabbixzone.com - - Fell free to send your contribution, bugs and suggestions - Ricardo Santos (rsantos at gmail.com) -============================================================= diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f572dd --- /dev/null +++ b/README.md @@ -0,0 +1,99 @@ +# Backup script for Zabbix configuration data (MySQL/PostgreSQL) + +This is a MySQL/PostgreSQL database backup script for the [Zabbix](http://www.zabbix.com/) monitoring software from version 1.3.1 up to 4.4. + +## Download + +Download the latest (stable) release here: + +https://github.com/maxhq/zabbix-backup/releases/latest + +## More informations + +Please see the [Project Wiki](https://github.com/maxhq/zabbix-backup/wiki). + +## Version history + +**0.9.3 (2020-01-17)** + +- ENH: Check for unknown tables +- ENH: Speed up MySQL backup by not calling mysqldump for every single table anymore +- ENH: New option -S to specify PostgreSQL schema +- FIX: Stabilize and enhance PostgreSQL dump +- FIX: Skip IP reverse lookup for localhost, fix multiline dig answers + +**0.9.2 (2020-01-16)** + +- ENH: Support for Zabbix 4.4 +- ENH: Fix (non-critical) shellcheck issues (Mario Trangoni) +- CHG: Fix and enhance helper script get-table-list.pl +- FIX: Escape special characters while reading password (ironbishop) +- FIX: Re-enable accidentally disabled cleanup of postgresql password file +- FIX: Insert hostname into backup file also if database resides on localhost + +**0.9.1 (2019-03-21)** + +- FIX: Correctly process hostname option -H (Tiago Cruz) + +**0.9.0 (2019-03-14)** + +- NEW: Support for PostgreSQL databases (Sergey Galkin) +- NEW: Option -P to specify database server port (Sergey Galkin) +- NEW: Support for socket connections to MySQL and PostgreSQL server (Greg Cockburn) +- NEW: Database connection parameters are read from Zabbix servern config by default (Greg Cockburn) +- ENH: Support for Zabbix 4.0 (Wesley Schaft) +- ENH: Options -h and --help to show help (hostname is now specified using -H) +- ENH: Options -Z to skip reading the Zabbix server config file +- CHG: Rename script to "zabbix-dump" +- FIX: Support for whitespaces in database parameters (Greg Cockburn) +- FIX: Support for backslashes in manually entered password (Greg Cockburn) + +**0.8.2 (2016-09-08)** + +- NEW: Option -x to use XZ instead of GZ for compression (Jonathan Wright) +- NEW: Option -0 for "no compression" +- FIX: Evil space was masking end of here-document (fixed in #8 by @msjmeyer) +- FIX: Prevent "Warning: Using a password on the command line interface can be insecure." + +**0.8.1 (2016-07-11)** + +- ENH: Added Zabbix 3.0.x tables to list (added & tested by Ruslan Ohitin) + +**0.8.0 (2016-01-22)** + +- FIX: Only invoke `dig` if available +- ENH: Option -c to use a MySQL config ("options") file (suggested by Daniel Schneller) +- ENH: Option -r to rotate backup files (Daniel Schneller) +- ENH: Add database version to filename if available +- ENH: Add quiet mode. IP reverse lookup optional (Daniel Schneller) +- ENH: Bash related fixes (Misu Moldovan) +- CHG: Default output directory is now $PWD instead of script dir + +**0.7.1 (2015-01-27)** + +- NEW: Parsing of commandline arguments implemented +- ENH: Try reverse lookup of IPs and include hostname/IP in filename +- REV: Stop if database password is wrong + +**0.7.0 (2014-10-02)** + +- ENH: Complete overhaul to make script work with lots of Zabbix versions + +**0.6.0 (2014-09-15)** + +- REV: Updated the table list for use with zabbix v2.2.3 + +**0.5.0 (2013-05-13)** + +- NEW: Added table list comparison between database and script + +**0.4.0 (2012-03-02)** + +- REV: Incorporated mysqldump options (suggested by Jonathan Bayer) + +**0.3.0 (2012-02-06)** + +- ENH: Backup of Zabbix 1.9.x / 2.0.0, removed unnecessary use of + variables (DATEBIN etc) for commands that use to be in $PATH + +**0.2.0 (2011-11-05)** diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..086bd5e --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,49 @@ +## Releasing a new version + +### Before commit + +* Update README.md + +### After commit + +* Tag the release commit: `git tag v0.9.2 && git push --tags` +* Add release at https://github.com/maxhq/zabbix-backup/releases + + **Summary of main changes** + + ``` +This release fixes ... + +### Direct download + +[zabbix-mysql-dump](https://raw.githubusercontent.com/maxhq/zabbix-backup/v0.9.2/zabbix-dump) (v0.9.2) + +### Changelog + +Please see the [version history in the README](https://github.com/maxhq/zabbix-backup/blob/v0.9.2/README.md#version-history). + +### Thanks! +- @username + ``` + +* Update https://github.com/maxhq/zabbix-backup/wiki +* Update https://zabbix.org/wiki/Docs/howto/database_backup_script +* Announce release at https://www.linkedin.com/groups/161448 + + > **New version x.x.x of zabbix-dump** + > + > zabbix-dump is a Linux bash script for backing up the Zabbix configuration by saving MySQL or PostgreSQL database tables into a compressed file. + > Tables holding configuration data will be fully backed up. For mass data tables (events, history, trends, ...) only the table schema is stored without any data (to keep the backup small). + > + > Overiew: https://github.com/maxhq/zabbix-backup/blob/master/README.md + > Latest release: https://github.com/maxhq/zabbix-backup/releases/latest + +* Announce release at https://www.xing.com/communities/forums/100845147 + + > **Neue Version x.x.x von zabbix-dump** + > + > zabbix-dump ist ein Linux-Bash-Skript zum Backup der Zabbix-Konfiguration durch Sicherung der MySQL- bzw. PostgreSQL-Datenbanktabellen in eine komprimierte Datei. + > Es sichert Konfigurationsdaten komplett, bei Tabellen mit Massendaten (Historie, Events, Trends etc.) jedoch nur das "leere" Datenbankschema (um das Backup zu minimieren). + > + > Übersicht: https://github.com/maxhq/zabbix-backup/blob/master/README.md + > Neueste Version: https://github.com/maxhq/zabbix-backup/releases/latest diff --git a/get-table-list.pl b/get-table-list.pl new file mode 100755 index 0000000..852f108 --- /dev/null +++ b/get-table-list.pl @@ -0,0 +1,167 @@ +#!/usr/bin/env perl +# NAME +# get-table-list.pl - List current and historic Zabbix database tables +# +# SYNOPSIS +# This is mainly a helper script for developing the backup script. +# +# It connects to svn://svn.zabbix.com (using Subversion client "svn") and +# fetches the schema definitions of all tagged Zabbix versions beginning +# from 1.3.1 (this takes a while). +# +# It then prints out a list of all tables together with the first and last +# Zabbix version where they were used. +# +# HISTORY +# v0.1 - 2014-09-19 First version +# +# AUTHOR +# Jens Berthold (maxhq), 2020 +use strict; +use warnings; + +use version; + +my $REPO = 'https://git.zabbix.com/scm/zbx/zabbix.git'; +my $REPO_WEB = 'https://git.zabbix.com/projects/ZBX/repos/zabbix/raw'; + +sub stop { + my ($msg) = @_; + print "ERROR: $msg\n"; + exit; +} + +# sort version numbers correctly +sub cmpver { + my ($a, $b) = @_; + + # split version parts: 1.2.3rc1 --> 1 2 3rc1 + my @a_parts = split /\./, $a; + my @b_parts = split /\./, $b; + + for (my $i=0; $i= scalar(@b_parts); + # split number parts: 3rc1 --> 3 rc 1 + my ($a_num, $a_type, $a_idx) = $a_parts[$i] =~ m/^(\d+)(\D+)?(\d+)?$/; + my ($b_num, $b_type, $b_idx) = $b_parts[$i] =~ m/^(\d+)(\D+)?(\d+)?$/; + my $cmp; + # 3 before 4 + $cmp = $a_num <=> $b_num; return $cmp unless $cmp == 0; + # 3rc1 before 3 + return -1 if $a_type and not $b_type; + return 1 if not $a_type and $b_type; + # a1 before b1 + $cmp = ($a_type//"") cmp ($b_type//""); return $cmp unless $cmp == 0; + # rc1 before rc2 + $cmp = ($a_idx//0) <=> ($b_idx//0); return $cmp unless $cmp == 0; + } + # 1.2 before 1.2.1 + return -1 if scalar(@a_parts) < scalar(@b_parts); + # equal + return 0; +} + +# Get tag list from repo: +sub get_taglist { + print "Querying existing tags from $REPO...\n"; + + # Returned format: + # 7f6b20903537b9bbf72fe2b75ab7fac557856aad refs/tags/1.0 + # 693709cc4a80777f7759856c853b38cbc920f068 refs/tags/1.1 + my @tags_raw = `git ls-remote -t $REPO`; + # remove trailing newline + chomp @tags_raw; + # skip release candidates, betas and tags like "zabicom-xxx" + @tags_raw = grep { m{ refs/tags/ \d+ \. \d+ ( \. \d+ )? $}x } @tags_raw; + + # Create HashRef: + # 1.0 => 7f6b20903537b9bbf72fe2b75ab7fac557856aad + # 1.1 => 693709cc4a80777f7759856c853b38cbc920f068 + return { + map { m{^ (\w+) \s+ refs/tags/ (.*) $}x; $2 => $1 } @tags_raw + }; +} + +# Read old table informations from zabbix-dump +sub get_old_tabinfo { + my $tabinfo_old = {}; + + open my $fh, '<', './zabbix-dump' or stop("Couldn't find 'zabbix-dump': $!"); + + my $within_data_section = 0; + while (<$fh>) { + chomp; + if (/^__DATA__/) { $within_data_section = 1; next } + next unless $within_data_section; + my ($table, $from, undef, $to, $mode) = split /\s+/; + + $tabinfo_old->{$table} = { + from => $from, + to => $to, + schema_only => ($mode//"") eq "SCHEMAONLY" ? 1 : 0, + }; + } + + return $tabinfo_old; +} + + + +`which git` or stop("No Git client found"); + +my $tabinfo_old = get_old_tabinfo(); # old data from zabbix_dump + +my $tags = get_taglist(); +my $tabinfo = {}; # for each table, create a list of Zabbix versions that know it + +print "Reading table schemas...\n"; + +# Loop over tags and read table schema +for my $tag (sort { cmpver($a,$b) } keys %$tags) { + next if cmpver($tag, "1.3.1") < 0; # before Zabbix 1.3.1, schema was stored as pure SQL + + my ($schema, $subdir); + + printf " - %-8s %s", $tag, "Looking for schema..."; + # search in subdir /schema (<= 1.9.8) and /src for schema.(sql|tmpl) + for my $sub (qw(schema src)) { + # file list: + # 100644 blob 1f0a05eb826dfcdb26f9429ad30c720454374ca1 data.tmpl + # 100644 blob b98b5eecc62731508c09d9e76d7aed9d4eb201f2 schema.tmpl + my @files_raw = `curl -s $REPO_WEB/create/$sub?at=refs%2Ftags%2F$tag`; + next unless @files_raw; # directory not found? + chomp @files_raw; # remove trailing newline + my @files = map { /^ \d+ \s+ \w+ \s+ \w+ \s+ (.*) $/x; $1 } @files_raw; + + ($schema) = grep /^schema\.(sql|tmpl)/, @files; + $subdir = $sub; + last; + } + if (!$schema) { + print "\nNo schema found in tag $tag\n"; + next; + } + print " Processing ($schema)... "; + my @table = `curl -s $REPO_WEB/create/$subdir/$schema?at=refs%2Ftags%2F$tag`; + for (@table) { + chomp; + next unless m/^TABLE/; + my (undef, $table) = split /\|/; + $tabinfo->{$table} //= []; + push @{$tabinfo->{$table}}, $tag; + } + print " Done\n"; +} + +# +# Print out results +# +print "\n\n"; +print "TABLE FIRST USE LAST USE MODE\n"; +print "----------------------------------------------------\n"; +for my $tab (sort keys %$tabinfo) { + my $mode = $tabinfo_old->{$tab} + ? ($tabinfo_old->{$tab}->{schema_only} ? ' SCHEMAONLY' : '') + : ' <-- NEW TABLE! Only store schema?'; + printf "%-26s %-8s - %-8s%s\n", $tab, $tabinfo->{$tab}->[0], $tabinfo->{$tab}->[-1], $mode; +} diff --git a/zabbix-dump b/zabbix-dump new file mode 100755 index 0000000..23d5170 --- /dev/null +++ b/zabbix-dump @@ -0,0 +1,775 @@ +#!/usr/bin/env bash +VERSION=0.9.3 +# +# NAME +# zabbix-dump - Configuration Backup for Zabbix' MySQL or PostgreSQL data +# +# SYNOPSIS +# This is a MySQL configuration backup script for Zabbix 1.x, 2.x, 3.x and 4.x. +# It does a full backup of all configuration tables, but only a schema +# backup of large data tables. +# +# The script is based on a script by Ricardo Santos +# (http://zabbixzone.com/zabbix/backuping-only-the-zabbix-configuration/) +# +# CONTRIBUTORS +# - Ricardo Santos +# - Jens Berthold (maxhq) +# - Oleksiy Zagorskyi (zalex) +# - Petr Jendrejovsky +# - Jonathan Bayer +# - Andreas Niedermann (dre-) +# - Mișu Moldovan (dumol) +# - Daniel Schneller (dschneller) +# - Ruslan Ohitin (ruslan-ohitin) +# - Jonathan Wright (neonardo1) +# - msjmeyer +# - Sergey Galkin (sergeygalkin) +# - Greg Cockburn (gergnz) +# - yangqi +# - Johannes Petz (PetzJohannes) +# - Wesley Schaft (wschaft) +# - Tiago Cruz (tiago-cruz-movile) +# - Mario Trangoni (mjtrangoni) +# - ironbishop +# +# AUTHOR +# Jens Berthold (maxhq), 2020 +# +# LICENSE +# This script is released under the MIT License (see LICENSE.txt) + + +# +# DEFAULT VALUES +# +# DO NOT EDIT THESE VALUES! +# Instead, use command line parameters or a config file to specify options. +# +DUMPDIR="$PWD" +DBTYPE="mysql" +DEFAULT_DBHOST="127.0.0.1" +DEFAULT_DBSCHEMA="public" +DEFAULT_DBNAME="zabbix" +DEFAULT_DBUSER="zabbix" +DEFAULT_DBPASS="" +COMPRESSION="gz" +QUIET="no" +REVERSELOOKUP="yes" +GENERATIONSTOKEEP=0 +ZBX_CONFIG="/etc/zabbix/zabbix_server.conf" +READ_ZBX_CONFIG="yes" +HANDLE_UNKNOWN="fail" + +# +# Show version +# +show_version() { + echo "zabbix-dump version $VERSION" + exit +} + +if [[ "$1" == "--version" ]]; then show_version; fi + +# +# Show help +# +if [[ "$1" == "--help" || "$1" == "-h" ]]; then + cat <&2; exit 1 ;; + :) echo "Option -$OPTARG requires an argument" >&2; exit 1 ;; + esac +done + +[ -n "$MYSQL_CONFIG" ] && READ_ZBX_CONFIG="no" + +# (Try) reading database config from zabbix_server.conf +if [[ "${READ_ZBX_CONFIG}" == "yes" && -f "${ZBX_CONFIG}" && -r "${ZBX_CONFIG}" ]]; then + [ "$QUIET" == "no" ] && echo "Reading database options from ${ZBX_CONFIG}..." + + # Reading config with awk (instead of source'ing the file) to avoid shell special characters execution + DBHOST="$(/usr/bin/awk -F'=' '/^DBHost/{ print $2 }' "${ZBX_CONFIG}")" + DBPORT="$(/usr/bin/awk -F'=' '/^DBPort/{ print $2 }' "${ZBX_CONFIG}")" + DBNAME="$(/usr/bin/awk -F'=' '/^DBName/{ print $2 }' "${ZBX_CONFIG}")" + DBSCHEMA="$(/usr/bin/awk -F'=' '/^DBSchema/{ print $2 }' "${ZBX_CONFIG}")" + DBUSER="$(/usr/bin/awk -F'=' '/^DBUser/{ print $2 }' "${ZBX_CONFIG}")" + DBPASS="$(/usr/bin/awk -F'=' '/^DBPassword/{ print $2 }' "${ZBX_CONFIG}")" + + # set non-existing variables to their Zabbix defaults (if they are non-empty string) + [ -z ${DBHOST+x} ] && DBHOST="localhost" + + # Zabbix config has a special treatment for DBHost: + # > If set to localhost, socket is used for MySQL. + # > If set to empty string, socket is used for PostgreSQL. + if [[ ( "$DBTYPE" == "mysql" && "$DBHOST" == "localhost" ) || ( "$DBTYPE" == "psql" && "$DBHOST" == "" ) ]]; then + [ "$DBTYPE" == "mysql" ] && searchstr="mysql" + [ "$DBTYPE" == "psql" ] && searchstr="postgres" + sock=$(netstat -axn | grep -m1 "$searchstr" | sed -r 's/^.*\s+([^ ]+)$/\1/') + if [[ -n "$sock" && -S $sock ]]; then DBSOCKET="$sock"; DBHOST=""; fi + else + DBSOCKET="$(/usr/bin/awk -F'=' '/^DBSocket/{ print $2 }' "${ZBX_CONFIG}")" + fi + +# Otherwise: set default values +else + # if a MySQL config file is specified we assume it contains all connection parameters + if [ -z "$MYSQL_CONFIG" ]; then + DBHOST="$DEFAULT_DBHOST" + DBNAME="$DEFAULT_DBNAME" + DBUSER="$DEFAULT_DBUSER" + DBPASS="$DEFAULT_DBPASS" + fi +fi + +# Always set default ports, even if we read other parameters from zabbix_server.conf +[[ -z "$DBPORT" && "$DBTYPE" == "mysql" ]] && DBPORT="3306" +[[ -z "$DBPORT" && "$DBTYPE" == "psql" ]] && DBPORT="5432" + +# Options specified via command line override defaults or those from zabbix_server.conf (if any) +[ -n "$ODBHOST" ] && DBHOST=$ODBHOST +[ -n "$ODBPORT" ] && DBPORT=$ODBPORT +[ -n "$ODBSOCKET" ] && DBSOCKET=$ODBSOCKET && DBHOST="" +[ -n "$ODBSCHEMA" ] && DBSCHEMA=$ODBSCHEMA +[ -n "$ODBNAME" ] && DBNAME=$ODBNAME +[ -n "$ODBUSER" ] && DBUSER=$ODBUSER +[ -n "$ODBPASS" ] && DBPASS=$ODBPASS + +# Password prompt +if [ "$DBPASS" = "-" ]; then + read -r -s -p "Enter database password for user '$DBUSER' (input will be hidden): " DBPASS + echo "" +fi + +# MySQL config file validations +if [ -n "$MYSQL_CONFIG" ]; then + if [ ! -r "$MYSQL_CONFIG" ]; then + echo "ERROR: Cannot read configuration file $MYSQL_CONFIG" >&2 + exit 1 + fi + # Database name needs special treatment: + # For mysqldump it has to be specified on the command line! + # Therefore we need to get it from the config file + if [ $DB_GIVEN -eq 0 ]; then + DBNAME=$(grep -m 1 ^database= "$MYSQL_CONFIG" | cut -d= -f2) + fi +fi + +if [ -z "$DBNAME" ]; then + echo "ERROR: Please specify a database name (option -d)" + exit 1 +fi + +# +# CONSTANTS +# +SUFFIX=""; test ! -z $COMPRESSION && SUFFIX=".${COMPRESSION}" + +DB_OPTS=() +case $DBTYPE in + mysql) + [ -n "$MYSQL_CONFIG" ] && DB_OPTS=("${DB_OPTS[@]}" --defaults-extra-file="$MYSQL_CONFIG") + [ -n "$DBSOCKET" ] && DB_OPTS=("${DB_OPTS[@]}" -S $DBSOCKET) + [ -n "$DBHOST" ] && DB_OPTS=("${DB_OPTS[@]}" -h $DBHOST) + [ -n "$DBUSER" ] && DB_OPTS=("${DB_OPTS[@]}" -u $DBUSER) + [ -n "$DBPASS" ] && DB_OPTS=("${DB_OPTS[@]}" -p"$DBPASS") + DB_OPTS=("${DB_OPTS[@]}" -P"$DBPORT") + DB_OPTS_BATCH=("${DB_OPTS[@]}" --batch --silent) + [ -n "$DBNAME" ] && DB_OPTS_BATCH=("${DB_OPTS_BATCH[@]}" -D $DBNAME) + ;; + psql) + [ -n "$DBSOCKET" ] && DB_OPTS=("${DB_OPTS[@]}" -h $DBSOCKET) + [ -n "$DBHOST" ] && DB_OPTS=("${DB_OPTS[@]}" -h $DBHOST) + [ -n "$DBUSER" ] && DB_OPTS=("${DB_OPTS[@]}" -U $DBUSER) + DB_OPTS=("${DB_OPTS[@]}" -p"$DBPORT") + if [ -n "$DBPASS" ]; then + export PGPASSFILE=$(mktemp -u) + echo "$DBHOST:$DBPORT:$DBNAME:$DBUSER:$DBPASS" > $PGPASSFILE + chmod 600 $PGPASSFILE + fi + DB_OPTS_BATCH=("${DB_OPTS[@]}" -Atw) + [ -n "$DBNAME" ] && DB_OPTS_BATCH=("${DB_OPTS_BATCH[@]}" -d $DBNAME) + ;; +esac + +# Log file for errors +ERRORLOG=$(mktemp) + +# Host name +if [[ -z "$DBHOST" || "$DBHOST" == "127.0.0.1" || "$DBHOST" == "127.0.0.1" ]]; then + DBHOSTNAME="$(uname -n)" +else + DBHOSTNAME="$DBHOST" + + # Try reverse lookup if IP is given + command -v dig >/dev/null 2>&1 + FIND_DIG=$? + if [[ "$REVERSELOOKUP" == "yes" && $FIND_DIG -eq 0 && -n "$DBHOST" ]]; then + # Try resolving a given host ip + newHostname=$(dig +noall +answer -x "${DBHOST}" | head -n1 | sed -r 's/((\S+)\s+)+([^\.]+)\..*/\3/') + test \! -z "$newHostname" && DBHOSTNAME="$newHostname" + fi +fi + +# +# CONFIG DUMP +# +if [ "$QUIET" == "no" ]; then + cat <<-EOF +Configuration: + - type: $DBTYPE +EOF + [ -n "$MYSQL_CONFIG" ] && echo " - cfg file: $MYSQL_CONFIG" + [ -n "$DBHOST" ] && echo " - host: $DBHOST ($DBHOSTNAME)" && echo " - port: $DBPORT" + [ -n "$DBSOCKET" ] && echo " - socket: $DBSOCKET" + [ -n "$DBSCHEMA" ] && echo " - schema: $DBSCHEMA" + [ -n "$DBNAME" ] && echo " - database: $DBNAME" + [ -n "$DBUSER" ] && echo " - user: $DBUSER" + [ -n "$DUMPDIR" ] && echo " - output: $DUMPDIR" +fi + +# +# FUNCTIONS +# + +# Returns TRUE if argument 1 is part of the given array (remaining arguments) +elementIn () { + local e + for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done + return 1 +} +check_binary() { + if ! which $1 > /dev/null; then + echo "Executable '$1' not found." >&2 + case $1 in + mysql) + echo "(with Debian try \"apt-get install mysql-client\")" >&2 ;; + psql) + echo "(with Debian try \"apt-get install postgresql-client\")" >&2 ;; + esac + exit 1 + fi +} +clean_psql_pass() { + if [ $DBTYPE = "psql" -a -n "$PGPASSFILE" ]; then + rm -f $PGPASSFILE + fi +} + +# +# CHECKS +# +case $DBTYPE in + mysql) + check_binary mysqldump ;; + psql) + check_binary pg_dump ;; + *) + echo "Sorry, database type '$DBTYPE' is not supported." + echo "Please specify either 'mysql' or 'psql'." + exit 1 ;; +esac + +# +# READ TABLE LIST from __DATA__ section at the end of this script +# (http://stackoverflow.com/a/3477269/2983301) +# +SCHEMAONLY_TABLES=() +KNOWN_TABLES=() +while read -r line; do + table=$(echo "$line" | cut -d" " -f1) + echo "$line" | cut -d" " -f5 | grep -qi "SCHEMAONLY" + test $? -eq 0 && SCHEMAONLY_TABLES+=($table) + KNOWN_TABLES+=($table) +done < <(sed '0,/^__DATA__$/d' "${BASH_SOURCE[*]}" | tr -s " ") + +# paranoid check +if [ ${#SCHEMAONLY_TABLES[@]} -lt 5 ]; then + echo "ERROR: The number of large data tables configured in this script is less than 5." >&2 + exit 1 +fi + +# +# BACKUP +# +# Read table list from database +[ "$QUIET" == "no" ] && echo "Fetching list of existing tables..." +case $DBTYPE in + mysql) + DB_TABLES=$(mysql "${DB_OPTS_BATCH[@]}" -e "SELECT table_name FROM information_schema.tables WHERE table_schema = '$DBNAME'" 2>$ERRORLOG) + ;; + psql) + DB_TABLES=$(psql "${DB_OPTS_BATCH[@]}" -c "SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_catalog='$DBNAME' AND table_type='BASE TABLE'" 2>$ERRORLOG) + ;; +esac +if [ $? -ne 0 ]; then + echo "ERROR while trying to access database:" 2>&1; + cat $ERRORLOG 2>&1; + clean_psql_pass + exit 1; +fi + +DB_TABLES=$(echo "$DB_TABLES" | sort) +DB_TABLE_NUM=$(echo "$DB_TABLES" | wc -l) + +# Check if existing tables are known +UNKNOWN_TABLES=() +while read -r table; do + elementIn "$table" "${KNOWN_TABLES[@]}" || UNKNOWN_TABLES+=($table) +done <<<"$DB_TABLES" +if [ ${#UNKNOWN_TABLES[@]} -gt 0 ]; then + if [[ "$QUIET" == "no" || $HANDLE_UNKNOWN == "fail" ]]; then + echo "" + [ $HANDLE_UNKNOWN == "fail" ] && echo "ERROR" + echo "Unknown tables found in database:" + for tab in "${UNKNOWN_TABLES[@]}"; do echo " - $tab"; done + [ $HANDLE_UNKNOWN == "backup" ] && echo "They will be included (full data backup) as -f was specified" + [ $HANDLE_UNKNOWN == "ignore" ] && echo "They will be ignored as -i was specified" + [ $HANDLE_UNKNOWN == "fail" ] && echo "To include them (full data backup) specify -f, to ignore them use -i" + echo "" + fi + if [ $HANDLE_UNKNOWN == "fail" ]; then + clean_psql_pass + exit 1; + fi +fi + +# Query Zabbix database version +VERSION="" +case $DBTYPE in + mysql) + DB_VER=$(mysql "${DB_OPTS_BATCH[@]}" -N -e "select optional from dbversion;" 2>/dev/null) + ;; + psql) + DB_VER=$(psql "${DB_OPTS_BATCH[@]}" -c "select optional from dbversion;" 2>/dev/null) + ;; +esac +if [ $? -eq 0 ]; then + # version string is like: 02030015 + re='(.*)([0-9]{2})([0-9]{4})' + if [[ $DB_VER =~ $re ]]; then + VERSION="_db-${DBTYPE}-${BASH_REMATCH[1]}.$(( ${BASH_REMATCH[2]} + 0 )).$(( ${BASH_REMATCH[3]} + 0 ))" + fi +fi + +# Assemble file name +DUMPFILENAME_PREFIX="zabbix_cfg_${DBHOSTNAME}" +DUMPFILEBASE="${DUMPFILENAME_PREFIX}_$(date +%Y%m%d-%H%M)${VERSION}.sql" +DUMPFILE="$DUMPDIR/$DUMPFILEBASE" + +PROCESSED_SCHEMAONLY_TABLES=() +i=0 + +mkdir -p "${DUMPDIR}" + +[ "$QUIET" == "no" ] && echo "Starting table backups..." +case $DBTYPE in + mysql) + # dump schemas + DUMP_OPTS=(--opt --single-transaction --skip-lock-tables --no-data --routines) + if [ $HANDLE_UNKNOWN == "ignore" ]; then + while read -r table; do + if elementIn "$table" "${UNKNOWN_TABLES[@]}"; then + DUMP_OPTS+=(--ignore-table=$DBNAME.$table) + fi + done <<<"$DB_TABLES" + fi + + mysqldump "${DB_OPTS[@]}" "${DUMP_OPTS[@]}" $DBNAME > "$DUMPFILE" 2>$ERRORLOG + + if [ $? -ne 0 ]; then echo $'\nERROR: Could not backup table schemas.\n' >&2; cat $ERRORLOG >&2; exit 1; fi + + # dump data + DUMP_OPTS=(--opt --single-transaction --skip-lock-tables --no-create-info --skip-extended-insert) + while read -r table; do + if elementIn "$table" "${SCHEMAONLY_TABLES[@]}"; then + DUMP_OPTS+=(--ignore-table=$DBNAME.$table) + PROCESSED_SCHEMAONLY_TABLES+=($table) + fi + if [ $HANDLE_UNKNOWN == "ignore" ]; then + if elementIn "$table" "${UNKNOWN_TABLES[@]}"; then + DUMP_OPTS+=(--ignore-table=$DBNAME.$table) + fi + fi + done <<<"$DB_TABLES" + + mysqldump "${DB_OPTS[@]}" "${DUMP_OPTS[@]}" $DBNAME >> "$DUMPFILE" 2>$ERRORLOG + + if [ $? -ne 0 ]; then echo $'\nERROR: Could not backup table data.\n' >&2; cat $ERRORLOG >&2; exit 1; fi + ;; + psql) + DUMP_OPTS=() + while read -r table; do + if [ $HANDLE_UNKNOWN == "ignore" ]; then + if elementIn "$table" "${UNKNOWN_TABLES[@]}"; then + DUMP_OPTS+=(--exclude-table=$table) + fi + fi + if elementIn "$table" "${SCHEMAONLY_TABLES[@]}"; then + DUMP_OPTS+=(--exclude-table-data=$table) + PROCESSED_SCHEMAONLY_TABLES+=($table) + fi + done <<<"$DB_TABLES" + + [ -n "$DBSCHEMA" ] && DUMP_OPTS=("${DUMP_OPTS[@]}" -n $DBSCHEMA) + + pg_dump "${DB_OPTS[@]}" "${DUMP_OPTS[@]}" -d $DBNAME > "$DUMPFILE" 2>$ERRORLOG + + if [ $? -ne 0 ]; then + echo $'\nERROR: Could not backup database.\n' >&2 + cat $ERRORLOG >&2 + clean_psql_pass + exit 1 + fi + ;; +esac + +rm $ERRORLOG + +# +# COMPRESS BACKUP +# +if [ "$QUIET" == "no" ]; then + echo $'\nFor the following large tables only the schema (without data) was stored:' + for table in "${PROCESSED_SCHEMAONLY_TABLES[@]}"; do echo " - $table"; done + + echo $'\nCompressing backup file...' +fi + +EXITCODE=0 +if [ "$COMPRESSION" == "gz" ]; then gzip -f "$DUMPFILE"; EXITCODE=$?; fi +if [ "$COMPRESSION" == "xz" ]; then xz -f "$DUMPFILE"; EXITCODE=$?; fi +if [ $EXITCODE -ne 0 ]; then + echo $'\nERROR: Could not compress backup file, see previous messages' >&2 + clean_psql_pass + exit 1 +fi + +[ "$QUIET" == "no" ] && echo "Backup Completed" && echo "${DUMPFILE}${SUFFIX}" + +# +# ROTATE OLD BACKUPS +# +if [ $GENERATIONSTOKEEP -gt 0 ]; then + [ "$QUIET" == "no" ] && echo "Removing old backups, keeping up to $GENERATIONSTOKEEP" + REMOVE_OLD_CMD="cd \"$DUMPDIR\" && ls -t \"${DUMPFILENAME_PREFIX}\"* | /usr/bin/awk \"NR>${GENERATIONSTOKEEP}\" | xargs rm -f " + eval ${REMOVE_OLD_CMD} + if [ $? -ne 0 ]; then + echo "ERROR: Could not rotate old backups" >&2 + clean_psql_pass + exit 1 + fi +fi + +clean_psql_pass +exit 0 + +################################################################################ +# List of all known table names. +# The flag SCHEMAONLY marks tables that contain monitoring data (as opposed to +# config data), so only their database schema will be backed up. +# + +__DATA__ +acknowledges 1.3.1 - 4.4.4 SCHEMAONLY +actions 1.3.1 - 4.4.4 +alerts 1.3.1 - 4.4.4 SCHEMAONLY +application_discovery 2.5.0 - 4.4.4 +application_prototype 2.5.0 - 4.4.4 +application_template 2.1.0 - 4.4.4 +applications 1.3.1 - 4.4.4 +auditlog 1.3.1 - 4.4.4 SCHEMAONLY +auditlog_details 1.7 - 4.4.4 SCHEMAONLY +autoreg 1.3.1 - 1.3.4 +autoreg_host 1.7 - 4.4.4 +conditions 1.3.1 - 4.4.4 +config 1.3.1 - 4.4.4 +config_autoreg_tls 4.4.0 - 4.4.4 +corr_condition 3.2.0 - 4.4.4 +corr_condition_group 3.2.0 - 4.4.4 +corr_condition_tag 3.2.0 - 4.4.4 +corr_condition_tagpair 3.2.0 - 4.4.4 +corr_condition_tagvalue 3.2.0 - 4.4.4 +corr_operation 3.2.0 - 4.4.4 +correlation 3.2.0 - 4.4.4 +dashboard 3.4.0 - 4.4.4 +dashboard_user 3.4.0 - 4.4.4 +dashboard_usrgrp 3.4.0 - 4.4.4 +dbversion 2.1.0 - 4.4.4 +dchecks 1.3.4 - 4.4.4 +dhosts 1.3.4 - 4.4.4 +drules 1.3.4 - 4.4.4 +dservices 1.3.4 - 4.4.4 +escalations 1.5.3 - 4.4.4 +event_recovery 3.2.0 - 4.4.4 SCHEMAONLY +event_suppress 4.0.0 - 4.4.4 SCHEMAONLY +event_tag 3.2.0 - 4.4.4 SCHEMAONLY +events 1.3.1 - 4.4.4 SCHEMAONLY +expressions 1.7 - 4.4.4 +functions 1.3.1 - 4.4.4 +globalmacro 1.7 - 4.4.4 +globalvars 1.9.6 - 4.4.4 +graph_discovery 1.9.0 - 4.4.4 +graph_theme 1.7 - 4.4.4 +graphs 1.3.1 - 4.4.4 +graphs_items 1.3.1 - 4.4.4 +group_discovery 2.1.4 - 4.4.4 +group_prototype 2.1.4 - 4.4.4 +groups 1.3.1 - 3.4.15 +help_items 1.3.1 - 2.1.8 +history 1.3.1 - 4.4.4 SCHEMAONLY +history_log 1.3.1 - 4.4.4 SCHEMAONLY +history_str 1.3.1 - 4.4.4 SCHEMAONLY +history_str_sync 1.3.1 - 2.2.23 SCHEMAONLY +history_sync 1.3.1 - 2.2.23 SCHEMAONLY +history_text 1.3.1 - 4.4.4 SCHEMAONLY +history_uint 1.3.1 - 4.4.4 SCHEMAONLY +history_uint_sync 1.3.1 - 2.2.23 SCHEMAONLY +host_discovery 2.1.4 - 4.4.4 +host_inventory 1.9.6 - 4.4.4 +host_profile 1.9.3 - 1.9.5 +host_tag 4.2.0 - 4.4.4 +hostmacro 1.7 - 4.4.4 +hosts 1.3.1 - 4.4.4 +hosts_groups 1.3.1 - 4.4.4 +hosts_profiles 1.3.1 - 1.9.2 +hosts_profiles_ext 1.6 - 1.9.2 +hosts_templates 1.3.1 - 4.4.4 +housekeeper 1.3.1 - 4.4.4 +hstgrp 4.0.0 - 4.4.4 +httpstep 1.3.3 - 4.4.4 +httpstep_field 3.4.0 - 4.4.4 +httpstepitem 1.3.3 - 4.4.4 +httptest 1.3.3 - 4.4.4 +httptest_field 3.4.0 - 4.4.4 +httptestitem 1.3.3 - 4.4.4 +icon_map 1.9.6 - 4.4.4 +icon_mapping 1.9.6 - 4.4.4 +ids 1.3.3 - 4.4.4 +images 1.3.1 - 4.4.4 +interface 1.9.1 - 4.4.4 +interface_discovery 2.1.4 - 4.4.4 +item_application_prototype 2.5.0 - 4.4.4 +item_condition 2.3.0 - 4.4.4 +item_discovery 1.9.0 - 4.4.4 +item_preproc 3.4.0 - 4.4.4 +item_rtdata 4.4.0 - 4.4.4 SCHEMAONLY +items 1.3.1 - 4.4.4 +items_applications 1.3.1 - 4.4.4 +lld_macro_path 4.2.0 - 4.4.4 +maintenance_tag 4.0.0 - 4.4.4 +maintenances 1.7 - 4.4.4 +maintenances_groups 1.7 - 4.4.4 +maintenances_hosts 1.7 - 4.4.4 +maintenances_windows 1.7 - 4.4.4 +mappings 1.3.1 - 4.4.4 +media 1.3.1 - 4.4.4 +media_type 1.3.1 - 4.4.4 +media_type_param 4.4.0 - 4.4.4 +node_cksum 1.3.1 - 2.2.23 +node_configlog 1.3.1 - 1.4.7 +nodes 1.3.1 - 2.2.23 +opcommand 1.9.4 - 4.4.4 +opcommand_grp 1.9.2 - 4.4.4 +opcommand_hst 1.9.2 - 4.4.4 +opconditions 1.5.3 - 4.4.4 +operations 1.3.4 - 4.4.4 +opgroup 1.9.2 - 4.4.4 +opinventory 3.0.0 - 4.4.4 +opmediatypes 1.7 - 1.8.22 +opmessage 1.9.2 - 4.4.4 +opmessage_grp 1.9.2 - 4.4.4 +opmessage_usr 1.9.2 - 4.4.4 +optemplate 1.9.2 - 4.4.4 +problem 3.2.0 - 4.4.4 SCHEMAONLY +problem_tag 3.2.0 - 4.4.4 SCHEMAONLY +profiles 1.3.1 - 4.4.4 +proxy_autoreg_host 1.7 - 4.4.4 +proxy_dhistory 1.5 - 4.4.4 +proxy_history 1.5.1 - 4.4.4 +regexps 1.7 - 4.4.4 +rights 1.3.1 - 4.4.4 +screen_user 3.0.0 - 4.4.4 +screen_usrgrp 3.0.0 - 4.4.4 +screens 1.3.1 - 4.4.4 +screens_items 1.3.1 - 4.4.4 +scripts 1.5 - 4.4.4 +service_alarms 1.3.1 - 4.4.4 +services 1.3.1 - 4.4.4 +services_links 1.3.1 - 4.4.4 +services_times 1.3.1 - 4.4.4 +sessions 1.3.1 - 4.4.4 +slides 1.3.4 - 4.4.4 +slideshow_user 3.0.0 - 4.4.4 +slideshow_usrgrp 3.0.0 - 4.4.4 +slideshows 1.3.4 - 4.4.4 +sysmap_element_trigger 3.4.0 - 4.4.4 +sysmap_element_url 1.9.0 - 4.4.4 +sysmap_shape 3.4.0 - 4.4.4 +sysmap_url 1.9.0 - 4.4.4 +sysmap_user 3.0.0 - 4.4.4 +sysmap_usrgrp 3.0.0 - 4.4.4 +sysmaps 1.3.1 - 4.4.4 +sysmaps_elements 1.3.1 - 4.4.4 +sysmaps_link_triggers 1.5 - 4.4.4 +sysmaps_links 1.3.1 - 4.4.4 +tag_filter 4.0.0 - 4.4.4 +task 3.2.0 - 4.4.4 SCHEMAONLY +task_acknowledge 3.4.0 - 4.4.4 SCHEMAONLY +task_check_now 4.0.0 - 4.4.4 SCHEMAONLY +task_close_problem 3.2.0 - 4.4.4 SCHEMAONLY +task_remote_command 3.4.0 - 4.4.4 SCHEMAONLY +task_remote_command_result 3.4.0 - 4.4.4 SCHEMAONLY +timeperiods 1.7 - 4.4.4 +trends 1.3.1 - 4.4.4 SCHEMAONLY +trends_uint 1.5 - 4.4.4 SCHEMAONLY +trigger_depends 1.3.1 - 4.4.4 +trigger_discovery 1.9.0 - 4.4.4 +trigger_tag 3.2.0 - 4.4.4 +triggers 1.3.1 - 4.4.4 +user_history 1.7 - 2.4.8 +users 1.3.1 - 4.4.4 +users_groups 1.3.1 - 4.4.4 +usrgrp 1.3.1 - 4.4.4 +valuemaps 1.3.1 - 4.4.4 +widget 3.4.0 - 4.4.4 +widget_field 3.4.0 - 4.4.4 diff --git a/zabbix-mysql-autopartitioning.sql b/zabbix-mysql-autopartitioning.sql deleted file mode 100644 index 137a8ca..0000000 --- a/zabbix-mysql-autopartitioning.sql +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************** - MySQL Auto Partitioning Procedure for Zabbix 1.8 - http://zabbixzone.com/zabbix/partitioning-tables/ - - Author: Ricardo Santos (rsantos at gmail.com) - Version: 20110518 -**************************************************************/ -DELIMITER // -DROP PROCEDURE IF EXISTS `zabbix`.`create_zabbix_partitions` // -CREATE PROCEDURE `zabbix`.`create_zabbix_partitions` () -BEGIN - CALL zabbix.create_next_partitions("zabbix","history"); - CALL zabbix.create_next_partitions("zabbix","history_log"); - CALL zabbix.create_next_partitions("zabbix","history_str"); - CALL zabbix.create_next_partitions("zabbix","history_text"); - CALL zabbix.create_next_partitions("zabbix","history_uint"); - CALL zabbix.drop_old_partitions("zabbix","history"); - CALL zabbix.drop_old_partitions("zabbix","history_log"); - CALL zabbix.drop_old_partitions("zabbix","history_str"); - CALL zabbix.drop_old_partitions("zabbix","history_text"); - CALL zabbix.drop_old_partitions("zabbix","history_uint"); -END // -DROP PROCEDURE IF EXISTS `zabbix`.`create_next_partitions` // -CREATE PROCEDURE `zabbix`.`create_next_partitions` (SCHEMANAME varchar(64), TABLENAME varchar(64)) -BEGIN - DECLARE NEXTCLOCK timestamp; - DECLARE PARTITIONNAME varchar(16); - DECLARE CLOCK int; - SET @totaldays = 7; - SET @i = 1; - createloop: LOOP - SET NEXTCLOCK = DATE_ADD(NOW(),INTERVAL @i DAY); - SET PARTITIONNAME = DATE_FORMAT( NEXTCLOCK, 'p%Y%m%d' ); - SET CLOCK = UNIX_TIMESTAMP(DATE_FORMAT(DATE_ADD( NEXTCLOCK ,INTERVAL 1 DAY),'%Y-%m-%d 00:00:00')); - CALL zabbix.create_partition( SCHEMANAME, TABLENAME, PARTITIONNAME, CLOCK ); - SET @i=@i+1; - IF @i > @totaldays THEN - LEAVE createloop; - END IF; - END LOOP; -END // -DROP PROCEDURE IF EXISTS `zabbix`.`drop_old_partitions` // -CREATE PROCEDURE `zabbix`.`drop_old_partitions` (SCHEMANAME varchar(64), TABLENAME varchar(64)) -BEGIN - DECLARE OLDCLOCK timestamp; - DECLARE PARTITIONNAME varchar(16); - DECLARE CLOCK int; - SET @mindays = 3; - SET @maxdays = @mindays+4; - SET @i = @maxdays; - droploop: LOOP - SET OLDCLOCK = DATE_SUB(NOW(),INTERVAL @i DAY); - SET PARTITIONNAME = DATE_FORMAT( OLDCLOCK, 'p%Y%m%d' ); - CALL zabbix.drop_partition( SCHEMANAME, TABLENAME, PARTITIONNAME ); - SET @i=@i-1; - IF @i <= @mindays THEN - LEAVE droploop; - END IF; - END LOOP; -END // -DROP PROCEDURE IF EXISTS `zabbix`.`create_partition` // -CREATE PROCEDURE `zabbix`.`create_partition` (SCHEMANAME varchar(64), TABLENAME varchar(64), PARTITIONNAME varchar(64), CLOCK int) -BEGIN - DECLARE RETROWS int; - SELECT COUNT(1) INTO RETROWS - FROM `information_schema`.`partitions` - WHERE `table_schema` = SCHEMANAME AND `table_name` = TABLENAME AND `partition_name` = PARTITIONNAME; - - IF RETROWS = 0 THEN - SELECT CONCAT( "create_partition(", SCHEMANAME, ",", TABLENAME, ",", PARTITIONNAME, ",", CLOCK, ")" ) AS msg; - SET @sql = CONCAT( 'ALTER TABLE `', SCHEMANAME, '`.`', TABLENAME, '`', - ' ADD PARTITION (PARTITION ', PARTITIONNAME, ' VALUES LESS THAN (', CLOCK, '));' ); - PREPARE STMT FROM @sql; - EXECUTE STMT; - DEALLOCATE PREPARE STMT; - END IF; -END // -DROP PROCEDURE IF EXISTS `zabbix`.`drop_partition` // -CREATE PROCEDURE `zabbix`.`drop_partition` (SCHEMANAME varchar(64), TABLENAME varchar(64), PARTITIONNAME varchar(64)) -BEGIN - DECLARE RETROWS int; - SELECT COUNT(1) INTO RETROWS - FROM `information_schema`.`partitions` - WHERE `table_schema` = SCHEMANAME AND `table_name` = TABLENAME AND `partition_name` = PARTITIONNAME; - - IF RETROWS = 1 THEN - SELECT CONCAT( "drop_partition(", SCHEMANAME, ",", TABLENAME, ",", PARTITIONNAME, ")" ) AS msg; - SET @sql = CONCAT( 'ALTER TABLE `', SCHEMANAME, '`.`', TABLENAME, '`', - ' DROP PARTITION ', PARTITIONNAME, ';' ); - PREPARE STMT FROM @sql; - EXECUTE STMT; - DEALLOCATE PREPARE STMT; - END IF; -END // -DELIMITER ; diff --git a/zabbix-mysql-backupconf.sh b/zabbix-mysql-backupconf.sh deleted file mode 100644 index 4851066..0000000 --- a/zabbix-mysql-backupconf.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -# -# zabbix-mysql-backupconf.sh -# v0.2 - 20111105 -# -# Configuration Backup for Zabbix 1.8 w/MySQL -# -# Author: Ricardo Santos (rsantos at gmail.com) -# http://zabbixzone.com -# -# Thanks for suggestions from: -# - Oleksiy Zagorskyi (zalex) -# - Petr Jendrejovsky -# - -# mysql config -DBHOST="localhost" -DBNAME="zabbix" -DBUSER="zabbix" -DBPASS="YOURMYSQLPASSWORDHERE" - -# some tools -MYSQLDUMP="`which mysqldump`" -GZIP="`which gzip`" -DATEBIN="`which date`" -MKDIRBIN="`which mkdir`" - -# target path -MAINDIR="/var/lib/zabbix/backupconf" -DUMPDIR="${MAINDIR}/`${DATEBIN} +%Y%m%d%H%M`" -${MKDIRBIN} -p ${DUMPDIR} - -# configuration tables -CONFTABLES=( actions applications autoreg_host conditions config dchecks dhosts \ -drules dservices escalations expressions functions globalmacro graph_theme \ -graphs graphs_items groups help_items hostmacro hosts hosts_groups \ -hosts_profiles hosts_profiles_ext hosts_templates housekeeper httpstep \ -httpstepitem httptest httptestitem ids images items items_applications \ -maintenances maintenances_groups maintenances_hosts maintenances_windows \ -mappings media media_type node_cksum nodes opconditions operations \ -opmediatypes profiles proxy_autoreg_host proxy_dhistory proxy_history regexps \ -rights screens screens_items scripts service_alarms services services_links \ -services_times sessions slides slideshows sysmaps sysmaps_elements \ -sysmaps_link_triggers sysmaps_links timeperiods trigger_depends triggers \ -user_history users users_groups usrgrp valuemaps ) - -# tables with large data -DATATABLES=( acknowledges alerts auditlog_details auditlog events \ -history history_log history_str history_str_sync history_sync history_text \ -history_uint history_uint_sync trends trends_uint ) - -# CONFTABLES -for table in ${CONFTABLES[*]}; do - DUMPFILE="${DUMPDIR}/${table}.sql" - echo "Backuping table ${table}" - ${MYSQLDUMP} -R --opt --extended-insert=FALSE \ - -h ${DBHOST} -u ${DBUSER} -p${DBPASS} ${DBNAME} --tables ${table} >${DUMPFILE} - ${GZIP} -f ${DUMPFILE} -done - -# DATATABLES -for table in ${DATATABLES[*]}; do - DUMPFILE="${DUMPDIR}/${table}.sql" - echo "Backuping schema table ${table}" - ${MYSQLDUMP} -R --opt --no-data \ - -h ${DBHOST} -u ${DBUSER} -p${DBPASS} ${DBNAME} --tables ${table} >${DUMPFILE} - ${GZIP} -f ${DUMPFILE} -done - -echo -echo "Backup Completed - ${DUMPDIR}"