Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BACKUP_PROG_OPTIONS used to be a string variable, turn it into an array #1475

Merged
merged 3 commits into from Sep 9, 2017
Merged

BACKUP_PROG_OPTIONS used to be a string variable, turn it into an array #1475

merged 3 commits into from Sep 9, 2017

Conversation

gdha
Copy link
Member

@gdha gdha commented Sep 6, 2017

BACKUP_PROG_OPTIONS used to be a string variable, turn it into an array (GD, 06/SEP/2017 - issue #1175)

added new script prep/NETFS/GNU/Linux/205_inspect_tar_capabilities.sh which will automatically add capabilities to the BACKUP_PROG_OPTIONS array

…ay (GD, 06/SEP/2017 - issue #1175)

added new script prep/NETFS/GNU/Linux/205_inspect_tar_capabilities.sh which will automatically add capabilities to the BACKUP_PROG_OPTIONS array
@gdha gdha requested a review from a team September 6, 2017 16:41
Copy link
Member

@schlomo schlomo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice improvement, thanks a lot.


if [[ "$(basename $BACKUP_PROG)" = "tar" ]] ; then
# Verify extended attributes being present:
if tar --usage | grep -q "\-\-xattrs" ; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO tar --usage | grep -- --xattrs is easier to read (or quote the search term to make it even more visible)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schlomo thanks for the tip.

# Verify extended attributes being present:
if tar --usage | grep -q "\-\-xattrs" ; then
BACKUP_PROG_OPTIONS=( "${BACKUP_PROG_OPTIONS[@]}" "--xattrs" )
PROGS=( "${PROGS[@]}" getfattr setfattr )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does tar require the setfattr programs to restore the archive with xattrs? Or this this more for the convenience of the user?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schlomo well it is always better to be as complete as possible. You never know.

@@ -43,7 +43,7 @@ case $(basename $BACKUP_PROG) in
(tar)
if tar --usage | grep -q selinux ; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is worth to extract this into a function, it appears several times.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schlomo Indeed might be a good idea to do that

@@ -503,7 +503,8 @@ BACKUP_PROG_WARN_PARTIAL_TRANSFER=1
# then you also have to set the CREATE and RESTORE archive options. They are *ignored* if the
# backup program is supported.
# default setting for BACKUP_PROG_OPTIONS="" became "--anchored" (GD, 02/DEC/2014 - issue #475)
BACKUP_PROG_OPTIONS="--anchored"
# BACKUP_PROG_OPTIONS used to be a string variable, turn it into an array (GD, 06/SEP/2017 - issue #1175)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change so that we should mention it in the release notes with an explanation of what users have to adjust.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schlomo Yes that is the plan!

@gdha gdha self-assigned this Sep 7, 2017
@gdha gdha added the enhancement Adaptions and new features label Sep 7, 2017
@gdha gdha added this to the ReaR v2.3 milestone Sep 7, 2017
Copy link
Member

@jsmeix jsmeix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I blindly trust you @gdha and I even more blindly ;-) trust what @schlomo already approved :-)

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

@schlomo
I wonder if that is really a "breaking change"
(i.e. a backward incompatible change) because
according to my current (limited) experience
in general bash behaves well backward compatible
for strings and arrays.
For example:
a string variable 'var' can also be evaluated
by using array syntax "${var[@]}" e.g.

# BACKUP_PROG_OPTIONS="--this --that"

# echo "${BACKUP_PROG_OPTIONS[@]}"
--this --that

and also for adding more array elements

# BACKUP_PROG_OPTIONS="--this --that"

# BACKUP_PROG_OPTIONS=( "${BACKUP_PROG_OPTIONS[@]}" "--xattrs" )

# echo "${BACKUP_PROG_OPTIONS[@]}"
--this --that --xattrs

so that for users who specify BACKUP_PROG_OPTIONS
as a string of words in their local.conf things should still
work o.k. (unless I overlooked something special here).

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

It looks as if this pull request already implements
#1411
or do I misunderstand something here?

@gdha
Copy link
Member Author

gdha commented Sep 7, 2017

@jsmeix Good catch of #1411 (forgot about that request) - thanks.

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

@jsmeix please use declare -p to "view" variables and arrays. Consider this example:

$ v="hello world" ; declare -p v ; v=( "${v[@]}" yes we can) ; declare -p v
declare -- v="hello world"
declare -a v=([0]="hello world" [1]="yes" [2]="we" [3]="can")

We can see how the initial value that consists of two words is now a single value with two words. The root cause is that we now quote the array variable whereas the previous implementation on purpose did not quote it. This is actually the core of the breaking change:
image

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

Good grief!
@schlomo you are right:

# set -x

# opts="-i -s"
+ opts='-i -s'

# echo 'Hello World' | grep $opts 'hello' | cat -n
+ grep -i -s hello
+ echo 'Hello World'
+ cat -n
     1  Hello World

# opts=( "${opts[@]}" "-o" )
+ opts=("${opts[@]}" "-o")

# echo 'Hello World' | grep "${opts[@]}" 'hello' | cat -n
+ grep '-i -s' -o hello
+ echo 'Hello World'
+ cat -n
grep: invalid option -- ' '
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

# echo 'Hello World' | grep ${opts[*]} 'hello' | cat -n
+ grep -i -s -o hello
+ echo 'Hello World'
+ cat -n
     1  Hello

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

Let's just try to keep unquoted arrays like ${opts[*]} to the absolute minimum :-)

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

@gdha
can you check if using explicitly unquoted

${BACKUP_PROG_OPTIONS[*]}

in the backup restore command pipe

dd if=$restore_input | $BACKUP_PROG_DECRYPT_OPTIONS $BACKUP_PROG_CRYPT_KEY | $BACKUP_PROG --block-number --totals --verbose ${BACKUP_PROG_OPTIONS[*]} "${BACKUP_PROG_COMPRESS_OPTIONS[@]}" -C $TARGET_FS_ROOT/ -x -f -

could make it behave still backward compatible
or - if that is not possible -
could you check if we could somehow import a user-defined
BACKUP_PROG_OPTIONS string of words like

BACKUP_PROG_OPTIONS="--this --that"

with each word as a separated array element
into the new BACKUP_PROG_OPTIONS() array?

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

I am against unquoted arrays for the sake of backwards compatibility. In general I want ReaR to look forward more than backward. That means that we should guide users in their upgrade process without compromising on the new functionality.

Specifically, I can imagine adding a test that occurs after reading the user configuration. This test would check for blanks in $BACKUP_PROG_OPTIONS (just the first value, therefore no array) and abort ReaR with a error message that the user has to update their configuration to use the array notation instead. The error message can even suggest how:

Error "The BACKUP_PROG_OPTIONS variable is now a Bash array and not a string. Please update your configuration to look like this:${IFS}BACKUP_PROG_OPTIONS+=( $BACKUP_PROG_OPTIONS )"

Example:

2017-09-07 14:19:53.284830783 ERROR: The BACKUP_PROG_OPTIONS variable is now a Bash array and not a string. Please update your configuration to look like this: 	
BACKUP_PROG_OPTIONS+=( --anchored )

This will actually put the old - bad - options there and how how to write it 😄

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

Only a quick unpolished proposal how we might import
user-defined BACKUP_PROG_OPTIONS string of words
as separated array elements into BACKUP_PROG_OPTIONS()

# BACKUP_PROG_OPTIONS="--this --that"

# old_backup_prog_options="$BACKUP_PROG_OPTIONS"

# unset BACKUP_PROG_OPTIONS

# for backup_prog_option in $old_backup_prog_options ; do BACKUP_PROG_OPTIONS=( "${BACKUP_PROG_OPTIONS[@]}" "$backup_prog_option" ) ; done

# for backup_prog_option in "${BACKUP_PROG_OPTIONS[@]}" ; do echo $backup_prog_option ; done
--this
--that

With some additional testing via "declare -p" whether or not
the initial BACKUP_PROG_OPTIONS is a string or
already an array we could keep backward compatibility.

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

@schlomo
a test with a meaningful Error exit message is perfectly fine for me.
I only do not want to rely only on release notes
because nobody reads documentation until it is too late ;-)

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

I also initially thought about an automatic migration but favor the Error message to make the whole topic more explicit and to get our users to actually update their configuration.

@jsmeix
Copy link
Member

jsmeix commented Sep 7, 2017

In general I would prefer a test using 'declare -p'
over a test of spaces in plain $VAR because it could be

VAR=( "first value" "second value" )

i.e. already an array where the first element intentionally
and rightfully contains a blank.
I mean "in general" for BACKUP_PROG_OPTIONS the
values might never contain blanks - hmmm wait:

BACKUP_PROG_OPTIONS=( '--suffix="my suffix"' )

or some other unexpected special things like that ;-)

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

Actually BACKUP_PROG_OPTIONS=( '--suffix="my suffix"' ) won't work as intended because the " would be part of the string. If at all then BACKUP_PROG_OPTIONS=( '--suffix=my suffix' ). However, in this specific case IMHO we can keep it simple and really just check for $IFS in the first value because the previous implementation for tar specifically did not really make it simple for users to put there complex multi word options (quoted quoting hell).

For the sake of simplicity I would therefore keep the test simple and trust that the actual backup will die complaining about strange options. So in any case, our test for the old form is just a courtesy to the user.

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

@gdha maybe you just merge and continue?

@gdha
Copy link
Member Author

gdha commented Sep 7, 2017

@schlomo I like the Error bail-out : +1

$ BACKUP_PROG_OPTIONS="--anchored --selinux"
$ echo "${BACKUP_PROG_OPTIONS}"
--anchored --selinux
$ echo "${BACKUP_PROG_OPTIONS}" | grep " "
--anchored --selinux
$ echo "${#BACKUP_PROG_OPTIONS[@]}"
1

If I understand it well we check if the variable (string) contains a blank and if the amount of values in the array is 1 we have a mismatch, right?

@schlomo
Copy link
Member

schlomo commented Sep 7, 2017

Yes, good point. If there are two array values and the first one has a blank then it might be intentional.

[[ ${#BACKUP_PROG_OPTIONS[@]} -eq 1 && "$BACKUP_PROG_OPTIONS" == *\ * ]] && Error "..."

should work just fine. No external program calls and positive logic 😄

…ities.sh to analyse config files;

saved the BACKUP_PROG_OPTIONS array to the rescue.conf file; commented block in 400_restore_backup.sh
@gdha
Copy link
Member Author

gdha commented Sep 8, 2017

@schlomo @jsmeix Could you verify and give your blessing?

Copy link
Member

@schlomo schlomo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks good.


# save the BACKUP_PROG_OPTIONS array content to the $ROOTFS_DIR/etc/rear/rescue.conf
# we need that for the restore part with tar
echo "BACKUP_PROG_OPTIONS=( ${BACKUP_PROG_OPTIONS[@]} )" >> $ROOTFS_DIR/etc/rear/rescue.conf
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest marking BACKUP_PROG_OPTIONS to be readonly so that nobody would accidentally modify it. Such a modification after this point would be in the rescue system.

Alternative approach would be storing these options together with the backup and not with the rescue system. One one hand they have a strong coupling to the backup archive and the stuff that it contains. On the other hand of course they depend on a certain minimum tar / rsync version and thus have a coupling with the rescue system.


# As we will only inspect 'tar' we make one big if block:

if [[ "$(basename $BACKUP_PROG)" = "tar" ]] ; then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess @jsmeix would suggest here to check for tar or return out of this script instead.

@gdha gdha merged commit e7271e8 into rear:master Sep 9, 2017
@jsmeix
Copy link
Member

jsmeix commented Sep 11, 2017

@gdha
now there is in prep/NETFS/GNU/Linux/205_inspect_tar_capabilities.sh

echo "BACKUP_PROG_OPTIONS=( ${BACKUP_PROG_OPTIONS[@]} )" >> $ROOTFS_DIR/etc/rear/rescue.conf

which fails if a BACKUP_PROG_OPTIONS array element
contains a string of words.
E.g. on commandline:

# arr=( 'first' 'second=foo.bar' 'the end' )

# for e in "${arr[@]}" ; do echo "'$e'" ; done
'first'
'second=foo.bar'
'the end'

# echo "arr=( ${arr[@]} )"
arr=( first second=foo.bar the end )

# arr=( first second=foo.bar the end )

# for e in "${arr[@]}" ; do echo "'$e'" ; done
'first'
'second=foo.bar'
'the'
'end'

What seems to work for me is:

# arr=( 'first' 'second=foo.bar' 'the end' )

# echo "arr=( $( for e in "${arr[@]}" ; do echo -n "'$e' " ; done ) )"
arr=( 'first' 'second=foo.bar' 'the end'  )

It looks rather complicated but currently I don't know
a better way.

@schlomo
Copy link
Member

schlomo commented Sep 11, 2017

declare -p is the official way to solve this problem, I indeed did not catch this one. Sorry.

@jsmeix
Copy link
Member

jsmeix commented Sep 11, 2017

Somewhere in the ReaR code I noticed a comment
that in particular the "declare -p" output for arrays
cannot be used to re-create arrays
but I cannot find it right now.

At least on my SLES11 machine it seems to work
to use the "declare -p" output to re-create arrays:

# unset arr

# arr=( 'first' '--second=foo.bar' 'the end'  )

# for e in "${arr[@]}" ; do echo "'$e'" ; done
'first'
'--second=foo.bar'
'the end'

# declare -p arr
declare -a arr='([0]="first" [1]="--second=foo.bar" [2]="the end")'

# declare -a arr='([0]="first" [1]="--second=foo.bar" [2]="the end")'

# for e in "${arr[@]}" ; do echo "'$e'" ; done
'first'
'--second=foo.bar'
'the end'

@jsmeix
Copy link
Member

jsmeix commented Sep 11, 2017

I found the comment about 'declare' in an older ReaR version
(but it is not about arrays - I confused that)
therein in rescue/NETFS/default/60_store_NETFS_variables.sh

# store all NETFS* variables
# I don't know why it does not work with the full declare -- var=value syntax
# found out by experiment that I need to remove the declare -- stuff.
declare -p ${!NETFS*} | sed -e 's/declare .. //' >>$ROOTFS_DIR/etc/rear/rescue.conf

and according to
52b6c06
that comment is from you @schlomo - could you
perhaps still explain what the reasoning behind was?

@schlomo
Copy link
Member

schlomo commented Sep 11, 2017

It might be related to Bash 2.x, not sure any more. If I wrote it then for sure I observed that behavior somewhere.

Maybe we should add some test code to our Makefile. If not to test ReaR scripts we could at least test for features that we use.

@jsmeix
Copy link
Member

jsmeix commented Sep 11, 2017

For me on SLES11 'declare -p' also seems to
"just work" to recreate string variables:

# unset var

# var=" this and that "

# echo "'$var'"
' this and that '

# declare -p var
declare -- var=" this and that "

# declare -- var=" this and that "

# echo "'$var'"
' this and that '

@gdha
Copy link
Member Author

gdha commented Sep 11, 2017

@jsmeix @schlomo there is not need to over-engineer this array declaration in rescue.conf as I could not find any option declaration with a space within tar.

@jsmeix
Copy link
Member

jsmeix commented Sep 11, 2017

@gdha see
#1475 (comment)

BACKUP_PROG_OPTIONS=( '--suffix="my suffix"' )

@gdha
Copy link
Member Author

gdha commented Sep 11, 2017

@jsmeix I was referring to tar --usage option and not to hypothetical cases.

@schlomo
Copy link
Member

schlomo commented Sep 11, 2017

👍 for keeping it simple and sticking to problems that we know from reality.

That said, if we can use a Bash feature vs. self-coding then I would expect that to reduce the risk for bugs.

@jsmeix
Copy link
Member

jsmeix commented Sep 12, 2017

I am referring to a real tar option and not to hypothetical cases.
You could have done "man tar" or "tar --usage | grep STRING"
to verify what I am talking about - didn't you?
Here for your convenience a real example
(on my SLES11 system):

# mkdir foo

# echo Hello >foo/hello

# tar -cvf foo.tar foo
foo/
foo/hello

# tar -xv --suffix="my suffix" -f foo.tar
foo/
foo/hello
Renaming `foo/hello' to `foo/hellomy suffix'

# find foo
foo
foo/hello
foo/hellomy suffix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Adaptions and new features fixed / solved / done
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants