Vorläufige Aufteilung auf einzelne Scripts
This commit is contained in:
1 parent
0c78fbaa4f
commit
1fcdb5669a
7 files changed
+541
No files matched your search
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Aufruf via ssh auf dem jew. Server
|
||||||
|
#
|
||||||
|
# $1 - Logfile für den Backup-Lauf
|
||||||
|
#
|
||||||
|
|
||||||
|
# cron job auf nathan
|
||||||
|
#
|
||||||
|
# je Server:
|
||||||
|
#
|
||||||
|
# ssh nathan sudo /var/srv/nas/Server/bin/backup/cron.sh /var/srv/nas/backups/log/nathan-backup-full.log --daily
|
||||||
|
# ssh hamiller sudo /var/srv/nas/Server/bin/backup/cron.sh /var/srv/nas/backups/log/hamiller-backup-full.log --daily
|
||||||
|
# ssh synology sudo /volume1/nfs/Server/bin/backup/cron.sh /volume1/nfs/backups/log/synology-backup-full.log --daily
|
||||||
|
# ssh synology sudo /volume1/nfs/Server/bin/backup/cron.sh /volume1/nfs/backups/log/synology-backup-media-full.log --weekly
|
||||||
|
#
|
||||||
|
|
||||||
|
LOG="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
HERE=$(dirname "$0")
|
||||||
|
$HERE/main.sh -a "$@" >"$LOG" 2>&1 &
|
||||||
Executable
+51
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/eval bash
|
||||||
|
|
||||||
|
# TODO: cmd line handling
|
||||||
|
# fn für div. Aktionen (gemeinsame?)
|
||||||
|
|
||||||
|
BACKUP_ROOT=/var/docker/tmp
|
||||||
|
|
||||||
|
backup_data() {
|
||||||
|
TARGET_DIR="$BACKUP_ROOT/backup.$DAY"
|
||||||
|
|
||||||
|
NAS_ROOT=/var/srv/nas/backups
|
||||||
|
|
||||||
|
LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup.log"
|
||||||
|
|
||||||
|
log INFO "*** *** Begin hamiller server backup"
|
||||||
|
delete_dir $TARGET_DIR
|
||||||
|
check_directory $TARGET_DIR
|
||||||
|
|
||||||
|
# TODO: docker down
|
||||||
|
|
||||||
|
backup_all_dirs "/var" "$TARGET_DIR" # docker
|
||||||
|
# backup_all_dirs "/var/docker" "$TARGET_DIR" vol tmp
|
||||||
|
# backup_all_dirs "/var/docker/vol" "$TARGET_DIR"
|
||||||
|
|
||||||
|
# TODO: docker up
|
||||||
|
|
||||||
|
# TODO: copy backup files to NAS
|
||||||
|
|
||||||
|
log INFO "*** End of hamiller server backup"
|
||||||
|
list_archives $BACKUP_ROOT
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO: restore fn
|
||||||
|
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
case $1 in
|
||||||
|
--daily)
|
||||||
|
backup_data
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--restore)
|
||||||
|
# TODO
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*) # Default case: No more options, so break out of the loop.
|
||||||
|
break
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
Executable
+222
@@ -0,0 +1,222 @@
|
|||||||
|
HOST_NAME=$(hostname)
|
||||||
|
DAY=$(date +%u)
|
||||||
|
|
||||||
|
PASSPHRASE=1234567890
|
||||||
|
EXT=tgz.gpg
|
||||||
|
LIST_EXT=txt
|
||||||
|
|
||||||
|
# check if function $1 exists
|
||||||
|
#
|
||||||
|
# returns true/false
|
||||||
|
#
|
||||||
|
isFunction() { declare -Ff "$1" ; }
|
||||||
|
|
||||||
|
# Log-Datei schreiben.
|
||||||
|
#
|
||||||
|
# Die Ausgabe geht auch auf STDOUT, dadurch kann die vollständige Ausgabe,
|
||||||
|
# einschließlich Status- und Fehlermeldungen der Programme in ein erweitertes
|
||||||
|
# Log für die Fehlersuche umgeleitet werden.
|
||||||
|
#
|
||||||
|
# $1 - Typ, z.B. INFO, WARN, ERROR, etc.
|
||||||
|
# $2 ff. - die Meldung, die ins Log geschreiben wird
|
||||||
|
#
|
||||||
|
log() {
|
||||||
|
local type=$1
|
||||||
|
if [ "$type" == "ERROR" ]; then ERROR=0; fi
|
||||||
|
shift 1
|
||||||
|
echo "$(date '+%d.%m.%Y %H:%M:%S') - $type $@" | sudo tee -a $LOG_FILE
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ist $1 in der Liste der restlichen args $2, $3 ...
|
||||||
|
#
|
||||||
|
# zB. if is_in "foo" "foo" "bar" "foo bar" ; then ...
|
||||||
|
# Leere Liste liefert immer false
|
||||||
|
#
|
||||||
|
is_in() {
|
||||||
|
local search="$1"
|
||||||
|
shift 1
|
||||||
|
local e
|
||||||
|
for e in "$@"; do [[ "$e" == "$search" ]] && return 0; done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alle Verzechnisnamen in einem Verzeichnis holen.
|
||||||
|
#
|
||||||
|
# $1 - Verzeichnis in dem gesucht wird als absoluter Pfad
|
||||||
|
# $2 ff. - auszuschliessende Verzeichnisse (kann leer bleiben)
|
||||||
|
#
|
||||||
|
iterate_dirs_in() {
|
||||||
|
local dirname
|
||||||
|
local root=$1
|
||||||
|
shift 1
|
||||||
|
for dir in $(sudo find "$root" -maxdepth 1 -type d \! -wholename "$root"); do
|
||||||
|
dirname=$(basename $dir)
|
||||||
|
if ! is_in "$dirname" "$@"; then
|
||||||
|
echo "$dirname"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# create directory if it not exists
|
||||||
|
#
|
||||||
|
# $1 - dir to check
|
||||||
|
#
|
||||||
|
check_directory() {
|
||||||
|
local dir=$1
|
||||||
|
if [ -d "$1" ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
mkdir -p "$1" && return 0
|
||||||
|
sudo mkdir -p "$1" && return 0
|
||||||
|
log ERROR "### could not create directory $1!"
|
||||||
|
# no chance to recover
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verzeichnis löschen
|
||||||
|
#
|
||||||
|
# Im Fehlerfall wird rc=1 zurückgegeben
|
||||||
|
#
|
||||||
|
# $1 - zu löschendes Verzeichnis
|
||||||
|
#
|
||||||
|
delete_dir() {
|
||||||
|
local dir=$1
|
||||||
|
sudo rm -rf "$dir" && return 0
|
||||||
|
log ERROR "### could not delete directory $1!"
|
||||||
|
# return error, so caller can decide what to do
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Slashes "/" im Pfadnamen durch Dashes "-" ersetzen, so dass der String als Dateiname verwendet werden kann.
|
||||||
|
#
|
||||||
|
# $1 - path
|
||||||
|
backup_file_prefix() {
|
||||||
|
echo "$1" | sed -E 's/^\///' | sed -E 's/\//-/g'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verzeichnise in .tgz.gpg-Dateien sichern.
|
||||||
|
#
|
||||||
|
# $1 - Verzeichnis, das gesichert wird: alle Verzeichnisse darunter werden einzeln als .tgz.gpg-Datei gesichert
|
||||||
|
# $2 - Zielverzeichnis für .tgz.gpg-Dateien
|
||||||
|
# $3 ff. - Verzeichnisse, die nicht gesichert werden sollen (kann leer bleiben)
|
||||||
|
#
|
||||||
|
backup_all_dirs() {
|
||||||
|
local root=$1
|
||||||
|
local target=$2
|
||||||
|
local prefix=$(backup_file_prefix $root)
|
||||||
|
local tar_file
|
||||||
|
local dir
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
for dir in $(iterate_dirs_in "$root" "$@"); do
|
||||||
|
tar_file="$target/$prefix-$dir.$EXT"
|
||||||
|
backup_dir "$root" "$tar_file" "$dir"
|
||||||
|
create_list "$tar_file" "$dir"
|
||||||
|
test_integrity "$tar_file"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Einzelnes Verzeichnis sichern.
|
||||||
|
#
|
||||||
|
# $1 - Pfad um Verzeichnis, das gesichert werden soll
|
||||||
|
# $2 - Zielpfad und -name für das Archiv
|
||||||
|
# $2 - zu sicherndes Verzeichnis
|
||||||
|
#
|
||||||
|
backup_dir() {
|
||||||
|
local root=$1
|
||||||
|
local archive=$2
|
||||||
|
local dir=$3
|
||||||
|
log INFO "--- Backup $root/$dir -> $archive"
|
||||||
|
sudo tar -c -z --numeric-owner --one-file-system --exclude "@eaDir" -C "$root" "$dir" | sudo gpg --batch -c --passphrase $PASSPHRASE -o "$archive"
|
||||||
|
local rc=$?
|
||||||
|
if [ "$rc" == "0" ] ; then
|
||||||
|
log INFO "*** success"
|
||||||
|
else
|
||||||
|
log ERROR "### see full log"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Inhalt des Archivs in eine Textdatei ausgeben.
|
||||||
|
#
|
||||||
|
# $1 - Archiv
|
||||||
|
#
|
||||||
|
create_list() {
|
||||||
|
local archive=$1
|
||||||
|
log INFO "--- List $archive"
|
||||||
|
sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -tzv | sudo tee "$archive.$LIST_EXT" >/dev/null
|
||||||
|
local rc=$?
|
||||||
|
if [ "$rc" == "0" ] ; then
|
||||||
|
log INFO "*** success"
|
||||||
|
else
|
||||||
|
log ERROR "### see full log"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Integrität des Archivs testen, indem es entschlüsselt, entpackt
|
||||||
|
# und der Inhalt auf /dev/null ausgegeben wird.
|
||||||
|
#
|
||||||
|
# $1 - Archiv
|
||||||
|
#
|
||||||
|
test_integrity() {
|
||||||
|
local archive=$1
|
||||||
|
log INFO "--- Check integrity of $archive"
|
||||||
|
sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -xzO >/dev/null
|
||||||
|
local rc=$?
|
||||||
|
if [ "$rc" == "0" ] ; then
|
||||||
|
log INFO "*** success"
|
||||||
|
else
|
||||||
|
log ERROR "### see full log"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restore aus Archiv
|
||||||
|
#
|
||||||
|
# Wird nach pwd ausgegeben!
|
||||||
|
#
|
||||||
|
# $1 - Archiv, ggf. mit Pfad
|
||||||
|
# $2 ff. - zurückzusichernde Dateien/Verzeichnisse
|
||||||
|
#
|
||||||
|
restore() {
|
||||||
|
local archive=$1
|
||||||
|
shift 1
|
||||||
|
sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -xzv $@ >/dev/null
|
||||||
|
local rc=$?
|
||||||
|
if [ "$rc" == "0" ] ; then
|
||||||
|
log INFO "*** success"
|
||||||
|
else
|
||||||
|
log ERROR "### see full log"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Liste der Archives auf stdout ausgeben
|
||||||
|
#
|
||||||
|
# Zeigt alle Archive incl. Verzeichnis (ohne $1) an
|
||||||
|
#
|
||||||
|
# z.B.
|
||||||
|
# $1 = /volume1/nfs/backups
|
||||||
|
# ...
|
||||||
|
# /daily/synology/backup.3/volume1-nfs-Server.tgz.gpg
|
||||||
|
# /weekly/synology/volume1-media-books.tgz.gpg
|
||||||
|
#
|
||||||
|
# $1 - Verzeichnis unter dem alle Backups liegen
|
||||||
|
#
|
||||||
|
list_archives() {
|
||||||
|
local target=$1
|
||||||
|
local targ=${target//\//\\\/} # slashes escapen
|
||||||
|
echo "#$targ#"
|
||||||
|
sudo find "$target" -type f -name "*.$EXT" | grep "${HOST_NAME}/" | sed -E "s/^$targ//"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Inhalt des Archivs $2 auf stdout ausgeben
|
||||||
|
#
|
||||||
|
# $1 - Verzeichnis unter dem alle Backups liegen
|
||||||
|
# $2 - Archiv-Datei mit Pfad ab $1
|
||||||
|
#
|
||||||
|
list_archive_content() {
|
||||||
|
local root=$1
|
||||||
|
local archive=$2
|
||||||
|
|
||||||
|
sudo cat "$root/${archive/#\//}.$LIST_EXT"
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# entrypoint for all actions
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
HERE=$(dirname "$0")
|
||||||
|
. $HERE/main.inc.sh
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
echo "usage: $0 options"
|
||||||
|
echo " -a, --auto start nightly backup on local machine"
|
||||||
|
echo " --list list archives"
|
||||||
|
echo ' --content <archive> '
|
||||||
|
echo " show contents of archive"
|
||||||
|
echo ' -r, --restore <archive> <file(s)> '
|
||||||
|
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
|
||||||
|
;;
|
||||||
|
--list)
|
||||||
|
. $HERE/$HOST_NAME.sh -l
|
||||||
|
break;
|
||||||
|
;;
|
||||||
|
--content)
|
||||||
|
if [ "$2" ]; then
|
||||||
|
. $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
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# TODO: cmd line handling
|
||||||
|
# fn für div. Aktionen (gemeinsame?)
|
||||||
|
|
||||||
|
|
||||||
|
BACKUP_ROOT=/var/docker/tmp
|
||||||
|
|
||||||
|
backup_data() {
|
||||||
|
TARGET_DIR="$BACKUP_ROOT/backup.$DAY"
|
||||||
|
|
||||||
|
NAS_ROOT=/var/srv/nas/backups
|
||||||
|
|
||||||
|
LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup.log"
|
||||||
|
|
||||||
|
log INFO "*** *** Begin nathan server backup"
|
||||||
|
delete_dir "$TARGET_DIR"
|
||||||
|
check_directory "$TARGET_DIR"
|
||||||
|
|
||||||
|
# TODO: docker down
|
||||||
|
|
||||||
|
backup_all_dirs "/var" "$TARGET_DIR" docker
|
||||||
|
backup_all_dirs "/var/docker" "$TARGET_DIR" vol tmp
|
||||||
|
backup_all_dirs "/var/docker/vol" "$TARGET_DIR"
|
||||||
|
|
||||||
|
# TODO: docker up
|
||||||
|
|
||||||
|
# TODO: copy backup files to NAS
|
||||||
|
|
||||||
|
log INFO "*** End of nathan server backup"
|
||||||
|
list_archives $BACKUP_ROOT
|
||||||
|
}
|
||||||
|
# TODO: restore fn
|
||||||
|
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
case $1 in
|
||||||
|
--daily)
|
||||||
|
backup_data
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--restore)
|
||||||
|
# TODO
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*) # Default case: No more options, so break out of the loop.
|
||||||
|
break
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
Executable
+96
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/eval bash
|
||||||
|
|
||||||
|
# TODO: cmd line handling
|
||||||
|
# fn für div. Aktionen (gemeinsame?)
|
||||||
|
|
||||||
|
NAS_ROOT=/volume1/nfs/backups
|
||||||
|
|
||||||
|
backup_media() {
|
||||||
|
TARGET_DIR="$NAS_ROOT/weekly/$HOST_NAME"
|
||||||
|
|
||||||
|
LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup-media.log"
|
||||||
|
|
||||||
|
log INFO "*** *** Begin NAS backup (media/books, media/music)"
|
||||||
|
|
||||||
|
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 backup"
|
||||||
|
list_archives $TARGET_DIR
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
backup_data() {
|
||||||
|
|
||||||
|
TARGET_DIR="$NAS_ROOT/daily/$HOST_NAME/backup.$DAY"
|
||||||
|
|
||||||
|
LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup.log"
|
||||||
|
|
||||||
|
log INFO "*** *** Begin NAS backup (data, nfs)"
|
||||||
|
EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found")
|
||||||
|
delete_dir $TARGET_DIR # bei Fehler werden die Dateien hoffentlich überschrieben
|
||||||
|
check_directory $TARGET_DIR
|
||||||
|
# data
|
||||||
|
backup_all_dirs "/volume1/data" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}"
|
||||||
|
|
||||||
|
EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found" backups)
|
||||||
|
# nfs
|
||||||
|
backup_all_dirs "/volume1/nfs" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}"
|
||||||
|
|
||||||
|
log INFO "*** End of NAS backup"
|
||||||
|
list_archives $TARGET_DIR
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO: restore fn
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# auto backup handling
|
||||||
|
#
|
||||||
|
# hostname-scripte setzen vars und definieren Funktionen backup_daily1, 2, usw. und backup_weekly1, 2, usw.
|
||||||
|
# in den Funktionen werden die vars für den einzelnen backuü gesetzt (target, excludes, usw.)
|
||||||
|
# im main-script wird dann dass hostname-script gesourced und in einer Schleife werden die
|
||||||
|
# entsprechenden backup_*-Funktionen aufgerufen
|
||||||
|
#
|
||||||
|
# count=1
|
||||||
|
# while [ $(isFunction backup_daily$count) ]; do
|
||||||
|
# backup_daily$count # setzt die nötigen vars für den backup
|
||||||
|
# do_backup "daily"
|
||||||
|
# let "count += 1"
|
||||||
|
# done
|
||||||
|
#
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
case $1 in
|
||||||
|
--daily)
|
||||||
|
backup_data
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--weekly)
|
||||||
|
backup_media
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-l|--list)
|
||||||
|
list_archives "$NAS_ROOT"
|
||||||
|
break;
|
||||||
|
;;
|
||||||
|
-c|--content)
|
||||||
|
if [ "$2" ]; then
|
||||||
|
list_archive_content "$NAS_ROOT" "$2"
|
||||||
|
else
|
||||||
|
echo 'ERROR: "--content" requires a non-empty option argument.'
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
--restore)
|
||||||
|
# TODO
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*) # Default case: No more options, so break out of the loop.
|
||||||
|
break
|
||||||
|
esac
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
Reference in new issue
Block a user