diff --git a/shopts.sh b/shopts.sh new file mode 100755 index 0000000..a2d7407 --- /dev/null +++ b/shopts.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# ex33.sh: Exercising getopts and OPTIND +# Script modified 10/09/03 at the suggestion of Bill Gradwohl. + + +# Here we observe how 'getopts' processes command-line arguments to script. +# The arguments are parsed as "options" (flags) and associated arguments. + +# Try invoking this script with: +# 'scriptname -mn' +# 'scriptname -oq qOption' (qOption can be some arbitrary string.) +# 'scriptname -qXXX -r' +# +# 'scriptname -qr' +#+ - Unexpected result, takes "r" as the argument to option "q" +# 'scriptname -q -r' +#+ - Unexpected result, same as above +# 'scriptname -mnop -mnop' - Unexpected result +# (OPTIND is unreliable at stating where an option came from.) +# +# If an option expects an argument ("flag:"), then it will grab +#+ whatever is next on the command-line. + +NO_ARGS=0 +E_OPTERROR=85 + +if [ $# -eq "$NO_ARGS" ] # Script invoked with no command-line args? +then + echo "Usage: `basename $0` options (-mnopqrs)" + exit $E_OPTERROR # Exit and explain usage. + # Usage: scriptname -options + # Note: dash (-) necessary +fi + + +while getopts ":mnopq:rs" Option +do + case $Option in + m ) echo "$OPTIND -$Option ($OPTARG)";; + n | o ) echo "$OPTIND -$Option ($OPTARG)";; + p ) echo "$OPTIND -$Option ($OPTARG)";; + q ) echo "$OPTIND -$Option ($OPTARG)";; + # Note that option 'q' must have an associated argument, + #+ otherwise it falls through to the default. + r | s ) echo "$OPTIND -$Option ($OPTARG)";; + * ) echo "Unimplemented option chosen.";; # Default. + esac +done + +shift $(($OPTIND - 1)) +echo "Rest $@" + +# Decrements the argument pointer so it points to next argument. +# $1 now references the first non-option item supplied on the command-line +#+ if one exists. + +exit $? + +# As Bill Gradwohl states, +# "The getopts mechanism allows one to specify: scriptname -mnop -mnop +#+ but there is no reliable way to differentiate what came +#+ from where by using OPTIND." +# There are, however, workarounds. \ No newline at end of file diff --git a/test.sh b/test.sh index 0f95c43..6a35fb1 100755 --- a/test.sh +++ b/test.sh @@ -34,7 +34,7 @@ log() { # zB. if is_in "foo" "foo" "bar" "foo bar" ; then ... # Leere Liste liefert immer false # -function is_in { +is_in() { local search="$1" shift 1 local e @@ -47,7 +47,7 @@ function is_in { # $1 - Verzeichnis in dem gesucht wird als absoluter Pfad # $2 ff. - auszuschliessende Verzeichnisse (kann leer bleiben) # -function iterate_dirs_in() { +iterate_dirs_in() { local dirname local root=$1 shift 1 @@ -63,7 +63,7 @@ function iterate_dirs_in() { # # $1 - dir to check # -function check_directory() { +check_directory() { local dir=$1 if [ -d "$1" ]; then return 0 @@ -82,7 +82,7 @@ function check_directory() { # # $1 - zu löschendes Verzeichnis # -function delete_dir() { +delete_dir() { local dir=$1 sudo rm -rf "$dir" && return 0 log ERROR "### could not delete directory $1!" @@ -93,7 +93,7 @@ function delete_dir() { # Slashes "/" im Pfadnamen durch Dashes "-" ersetzen, so dass der String als Dateiname verwendet werden kann. # # $1 - path -function backup_file_prefix() { +backup_file_prefix() { echo "$1" | sed -E 's/^\///' | sed -E 's/\//-/g' } @@ -103,7 +103,7 @@ function backup_file_prefix() { # $2 - Zielverzeichnis für .tgz.gpg-Dateien # $3 ff. - Verzeichnisse, die nicht gesichert werden sollen (kann leer bleiben) # -function backup_all_dirs() { +backup_all_dirs() { local root=$1 local target=$2 local prefix=$(backup_file_prefix $root) @@ -114,7 +114,7 @@ function backup_all_dirs() { for dir in $(iterate_dirs_in "$root" "$@"); do tar_file="$target/$prefix-$dir.$EXT" backup_dir "$root" "$tar_file" "$dir" - list "$tar_file" "$dir" + create_list "$tar_file" "$dir" test_integrity "$tar_file" done } @@ -125,7 +125,7 @@ function backup_all_dirs() { # $2 - Zielpfad und -name für das Archiv # $2 - zu sicherndes Verzeichnis # -function backup_dir() { +backup_dir() { local root=$1 local archive=$2 local dir=$3 @@ -143,7 +143,7 @@ function backup_dir() { # # $1 - Archiv # -function list() { +create_list() { local archive=$1 log INFO "--- List $archive" sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -tzv | sudo tee $archive.txt >/dev/null @@ -160,7 +160,7 @@ function list() { # # $1 - Archiv # -function test_integrity() { +test_integrity() { local archive=$1 log INFO "--- Check integrity of $archive" sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -xzO >/dev/null @@ -179,7 +179,7 @@ function test_integrity() { # $1 - Archiv, ggf. mit Pfad # $2 ff. - zurückzusichernde Dateien/Verzeichnisse # -function restore() { +restore() { local archive=$1 shift 1 sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -xzv $@ >/dev/null @@ -191,9 +191,25 @@ function restore() { fi } +# Liste der Archives auf stdout ausgeben +# +# Zeigt alle Archive incl. des letzten Verzeichnisses an +# +# z.B. +# backup.7/volume1-data-Web.tgz.gpg +# media/volume1-media-books.tgz.gpg +# +# $1 - root path i.d.R. ein Verzeichnis oberhalb, damit alle täglichen Backups angezeigt werden +# +list_archives() { + local target=$1 + local targ=${target//\//\\\/} # slashes escapen + echo "#$targ#" + sudo find "$target" -type f -name "*.gpg" | sed -E "s/^$targ//" +} # *** NAS Test *** -function nas_test() { +nas_test() { LOG_FILE="/volume1/nfs/Server/tmp/backup.log" log INFO "*** *** Begin NAS backup (data, nfs, media/books, media/music)" @@ -208,22 +224,26 @@ function nas_test() { # nfs backup_all_dirs "/volume1/nfs" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}" - TARGET_DIR="/volume1/nfs/backups/tmp/media" + BACKUP_ROOT=/volume1/nfs/backups/tmp + TARGET_DIR="$BACKUP_ROOT/media" EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found" serien tmp video "video.archive") check_directory $TARGET_DIR # media/books media/music backup_all_dirs "/volume1/media" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}" - log INFO "*** End of NAS backuip" + log INFO "*** End of NAS backup" + list_archives $BACKUP_ROOT + } # *** NATHAN Test *** -function nathan_test() { +nathan_test() { LOG_FILE=/var/docker/tmp/backup.log log INFO "*** *** Begin nathan server backup" - TARGET_DIR=/var/docker/tmp/backup.$DAY + BACKUP_ROOT=/var/docker/tmp + TARGET_DIR="$BACKUP_ROOT/backup.$DAY" delete_dir $TARGET_DIR check_directory $TARGET_DIR @@ -232,14 +252,17 @@ function nathan_test() { backup_all_dirs "/var/docker/vol" "$TARGET_DIR" log INFO "*** End of nathan server backup" + list_archives $BACKUP_ROOT + } # *** HANILLER Test *** -function hamiller_test() { +hamiller_test() { LOG_FILE=/var/docker/tmp/backup.log log INFO "*** *** Begin hamiller server backup" - TARGET_DIR=/var/docker/tmp/backup.$DAY + BACKUP_ROOT=/var/docker/tmp + TARGET_DIR="$BACKUP_ROOT/backup.$DAY" delete_dir $TARGET_DIR check_directory $TARGET_DIR @@ -248,9 +271,10 @@ function hamiller_test() { # backup_all_dirs "/var/docker/vol" "$TARGET_DIR" log INFO "*** End of hamiller server backup" + list_archives $BACKUP_ROOT } -function test() { +test() { #LOG_FILE=./t1.log #log INFO "error test" echo "host: #$1#" @@ -261,13 +285,7 @@ function test() { #hamiller_test #test1 -test "$HOSTNAME" - -if [ ! -z $ERROR ]; then - log ERROR "*** *** Errors occured during the progem run, see full log for details." -else - log INFO "*** *** Program ended successfully." -fi +list_archives /var/docker/tmp exit diff --git a/test/main.inc b/test/main.inc new file mode 100755 index 0000000..cf1e801 --- /dev/null +++ b/test/main.inc @@ -0,0 +1,8 @@ + +INC=include +HOST_NAME=$(hostname) + +testfunc() { + echo "testfunc() works!" +} + \ No newline at end of file diff --git a/test/main.sh b/test/main.sh new file mode 100755 index 0000000..8fe24cc --- /dev/null +++ b/test/main.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +show_help() { + echo "usage: $0 options" + echo " -a, --auto start nightly backup" + echo " -l, --list list archives" + echo ' -c, --content ' + echo " show contents of archive" + echo ' -r, --restore ' + echo " restore files from archive to pwd" + echo " -h, -?. --help show this help" +} + +echo " ### main.sh" + +# Initialize all the option variables. +# This ensures we are not contaminated by variables from the environment. +file= +archive= + +while :; do + case $1 in + -h|-\?|--help) + show_help # Display a usage synopsis. + exit 0 + ;; + -a|--auto) + shift + . $HERE/$HOST_NAME.sh "$@" >$LOGF 2>&1 + break # exit kehrt nicht zu run.sh zurück + ;; + -l|--list) + . $HERE/$HOST_NAME.sh -l + break; + ;; + -c|--content) + if [ "$2" ]; then + echo "not yet implemented" + #. $HERE/$HOST_NAME.sh -c $2 + else + echo 'ERROR: "--content" requires a non-empty option argument.' + fi + break + ;; + -r|--restore) + if [ "$2" ]; then + echo "not yet implemented" + archive=$2 + shift + #. $HERE/$HOST_NAME.sh -r $archive $@ + else + echo 'ERROR: "--restore" requires a non-empty option argument.' + fi + break + ;; + + # --- example -> https://mywiki.wooledge.org/BashFAQ/035 + -f|--file) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + file=$2 + shift + else + die 'ERROR: "--file" requires a non-empty option argument.' + fi + ;; + --file=?*) + file=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --file=) # Handle the case of an empty --file= + die 'ERROR: "--file" requires a non-empty option argument.' + ;; + --) # End of all options. + shift + break + ;; + -?*) + echo "WARN: Unknown option (ignored): $1" + echo + show_help + exit + ;; + *) # Default case: No more options, so break out of the loop. + break + esac + + shift +done + diff --git a/test/nathan.sh b/test/nathan.sh new file mode 100755 index 0000000..bbe6e69 --- /dev/null +++ b/test/nathan.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +echo " *** nathan.sh" +for i in "$@"; do echo "param: $i"; done + +echo " include=$INC" +echo " host=$HOST_NAME" +testfunc +echo " *** nathan.sh end" + diff --git a/test/run.sh b/test/run.sh new file mode 100755 index 0000000..33d6dc3 --- /dev/null +++ b/test/run.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +HERE=$(dirname "$0") +. $HERE/main.inc + +LOGF=$HERE/t1.log + +echo "--- run.sh" + +. $HERE/main.sh "$@" + +echo "--- run.sh end" diff --git a/test/t1.log b/test/t1.log new file mode 100644 index 0000000..e23e4a3 --- /dev/null +++ b/test/t1.log @@ -0,0 +1,10 @@ +testfunc() works! + ### main.sh +usage: ./run.sh options + -a, --auto start nightly backup + -l, --list list archives + -c, --content + show contents of archive + -r, --restore + restore files from archive to pwd + -h, -?. --help show this help