Bash 使用变量时使用 docker exec 编写脚本

Bash scripting with docker exec when using variables

我正在尝试创建一个基于变量的 Bash 脚本。当我通过 docker image:

使用 bash 命令行时效果很好
#docker exec app_mysql mysqldump --login-path=localroot masterdb | gzip > 1111111.sql.gz 

虽然我试图通过 shell 脚本通过使用变量重现相同的内容,但它什么也没给我,只是执行没有任何错误:

#!/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)'

我哪里错了?

Bash 变量在 single-quotes.

内部没有展开
$ foo=hello

$ echo '$foo'
$foo

$ echo "$foo"
hello

您脚本中的引用不一致,这可能会导致一些问题。

我不会像您展示的那样尝试扩展 multi-word 变量。相反,如果您想对 docker exec 命令进行某种抽象,我会使用 shell 函数 :

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

您原来的 docker exec 命令没有 sh -c 包装器,我也不会尝试在此处强制使用;它确实使引用变得更加复杂。

我也可以在一个简单的变量中构建输出文件名

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

请注意,整个字符串周围有双引号,以防止出现意外空格,但字符串中没有额外的引号。

将所有这些放在一起,并删除不必要的引号,您会得到如下内容:

#!/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"

另外请注意,我在这里展示的所有内容都是标准 POSIX shell 语法,没有 GNU bash 扩展,我使用了普通的 #!/bin/sh "shebang “ 线;即使在 bash 不可用或 /bin/sh 是不同的 shell.

的最小 Debian 或 Alpine 环境中,这也可以工作

上面的配置看起来我已经尝试重新发明轮子了。无论如何,解决方案很简单。我刚刚从我的脚本中删除了冗余数据。所以现在看起来像:

#!/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