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
我正在尝试创建一个基于变量的 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.
上面的配置看起来我已经尝试重新发明轮子了。无论如何,解决方案很简单。我刚刚从我的脚本中删除了冗余数据。所以现在看起来像:
#!/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