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

Posted

技术标签:

【中文标题】如何在不导致脚本失败的情况下满足 shellcheck?【英文标题】:How can I satisfy shellcheck without causing script failure? 【发布时间】:2021-05-10 07:10:39 【问题描述】:

我目前正在测试 GitHub Actions,quickstart 解释了如何将 super-linter 添加到 repo,这是一种在整个 repo 中应用 linting 的简单方法 - 我喜欢这个想法,所以我将它添加到我的 repo ,它应用的 linter 之一是 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 docker:无效的参考格式。

请注意如何在命令中添加了两个额外的撇号。

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

【问题讨论】:

将额外的 docker args 放入数组中可能会有所帮助。 【参考方案1】:

刚刚决定使用

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

更新。我认为@that-other-guy 的答案更好,所以我改了。

【讨论】:

【参考方案2】:

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

您应该:

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"

【讨论】:

【参考方案3】:

不禁用 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 是空格分隔的参数列表(与shell 引用的单词或换行符分隔的参数相反)时,这是一个不错的选择。 @thatotherguy 它只是作为扩展EXTRA_DOCKER_ARGS 没有双引号;只是让它明确。如果由于某种外部原因必须将多个包含空格的参数作为字符串传递,则可以使用mapfile -t -d $'\036ASCII Record Separator【参考方案4】:

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

忽略某些错误:

shellcheck --exclude SC2086 file.sh

如果您可以配置 shellcheck 参数以这种方式运行它,它应该可以修复它。通常我不喜欢覆盖 linters,但在这种情况下,看看那个变量做了什么,我看不出有什么办法。不能对 docker 引用一堆 args。它们确实需要作为单独的参数传递。

【讨论】:

谢谢,是的,我也不喜欢覆盖短绒。正在探索一些可能的选项来解决而不覆盖但看起来我可能不得不走那条路

以上是关于如何在不导致脚本失败的情况下满足 shellcheck?的主要内容,如果未能解决你的问题,请参考以下文章

Nightwatchjs:如何在不创建错误/失败/异常的情况下检查元素是不是存在

如何在不失败测试的情况下获得 Jest toThrow 的覆盖率

如何在不满足给定条件的情况下创建一系列变量并将它们存储在列表中?

如何在不显示窗口的情况下运行 PowerShell 脚本?

如何在不发送请求的情况下拦截 Moya 请求并返回失败响应

如何在不修改脚本的情况下计算 PHP 脚本的文件读取和写入?