1

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?

2
  • You shouldn't need docker exec here. Can you run mysqldump on your host, pointing at a docker run -p published port of the container, without involving Docker at all? Commented Apr 9, 2022 at 21:31
  • But what about if I want to avoid any local installations? Docker has all necessary tools already Commented Apr 10, 2022 at 10:50

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for helping me. But I'm not familiar with POSIX syntax and I would have to adapt other parts of my whole shell script to it (posted above is just a part of my shell script). So in that case I would stick with bash
GNU bash can run POSIX scripts too (you should be able to run bash this-script.sh). Particularly in a Docker context, I'd recommend sticking to the POSIX syntax if you can; avoid unnecessary bashisms like function or source, for example, and it will be easier to run your scripts in places like Alpine-based containers.
0

Bash variables are not expanded inside single-quotes.

$ foo=hello

$ echo '$foo'
$foo

$ echo "$foo"
hello

1 Comment

I've tried different approaches but no success. Is there any chance to get some help from you side in changing the code posted above?
0

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

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.