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

问题描述

我目前正在测试 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。通过将代码更改为:

,我可以轻松删除 Shellcheck 错误
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 的回答更好,所以我改成了那个。