ubuntuusers.de

borgbackup Whitespaces and shell script

Status: Gelöst | Ubuntu-Version: Ubuntu 18.04 (Bionic Beaver)
Antworten |

oparilames

Anmeldungsdatum:
21. April 2019

Beiträge: 16

Hallo ihr,

ich bin recht grün hinter den Linux Ohren und bin vor ein paar Tagen auf besagtes Programm gestoßen. Kann mir jemand sagen, wie das Program mit mehr als einem Leerzeichen zwischen zwei Argumenten umgeht?

Ich schreibe grade ein shell script und als ich den "borg create" Befehl mal über echo ausgegeben, also den Befehl nicht gestartet/aufgerufen habe, sah ich, dass bei meinem output manchmal zwei Leerzeichen sind, wo nur eins ist.

Zudem wollte ich Fragen, ob es soweit OK aussieht? Gestern dachte ich, ich hätte es richtig und als ich heute nochmal drüber geschaut habe, meine ich festgestellt zu haben, dass ich das mit dem Zuweisen von archives und repositories noch unschlüssig bin.

Mein Vorhaben: Zwei Festplatten haben jeweils eine ext4/ntfs partition und ich möchte die aktuellen Daten, die sich laufend verändern (auf Festplatte A) auf Festplatte B als archiv haben, das Borg repository soll aber auf Festplatte A sein. Meine Festplatten:

# LABEL				Mount point					SIZE (GB)	FREE(GB:%)		USED(GB:%)			DEV			#
# HDD_Data			/mnt/Data_Linux             670			314:49			322:51				/dev/sdC	1
# HDD_WinData		/mnt/DataBackup_Linux      	356			 27: 7			312:93				/dev/sdA	1
#
# HDD_DataBkp		/mnt/Data_Windows          	251			251:99			  1: 1				/dev/sdC	2
# HDD_WinDataBkp	/mnt/DataBackup_Windows     105			 22:21			 83:79				/dev/sdA	2

Ein vom Script erstellter Beispiel-Befehl:

Starting backup for Profession: main (2019-04-21)
borg create \ 
-p -v -s --noatime --checkpoint-interval 900 \ 
--compression auto,lzma,8 /mnt/DataBackup_Linux::2019-04-21_Profession-main \ 
/mnt/Data_Linux/Profession \ 
--exclude /mnt/Data_Linux/Profession/Movies \ 
--exclude /mnt/Data_Linux/Profession/Audio


Starting backup for Profession: subs (2019-04-21)
borg create \ 
-p -v -s --noatime --checkpoint-interval 900 \ 
--compression none \ 
/mnt/DataBackup_Linux::2019-04-21_Profession-subs \ 
 /mnt/Data_Linux/Profession/Movies /mnt/Data_Linux/Profession/Audio

In diesem Fall habe ich keine doppelten Leerzeichen, aber so generell, interessiert mich, ob ich damit etwas riskiere, oder ob das Programm solche Fehler automatisch realisiert.

Vielen Dank!

Thomas_Do Team-Icon

Moderator
Avatar von Thomas_Do

Anmeldungsdatum:
24. November 2009

Beiträge: 8808

Hallo oparilames, willkommen im Forum!

oparilames schrieb:

Kann mir jemand sagen, wie das Program mit mehr als einem Leerzeichen zwischen zwei Argumenten umgeht?

Ich denke, die Zahl der Leerzeichen ist nicht relevant. Kannst Du aber doch selbst kurz im Terminal testen.

Ich schreibe grade ein shell script und als ich den "borg create" Befehl mal über echo ausgegeben, also den Befehl nicht gestartet/aufgerufen habe, sah ich, dass bei meinem output manchmal zwei Leerzeichen sind, wo nur eins ist.

Was soll das Skript tun, gibt es da besondere Anforderungen? Warum schreibst Du das Skript selber und nutzt nicht eine Vorlage (als Linux Neuling)?

Zudem wollte ich Fragen, ob es soweit OK aussieht?

Was? Das Skript zeigst Du ja nicht, meinst Du den Befehl? Da sind Optionen drin, die ich bisher nicht benutzt habe. Müsste ich nachschauen, wofür die gut sind.

Mein Vorhaben: Zwei Festplatten haben jeweils eine ext4/ntfs partition und ich möchte die aktuellen Daten, die sich laufend verändern (auf Festplatte A) auf Festplatte B als archiv haben, das Borg repository soll aber auf Festplatte A sein.

Das ergibt für mich wenig Sinn. Was bedeutet "ext4/ntfs partition"? Ein Repository besteht aus einem oder mehreren Archiven. Was willst Du da auf zwei Festplatten aufteilen?

oparilames

(Themenstarter)

Anmeldungsdatum:
21. April 2019

Beiträge: 16

Hallo Thomas, danke für die Begrüßung.

Thomas_Do schrieb:

[…]

oparilames schrieb:

Kann mir jemand sagen, wie das Program mit mehr als einem Leerzeichen zwischen zwei Argumenten umgeht?

Ich denke, die Zahl der Leerzeichen ist nicht relevant. Kannst Du aber doch selbst kurz im Terminal testen.

Oh, danke! Darauf bin ich garnicht von selbst gekommen. In meiner nächsten Antwort werde ich anmerken, wie es sich damit verhält.

Ich schreibe grade ein shell script und als ich den "borg create" Befehl mal über echo ausgegeben, also den Befehl nicht gestartet/aufgerufen habe, sah ich, dass bei meinem output manchmal zwei Leerzeichen sind, wo nur eins ist.

Was soll das Skript tun, gibt es da besondere Anforderungen? Warum schreibst Du das Skript selber und nutzt nicht eine Vorlage (als Linux Neuling)?

Zudem wollte ich Fragen, ob es soweit OK aussieht?

Was? Das Skript zeigst Du ja nicht, meinst Du den Befehl? Da sind Optionen drin, die ich bisher nicht benutzt habe. Müsste ich nachschauen, wofür die gut sind.

Warum ich das Script selbst schreibe? Ich komme von C++, nutze Linux nun schon seit ca. 8 Jahren, aber bin nie tiefer eingestiegen und will jetzt doch ein bisschen was mit dem Terminal tun. Außerdem ist es für mich hilfreicher, wenn ich genau entscheiden kann, was der Code tun soll und was nicht.

Das Script habe ich euch nicht gezeigt, weil ich euch nicht gleich erschlagen wollte. Es basiert auf dem Offiziellen (siehe ¹). Es soll wie im Original die Datein von der Windows partition und von der Linux partition auf einem Repositories für jede dieser Partitionen auf der kleineren HDD ablegen. Die 'Anleitung', dass diese Archive existieren und wie sie zu öffnen sind, soll auf den Partitionen der Festplatte bleiben, auf der sich diese Rohdaten befinden.

Entsprechend der Form borg init --encryption /PartitionDerUrsprungsdaten/Backup borg create … /Ursprungsdaten /NeueFestplattenPartition/ /PartitionDerUrsprungsdaten/Backup::NAME /PartitionDerUrsprungsdaten /NeueFestplattenPartition --exclude /PartitionDerUrsprungsdaten/Backup

Aber gut, hier ist es (entschudligt bitte, dass ich es kaum kommentiert habe). Die benutzen Argumente sind im Script nochmal erklärt, größtenteils als copy and paste von der Seite der Ersteller.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

initSecurity()
{
# Set BORG_PASSPHRASE or BORG_PASSCOMMAND somewhere around here, using export,
# if encryption is used.

# No one can answer if Borg asks these questions, it is better to just fail quickly
# instead of hanging.
export BORG_RELOCATED_REPO_ACCESS_IS_OK=no
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=no
}

initTests()
{
# Find whether the connected block device is a backup drive
for uuid in $(lsblk --noheadings --list --output uuid)
do
        if grep --quiet --fixed-strings $uuid $DISKS; then
                break
        fi
        uuid=
done

if [ ! $uuid ]; then
        echo "No backup disk found, exiting"
        exit 0
fi

echo "Disk $uuid is a backup disk"
partition_path=/dev/disk/by-uuid/$uuid
# Mount file system if not already done. This assumes that if something is already
# mounted at $MOUNTPOINT, it is the backup drive. It won't find the drive if
# it was mounted somewhere else.
(mount | grep $MOUNTPOINT) || mount $partition_path $MOUNTPOINT
drive=$(lsblk --inverse --noheadings --list --paths --output name $partition_path | head --lines 1)
echo "Drive path: $drive"
}

init ()
{
sleep 5
# The backup partition is mounted there
MOUNTPOINT_WIN=/mnt/DataBackup_Windows
MOUNTPOINT_LIN=/mnt/DataBackup_Linux

# Compression lvls
COMPRESSION_YES="--compression auto,lzma,8"
COMPRESSION_NO="--compression none"


# This is the location of the Borg repository
TARGET_WIN=/mnt/Data_Windows
TARGET_LIN=/mnt/Data_Linux
EXCLUDES="rubbish"
DIR_SUBFOLDERS=$EXCLUDES
# Archive name schema
PREFIX=$(date --iso-8601)
SUBPREFIX=_Borg-{$borgversion}.

# This is the file that will later contain UUIDs of registered backup drives
DISKS=/etc/backups/backup.disks

 initTests
# Options for borg create
# -p, --progress 	show progress information
# -v, --verbose 	work on log level INFO
#--stats 			print statistics for the created archive
#--compression		select compression algorithm, see the output of the “borg help compression” command for details.
#--noatime 			don't save access time
#--checkpoint-interval 900 Standard is 1800 seconds
BORG_OPTS="-p -v -s --noatime --checkpoint-interval 900"
}

# This builds one or more absolute paths for directories and or files which will find their way into the backup
addSubFolder()
{
DIR_SUBFOLDERS=$DIR_SUBFOLDERS" "$TARGET"/"$FILENAME$1
}
# Similar to the previous function does this chain up the excludes.
addExcludes()
{ 
EXCLUDES=$EXCLUDES" \ \n--exclude "$TARGET"/"$FILENAME$1
}

# Here we define a main folder, which is equally a borg archive.
setMainFolder()
{
FILENAME=$1
FNSUFFIX=main
unset DIR_SUBFOLDERS
unset EXCLUDES


# Check all excluded paths. If they don't end on .tar.gz they will get included as sub directories with no compression.
while test $# -gt 0
do
    shift
    if test -n "$1"
    then
		addExcludes $1
		if !(echo "$1" | grep -q ".tar.gz")
		then
			#echo "Excluded: $1"
		#else 
			addSubFolder $1
		fi
    fi
done


echo "\n\nStarting backup for $FILENAME: $FNSUFFIX ($PREFIX)"
echo "borg create \ \n"$BORG_OPTS" \ \n"$COMPRESSION_YES $MOUNTPOINT"::"$PREFIX"_"$FILENAME"-"$FNSUFFIX" \ \n"$TARGET"/"$FILENAME$EXCLUDES

# changing to subfolders
SUBPREFIX=subs

# If there are subfolders, include them as sub unit of archiv
if [ ! -z "$DIR_SUBFOLDERS" ]
then
echo "\n\nStarting backup for $FILENAME: $SUBPREFIX ($PREFIX)"
echo "borg create \ \n"$BORG_OPTS" \ \n"$COMPRESSION_NO" \ \n"$MOUNTPOINT"::"$PREFIX"_"$FILENAME-$SUBPREFIX" \ \n"$DIR_SUBFOLDERS
else
echo "No subs for "$MOUNTPOINT"::"$PREFIX"_"$FILENAME"."
fi
echo "\n\nAssimilation complete"
}

endFunc()
{
# Just to be completely paranoid
sync

if [ -f /etc/backups/autoeject ]; then
        umount $MOUNTPOINT
        hdparm -Y $drive
fi

if [ -f /etc/backups/backup-suspend ]; then
        systemctl suspend
fi

}


## Main script start point
init

# Log Borg version
borg --version

# WINDOWS Actual borg creation
TARGET=$TARGET_WIN
MOUNTPOINT=$MOUNTPOINT_WIN
setMainFolder Files /ISOs
setMainFolder Games /Saved-Games_Cat-lady_Risen.7z "/setup_exanima_0.7.0.6d_(22484)-1.bin"
setMainFolder Programs

unset TARGET
unset MOUNTPOINT

# LINUX Actual borg creation
TARGET=$TARGET_LIN
MOUNTPOINT=$MOUNTPOINT_LIN

setMainFolder Profession /Movies /Audio
setMainFolder Money
setMainFolder Private /Movies /Pictures /Projects/Wip/Programming/2019-04-16_GameEngine/dev/doc/fromOthers/german-speechdata-package-v2.tar.gz /Projects/Wip/Programming/2019-04-16_GameEngine/dev/doc/fromOthers/german-speechdata-TUDa-2015.tar.gz
endFunc

Mein Vorhaben: Zwei Festplatten haben jeweils eine ext4/ntfs partition und ich möchte die aktuellen Daten, die sich laufend verändern (auf Festplatte A) auf Festplatte B als archiv haben, das Borg repository soll aber auf Festplatte A sein.

Das ergibt für mich wenig Sinn. Was bedeutet "ext4/ntfs partition"? Ein Repository besteht aus einem oder mehreren Archiven. Was willst Du da auf zwei Festplatten aufteilen?

¹ https://borgbackup.readthedocs.io/en/1.1.5/deployment/automated-local.html

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7790

In diesem Fall habe ich keine doppelten Leerzeichen

Mir ist jetzt nicht klar von welchen doppelten Leerzeichen du überhaupt sprichst.

Dein Script verkraftet keine Leerzeichen in Ordner- oder Pfadnamen.

Zum einen weil nicht richtig gequotet wird (irgendwas $1 statt irgendwas "$1") und zum anderen weils dann alles zusammen in einen String geworfen wird, wo es nicht mehr auseinandergehalten werden kann.

Dann sieht das halbe Script so aus als hättest du das Quoting umgeschrieben damit es für echo passt. Das ist verwirrend und klappt eigentlich nie, weil bis du das wieder zurückgeändert hast, stimmt wieder irgendwas anderes nicht.

Du kannst dir Befehle mit set -x ausgeben lassen oder ein printf "«%s» " davor setzen, die «» damit man sieht wie die Shell die Argumente zerlegt hat.

Wieviel Whitespace (Leerzeichen Tabs oder Newlines) du zwischen den Argumenten hast, das spielt dann keine Rolle...

oparilames

(Themenstarter)

Anmeldungsdatum:
21. April 2019

Beiträge: 16

Hallo forstschutz.

Ich sprach von doppelten Leerzeichen zwischen Argumenten bzw. zwischen Argument und Wert für das Argument. Deine Beobachtung zum Quoten stimmt, ich habe es zwecks echo-Ausgabe so eingebaut.

Danke für die Tipps, habe mal versucht es auf die printf Variante umzustellen, war aber natürlich nicht sehr von Erfolg gekrönt. Mir wurden dann Fehler wie dieser angezeigt: borgsc.sh: 92: borgsc.sh: auto,lzma,8: not found

Sieht das nur so aus, oder werden hier tatsächlich, Befehle auszuführen, wobei ich doch nur ausgegeben haben möchte, was theoretisch ausgeführt würde, würde ich es nicht ausgeben wollen? Die entsprechende Zeile sieht so aus:

1
printf "«%s» "DIR_SUBFOLDERS=$DIR_SUBFOLDERS $TARGET/$FILENAME$1

Im Umkehrschluss, warum wird dann aber borg create nichr aufgerufen und spuckt Fehlermeldungen aus? Kurzum, ich verstehe die Arbeitsweise bash scripten (noch) nicht und überlegen ob ich es nicht schnell in C++ zu einem Programm umsetze und mich später wieder mit der bash beschäftige.

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7790

Bei C++ solltest du argc / argv ja eigentlich auch kennen.

argv ist ja nicht ein langer String sondern ein Array von Strings. Und diese können auch Leerzeichen enthalten - wenn sie so übergeben worden sind.

Die Bash zerteilt Strings anhand von Whitespace, und wenn du das nicht willst, brauchst du eben die Quotes. Oder du setzt IFS. Oder du machst was mit Zero-Delimited Strings und xargs -0.

Die entsprechende Zeile sieht so aus:

Ich dachte da eigentlich an deinen borg create ... Befehl und nicht an Variablenzuweisung.

DIR_SUBFOLDERS="${DIR_SUBFOLDERS} ${TARGET}/${FILENAME}$1"
printf "«%s» " borg create $zeugs oder doch "$zeugs"

bzw. du kannst auch allgemeines Debugging einschalten entweder direkt in der Shebang

#!/bin/bash -x

oder eben mit set

set -x
echo Debug ist an.
set +x
echo Debug ist aus.

Die Debugfunktion erzeugt eben nur eine zusätzliche Ausgabe, das Kommando an sich wird trotzdem ausgeführt.

echo oder printf vor ein Kommando setzen verhindert dessen Ausführung bzw. das Kommando ist dann eben echo. Da muss man nur mit Redirects (befehl > ausgabe) etc. aufpassen, statt Befehlsausgabe hat man dann die echo-Ausgabe umgeleitet... aber in deinem Beispiel war das (glaube ich) nicht drin.

debug() {
    printf "«%s» " "$@"
    printf "\n"
}

| debug gibt die folgenden Parameter einzeln aus
$ debug a b c
«a» «b» «c»

| mehr Leerzeichen machen keinen Unterschied
$ debug a    b    c
«a» «b» «c»

| Leerzeichen kommen nur mit Quotes an:
$ debug "a b c"
«a b c»
$ debug "a    " "b    " "c    "
«a    » «b    » «c    »

Bei C hast du diese Kopfschmerzen nicht, wenn du da was nicht ordentlich trennst oder zusammenschreibst was nicht zusammen gehört, hast du sofort einen Compilerfehler bzw. -warnung am Hals.

Die Shell hat eben das Problem, daß sie beliebige Eingaben verstehen muss. Wenn du da Variablen falsch aneinander klebst, könntest du das ja so gewollt haben.

oparilames

(Themenstarter)

Anmeldungsdatum:
21. April 2019

Beiträge: 16

Danke Frostschutz, mit Hilfe deiner Tipps habe ich das Script nun ein gutes Stück voran gebracht. 😀 Konkret heißt es, dass ich die Codeteile für das Linuxbackup ausgelassen habe, aber die ausgegebenen Befehle für's Windowsbackup benutzt habe und es hat funktioniert.

Die Tage über gucke ich, ob ich das Script voll funktionstüchtig bekomme und poste es dann hier.

Antworten |