diff --git a/.github/workflows/ssh.yml b/.github/workflows/ssh.yml index 6b39d96..a6deffe 100644 --- a/.github/workflows/ssh.yml +++ b/.github/workflows/ssh.yml @@ -35,6 +35,15 @@ jobs: target: - test-remote-default-abs - test-remote-default-rel + - test-remote-ssh_1111_port-nouser + - test-remote-ssh_1111_port-user + - test-remote-ssh_22_port-nouser + - test-remote-ssh_22_port-user + - test-remote-ssh_def_port-nouser + - test-remote-ssh_def_port-user + - test-remote-ssh_config-default + - test-remote-ssh_config-port_1111 + - test-remote-ssh_config-port_overwrite name: "[SSH ${{ matrix.target }}]" steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index a1d734b..dc77400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ # Changelog +## Release v1.0 + +#### Fixed +- Use correct SSH port when using SSH aliases from ~/.ssh/config + +#### Added +- Integration and regression tests for Linux, MacOS and remote backups over SSH +- GitHub Actions integration + +#### Removed +- Travis CI + + ## Release v0.9 #### Added diff --git a/Makefile b/Makefile index b608720..a8f6769 100644 --- a/Makefile +++ b/Makefile @@ -93,6 +93,15 @@ test: test-local-no_times test: test-local-copy_links test: test-remote-default-abs test: test-remote-default-rel +test: test-remote-ssh_1111_port-nouser +test: test-remote-ssh_1111_port-user +test: test-remote-ssh_22_port-nouser +test: test-remote-ssh_22_port-user +test: test-remote-ssh_def_port-nouser +test: test-remote-ssh_def_port-user +test: test-remote-ssh_config-default +test: test-remote-ssh_config-port_1111 +test: test-remote-ssh_config-port_overwrite test-local-default-abs-noslash-noslash: @@ -135,6 +144,34 @@ test-remote-default-abs: test-remote-default-rel: ./tests/10-run-remote-default-rel.sh +test-remote-ssh_1111_port-nouser: + ./tests/11-run-remote-ssh_port_1111-nouser.sh + +test-remote-ssh_1111_port-user: + ./tests/11-run-remote-ssh_port_1111-user.sh + +test-remote-ssh_22_port-nouser: + ./tests/11-run-remote-ssh_port_22-nouser.sh + +test-remote-ssh_22_port-user: + ./tests/11-run-remote-ssh_port_22-user.sh + +test-remote-ssh_def_port-nouser: + ./tests/11-run-remote-ssh_port_def-nouser.sh + +test-remote-ssh_def_port-user: + ./tests/11-run-remote-ssh_port_def-user.sh + +test-remote-ssh_config-default: + ./tests/12-run-remote-ssh_config-default.sh + +test-remote-ssh_config-port_1111: + ./tests/12-run-remote-ssh_config-port_1111.sh + +test-remote-ssh_config-port_overwrite: + ./tests/12-run-remote-ssh_config-port_overwrite.sh + + # ------------------------------------------------------------------------------------------------- # Helper targets # ------------------------------------------------------------------------------------------------- diff --git a/README.md b/README.md index 5d4c0f1..241a9da 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,13 @@ [![Tag](https://img.shields.io/github/tag/cytopia/linux-timemachine.svg)](https://github.com/cytopia/linux-timemachine/releases) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) -`linux-timemachine` is a tiny and stable [KISS](https://en.wikipedia.org/wiki/KISS_principle) driven and [POSIX](https://en.wikipedia.org/wiki/POSIX) compliant script that mimics the behavior of OSX's timemachine. +`timemachine` is a tiny and stable [KISS](https://en.wikipedia.org/wiki/KISS_principle) driven and [POSIX](https://en.wikipedia.org/wiki/POSIX) compliant script that mimics the behavior of OSX's timemachine. It uses [rsync](https://linux.die.net/man/1/rsync) to incrementally back up your data to a different directory, hard disk or remote server via SSH. All operations are incremental, atomic and automatically resumable. By default it uses the rsync options: `--recursive`, `--perms`, `--owner`, `--group`, `--times` and `--links`. In case your target filesystem does not support any of those options or you cannot use them due -to missing permission, you can explicitly disable them via `--no-perms`, `--no-owner`, `--no-group`, `--no-times`, and `--copy-links`. +to missing permission, you can explicitly disable them via `--no-perms`, `--no-owner`, `--no-group`, `--no-times`, and `--copy-links`. See [FAQ](#bulb-faq) for examples. **Motivation** @@ -194,6 +194,20 @@ As decribed above this project is [KISS](https://en.wikipedia.org/wiki/KISS_prin Retention is a delicate topic as you want to be sure that data is removed as intended. For this there are already well-established tools that do an excellent job and have proven themselves over time: [tmpreaper](http://manpages.ubuntu.com/manpages/precise/man8/tmpreaper.8.html) and [tmpwatch](https://linux.die.net/man/8/tmpwatch). +## :lock: Reliability + +[![Linting](https://github.com/cytopia/linux-timemachine/workflows/Linting/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=Linting) +[![Linux](https://github.com/cytopia/linux-timemachine/workflows/Linux/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=Linux) +[![MacOS](https://github.com/cytopia/linux-timemachine/workflows/MacOS/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=MacOS) +[![SSH](https://github.com/cytopia/linux-timemachine/workflows/SSH/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=SSH) + +The script is written and maintained with maximum care. +In order to retain a reliable and stable backup solution, a lot of effort goes into a vast amount of +**[integration and regression tests](https://github.com/cytopia/linux-timemachine/actions)**. +These tests not only give you measurable confidence, but also help new contributors to not +accidentally introduce new or old bugs. + + ## :computer: Usage ### Available options @@ -203,6 +217,7 @@ $ timemachine -h Usage: timemachine [-vdp] -- [rsync opts] timemachine [-vdp] : -- [rsync opts] timemachine [-vdp] @: -- [rsync opts] + timemachine [-vdp] : -- [rsync opts] timemachine -V, --version timemachine -h, --help @@ -212,13 +227,14 @@ All operations are incremental, atomic and automatically resumable. By default it uses --recursive --perms --owner --group --times --links. In case your target filesystem does not support any of those options, you can explicitly -disable those options via --no-perms --no-owner --no-group --no-times and --copy-links. +disable those options via --no-perms --no-owner --no-group --no-times and --copy-links. Required arguments: - Source directory - Destination directory. - : SSH host and destination directory - @: SSH user, SSH host and destination directory + Local source directory + Local destination directory. + : SSH host and destination directory on server + @: SSH user, SSH host and destination directory on server + : SSH alias (defined in ~/.ssh/config) and destination directory on server Options: -p, --port Specify alternative SSH port for remote backups if it is not 22. @@ -231,13 +247,13 @@ Misc Options: Examples: Simply back up one directory recursively - timemachine /home/user /mnt/bak + timemachine /home/user /data Do the same, but be verbose - timemachine -v /home/user /mnt/bak - Append rsync options and be verbose - timemachine -v /home/user /mnt/bak -- --archive --progress --verbose + timemachine -v /home/user /data + Append rsync options and be very verbose + timemachine -d /home/user /data -- --progress --verbose Log to file - timemachine -v /home/user /mnt/bak > /var/log/timemachine.log 2> /var/log/timemachine.err + timemachine -v /home/user /data > /var/log/timemachine.log 2> /var/log/timemachine.err ``` ### Use with cron @@ -256,11 +272,36 @@ Next, add the following to crontab using `crontab -e` as whichever user you inte 0 2 * * * if [[ -e /backup/mounted ]]; then /usr/local/bin/timemachine /home/someuser /backup; fi ``` -This will cause `linux-timemachine` to run at 2AM once per day. Since `timemachine` keeps track of backups with granularity up to the hour, minute and second, you could have it run more than once per day if you want backups to run more often. +This will cause `timemachine` to run at 2AM once per day. Since `timemachine` keeps track of backups with granularity up to the hour, minute and second, you could have it run more than once per day if you want backups to run more often. ## :bulb: FAQ +**Should I add trailing directory slashes (`/`)?** + +Trailing directory slashes only matter for the source directory and will not make a difference +if added to the destination directory. +```bash +# The following backs up the contents of the src directory +$ timemachine src/ dst/ +$ tree -L 2 /dst +. +├── 2018-01-06__18-43-30/ +│   └── file.txt +└── current -> 2018-01-06__18-43-30/ +``` + +```bash +# The following backs up the the src directory itself +$ timemachine src dst/ +$ tree -L 3 /dst +. +├── 2018-01-06__18-43-30/ +│   └── src +│   └── file.txt +└── current -> 2018-01-06__18-43-30/ +``` + **How to dry-run the backup?** ```bash $ timemachine src/ dst/ -- --dry-run @@ -268,14 +309,27 @@ $ timemachine src/ dst/ -- --dry-run **How to use a non-standard SSH port?** ```bash -$ timemachine --port 1337 src/ user@host:path/to/backup +$ timemachine --port 1337 src/ user@host:dst/ +``` + +**How to use SSH aliases from `~/.ssh/config`?** +```bash +$ cat ~/.ssh/config +Host my-ssh-alias + HostName 192.168.0.1 + Port 1234 + User john + IdentityFile ~/.ssh/id_rsa__alternative_key +``` +```bash +$ timemachine src/ my-ssh-alias:dst/ ``` **How to speed up remote backups?** ```bash # With this option, rsync compresses the file data as it is sent to the des‐ # tination machine, which reduces the amount of data being transmitted -$ timemachine src/ user@host:path/to/backup --compress +$ timemachine src/ user@host:dst/ --compress ``` **How to preserve ACLs?** @@ -295,7 +349,7 @@ $ timemachine src/ dst/ -- --no-owner --no-perms **How to disable preserving modification time?** ```bash -$ timemachine src/ dst/ -- --no-owner --no-times +$ timemachine src/ dst/ -- --no-times ``` **How to copy the content instead of a symlink?** @@ -324,33 +378,21 @@ $ sudo timemachine src/ dst/ -- --chown=: Backups are one of the most important things. We all care about our data and want it to be safe, so do not blindly trust scripts when it comes to backups! -Do [review the code](https://github.com/cytopia/linux-timemachine/blob/master/timemachine), -it is not too complex and kept as short as possible. - -Learn about [rsync](https://linux.die.net/man/1/rsync) it is a very powerful tool and you might even -be able to just use this for backups. +Do **[review the code](https://github.com/cytopia/linux-timemachine/blob/master/timemachine)**, +it is not too complex and kept as short as possible. Have a look at how much effort goes into the +**[integration tests](https://github.com/cytopia/linux-timemachine/actions)** to provide measurable +stability. -There are many other backup tools out there that might be a better fit for your needs. Do your own -research, look at GitHub issues, source code and try out other projects. +Learn about **[rsync](https://linux.die.net/man/1/rsync)** it is a very powerful tool and you might +even be able to just use this for backups. - -## :lock: Reliability - -[![Linting](https://github.com/cytopia/linux-timemachine/workflows/Linting/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=Linting) -[![Linux](https://github.com/cytopia/linux-timemachine/workflows/Linux/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=Linux) -[![MacOS](https://github.com/cytopia/linux-timemachine/workflows/MacOS/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=MacOS) -[![SSH](https://github.com/cytopia/linux-timemachine/workflows/SSH/badge.svg)](https://github.com/cytopia/linux-timemachine/actions?workflow=SSH) - -The script is written and maintained with maximum care. -In order to retain a reliable and stable backup solution, a lot of effort goes into a huge amount of -**[integration and regression tests](https://github.com/cytopia/linux-timemachine/actions)**. -These tests not only give you measurable confidence, but also help new contributors to not -accidentally introduce new or old bugs. +There are many other backup solutions out there that might be a better fit for your needs. Do your +own research, look at GitHub issues, source code, integration tests and try them out as well. ## :octocat: Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) to help to make this project more awesome. +See **[Contributing guidelines](CONTRIBUTING.md)** to help to improve this project. ## :page_facing_up: License diff --git a/tests/.lib/print.sh b/tests/.lib/print.sh index 963f375..c24a217 100644 --- a/tests/.lib/print.sh +++ b/tests/.lib/print.sh @@ -14,18 +14,20 @@ set -o pipefail ### print_section() { local text="${1}" - printf '@%.0s' {1..120}; printf "\\r\\n" - printf '@%.0s' {1..120}; + printf '@%.0s' {1..110}; + printf "\\r\\n" + printf '@%.0s' {1..110}; printf "\\r\\n" printf "@@@@@@\\r\\n" printf "@@@@@@ %s\\r\\n" "${text}" printf "@@@@@@\\r\\n" - printf '@%.0s' {1..120}; + printf '@%.0s' {1..110}; + printf "\\r\\n" + printf '@%.0s' {1..110}; printf "\\r\\n" - printf '@%.0s' {1..120}; printf "\\r\\n" } @@ -36,6 +38,7 @@ print_section() { print_headline() { local text="${1}" + printf "\\r\\n" printf '### ' printf '#%.0s' {1..96}; printf "\\r\\n" @@ -47,6 +50,7 @@ print_headline() { printf '### ' printf '#%.0s' {1..96}; printf "\\r\\n" + printf "\\r\\n" } diff --git a/tests/.lib/run-backup.sh b/tests/.lib/run-backup.sh index cbe8f4e..cd9df56 100644 --- a/tests/.lib/run-backup.sh +++ b/tests/.lib/run-backup.sh @@ -43,6 +43,7 @@ run_backup() { exit 1 fi cat "${out}" + echo ### ### Check for warnings @@ -95,3 +96,106 @@ run_backup() { rm "${out}" rm "${err}" } + + +### +### Run backup over SSH via Docker +### +run_remote_backup() { + local docker_client_name="${1}" + local docker_server_name="${2}" + local timemachine_path="${3}" + local timemachine_args="${4}" + local src_dir="${5}" + local ssh_string="${6}" + local dst_dir="${7}" + local rsync_args="${8}" + local backup_type="${9}" + local pwd="${10:-}" + + local out + local err + + out="$( create_tmp_file )" + err="$( create_tmp_file )" + + ### + ### Give 2 seconds time for a new unique directory name (second based) to be created + ### + sleep 2 + + ### + ### Run and check for failure + ### + if ! run "docker exec ${docker_client_name} ${timemachine_path} -d ${timemachine_args} ${src_dir} ${ssh_string}:${dst_dir} ${rsync_args} > \"${out}\" 2> \"${err}\""; then + printf "[TEST] [FAIL] Run failed.\\r\\n" + cat "${out}" + cat "${err}" + rm "${out}" + rm "${err}" + run "docker rm -f ${docker_client_name}" || true + run "docker rm -f ${docker_server_name}" || true + exit 1 + fi + cat "${out}" + echo + + ### + ### Check for warnings + ### + if [ -s "${err}" ]; then + printf "[TEST] [FAIL] Warnings detected.\\r\\n" + printf "Warnings:\\r\\n----------\\r\\n%s\\r\\n" "$( cat "${err}" )" + rm "${out}" + rm "${err}" + run "docker rm -f ${docker_client_name}" || true + run "docker rm -f ${docker_server_name}" || true + exit 1 + fi + printf "[TEST] [OK] No warnings detected.\\r\\n" + + ### + ### Check for backup type + ### + if ! grep "Starting ${backup_type} backup" "${out}" >/dev/null; then + printf "[TEST] [FAIL] Not a '%s' backup\\r\\n" "${backup_type}" + rm "${out}" + rm "${err}" + run "docker rm -f ${docker_client_name}" || true + run "docker rm -f ${docker_server_name}" || true + exit 1 + fi + printf "[TEST] [OK] Backup type: '%s' backup.\\r\\n" "${backup_type}" + + ### + ### Check for existing latest symlink + ### + if ! docker exec "${docker_server_name}" test -L "${pwd}${dst_dir}/current"; then + printf "[TEST] [FAIL] No latest symlink available: %s\\r\\n" "${ssh_string}:${pwd}${dst_dir}/current" + rm "${out}" + rm "${err}" + run "docker rm -f ${docker_client_name}" || true + run "docker rm -f ${docker_server_name}" || true + exit 1 + fi + printf "[TEST] [OK] Latest symlink available: %s\\r\\n" "${ssh_string}:${pwd}${dst_dir}/current" + + ### + ### Check partial backup .inprogress directory + ### + if docker exec "${docker_server_name}" test -d "${pwd}${dst_dir}/current/.inprogress"; then + printf "[TEST] [FAIL] Undeleted '.inprogress' directory found: %s\\r\\n" "${ssh_string}:${pwd}${dst_dir}/current/.inprogress" + rm "${out}" + rm "${err}" + run "docker rm -f ${docker_client_name}" || true + run "docker rm -f ${docker_server_name}" || true + exit 1 + fi + printf "[TEST] [OK] No '.inprogress' directory found\\r\\n" + + ### + ### Remove artifacts + ### + rm "${out}" + rm "${err}" +} diff --git a/tests/10-run-remote-default-abs.sh b/tests/10-run-remote-default-abs.sh index 7ee266d..a2ebb01 100755 --- a/tests/10-run-remote-default-abs.sh +++ b/tests/10-run-remote-default-abs.sh @@ -10,55 +10,149 @@ FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" . "${FUNCPATH}" +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="22" + +TIMEMACHINE_ARGS="" +RSYNC_ARGS= + +print_section "10 Remote (absolute path)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + ### ### Kill accidentally left artifacts ### run "docker rm -f ssh-server || true" >/dev/null 2>&1 run "docker rm -f ssh-client || true" >/dev/null 2>&1 - ### ### Startup ### -run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server" -run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SCRIPTPATH}/../tests:/tests' cytopia/ssh-client" +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" +### ################################################################################################ +### ################################################################################################ ### -### Run 1 +### Run backup (Round 1) ### -run "sleep 5" -if ! ERR="$( run "docker exec ssh-client /usr/bin/timemachine -d /tests root@server:/backup2" 3>&1 1>&2 2>&3 )"; then - run "docker rm -f ssh-server" - run "docker rm -f ssh-client" - exit 1 -fi -if [ -n "${ERR}" ]; then - printf "[TEST] [FAIL] Warnings detected.\\r\\n" - printf "Warnings:\\r\\n----------\\r\\n%s\\r\\n" "${ERR}" - run "docker rm -f ssh-server || true" >/dev/null 2>&1 - run "docker rm -f ssh-client || true" >/dev/null 2>&1 - exit 1 -fi +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ ### -### Run 2 +### Run backup (Round 2) ### -run "sleep 5" -if ! ERR="$( run "docker exec ssh-client /usr/bin/timemachine -d /tests root@server:/backup2" 3>&1 1>&2 2>&3 )"; then - run "docker rm -f ssh-server" - run "docker rm -f ssh-client" - exit 1 -fi -if [ -n "${ERR}" ]; then - printf "[TEST] [FAIL] Warnings detected.\\r\\n" - printf "Warnings:\\r\\n----------\\r\\n%s\\r\\n" "${ERR}" - run "docker rm -f ssh-server || true" >/dev/null 2>&1 - run "docker rm -f ssh-client || true" >/dev/null 2>&1 - exit 1 -fi +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ +print_headline "Cleanup" ### ### Remove artifacts diff --git a/tests/10-run-remote-default-rel.sh b/tests/10-run-remote-default-rel.sh index 3613dc3..9d28a85 100755 --- a/tests/10-run-remote-default-rel.sh +++ b/tests/10-run-remote-default-rel.sh @@ -10,55 +10,151 @@ FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" . "${FUNCPATH}" +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="22" + +TIMEMACHINE_ARGS="" +RSYNC_ARGS= + +print_section "10 Remote (relative path)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + ### ### Kill accidentally left artifacts ### run "docker rm -f ssh-server || true" >/dev/null 2>&1 run "docker rm -f ssh-client || true" >/dev/null 2>&1 - ### ### Startup ### -run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server" -run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SCRIPTPATH}/../tests:/tests' cytopia/ssh-client" +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" +### ################################################################################################ +### ################################################################################################ ### -### Run 1 +### Run backup (Round 1) ### -run "sleep 5" -if ! ERR="$( run "docker exec ssh-client /usr/bin/timemachine -d /tests root@server:backup1" 3>&1 1>&2 2>&3 )"; then - run "docker rm -f ssh-server" - run "docker rm -f ssh-client" - exit 1 -fi -if [ -n "${ERR}" ]; then - printf "[TEST] [FAIL] Warnings detected.\\r\\n" - printf "Warnings:\\r\\n----------\\r\\n%s\\r\\n" "${ERR}" - run "docker rm -f ssh-server || true" >/dev/null 2>&1 - run "docker rm -f ssh-client || true" >/dev/null 2>&1 - exit 1 -fi +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "backup1" \ + "${RSYNC_ARGS}" \ + "full" \ + "/root/" +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ ### -### Run 2 +### Run backup (Round 2) ### -run "sleep 5" -if ! ERR="$( run "docker exec ssh-client /usr/bin/timemachine -d /tests root@server:backup1" 3>&1 1>&2 2>&3 )"; then - run "docker rm -f ssh-server" - run "docker rm -f ssh-client" - exit 1 -fi -if [ -n "${ERR}" ]; then - printf "[TEST] [FAIL] Warnings detected.\\r\\n" - printf "Warnings:\\r\\n----------\\r\\n%s\\r\\n" "${ERR}" - run "docker rm -f ssh-server || true" >/dev/null 2>&1 - run "docker rm -f ssh-client || true" >/dev/null 2>&1 - exit 1 -fi +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "backup1" \ + "${RSYNC_ARGS}" \ + "incremental" \ + "/root/" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ +print_headline "Cleanup" ### ### Remove artifacts diff --git a/tests/11-run-remote-ssh_port_1111-nouser.sh b/tests/11-run-remote-ssh_port_1111-nouser.sh new file mode 100755 index 0000000..6ae77a3 --- /dev/null +++ b/tests/11-run-remote-ssh_port_1111-nouser.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +#SSH_USER="root" +SSH_HOST="server" +SSH_PORT="1111" + +TIMEMACHINE_ARGS="--port ${SSH_PORT}" +RSYNC_ARGS= + +print_section "11 Remote (no user && non-standard SSH port: 1111)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/11-run-remote-ssh_port_1111-user.sh b/tests/11-run-remote-ssh_port_1111-user.sh new file mode 100755 index 0000000..0983331 --- /dev/null +++ b/tests/11-run-remote-ssh_port_1111-user.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="1111" + +TIMEMACHINE_ARGS="--port ${SSH_PORT}" +RSYNC_ARGS= + +print_section "11 Remote (explicit user && non-standard SSH port: 1111)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/11-run-remote-ssh_port_22-nouser.sh b/tests/11-run-remote-ssh_port_22-nouser.sh new file mode 100755 index 0000000..130e513 --- /dev/null +++ b/tests/11-run-remote-ssh_port_22-nouser.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +#SSH_USER="root" +SSH_HOST="server" +SSH_PORT="22" + +TIMEMACHINE_ARGS="--port ${SSH_PORT}" +RSYNC_ARGS= + +print_section "11 Remote (no user && non-standard SSH port: 22)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/11-run-remote-ssh_port_22-user.sh b/tests/11-run-remote-ssh_port_22-user.sh new file mode 100755 index 0000000..f16dcb4 --- /dev/null +++ b/tests/11-run-remote-ssh_port_22-user.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="22" + +TIMEMACHINE_ARGS="--port ${SSH_PORT}" +RSYNC_ARGS= + +print_section "11 Remote (explicit user && non-standard SSH port: 22)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/11-run-remote-ssh_port_def-nouser.sh b/tests/11-run-remote-ssh_port_def-nouser.sh new file mode 100755 index 0000000..3aa39e1 --- /dev/null +++ b/tests/11-run-remote-ssh_port_def-nouser.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +#SSH_USER="root" +SSH_HOST="server" +#SSH_PORT="22" + +TIMEMACHINE_ARGS="" +RSYNC_ARGS= + +print_section "11 Remote (no user && default SSH port)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/11-run-remote-ssh_port_def-user.sh b/tests/11-run-remote-ssh_port_def-user.sh new file mode 100755 index 0000000..139752e --- /dev/null +++ b/tests/11-run-remote-ssh_port_def-user.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +#SSH_PORT="22" + +TIMEMACHINE_ARGS="" +RSYNC_ARGS= + +print_section "11 Remote (explicit user && default SSH port)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' cytopia/ssh-client" +run "sleep 5" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_USER}@${SSH_HOST}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/12-run-remote-ssh_config-default.sh b/tests/12-run-remote-ssh_config-default.sh new file mode 100755 index 0000000..5942036 --- /dev/null +++ b/tests/12-run-remote-ssh_config-default.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="22" +SSH_ALIAS="mysshalias" + +TIMEMACHINE_ARGS="" +RSYNC_ARGS= + +print_section "12 Remote (SSH config with standard SSH port: 22)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Create SSH client config +### +SSH_CONFIG="$( create_tmp_file )" +{ + echo "Host ${SSH_ALIAS}"; + echo " HostName ${SSH_HOST}"; + echo " Port ${SSH_PORT}"; + echo " User ${SSH_USER}"; +} > "${SSH_CONFIG}" + + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' -v '${SSH_CONFIG}:/root/.ssh/config' cytopia/ssh-client" +run "sleep 5" + + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_ALIAS}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_ALIAS}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/12-run-remote-ssh_config-port_1111.sh b/tests/12-run-remote-ssh_config-port_1111.sh new file mode 100755 index 0000000..da5ab53 --- /dev/null +++ b/tests/12-run-remote-ssh_config-port_1111.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="1111" +SSH_ALIAS="mysshalias" + +TIMEMACHINE_ARGS="" +RSYNC_ARGS= + +print_section "12 Remote (SSH config with non-standard SSH port: 1111)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Create SSH client config +### +SSH_CONFIG="$( create_tmp_file )" +{ + echo "Host ${SSH_ALIAS}"; + echo " HostName ${SSH_HOST}"; + echo " Port ${SSH_PORT}"; + echo " User ${SSH_USER}"; +} > "${SSH_CONFIG}" + + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' -v '${SSH_CONFIG}:/root/.ssh/config' cytopia/ssh-client" +run "sleep 5" + + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_ALIAS}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_ALIAS}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/12-run-remote-ssh_config-port_overwrite.sh b/tests/12-run-remote-ssh_config-port_overwrite.sh new file mode 100755 index 0000000..c750a9f --- /dev/null +++ b/tests/12-run-remote-ssh_config-port_overwrite.sh @@ -0,0 +1,175 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +FUNCPATH="${SCRIPTPATH}/.lib/functions.sh" +# shellcheck disable=SC1090 +. "${FUNCPATH}" + + +### +### GLOBALS +### +SSH_USER="root" +SSH_HOST="server" +SSH_PORT="1111" +SSH_ALIAS="mysshalias" + +TIMEMACHINE_ARGS="--port ${SSH_PORT}" +RSYNC_ARGS= + +print_section "12 Remote (SSH config and overwrite port)" + +### ################################################################################################ +### ################################################################################################ +### +### CREATE FILES AND DIRS +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Creating files and directories" + +### +### Create source dir +### +SRC_DIR="$( create_tmp_dir )" + +FILE1_NAME="file1.txt" +FILE2_NAME="file2.txt" +FILE3_NAME="sub/file3.txt" + +FILE1_PERM="607" +FILE2_PERM="707" +FILE3_PERM="607" + +### +### Create source files +### +create_file "${SRC_DIR}" "${FILE1_NAME}" "2" "${FILE1_PERM}" +create_file "${SRC_DIR}" "${FILE2_NAME}" "5" "${FILE2_PERM}" +create_file "${SRC_DIR}" "${FILE3_NAME}" "1" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### DEFINE CHECKS +### +### ################################################################################################ +### ################################################################################################ + +check() { + printf "" +} + + +### ################################################################################################ +### ################################################################################################ +### +### Start container +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Start container" + +### +### Kill accidentally left artifacts +### +run "docker rm -f ssh-server || true" >/dev/null 2>&1 +run "docker rm -f ssh-client || true" >/dev/null 2>&1 + +### +### Create SSH client config +### +SSH_CONFIG="$( create_tmp_file )" +{ + echo "Host ${SSH_ALIAS}"; + echo " HostName ${SSH_HOST}"; + echo " Port 50"; # This will be overwritten by the run + echo " User ${SSH_USER}"; +} > "${SSH_CONFIG}" + + +### +### Startup +### +run "docker run -d --rm --name ssh-server -h server cytopia/ssh-server /usr/sbin/sshd -p ${SSH_PORT} -D" +run "docker run -d --rm --name ssh-client -h client --link ssh-server -v '${SCRIPTPATH}/../timemachine:/usr/bin/timemachine' -v '${SRC_DIR}:/data' -v '${SSH_CONFIG}:/root/.ssh/config' cytopia/ssh-client" +run "sleep 5" + + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 1) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 1)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_ALIAS}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "full" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Run backup (Round 2) +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Backup (Round 2)" + +print_subline "Run Backup" +run_remote_backup \ + "ssh-client" \ + "ssh-server" \ + "/usr/bin/timemachine" \ + "${TIMEMACHINE_ARGS}" \ + "/data" \ + "${SSH_ALIAS}" \ + "/backup2" \ + "${RSYNC_ARGS}" \ + "incremental" + +check "${FILE1_NAME}" "${FILE1_PERM}" +check "${FILE2_NAME}" "${FILE2_PERM}" +check "${FILE3_NAME}" "${FILE3_PERM}" + + +### ################################################################################################ +### ################################################################################################ +### +### Cleanup +### +### ################################################################################################ +### ################################################################################################ + +print_headline "Cleanup" + +### +### Remove artifacts +### +run "docker rm -f ssh-server" +run "docker rm -f ssh-client" diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100644 index 0000000..290a3a9 --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,21 @@ +--- + +version: '2.3' +services: + + server: + hostname: server + build: ./docker-ssh-server + image: cytopia/ssh-server + ports: + - "2222:22" + + client: + hostname: client + build: ./docker-ssh-client + image: cytopia/ssh-client + volumes: + - "../timemachine:/usr/bin/timemachine" + - "../tests:/tests" + depends_on: + - server diff --git a/tests/docker-ssh-client/Dockerfile b/tests/docker-ssh-client/Dockerfile index 8c7eb5d..94c7b7f 100644 --- a/tests/docker-ssh-client/Dockerfile +++ b/tests/docker-ssh-client/Dockerfile @@ -32,5 +32,5 @@ RUN set -eux \ && mkdir -p /root/backup1 \ && mkdir -p /backup2 - -CMD ["sleep", "999999999"] +COPY docker-entrypoint.sh /docker-entrypoint.sh +CMD ["/docker-entrypoint.sh"] diff --git a/tests/docker-ssh-client/docker-entrypoint.sh b/tests/docker-ssh-client/docker-entrypoint.sh new file mode 100755 index 0000000..b87fd2c --- /dev/null +++ b/tests/docker-ssh-client/docker-entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +chown -R root:root /root +exec sleep 99999 diff --git a/timemachine b/timemachine index ec2a3da..095fcde 100755 --- a/timemachine +++ b/timemachine @@ -12,12 +12,15 @@ MY_DESC="OSX-like timemachine cli script for Linux and BSD (and even OSX)" MY_PROJ="https://github.com/cytopia/linux-timemachine" MY_AUTH="cytopia" MY_MAIL="cytopia@everythingcli.org" -MY_VERS="0.9" -MY_DATE="2020-03-29" +MY_VERS="1.0" +MY_DATE="2020-04-02" -# cmd [-r] [rsync opts] -verbose= # -v Verbose output -port=22 +# Default command line arguments +VERBOSE= +PORT= + +# Default variables +SSH_ARGS="-oStrictHostKeyChecking=no -oLogLevel=QUIET -q" @@ -26,11 +29,12 @@ port=22 ################################################################################ print_usage() { - echo "Usage: ${MY_NAME} [-vd] -- [rsync opts]" - echo " ${MY_NAME} [-vd] : -- [rsync opts]" - echo " ${MY_NAME} [-vd] @: -- [rsync opts]" - echo " ${MY_NAME} -V" - echo " ${MY_NAME} -h" + echo "Usage: ${MY_NAME} [-vdp] -- [rsync opts]" + echo " ${MY_NAME} [-vdp] : -- [rsync opts]" + echo " ${MY_NAME} [-vdp] @: -- [rsync opts]" + echo " ${MY_NAME} [-vdp] : -- [rsync opts]" + echo " ${MY_NAME} -V, --version" + echo " ${MY_NAME} -h, --help" echo echo "This shell script mimics the behavior of OSX's timemachine." echo "It uses rsync to incrementally back up your data to a different directory or remote server via SSH." @@ -38,13 +42,14 @@ print_usage() { echo echo "By default it uses --recursive --perms --owner --group --times --links." echo "In case your target filesystem does not support any of those options, you can explicitly" - echo "disable those options via --no-perms --no-owner --no-group --no-times and --copy-links." + echo "disable those options via --no-perms --no-owner --no-group --no-times and --copy-links." echo echo "Required arguments:" - echo " Source directory" - echo " Destination directory." - echo " : SSH host and destination directory" - echo " @: SSH user, SSH host and destination directory" + echo " Local source directory" + echo " Local destination directory." + echo " : SSH host and destination directory on server" + echo " @: SSH user, SSH host and destination directory on server" + echo " : SSH alias (defined in ~/.ssh/config) and destination directory on server" echo echo "Options:" @@ -61,12 +66,10 @@ print_usage() { echo " timemachine /home/user /data" echo " Do the same, but be verbose" echo " timemachine -v /home/user /data" - echo " Append rsync options and be verbose" - echo " timemachine /home/user /data -- --no-perms" - echo " timemachine --verbose /home/user /data -- --archive --progress --verbose" - echo " Recommendation for cron run (no stdout, but stderr)" - echo " timemachine /home/user /data -- -q" - echo " timemachine /home/user -v /data -- --verbose > /var/log/timemachine.log" + echo " Append rsync options and be very verbose" + echo " timemachine -d /home/user /data -- --progress --verbose" + echo " Log to file" + echo " timemachine -v /home/user /data > /var/log/timemachine.log 2> /var/log/timemachine.err" } print_version() { @@ -79,14 +82,14 @@ print_version() { logdebug() { # Only log to stdout when verbose is turned on - if [ "${verbose}" = "debug" ]; then + if [ "${VERBOSE}" = "debug" ]; then echo "$(date +'%Y-%m-%d %H:%M:%S') ${MY_NAME}: [DEBUG] ${*}" fi } logmsg() { - # Only log to stdout when verbose is turned on - if [ "${verbose}" = "verbose" ] || [ "${verbose}" = "debug" ]; then + # Only log to stdout when verbose/debug is turned on + if [ "${VERBOSE}" = "verbose" ] || [ "${VERBOSE}" = "debug" ]; then echo "$(date +'%Y-%m-%d %H:%M:%S') ${MY_NAME}: [INFO] ${*}" fi } @@ -95,16 +98,13 @@ logerr() { echo "$(date +'%Y-%m-%d %H:%M:%S') ${MY_NAME}: [ERROR] ${*}" >&2 } - ### ### Check if the destination is a remote server ### is_remote() { - destination="${1}" - echo "${destination}" | grep -q ':' + echo "${1}" | grep -E '.+:.+' >/dev/null } - ### ### Check if a directory exists locally or remotely ### @@ -114,16 +114,14 @@ dir_exists() { if is_remote "${directory}"; then ssh_part="$( echo "${directory}" | awk -F':' '{print $1}' )" dir_part="$( echo "${directory}" | awk -F':' '{print $2}' )" - cmd="ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port} ${ssh_part} 'test -d \"${dir_part}\"'" + cmd="ssh ${SSH_ARGS} ${ssh_part} 'test -d \"${dir_part}\"'" else cmd="test -d '${directory}'" fi - logdebug "${cmd}" eval "${cmd}" >/dev/null } - ### ### Check if a symlink exists locally or remotely ### @@ -133,16 +131,14 @@ link_exists() { if is_remote "${directory}"; then ssh_part="$( echo "${directory}" | awk -F':' '{print $1}' )" dir_part="$( echo "${directory}" | awk -F':' '{print $2}' )" - cmd="ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port} ${ssh_part} 'test -L \"${dir_part}\"'" + cmd="ssh ${SSH_ARGS} ${ssh_part} 'test -L \"${dir_part}\"'" else cmd="test -L '${directory}'" fi - logdebug "${cmd}" eval "${cmd}" >/dev/null } - ### ### Remove local or remote file ### @@ -152,16 +148,14 @@ remove_file() { if is_remote "${file}"; then ssh_part="$( echo "${file}" | awk -F':' '{print $1}' )" file_part="$( echo "${file}" | awk -F':' '{print $2}' )" - cmd="ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port} ${ssh_part} 'rm \"${file_part}\"'" + cmd="ssh ${SSH_ARGS} ${ssh_part} 'rm \"${file_part}\"'" else cmd="rm '${file}'" fi - logdebug "${cmd}" eval "${cmd}" >/dev/null } - ### ### Rename local or remote directory ### @@ -171,20 +165,16 @@ rename_directory() { if is_remote "${from}"; then ssh_part="$( echo "${from}" | awk -F':' '{print $1}' )" - dir_from_part="$( echo "${from}" | awk -F':' '{print $2}' )" dir_to_part="$( echo "${to}" | awk -F':' '{print $2}' )" - - cmd="ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port} ${ssh_part} 'mv \"${dir_from_part}\" \"${dir_to_part}\"'" + cmd="ssh ${SSH_ARGS} ${ssh_part} 'mv \"${dir_from_part}\" \"${dir_to_part}\"'" else cmd="mv '${from}' '${to}'" fi - logdebug "${cmd}" eval "${cmd}" >/dev/null } - ### ### Symlink local or remote directory ### @@ -195,12 +185,10 @@ link_directory() { if is_remote "${lnk}"; then ssh_part="$( echo "${lnk}" | awk -F':' '{print $1}' )" lnk_part="$( echo "${lnk}" | awk -F':' '{print $2}' )" - - cmd="ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port} ${ssh_part} 'ln -s \"${dir}\" \"${lnk_part}\"'" + cmd="ssh ${SSH_ARGS} ${ssh_part} 'ln -s \"${dir}\" \"${lnk_part}\"'" else cmd="ln -s '${dir}' '${lnk}'" fi - logdebug "${cmd}" eval "${cmd}" >/dev/null } @@ -214,12 +202,12 @@ link_directory() { # Parse input args with getopts while getopts :vdp:hV-: opt; do # ----- long options - if [ "$opt" = "-" ]; then - opt=$OPTARG - [ -z "$opt" ] && break # "--" terminates argument processing + if [ "${opt}" = "-" ]; then + opt=${OPTARG} + [ -z "${opt}" ] && break # "--" terminates argument processing fi # shellcheck disable=SC2214 - case $opt in + case "${opt}" in # ---- Help / version V | version) print_version @@ -232,20 +220,21 @@ while getopts :vdp:hV-: opt; do # ----- Options p | port) shift - port="${1}" + PORT="${1}" + SSH_ARGS="${SSH_ARGS} -p ${PORT}" ;; v | verbose) - if [ "${verbose}" != "debug" ]; then - verbose="verbose" + if [ "${VERBOSE}" != "debug" ]; then + VERBOSE="verbose" fi ;; d | debug) - verbose="debug" + VERBOSE="debug" ;; - \?) logerr "Unknown option -$OPTARG, see -h for help." + \?) logerr "Unknown option -${OPTARG}, see -h for help." exit 2 ;; - *) logerr "Unknown option --$opt, see -h for help." + *) logerr "Unknown option --${opt}, see -h for help." exit 2 ;; esac @@ -323,7 +312,7 @@ if link_exists "${DEST}/${BACKUP_LATEST}"; then logmsg "\$ rsync $* ${SRC} ${DEST}/${BACKUP_INPROGRESS}" rsync \ - -e "ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port}" \ + -e "ssh ${SSH_ARGS}" \ --recursive \ --perms \ --owner \ @@ -342,7 +331,7 @@ else logmsg "\$ rsync $* ${SRC} ${DEST}/${BACKUP_INPROGRESS}" rsync \ - -e "ssh -oStrictHostKeyChecking=no -oLogLevel=QUIET -q -p ${port}" \ + -e "ssh ${SSH_ARGS}" \ --recursive \ --perms \ --owner \