问题描述
我目前正在测试 GitHub Actions,quickstart 解释了如何向存储库添加超级 linter,这是在整个存储库中应用 linting 的一种简单方法 - 我喜欢这个想法,所以我将它添加到我的 repo,它应用的短绒工具之一是 shellcheck,它在我的一个 shell 脚本中抛出了一些错误。
该 shell 脚本使用以下代码发出 docker run
:
docker run --rm \
"${INteraCTIVE_MODE_FLAG}" \
${EXTRA_DOCKER_ARGS} \
"${IMAGE}":"${IMAGE_VERSION}" "$@"
Shellcheck 在 ${EXTRA_DOCKER_ARGS}
上抛出 SC2086 Double quote to prevent globbing and word splitting。通过将代码更改为:
docker run --rm \
"${INteraCTIVE_MODE_FLAG}" \
"${EXTRA_DOCKER_ARGS}" \
"${IMAGE}":"${IMAGE_VERSION}" "$@"
(注意用引号括起来 ${EXTRA_DOCKER_ARGS}
)
docker: 无效的参考格式
如果我将 set -x
添加到脚本的顶部,它会显示问题所在:
+ docker run --rm -it '' myimage:mytag
泊坞窗:无效的参考格式。
注意如何在命令中添加了两个额外的撇号。
我的问题很简单……我该如何解决这个问题?我想消除 Shellcheck 错误,但仍然有一个正常运行的脚本。
解决方法
您的代码使用字符串作为列表,这种概念上的不匹配导致了警告。这是一个真正的问题,你应该解决它。
你应该:
A.将 EXTRA_DOCKER_ARGS 作为一个列表开始。
或
B.将 EXTRA_DOCKER_ARGS 保留为字符串,并考虑如何将其拆分为参数(在空白处?逐行?shell 引用的参数?)。这需要符合设置变量的人的期望。
对于 A,您可以简化将变量指定为数组并相应地扩展它:
EXTRA_DOCKER_ARGS=()
docker run --rm \
"${INTERACTIVE_MODE_FLAG}" \
"${EXTRA_DOCKER_ARGS[@]}" \
"${IMAGE}":"${IMAGE_VERSION}" "$@"
对于 B,您可以例如将其视为需要通过 eval 扩展的 shell 引用字符串:
extras=()
eval "extras+=( $EXTRA_DOCKER_ARGS )"
docker run --rm \
"${INTERACTIVE_MODE_FLAG}" \
"${extras[@]}" \
"${IMAGE}":"${IMAGE_VERSION}" "$@"
如果你不解决这个问题,继续依赖隐式分词,那么你将无法传递包含空格的额外参数,例如-v "$HOME/My Documents:/mnt"
不禁用 shellcheck 警告:
#!/usr/bin/env bash
# Word split EXTRA_DOCKER_ARGS into extra_docker_args_array
read -r -a extra_docker_args_array <<<"$EXTRA_DOCKER_ARGS"
docker run --rm \
"$INTERACTIVE_MODE_FLAG" \
"${extra_docker_args_array[@]}" \
"$IMAGE:$IMAGE_VERSION" "$@"
,
看起来手册页 https://www.mankier.com/1/shellcheck 描述了覆盖错误的方法。
忽略某些错误:
shellcheck --exclude SC2086 file.sh
如果您可以配置 shellcheck 参数以这种方式运行它,它应该可以修复它。通常我不喜欢覆盖 linter,但在这种情况下,查看该变量的作用,我看不出有什么解决办法。不能用双引号将一堆 args 引用到 docker。它们确实需要作为单独的参数传递。
,刚刚决定使用
禁用shellcheck# shellcheck disable=SC2086
docker run --rm \
"${INTERACTIVE_MODE_FLAG}" \
${EXTRA_DOCKER_ARGS} \
"${IMAGE}":"${IMAGE_VERSION}" "$@"
更新。我觉得@that-other-guy 的回答更好,所以我改成了那个。