如何在不导致脚本失败的情况下满足 shellcheck?

How can I satisfy shellcheck without causing script failure?

我目前正在测试 GitHub 操作,quickstart 解释了如何将 super-linter 添加到存储库,这是在整个存储库中应用 linting 的简单方法 - 我喜欢这个想法所以我将它添加到我的回购协议中,它应用的 linters 之一是 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。我可以通过将代码更改为:

轻松消除 Shellcheck 错误
docker run --rm \
    "${INTERACTIVE_MODE_FLAG}" \
    "${EXTRA_DOCKER_ARGS}" \
    "${IMAGE}":"${IMAGE_VERSION}" "$@"

(注意将 ${EXTRA_DOCKER_ARGS} 括在引号中)

docker: invalid reference format

如果我将 set -x 添加到脚本的顶部,它会显示问题所在:

+ docker run --rm -it '' myimage:mytag
docker: invalid reference format.

注意如何向命令添加两个额外的撇号。

我的问题很简单...我该如何解决?我想消除 Shellcheck 错误,但仍然有一个正常运行的脚本。

看起来手册页 https://www.mankier.com/1/shellcheck 描述了覆盖错误的方法。

忽略某些错误:

shellcheck --exclude SC2086 file.sh

如果您可以将 shellcheck 参数配置为 运行,那么应该可以修复它。通常我不喜欢覆盖 linters,但在这种情况下,查看该变量的作用,我没有找到解决它的方法。不能将一堆参数双引号到 docker。它们确实需要作为单独的参数传递。

刚刚决定使用

禁用 shellcheck
# shellcheck disable=SC2086
docker run --rm \
    "${INTERACTIVE_MODE_FLAG}" \
    ${EXTRA_DOCKER_ARGS} \
    "${IMAGE}":"${IMAGE_VERSION}" "$@"

更新。我认为 @that-other-guy 的回答更好,所以我改成了那个。

不禁用 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" "$@"

您的代码使用字符串作为列表,这种概念上的不匹配导致了警告。这是一个真正的问题,您应该解决它。

您应该:

一个。制作 EXTRA_DOCKER_ARGS 列表作为开头。

乙。将 EXTRA_DOCKER_ARGS 保留为字符串,并考虑一下您希望如何将其拆分为参数(在空格上?逐行?shell 引用的参数?)。这需要符合设置变量的人的期望。


对于A,可以简化指定变量为数组,并相应展开:

EXTRA_DOCKER_ARGS=()
docker run --rm \
    "${INTERACTIVE_MODE_FLAG}" \
    "${EXTRA_DOCKER_ARGS[@]}" \
    "${IMAGE}":"${IMAGE_VERSION}" "$@"

对于 B,您可以例如将其视为 shell 带引号的字符串,需要通过 eval:

进行扩展
extras=()
eval "extras+=( $EXTRA_DOCKER_ARGS )"
docker run --rm \
    "${INTERACTIVE_MODE_FLAG}" \
    "${extras[@]}" \
    "${IMAGE}":"${IMAGE_VERSION}" "$@"

如果你不解决这个问题并继续依赖隐式分词,那么你将无法传递包含空格的额外参数,例如-v "$HOME/My Documents:/mnt"