0

I have been trying to customise this very useful (in principle) backup to s3 script. I really am not a shell scripter to any real level and I can't work out why this line is truncating the variable.

so e.g.

DB=abcdefg
abcdefg_USER=testuser

USER=$(eval echo \$${DB}_USER)

The eval statement is returning bcdefg_USER so is truncating the variable and echoing out bcdefg_USER not abcdefg_USER and so isn't evaluating the variable abcdefg_USER

Running on an amazon linux ec2 instance.

Anyone explain to me what I am missing, I've tried playing around with the escaping and braces etc and echoing out each stage in the process but can't get a handle on what is going on.

Thanks

full script below:

    ## Specify data base schemas to backup and credentials
DATABASES="wp myotherdb"

## Syntax databasename as per above _USER and _PW
wp_USER=username
wp_PW=password
myotherdb_USER=username
myotherdb_PW=password

## Specify directories to backup (it's clever to use relaive paths)
DIRECTORIES="/var/www root etc/cron.daily etc/cron.monthly etc/apache2 etc/mysql etc/php5" 

## Initialize some variables
DATE=$(date +%d)
BACKUP_DIRECTORY=/tmp/backups
S3_CMD="s3cmd"

## Specify where the backups should be placed
S3_BUCKET_URL=s3://mybackupbucket/$DATE/

## The script
cd /
mkdir -p $BACKUP_DIRECTORY
rm -rf $BACKUP_DIRECTORY/*

## Backup MySQL:s
for DB in $DATABASES
do
BACKUP_FILE=$BACKUP_DIRECTORY/${DB}.sql
USER=$(eval echo \$${DB}_USER)
PASSWORD=$(eval echo \$${DB}_PW)
/usr/bin/mysqldump -v -u $USER --password=$PASSWORD -h localhost -r $BACKUP_FILE $DB 2>&1
gzip $BACKUP_FILE 2>&1
$S3_CMD put ${BACKUP_FILE}.gz $S3_BUCKET_URL 2>&1
done

## Backup of config directories
for DIR in $DIRECTORIES
do
BACKUP_FILE=$BACKUP_DIRECTORY/$(echo $DIR | sed 's/\//-/g').tgz
tar zcvf ${BACKUP_FILE} $DIR 2>&1
$S3_CMD put ${BACKUP_FILE} $S3_BUCKET_URL 2>&1
done
4
  • When I run your example, USER is set to testuser as expected. Does this not happen for you? Can you make a test case, a shorter version of your script that shows the problem? (see the bash tag wiki for tips on what you can leave out) Commented Apr 17, 2014 at 20:15
  • Note that the eval command does not echo anything; the echo command does. The gluing together of ${DB} and _testuser is done as part of the expansion prior to the evaluation of the echo. If a character is being chopped at that point, it's quite a mystery; it generates the wrong variable name and so then the echo doesn't echo anything (or even raises an error if we trap uses of undefined variables with set -u). Commented Apr 17, 2014 at 20:28
  • "amazon linux ec2" isn't very helfpul: it is proving difficult to obtain any detailed specifications about what is the Amazon distribution of Linux. Are you using #!/bin/sh or #!/bin/bash in the script? What shell exactly is it using, and what version. Commented Apr 17, 2014 at 20:40
  • thank you for your comments and pointers, very much appreciated. I will know how to specify question better by detailing which shell etc next time. Commented Apr 18, 2014 at 14:57

2 Answers 2

3

Assuming that you are using bash, this is how to avoid eval:

$ DB=abcdefg
$ abcdefg_USER=testuser
$ tmpvar=${DB}_USER
$ USER=${!tmpvar}
$ echo $USER
testuser

If you have bash version 4, consider using associative arrays:

$ declare -A users
$ users[abcdefg]=testuser
$ echo "${users[$DB]}"
testuser
Sign up to request clarification or add additional context in comments.

3 Comments

Reference: look for "variable indirection" at gnu.org/software/bash/manual/…
Also, get out of the habit of using ALL_CAPS_VARNAMES -- someday you'll accidentally use PATH=... and break your script.
used arrays hence why accepted this answer. Thanks very much.
0

You're running into some weird bug involving command substitution and echo.

When using eval to access a computed variable name, it is not necessary to complicate things by involving echo wrapped in a process substitution. Try this pattern, which should work pretty much in any POSIX-like shell.

eval FINAL_VALUE=\$${COMPUTED_VAR_PREFIX}_FIXED_SUFFIX

That is to say, just generate the source code of the desired variable assignment, and eval that code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.