Bash scripting with docker exec when using variables

1k Views Asked by At

I'm trying to create a Bash script based on variables. It works well when I'm using bash command line via docker image:

#docker exec app_mysql mysqldump --login-path=localroot masterdb | gzip > 1111111.sql.gz 

While I'm trying to reproduce the same via shell script by using variables it gives me nothing but just executes without any errors:

#!/bin/bash

DOCKER="docker exec app_mysql bash -c"
CONF_LOCAL_MYSQL_ROOT="--login-path=localroot"
LOCALDBNAME="masterdb"

$DOCKER '(mysqldump '$CONF_LOCAL_MYSQL_ROOT' '$LOCALDBNAME' | gzip > '${LOCALDBNAME}'_local_'${DATE}'.sql.gz)'

Where I'm wrong?

3

There are 3 best solutions below

1
Bill Karwin On BEST ANSWER

Bash variables are not expanded inside single-quotes.

$ foo=hello

$ echo '$foo'
$foo

$ echo "$foo"
hello
2
David Maze On

The quoting in your script is inconsistent and that's probably causing some problems.

I would not try to expand a multi-word variable as you've shown. Instead, if you want to have some sort of abstraction around the docker exec command, I'd use a shell function:

dockerExec() {
  docker exec app_mysql "$@"
}

Your original docker exec command does not have a sh -c wrapper and I would not try to force one in here either; it does make the quoting significantly more complicated.

I also might construct the output filename in a simple variable

OUTFILE="${LOCALDBNAME}_local_${DATE}.sql.gz"

Note that there are double quotes around the string as a whole, protecting against unexpected spaces, but no additional quotes within the string.

Putting this all together, and removing unnecessary quotes, you'd get something like:

#!/bin/sh

CONTAINER=app_mysql
CONF_LOCAL_MYSQL_ROOT="--login-path=localroot"
LOCALDBNAME="masterdb"
DATE="$(date +%Y%m%d)"
OUTFILE="${LOCALDBNAME}_local_${DATE}.sql.gz"

dockerExec() {
  docker exec "$CONTAINER" "$@"
}

dockerExec mysql "$CONF_LOCAL_MYSQL_ROOT" "$LOCALDBNAME" \
  | gzip \
  > "$OUTFILE"

Further note that everything I've shown here is standard POSIX shell syntax without GNU bash extensions, and I've used a plain #!/bin/sh "shebang" line; this will work even in a minimal Debian or Alpine environment where either bash isn't available or /bin/sh is a different shell.

0
user3417586 On

It looks like with the configuration above I've tried to reinvent the wheel. Anyway the solution was simple. I've just removed redundant data from my script. So right now it looks like:

#!/bin/bash

DOCKER="docker exec app_mysql mysql"
CONF_LOCAL_MYSQL_ROOT="--login-path=localroot"
LOCALDBNAME="masterdb"

$DOCKER ${CONF_LOCAL_MYSQL_ROOT} ${LOCALDBNAME} | gzip > ${LOCALDBNAME}_local_${DATE}.sql.gz