Compare commits

...

58 commits

Author SHA1 Message Date
Darko Poljak
08cb857664 Release 2.10 2020-08-26 08:36:43 +02:00
Darko Poljak
309d8dc773 ++changelog 2020-05-25 17:52:23 +02:00
fabdefad82 Merge branch 'master' into 'master'
Add 'current' symlink to backup destinations

See merge request ungleich-public/ccollect!15
2020-05-25 17:51:13 +02:00
Steffen Zieger
616b1d9e3e Add 'current' symlink to backup destinations 2020-05-25 16:16:32 +02:00
Darko Poljak
7a7dec7751 Release 2.9 2020-05-25 12:05:35 +02:00
Darko Poljak
28dec3694a ++changelog 2020-05-24 17:29:29 +02:00
59b50e7f4b Merge branch 'ungleich-master-patch-28394' into 'master'
make rsync return code available in post_exec

See merge request ungleich-public/ccollect!14
2020-05-24 17:28:31 +02:00
Steffen Zieger
a261ef841e make rsync return code available in post_exec 2020-05-24 16:40:04 +02:00
Darko Poljak
109b70ea76 gitlab runner should have necessary tools 2019-12-02 09:29:02 +01:00
Darko Poljak
5341de86fb Release 2.8 2019-11-26 06:10:17 +01:00
Darko Poljak
987277f1cf Update Makefile
Simplify and generalize.
2019-11-25 20:52:48 +01:00
Darko Poljak
589fed6107 ++changelog 2019-11-25 14:41:41 +01:00
Darko Poljak
61ab45fc65 Fix excluding destination dir from removal
Touch can lead to wrong ls order, and destination dir gets selected for
removal.
Use grep -v to exclude, instead of touch.
2019-11-25 14:38:17 +01:00
Darko Poljak
6c24e8a7d3 Fix quoting in tests 2019-11-25 13:44:10 +01:00
Darko Poljak
42bd1afb09 Fix quoting in tests 2019-11-25 13:35:22 +01:00
Darko Poljak
9ed5912461 Improve unit tests 2019-11-25 08:42:42 +01:00
Darko Poljak
5ce3fddf62 Define gitlab CI 2019-11-24 23:01:34 +01:00
Darko Poljak
8f5d9b2c97 Add unit testing 2019-11-15 08:29:46 +01:00
Darko Poljak
401dd4fa8e Fix path with spaces in eval 2019-11-15 08:29:46 +01:00
Darko Poljak
f818f011e3 Release 2.7 2019-11-14 19:20:16 +01:00
c9eef21e43 Merge branch 'bugfix/shellcheck' into 'master'
Fix shellcheck reported issues

See merge request ungleich-public/ccollect!13
2019-11-14 19:17:50 +01:00
Darko Poljak
a5e565b5d6 Add shellcheck makefile target 2019-11-14 19:16:11 +01:00
Darko Poljak
2cefdaa1a5 Fix shellcheck reported issues 2019-11-12 19:26:25 +01:00
Darko Poljak
74e3b26790 Release 2.6 2019-11-12 17:55:15 +01:00
dcc72aebf7 Merge branch 'performance/speed-up-removal' into 'master'
Improve performance

See merge request ungleich-public/ccollect!12
2019-11-12 17:50:41 +01:00
Darko Poljak
de720ecfe9 If renaming oldest bak dir fails then fallback to removing it 2019-10-17 11:53:46 +02:00
Darko Poljak
e44dede92f ++changelog 2019-10-17 09:05:55 +02:00
Darko Poljak
7701bdb0a8 Use destination dir basename 2019-10-17 08:06:13 +02:00
Darko Poljak
c39205d308 Exclude destintion dir from listing for last dir 2019-10-17 08:03:12 +02:00
Darko Poljak
2788de47b8 Improve log line 2019-10-17 07:52:53 +02:00
Darko Poljak
1e18e71b9d Use oldest backup as destination dir without deletion 2019-10-17 07:42:31 +02:00
Darko Poljak
51dcf4a02f Use hidden empty directory for deletion 2019-10-17 06:55:20 +02:00
Darko Poljak
702cdf931e Use hidden directory for deletion 2019-10-17 06:52:51 +02:00
Darko Poljak
bfb3c6338c _techo instead of very verbose 2019-10-16 15:50:54 +02:00
Darko Poljak
30abef474d Delete in background and finally wait for children 2019-10-16 14:03:13 +02:00
Darko Poljak
ca6d06c2c3 Add more verbose logging 2019-10-10 10:54:56 +02:00
Darko Poljak
1628ce58c7 Replace rm with faster rsync --delete with empty src dir 2019-10-05 10:48:19 +02:00
Darko Poljak
10dcf076a9 Release 2.5 2019-05-01 14:38:35 +02:00
086c95f98d Merge branch 'bugfix/subshell_exit' into 'master'
exit in case of subshell error

See merge request ungleich-public/ccollect!11
2019-05-01 14:32:06 +02:00
Darko Poljak
2725a1ced4 github -> code.ungleich.ch 2019-04-26 14:47:21 +02:00
Darko Poljak
835e21c56c exit in case of subshell error 2019-04-26 14:03:01 +02:00
Darko Poljak
71eabe2f23 Release 2.4 2018-09-25 21:14:55 +02:00
Darko Poljak
5c1bf8a8de
Merge pull request #10 from darko-poljak/output-backup-source
Add source name tag in log line
2018-09-25 13:15:21 +02:00
Darko Poljak
a63e16efc5 Use better expansion and parameter setting 2018-09-23 11:42:09 +02:00
Darko Poljak
b47a828af0 Add source name tag in log line 2018-09-22 20:47:14 +02:00
Darko Poljak
420dc3fe7f Add source name tag in log line 2018-09-20 16:08:00 +02:00
Darko Poljak
51f468182f Document Windows(Cygwin) as supported OS. 2018-04-20 17:27:56 +02:00
Darko Poljak
eeccc0b260 Release 2.3 2018-02-02 07:57:41 +01:00
Darko Poljak
fc0b86005c Fix parallel mode deadlock when MAX_JOBS > number of sources. 2018-01-30 09:48:43 +01:00
Jun Futagawa
bd0fe05003 Update rpm spec file to version 2.2 (#9) 2017-12-19 09:42:49 +01:00
Darko Poljak
890b166a43 Release 2.2 2017-09-03 23:11:13 +02:00
Darko Poljak
e504d1f42b Release 2.2 2017-09-03 22:29:13 +02:00
Darko Poljak
b0f1317713 changelog++ 2017-09-03 20:02:42 +02:00
Darko Poljak
04bf9aff39 Bugfix: empty rsync_options line causes destroying source. (#8)
Bugfix: empty rsync_options line causes destroying source.
2017-09-03 20:00:54 +02:00
Darko Poljak
07c925de5d Release 2.1 2017-03-22 10:46:57 +01:00
Darko Poljak
89a82ba55e Release 2.1 2017-03-22 10:24:18 +01:00
Darko Poljak
12b6b2cf28 Merge pull request #7 from darko-poljak/improve-logging
Improve logging: stdout, file, syslog options.
2017-03-22 08:13:15 +01:00
Darko Poljak
fbe17cae44 Improve logging: stdout, file, syslog options. 2017-03-19 08:10:41 +01:00
68 changed files with 435 additions and 218 deletions

1
.gitignore vendored
View file

@ -8,7 +8,6 @@ doc/man/*.html
doc/man/*.htm doc/man/*.htm
doc/man/*.texi doc/man/*.texi
doc/man/*.man doc/man/*.man
test/*
.*.swp .*.swp
doc/man/*.[0-9] doc/man/*.[0-9]
doc/*.xml doc/*.xml

12
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,12 @@
stages:
- test
unit_tests:
stage: test
script:
- make test
shellcheck:
stage: test
script:
- make shellcheck

View file

@ -29,7 +29,7 @@ ASCIIDOC=asciidoc
DOCBOOKTOTEXI=docbook2x-texi DOCBOOKTOTEXI=docbook2x-texi
DOCBOOKTOMAN=docbook2x-man DOCBOOKTOMAN=docbook2x-man
XSLTPROC=xsltproc XSLTPROC=xsltproc
XSL=/usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl XSL=/usr/local/share/xsl/docbook/html/docbook.xsl
A2X=a2x A2X=a2x
prefix=/usr/packages/ccollect-git prefix=/usr/packages/ccollect-git
@ -41,11 +41,7 @@ manlink=/usr/local/man/man1
path_dir=/usr/local/bin path_dir=/usr/local/bin
path_destination=${path_dir}/${CCOLLECT_DEST} path_destination=${path_dir}/${CCOLLECT_DEST}
docs_archive_name=docs.tar
# where to publish
host=localhost
dir=/home/users/nico/privat/rechner/netz/seiten/www.nico.schottelius.org/src/software/ccollect
docdir=${dir}/documentation
# #
# Asciidoc will be used to generate other formats later # Asciidoc will be used to generate other formats later
@ -79,6 +75,8 @@ DOCBDOCS = ${DOCS:.text=.docbook}
DOC_ALL = ${HTMLDOCS} ${DBHTMLDOCS} ${TEXIDOCS} ${MANPDOCS} ${PDFDOCS} DOC_ALL = ${HTMLDOCS} ${DBHTMLDOCS} ${TEXIDOCS} ${MANPDOCS} ${PDFDOCS}
TEST_LOG_FILE = /tmp/ccollect/ccollect.log
# #
# End user targets # End user targets
# #
@ -89,6 +87,8 @@ all:
@echo "info: only generate Texinfo" @echo "info: only generate Texinfo"
@echo "man: only generate manpage{s}" @echo "man: only generate manpage{s}"
@echo "install: install ccollect to ${prefix}" @echo "install: install ccollect to ${prefix}"
@echo "shellcheck: shellcheck ccollect script"
@echo "test: run unit tests"
html: ${HTMLDOCS} html: ${HTMLDOCS}
htm: ${DBHTMLDOCS} htm: ${DBHTMLDOCS}
@ -175,12 +175,11 @@ t2:
# #
pub: pub:
git push git push
git push github
publish-doc: documentation publish-doc: documentation
@echo "Transferring files to ${host}"
@chmod a+r ${DOCS} ${DOC_ALL} @chmod a+r ${DOCS} ${DOC_ALL}
@tar c ${DOCS} ${DOC_ALL} | ssh ${host} "cd ${dir}; tar xv" @tar cf ${docs_archive_name} ${DOCS} ${DOC_ALL}
@echo "Documentation files are in ${docs_archive_name}"
# #
# Distribution # Distribution
@ -200,9 +199,52 @@ dist: distclean documentation
/tmp/ccollect: /tmp/ccollect:
mkdir -p /tmp/ccollect mkdir -p /tmp/ccollect
test: $(CCOLLECT_SOURCE) /tmp/ccollect shellcheck: ./ccollect
shellcheck -s sh -f gcc -x ./ccollect
test-nico: $(CCOLLECT_SOURCE) /tmp/ccollect
cd ./conf/sources/; for s in *; do CCOLLECT_CONF=../ ../../ccollect daily "$$s"; done cd ./conf/sources/; for s in *; do CCOLLECT_CONF=../ ../../ccollect daily "$$s"; done
touch /tmp/ccollect/$$(ls /tmp/ccollect | head -n1).ccollect-marker touch /tmp/ccollect/$$(ls /tmp/ccollect | head -n1).ccollect-marker
CCOLLECT_CONF=./conf ./ccollect -a daily CCOLLECT_CONF=./conf ./ccollect -a daily
touch /tmp/ccollect/$$(ls /tmp/ccollect | head -n1).ccollect-marker touch /tmp/ccollect/$$(ls /tmp/ccollect | head -n1).ccollect-marker
CCOLLECT_CONF=./conf ./ccollect -a -p daily CCOLLECT_CONF=./conf ./ccollect -a -p daily
test-dir-source:
mkdir -p /tmp/ccollect/source
cp -R -f ./* /tmp/ccollect/source
test-dir-destination:
mkdir -p /tmp/ccollect/backup
test-dir-destination-chint:
mkdir -p /tmp/ccollect/backup-chint
test-fixed-intervals: $(CCOLLECT_SOURCE) test-dir-source test-dir-destination test-dir-destination-chint
for s in ./test/conf/sources/*; do \
CCOLLECT_CONF=./test/conf ./ccollect -l ${TEST_LOG_FILE} daily "$$(basename "$$s")"; \
test "$$(ls -1 /tmp/ccollect/backup | wc -l)" -gt "0" || { cat ${TEST_LOG_FILE}; exit 1; }; \
done
CCOLLECT_CONF=./test/conf ./ccollect -l ${TEST_LOG_FILE} -a -v daily
test "$$(ls -1 /tmp/ccollect/backup | wc -l)" -gt "0" || { cat ${TEST_LOG_FILE}; exit 1; }
CCOLLECT_CONF=./test/conf ./ccollect -l ${TEST_LOG_FILE} -a -p daily
test "$$(ls -1 /tmp/ccollect/backup | wc -l)" -gt "0" || { cat ${TEST_LOG_FILE}; exit 1; }
@printf "\nFixed intervals test ended successfully\n"
test-interval-changing: $(CCOLLECT_SOURCE) test-dir-source test-dir-destination-chint
rm -rf /tmp/ccollect/backup-chint/*
test "$$(ls -1 /tmp/ccollect/backup-chint | wc -l)" -eq "0" || { cat ${TEST_LOG_FILE}; exit 1; }
printf "3" > ./test/conf/sources/local-with-interval/intervals/daily
for x in 1 2 3 4 5; do CCOLLECT_CONF=./test/conf ./ccollect -l ${TEST_LOG_FILE} daily local-with-interval; done
test "$$(ls -1 /tmp/ccollect/backup-chint | wc -l)" -eq "3" || { cat ${TEST_LOG_FILE}; exit 1; }
printf "5" > ./test/conf/sources/local-with-interval/intervals/daily
for x in 1 2 3 4 5 6 7; do CCOLLECT_CONF=./test/conf ./ccollect -l ${TEST_LOG_FILE} daily local-with-interval; done
test "$$(ls -1 /tmp/ccollect/backup-chint | wc -l)" -eq "5" || { cat ${TEST_LOG_FILE}; exit 1; }
printf "4" > ./test/conf/sources/local-with-interval/intervals/daily
for x in 1 2 3 4 5 6; do CCOLLECT_CONF=./test/conf ./ccollect -l ${TEST_LOG_FILE} daily local-with-interval; done
test "$$(ls -1 /tmp/ccollect/backup-chint | wc -l)" -eq "4" || { cat ${TEST_LOG_FILE}; exit 1; }
printf "3" > ./test/conf/sources/local-with-interval/intervals/daily
@printf "\nInterval changing test ended successfully\n"
test: test-fixed-intervals test-interval-changing
test -f "${TEST_LOG_FILE}"
@printf "\nTests ended successfully\n"

334
ccollect
View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# 2005-2013 Nico Schottelius (nico-ccollect at schottelius.org) # 2005-2013 Nico Schottelius (nico-ccollect at schottelius.org)
# 2016 Darko Poljak (darko.poljak at gmail.com) # 2016-2019 Darko Poljak (darko.poljak at gmail.com)
# #
# This file is part of ccollect. # This file is part of ccollect.
# #
@ -27,9 +27,9 @@ set -u
# #
# Standard variables (stolen from cconf) # Standard variables (stolen from cconf)
# #
__pwd="$(pwd -P)" __mydir="${0%/*}"
__mydir="${0%/*}"; __abs_mydir="$(cd "$__mydir" && pwd -P)" __abs_mydir="$(cd "$__mydir" && pwd -P)"
__myname=${0##*/}; __abs_myname="$__abs_mydir/$__myname" __myname=${0##*/}
# #
# where to find our configuration and temporary file # where to find our configuration and temporary file
@ -41,11 +41,12 @@ CPREEXEC="${CDEFAULTS}/pre_exec"
CPOSTEXEC="${CDEFAULTS}/post_exec" CPOSTEXEC="${CDEFAULTS}/post_exec"
CMARKER=".ccollect-marker" CMARKER=".ccollect-marker"
export TMP="$(mktemp "/tmp/${__myname}.XXXXXX")" TMP="$(mktemp "/tmp/${__myname}.XXXXXX")"
export TMP
CONTROL_PIPE="/tmp/${__myname}-control-pipe" CONTROL_PIPE="/tmp/${__myname}-control-pipe"
VERSION="2.0" VERSION="2.10"
RELEASE="2016-09-26" RELEASE="2020-08-26"
HALF_VERSION="ccollect ${VERSION}" HALF_VERSION="ccollect ${VERSION}"
FULL_VERSION="ccollect ${VERSION} (${RELEASE})" FULL_VERSION="ccollect ${VERSION} (${RELEASE})"
@ -76,8 +77,9 @@ LOCKFD=4
lock_flock() lock_flock()
{ {
# $1 = source to backup # $1 = source to backup
# shellcheck disable=SC2059
lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")" lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")"
eval "exec ${LOCKFD}> ${lockfile}" eval "exec ${LOCKFD}> '${lockfile}'"
flock -n ${LOCKFD} && return 0 || return 1 flock -n ${LOCKFD} && return 0 || return 1
} }
@ -85,6 +87,7 @@ lock_flock()
unlock_flock() unlock_flock()
{ {
# $1 = source to backup # $1 = source to backup
# shellcheck disable=SC2059
lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")" lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")"
eval "exec ${LOCKFD}>&-" eval "exec ${LOCKFD}>&-"
rm -f "${lockfile}" rm -f "${lockfile}"
@ -96,6 +99,7 @@ unlock_flock()
lock_mkdir() lock_mkdir()
{ {
# $1 = source to backup # $1 = source to backup
# shellcheck disable=SC2059
lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")" lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")"
mkdir "${lockfile}" && return 0 || return 1 mkdir "${lockfile}" && return 0 || return 1
@ -104,6 +108,7 @@ lock_mkdir()
unlock_mkdir() unlock_mkdir()
{ {
# $1 = source to backup # $1 = source to backup
# shellcheck disable=SC2059
lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")" lockfile="${LOCKDIR}/$(printf "${LOCKFILE_PATTERN}" "$1")"
rmdir "${lockfile}" rmdir "${lockfile}"
@ -112,7 +117,7 @@ unlock_mkdir()
# #
# determine locking tool: flock or mkdir # determine locking tool: flock or mkdir
# #
if $(which flock > /dev/null 2>&1) if command -v flock > /dev/null 2>&1
then then
lockf="lock_flock" lockf="lock_flock"
unlockf="unlock_flock" unlockf="unlock_flock"
@ -127,34 +132,28 @@ fi
PARALLEL="" PARALLEL=""
MAX_JOBS="" MAX_JOBS=""
USE_ALL="" USE_ALL=""
LOGFILE=""
SYSLOG=""
# e - only errors, a - all output
LOGLEVEL="a"
LOGONLYERRORS=""
# #
# catch signals # catch signals
# #
TRAPFUNC="rm -f \"${TMP}\"" TRAPFUNC="rm -f \"${TMP}\""
# shellcheck disable=SC2064
trap "${TRAPFUNC}" 1 2 15 trap "${TRAPFUNC}" 1 2 15
# #
# Functions # Functions
# #
# time displaying echo # check if we are running interactive or non-interactive
_techo() # see: http://www.tldp.org/LDP/abs/html/intandnonint.html
_is_interactive()
{ {
echo "$(${DDATE}): $@" [ -t 0 ] || [ -p /dev/stdin ]
}
# exit on error
_exit_err()
{
_techo "Error: $@"
rm -f "${TMP}"
exit 1
}
add_name()
{
awk "{ print \"[${name}] \" \$0 }"
} }
# #
@ -167,16 +166,29 @@ delete_from_file()
file="$1"; shift file="$1"; shift
suffix="" # It will be set, if deleting incomplete backups. suffix="" # It will be set, if deleting incomplete backups.
[ $# -eq 1 ] && suffix="$1" && shift [ $# -eq 1 ] && suffix="$1" && shift
while read to_remove; do # dirs for deletion will be moved to this trash dir inside destination dir
# - for fast mv operation
trash="$(mktemp -d ".trash.XXXXXX")"
while read -r to_remove; do
mv "${to_remove}" "${trash}" ||
_exit_err "Moving ${to_remove} to ${trash} failed."
set -- "$@" "${to_remove}" set -- "$@" "${to_remove}"
if [ "${suffix}" ]; then if [ "${suffix}" ]; then
to_remove_no_suffix="$(echo ${to_remove} | sed "s/$suffix\$//")" to_remove_no_suffix="$(echo "${to_remove}" | sed "s/$suffix\$//")"
mv "${to_remove_no_suffix}" "${trash}" ||
_exit_err "Moving ${to_remove_no_suffix} to ${trash} failed."
set -- "$@" "${to_remove_no_suffix}" set -- "$@" "${to_remove_no_suffix}"
fi fi
done < "${file}" done < "${file}"
_techo "Removing $@ ..." _techo "Removing $* in ${trash}..."
[ "${VVERBOSE}" ] && echo rm "$@" empty_dir=".empty-dir"
rm -rf "$@" || _exit_err "Removing $@ failed." mkdir "${empty_dir}" || _exit_err "Empty directory ${empty_dir} cannot be created."
[ "${VVERBOSE}" ] && echo "Starting: rsync -a --delete ${empty_dir} ${trash}"
# rsync needs ending slash for directory content
rsync -a --delete "${empty_dir}/" "${trash}/" || _exit_err "Removing $* failed."
rmdir "${trash}" || _exit_err "Removing ${trash} directory failed"
rmdir "${empty_dir}" || _exit_err "Removing ${empty_dir} directory failed"
_techo "Removing $* in ${trash} finished."
} }
display_version() display_version()
@ -194,9 +206,12 @@ ${__myname}: [args] <interval name> <sources to backup>
-h, --help: Show this help screen -h, --help: Show this help screen
-a, --all: Backup all sources specified in ${CSOURCES} -a, --all: Backup all sources specified in ${CSOURCES}
-e, --errors: Log only errors
-j [max], --jobs [max] Specifies the number of jobs to run simultaneously. -j [max], --jobs [max] Specifies the number of jobs to run simultaneously.
If max is not specified then parallelise all jobs. If max is not specified then parallelise all jobs.
-l FILE, --logfile FILE Log to specified file
-p, --parallel: Parallelise backup processes (deprecated from 2.0) -p, --parallel: Parallelise backup processes (deprecated from 2.0)
-s, --syslog: Log to syslog with tag ccollect
-v, --verbose: Be very verbose (uses set -x) -v, --verbose: Be very verbose (uses set -x)
-V, --version: Print version information -V, --version: Print version information
@ -219,6 +234,57 @@ unlock()
"${unlockf}" "$@" "${unlockf}" "$@"
} }
# time displaying echo
# stdout version
_techo_stdout()
{
echo "$(${DDATE}): $*"
}
# syslog version
_techo_syslog()
{
logger -t ccollect "$@"
}
# specified file version
_techo_file()
{
_techo_stdout "$@" >> "${LOGFILE}"
}
# determine _techo version before parsing options
if _is_interactive
then
_techof="_techo_stdout"
else
_techof="_techo_syslog"
fi
# _techo with determined _techo version
_techo()
{
if [ "${LOGLEVEL}" = "a" ]
then
# name is exported before calling this function
# shellcheck disable=SC2154
set -- ${name:+"[${name}]"} "$@"
"${_techof}" "$@"
fi
}
_techo_err()
{
_techo "Error: $*"
}
_exit_err()
{
_techo_err "$@"
rm -f "${TMP}"
exit 1
}
# #
# Parse options # Parse options
# #
@ -247,6 +313,28 @@ while [ "$#" -ge 1 ]; do
esac esac
fi fi
;; ;;
-e|--errors)
LOGONLYERRORS="1"
;;
-l|--logfile)
if [ "$#" -ge 2 ]
then
case "$2" in
-*)
_exit_err "Missing log file"
;;
*)
LOGFILE="$2"
shift
;;
esac
else
_exit_err "Missing log file"
fi
;;
-s|--syslog)
SYSLOG="1"
;;
-v|--verbose) -v|--verbose)
set -x set -x
;; ;;
@ -268,10 +356,37 @@ while [ "$#" -ge 1 ]; do
shift shift
done done
# determine _techo version and logging level after parsing options
if [ "${LOGFILE}" ]
then
_techof="_techo_file"
LOGLEVEL="a"
elif _is_interactive
then
if [ "${SYSLOG}" ]
then
_techof="_techo_syslog"
LOGLEVEL="a"
else
_techof="_techo_stdout"
LOGLEVEL="e"
fi
else
_techof="_techo_syslog"
LOGLEVEL="a"
fi
if [ "${LOGFILE}" ] || [ "${SYSLOG}" ]
then
if [ "${LOGONLYERRORS}" ]
then
LOGLEVEL="e"
fi
fi
# check that MAX_JOBS is natural number > 0 # check that MAX_JOBS is natural number > 0
# empty string means run all in parallel # empty string means run all in parallel
echo "${MAX_JOBS}" | grep -q -E '^[1-9][0-9]*$|^$' if ! echo "${MAX_JOBS}" | grep -q -E '^[1-9][0-9]*$|^$'
if [ "$?" -ne 0 ]
then then
_exit_err "Invalid max jobs value \"${MAX_JOBS}\"" _exit_err "Invalid max jobs value \"${MAX_JOBS}\""
fi fi
@ -304,19 +419,22 @@ if [ "${USE_ALL}" = 1 ]; then
( cd "${CSOURCES}" && ls -1 > "${TMP}" ) || \ ( cd "${CSOURCES}" && ls -1 > "${TMP}" ) || \
_exit_err "Listing of sources failed. Aborting." _exit_err "Listing of sources failed. Aborting."
while read tmp; do while read -r tmp; do
eval export source_${no_sources}=\"${tmp}\" eval export "source_${no_sources}=\"${tmp}\""
no_sources=$((${no_sources}+1)) no_sources=$((no_sources + 1))
done < "${TMP}" done < "${TMP}"
else else
# #
# Get sources from command line # Get sources from command line
# #
while [ "$#" -ge 1 ]; do while [ "$#" -ge 1 ]; do
eval arg=\"\$1\"; shift eval "arg=\"\$1\""
shift
eval export source_${no_sources}=\"${arg}\" # arg is assigned in the eval above
no_sources="$((${no_sources}+1))" # shellcheck disable=SC2154
eval export "source_${no_sources}=\"${arg}\""
no_sources="$((no_sources + 1))"
done done
fi fi
@ -351,14 +469,20 @@ fi
if [ "${PARALLEL}" ]; then if [ "${PARALLEL}" ]; then
mkfifo "${CONTROL_PIPE}" mkfifo "${CONTROL_PIPE}"
# fd 5 is tied to control pipe # fd 5 is tied to control pipe
eval "exec 5<>${CONTROL_PIPE}" eval "exec 5<>'${CONTROL_PIPE}'"
TRAPFUNC="${TRAPFUNC}; rm -f \"${CONTROL_PIPE}\"" TRAPFUNC="${TRAPFUNC}; rm -f \"${CONTROL_PIPE}\""
# shellcheck disable=SC2064
trap "${TRAPFUNC}" 0 1 2 15 trap "${TRAPFUNC}" 0 1 2 15
# determine how much parallel jobs to prestart # determine how much parallel jobs to prestart
if [ "${MAX_JOBS}" ] && [ "${MAX_JOBS}" -le "${no_sources}" ] if [ "${MAX_JOBS}" ]
then
if [ "${MAX_JOBS}" -le "${no_sources}" ]
then then
prestart="${MAX_JOBS}" prestart="${MAX_JOBS}"
else
prestart="${no_sources}"
fi
else else
prestart=0 prestart=0
fi fi
@ -370,7 +494,7 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# Get current source # Get current source
# #
eval export name=\"\$source_${source_no}\" eval export name=\"\$source_${source_no}\"
source_no=$((${source_no}+1)) source_no=$((source_no + 1))
# #
# Start ourself, if we want parallel execution # Start ourself, if we want parallel execution
@ -385,12 +509,12 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
then then
# run prestart child if pending # run prestart child if pending
{ "$0" "${INTERVAL}" "${name}"; printf '\n' >&5; } & { "$0" "${INTERVAL}" "${name}"; printf '\n' >&5; } &
prestart=$((${prestart} - 1)) prestart=$((prestart - 1))
continue continue
else else
# each time a child finishes we get a line from the pipe # each time a child finishes we get a line from the pipe
# and then launch another child # and then launch another child
while read line while read -r line
do do
{ "$0" "${INTERVAL}" "${name}"; printf '\n' >&5; } & { "$0" "${INTERVAL}" "${name}"; printf '\n' >&5; } &
# get out of loop so we can contnue with main loop # get out of loop so we can contnue with main loop
@ -426,7 +550,7 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# Standard configuration checks # Standard configuration checks
# #
if [ ! -e "${backup}" ]; then if [ ! -e "${backup}" ]; then
_exit_err "Source does not exist." _exit_err "Source \"${backup}\" does not exist."
fi fi
# #
@ -444,6 +568,7 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# redefine trap to also unlock (rm lockfile) # redefine trap to also unlock (rm lockfile)
TRAPFUNC="${TRAPFUNC}; unlock \"${name}\"" TRAPFUNC="${TRAPFUNC}; unlock \"${name}\""
# shellcheck disable=SC2064
trap "${TRAPFUNC}" 1 2 15 trap "${TRAPFUNC}" 1 2 15
# #
@ -463,10 +588,10 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
for opt in verbose very_verbose summary exclude rsync_options \ for opt in verbose very_verbose summary exclude rsync_options \
delete_incomplete rsync_failure_codes \ delete_incomplete rsync_failure_codes \
mtime quiet_if_down ; do mtime quiet_if_down ; do
if [ -f "${backup}/${opt}" -o -f "${backup}/no_${opt}" ]; then if [ -f "${backup}/${opt}" ] || [ -f "${backup}/no_${opt}" ]; then
eval c_$opt=\"${backup}/$opt\" eval "c_$opt=\"${backup}/$opt\""
else else
eval c_$opt=\"${CDEFAULTS}/$opt\" eval "c_$opt=\"${CDEFAULTS}/$opt\""
fi fi
done done
@ -486,6 +611,8 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# #
# Sort by ctime (default) or mtime (configuration option) # Sort by ctime (default) or mtime (configuration option)
# #
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "${c_mtime}" ] ; then if [ -f "${c_mtime}" ] ; then
TSORT="t" TSORT="t"
else else
@ -529,6 +656,8 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# #
# Exclude list # Exclude list
# #
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "${c_exclude}" ]; then if [ -f "${c_exclude}" ]; then
set -- "$@" "--exclude-from=${c_exclude}" set -- "$@" "--exclude-from=${c_exclude}"
fi fi
@ -536,6 +665,8 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# #
# Output a summary # Output a summary
# #
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "${c_summary}" ]; then if [ -f "${c_summary}" ]; then
set -- "$@" "--stats" set -- "$@" "--stats"
fi fi
@ -544,6 +675,8 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# Verbosity for rsync, rm, and mkdir # Verbosity for rsync, rm, and mkdir
# #
VVERBOSE="" VVERBOSE=""
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "${c_very_verbose}" ]; then if [ -f "${c_very_verbose}" ]; then
set -- "$@" "-vv" set -- "$@" "-vv"
VVERBOSE="-v" VVERBOSE="-v"
@ -554,9 +687,21 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# #
# Extra options for rsync provided by the user # Extra options for rsync provided by the user
# #
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "${c_rsync_options}" ]; then if [ -f "${c_rsync_options}" ]; then
while read line; do while read -r line; do
set -- "$@" "${line}" # Trim line.
ln=$(echo "${line}" | awk '{$1=$1;print;}')
# Only if ln is non zero length string.
#
# If ln is empty then rsync '' DEST evaluates
# to transfer current directory to DEST which would
# with specific options destroy DEST content.
if [ -n "${ln}" ]
then
set -- "$@" "${ln}"
fi
done < "${c_rsync_options}" done < "${c_rsync_options}"
fi fi
@ -564,6 +709,8 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# Check: source is up and accepting connections (before deleting old backups!) # Check: source is up and accepting connections (before deleting old backups!)
# #
if ! rsync "$@" "${source}" >/dev/null 2>"${TMP}" ; then if ! rsync "$@" "${source}" >/dev/null 2>"${TMP}" ; then
# variable is assigned using eval
# shellcheck disable=SC2154
if [ ! -f "${c_quiet_if_down}" ]; then if [ ! -f "${c_quiet_if_down}" ]; then
cat "${TMP}" cat "${TMP}"
fi fi
@ -583,36 +730,77 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# #
# Check incomplete backups (needs echo to remove newlines) # Check incomplete backups (needs echo to remove newlines)
# #
# shellcheck disable=SC2010
ls -1 | grep "${CMARKER}\$" > "${TMP}"; ret=$? ls -1 | grep "${CMARKER}\$" > "${TMP}"; ret=$?
if [ "$ret" -eq 0 ]; then if [ "$ret" -eq 0 ]; then
_techo "Incomplete backups: $(echo $(cat "${TMP}"))" _techo "Incomplete backups: $(cat "${TMP}")"
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "${c_delete_incomplete}" ]; then if [ -f "${c_delete_incomplete}" ]; then
delete_from_file "${TMP}" "${CMARKER}" delete_from_file "${TMP}" "${CMARKER}" &
fi fi
fi fi
#
# Include current time in name, not the time when we began to remove above
#
destination_name="${INTERVAL}.$(${CDATE}).$$-${source_no}"
export destination_name
destination_dir="${ddir}/${destination_name}"
export destination_dir
# #
# Check: maximum number of backups is reached? # Check: maximum number of backups is reached?
# #
# shellcheck disable=SC2010
count="$(ls -1 | grep -c "^${INTERVAL}\\.")" count="$(ls -1 | grep -c "^${INTERVAL}\\.")"
_techo "Existing backups: ${count} Total keeping backups: ${c_interval}" _techo "Existing backups: ${count} Total keeping backups: ${c_interval}"
if [ "${count}" -ge "${c_interval}" ]; then if [ "${count}" -ge "${c_interval}" ]; then
remove="$((${count} - ${c_interval} + 1))" # Use oldest directory as new backup destination directory.
# It need not to be deleted, rsync will sync its content.
# shellcheck disable=SC2010
oldest_bak=$(ls -${TSORT}1r | grep "^${INTERVAL}\\." | head -n 1 || \
_exit_err "Listing oldest backup failed")
_techo "Using ${oldest_bak} for destination dir ${destination_dir}"
if mv "${oldest_bak}" "${destination_dir}"; then
# Touch dest dir so it is not sorted wrong in listings below.
ls_rm_exclude=$(basename "${destination_dir}")
# We have something to remove only if count > interval.
remove="$((count - c_interval))"
else
_techo_err "Renaming oldest backup ${oldest_bak} to ${destination_dir} failed, removing it."
remove="$((count - c_interval + 1))"
ls_rm_exclude=""
fi
if [ "${remove}" -gt 0 ]; then
_techo "Removing ${remove} backup(s)..." _techo "Removing ${remove} backup(s)..."
if [ -z "${ls_rm_exclude}" ]; then
# shellcheck disable=SC2010
ls -${TSORT}1r | grep "^${INTERVAL}\\." | head -n "${remove}" > "${TMP}" || \ ls -${TSORT}1r | grep "^${INTERVAL}\\." | head -n "${remove}" > "${TMP}" || \
_exit_err "Listing old backups failed" _exit_err "Listing old backups failed"
else
# shellcheck disable=SC2010
ls -${TSORT}1r | grep -v "${ls_rm_exclude}" | grep "^${INTERVAL}\\." | head -n "${remove}" > "${TMP}" || \
_exit_err "Listing old backups failed"
fi
delete_from_file "${TMP}" delete_from_file "${TMP}" &
fi
fi fi
# #
# Check for backup directory to clone from: Always clone from the latest one! # Check for backup directory to clone from: Always clone from the latest one!
# Exclude destination_dir from listing, it can be touched reused and renamed
# oldest existing destination directory.
# #
last_dir="$(ls -${TSORT}p1 | grep '/$' | head -n 1)" || \ dest_dir_name=$(basename "${destination_dir}")
# shellcheck disable=SC2010
last_dir="$(ls -${TSORT}p1 | grep '/$' | grep -v "${dest_dir_name}" | head -n 1)" || \
_exit_err "Failed to list contents of ${ddir}." _exit_err "Failed to list contents of ${ddir}."
# #
@ -623,12 +811,6 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
_techo "Hard linking from ${last_dir}" _techo "Hard linking from ${last_dir}"
fi fi
#
# Include current time in name, not the time when we began to remove above
#
export destination_name="${INTERVAL}.$(${CDATE}).$$-${source_no}"
export destination_dir="${ddir}/${destination_name}"
# #
# Mark backup running and go back to original directory # Mark backup running and go back to original directory
# #
@ -642,6 +824,11 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
rsync "$@" "${source}" "${destination_dir}"; ret=$? rsync "$@" "${source}" "${destination_dir}"; ret=$?
_techo "Finished backup (rsync return code: $ret)." _techo "Finished backup (rsync return code: $ret)."
#
# export rsync return code, might be useful in post_exec
#
export rsync_return_code=$ret
# #
# Set modification time (mtime) to current time, if sorting by mtime is enabled # Set modification time (mtime) to current time, if sorting by mtime is enabled
# #
@ -651,8 +838,10 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# Check if rsync exit code indicates failure. # Check if rsync exit code indicates failure.
# #
fail="" fail=""
# variable is assigned using eval
# shellcheck disable=SC2154
if [ -f "$c_rsync_failure_codes" ]; then if [ -f "$c_rsync_failure_codes" ]; then
while read code ; do while read -r code ; do
if [ "$ret" = "$code" ]; then if [ "$ret" = "$code" ]; then
fail=1 fail=1
fi fi
@ -672,6 +861,16 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
_techo "Warning: rsync failed with return code $ret." _techo "Warning: rsync failed with return code $ret."
fi fi
#
# Create symlink to newest backup
#
# shellcheck disable=SC2010
latest_dir="$(ls -${TSORT}p1 "${ddir}" | grep '/$' | head -n 1)" || \
_exit_err "Failed to list content of ${ddir}."
ln -snf "${ddir}${latest_dir}" "${ddir}current" || \
_exit_err "Failed to create 'current' symlink."
# #
# post_exec # post_exec
# #
@ -689,15 +888,18 @@ while [ "${source_no}" -lt "${no_sources}" ]; do
# Time calculation # Time calculation
# #
end_s="$(${SDATE})" end_s="$(${SDATE})"
full_seconds="$((${end_s} - ${begin_s}))" full_seconds="$((end_s - begin_s))"
hours="$((${full_seconds} / 3600))" hours="$((full_seconds / 3600))"
minutes="$(((${full_seconds} % 3600) / 60))" minutes="$(((full_seconds % 3600) / 60))"
seconds="$((${full_seconds} % 60))" seconds="$((full_seconds % 60))"
_techo "Backup lasted: ${hours}:${minutes}:${seconds} (h:m:s)" _techo "Backup lasted: ${hours}:${minutes}:${seconds} (h:m:s)"
unlock "${name}" unlock "${name}"
) | add_name
# wait for children (doing delete_from_file) if any still running
wait
) || exit
done done
# #

View file

@ -1,6 +1,6 @@
Summary: (pseudo) incremental backup with different exclude lists using hardlinks and rsync Summary: (pseudo) incremental backup with different exclude lists using hardlinks and rsync
Name: ccollect Name: ccollect
Version: 0.8.1 Version: 2.3
Release: 0 Release: 0
URL: http://www.nico.schottelius.org/software/ccollect URL: http://www.nico.schottelius.org/software/ccollect
Source0: http://www.nico.schottelius.org/software/ccollect/%{name}-%{version}.tar.bz2 Source0: http://www.nico.schottelius.org/software/ccollect/%{name}-%{version}.tar.bz2
@ -23,10 +23,10 @@ Only the inodes used by the hardlinks and the changed files need additional spac
%install %install
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
#Installing main ccollect.sh and /etc directory #Installing main ccollect and /etc directory
%__install -d 755 %buildroot%_bindir %__install -d 755 %buildroot%_bindir
%__install -d 755 %buildroot%_sysconfdir/%name %__install -d 755 %buildroot%_sysconfdir/%name
%__install -m 755 ccollect.sh %buildroot%_bindir/ %__install -m 755 ccollect %buildroot%_bindir/
#bin files from tools directory #bin files from tools directory
for t in $(ls tools/ccollect_*) ; do for t in $(ls tools/ccollect_*) ; do
@ -45,19 +45,13 @@ done
#Addition documentation and some config tools #Addition documentation and some config tools
%__install -d 755 %buildroot%_datadir/%name/tools %__install -d 755 %buildroot%_datadir/%name/tools
%__install -m 755 tools/called_from_remote_pre_exec %buildroot%_datadir/%name/tools
%__cp -pr tools/config-pre-* %buildroot%_datadir/%name/tools %__cp -pr tools/config-pre-* %buildroot%_datadir/%name/tools
%__install -m 755 tools/gnu-du-backup-size-compare.sh %buildroot%_datadir/%name/tools %__install -m 755 tools/report_success %buildroot%_datadir/%name/tools
%__install -m 755 tools/report_success.sh %buildroot%_datadir/%name/tools
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
%post
%__ln_s %_bindir/ccollect.sh %_bindir/ccollect
%preun
unlink %_bindir/ccollect
%files %files
%defattr(-,root,root) %defattr(-,root,root)
%_bindir/ccollect* %_bindir/ccollect*

View file

@ -1,7 +1,7 @@
ccollect - Installing, Configuring and Using ccollect - Installing, Configuring and Using
============================================ ============================================
Nico Schottelius <nico-ccollect__@__schottelius.org> Nico Schottelius <nico-ccollect__@__schottelius.org>
2.0, for ccollect 2.0, Initial Version from 2006-01-13 2.10, for ccollect 2.10, Initial Version from 2006-01-13
:Author Initials: NS :Author Initials: NS
@ -26,6 +26,7 @@ Supported and tested operating systems and architectures
- Mac OS X 10.5 - Mac OS X 10.5
- NetBSD on alpha/amd64/i386/sparc/sparc64 - NetBSD on alpha/amd64/i386/sparc/sparc64
- OpenBSD on amd64 - OpenBSD on amd64
- Windows by installing Cygwin, OpenSSH and rsync
It *should* run on any Unix that supports `rsync` and has a POSIX-compatible It *should* run on any Unix that supports `rsync` and has a POSIX-compatible
bourne shell. If your platform is not listed above and you have it successfully bourne shell. If your platform is not listed above and you have it successfully

1
doc/changes/2.1 Normal file
View file

@ -0,0 +1 @@
* Add options for stdout, file and syslog logging (Darko Poljak)

1
doc/changes/2.10 Normal file
View file

@ -0,0 +1 @@
* Add 'current' symlink to backup destinations (Steffen Zieger)

1
doc/changes/2.2 Normal file
View file

@ -0,0 +1 @@
* Bugfix: empty rsync_options line causes destroying source (Darko Poljak)

1
doc/changes/2.3 Normal file
View file

@ -0,0 +1 @@
* Bugfix: Fix parallel mode deadlock when max jobs > number of sources (Darko Poljak)

2
doc/changes/2.4 Normal file
View file

@ -0,0 +1,2 @@
* Add Windows(Cygwin) as supported OS
* Add source name tag in log line

1
doc/changes/2.5 Normal file
View file

@ -0,0 +1 @@
* Bugfix: exit in case of subshell error

1
doc/changes/2.6 Normal file
View file

@ -0,0 +1 @@
* Improve performance, improve process of deletion of old backups

1
doc/changes/2.7 Normal file
View file

@ -0,0 +1 @@
* Fix shellcheck reported issues

1
doc/changes/2.8 Normal file
View file

@ -0,0 +1 @@
* Fix excluding destination dir from removal

1
doc/changes/2.9 Normal file
View file

@ -0,0 +1 @@
* Make rsync return code available in post_exec (Steffen Zieger)

View file

@ -29,6 +29,9 @@ OPTIONS
-a, --all:: -a, --all::
Backup all sources specified in /etc/ccollect/sources Backup all sources specified in /etc/ccollect/sources
-e, --errors::
Log only errors
-h, --help:: -h, --help::
Show the help screen Show the help screen
@ -36,14 +39,41 @@ OPTIONS
Specifies the number of jobs to run simultaneously. Specifies the number of jobs to run simultaneously.
If max is not specified then parallelise all jobs. If max is not specified then parallelise all jobs.
-l FILE, --logfile FILE::
Log to specified file
-p, --parallel:: -p, --parallel::
Parallelise backup processes (deprecated from 2.0) Parallelise backup processes (deprecated from 2.0)
-s, --syslog::
Log to syslog with tag ccollect
-V, --version::
Show version and exit
-v, --verbose:: -v, --verbose::
Be very verbose (uses set -x) Be very verbose (uses set -x)
-V, --version::
Show version and exit LOGGING MECHANISM
-----------------
ccollect logging depends on running in non-interactive/interactive mode
and on specified optins. The mechanism behaves as the following:
non-interactive mode::
* standard output goes to syslog
* optional: specify logging into file
* log all output by default
* optional: log only errors
interactive mode::
* standard output goes to stdout
* log only errors
* optional: log into syslog or file
- log all output by default
- optional: log only errors
SEE ALSO SEE ALSO

View file

View file

View file

@ -0,0 +1 @@
5

View file

@ -0,0 +1 @@
4

View file

@ -0,0 +1 @@
4

View file

@ -0,0 +1 @@
2

3
test/conf/defaults/post_exec Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
echo 'General post_exec executed.'

3
test/conf/defaults/pre_exec Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
echo 'General pre__exec executed.'

View file

@ -0,0 +1 @@
.git

View file

View file

View file

View file

@ -0,0 +1 @@
/tmp/ccollect/backup

View file

@ -0,0 +1 @@
.git

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

@ -0,0 +1 @@
/tmp/ccollect/backup

View file

@ -0,0 +1 @@
.git

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

@ -0,0 +1 @@
/tmp/ccollect/backup-chint

View file

@ -0,0 +1 @@
.git

View file

@ -0,0 +1 @@
3

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

@ -0,0 +1 @@
/tmp/ccollect/backup

View file

@ -0,0 +1 @@
.git

View file

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

@ -0,0 +1 @@
/tmp/ccollect/backup

View file

@ -0,0 +1 @@
.git

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

@ -0,0 +1 @@
/tmp/ccollect/backup

View file

@ -0,0 +1 @@
.git

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

View file

View file

@ -0,0 +1 @@
/tmp/ccollect/backup

View file

@ -0,0 +1,5 @@
#!/bin/cat
######################################################################
Source post_exec executed.
######################################################################

View file

@ -0,0 +1,5 @@
#!/bin/cat
######################################################################
Source pre_exec executed.
######################################################################

View file

@ -0,0 +1 @@
/tmp/ccollect/source

View file

@ -1,18 +0,0 @@
#!/bin/sh
host="home.schottelius.org"
host=""
set -x
pcmd()
{
echo "$#", "$@"
if [ "$host" ]; then
ssh "$host" "$@"
else
$@
fi
}
#pcmd ls /
#pcmd cd /; ls "/is not there"
pcmd cd / && ls

View file

@ -1 +0,0 @@
CCOLLECT_CONF=./conf ./ccollect.sh daily -v local1

View file

@ -1 +0,0 @@
CCOLLECT_CONF=./conf ./ccollect.sh daily -v remote1

View file

@ -1,23 +0,0 @@
#!/bin/sh
ls /surely-not-existent$$ 2>/dev/null
if [ "$?" -ne 0 ]; then
echo "$?"
fi
ls /surely-not-existent$$ 2>/dev/null
ret=$?
if [ "$ret" -ne 0 ]; then
echo "$ret"
fi
# if is true, ls is fales
if [ "foo" = "foo" ]; then
ls /surely-not-existent$$ 2>/dev/null
fi
# but that's still the return of ls and not of fi
echo $?

View file

@ -1,29 +0,0 @@
#!/bin/sh
#
# 2009 Nico Schottelius (nico-ccollect at schottelius.org)
#
# This file is part of ccollect.
#
# ccollect is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ccollect is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ccollect. If not, see <http://www.gnu.org/licenses/>.
#
#
# Test the ccollect tools suite
#
set -x
tmp="$(mktemp /tmp/ccollect-tools.XXXXXXXXXXX)"
rm -rf "${tmp}"

View file

@ -1,44 +0,0 @@
#!/bin/sh
#
# Nico Schottelius <nico-linux //@// schottelius.org>
# Date: 27-Jan-2007
# Last Modified: -
# Description:
#
ccollect=../ccollect.sh
testdir="$(dirname $0)/test-backups"
confdir="$(dirname $0)/test-config"
source="$(hostname)"
source_source="/tmp"
interval="taeglich"
# backup destination
mkdir -p "$testdir"
source_dest="$(cd "$testdir"; pwd -P)"
# configuration
mkdir -p "${confdir}/sources/${source}"
ln -s "$source_dest" "${confdir}/sources/${source}/destination"
echo "$source_source" > "${confdir}/sources/${source}/source"
touch "${confdir}/sources/${source}/summary"
touch "${confdir}/sources/${source}/verbose"
mkdir -p "${confdir}/defaults/intervals/"
echo 3 > "${confdir}/defaults/intervals/$interval"
# create backups
CCOLLECT_CONF="$confdir" "$ccollect" "$interval" -p -a
touch "${source_source}/$(date +%s)-$$.1982"
CCOLLECT_CONF="$confdir" "$ccollect" "$interval" -p -a
touch "${source_source}/$(date +%s)-$$.42"
CCOLLECT_CONF="$confdir" "$ccollect" "$interval" -p -a
du -sh "$testdir"
du -shl "$testdir"
echo "Delete $testdir and $confdir after test"