如何检测是否已读取Bash环境变量?

时间:2013-05-10 11:52:48

标签: bash metadata environment-variables

我有一个通过环境变量提供配置的脚本。由于配置是手动编辑的,因此可能会将从未使用过的拼写错误和变量添加到配置中。

有没有办法获取有关变量的元数据,如果没有读取变量,该变量将允许执行后步骤发出警告?

可接受的答案包括,

  • 计算var读取次数的方法
  • 如果已读取var,则为true的标志
  • 确定访问var的最后时间的方法

上面没有列出其他可接受的答案。

出现此问题的部分原因是默认情况下Bash是无类型的。

1 个答案:

答案 0 :(得分:2)

您的帖子中有两个问题。第一个问题:

  

如何检测是否已读取Bash环境变量?

尽管没有一个可接受的答案包括我的,但我会回答第一个问题以造福他人:

无论如何,除了修改Bash。

你当然可以拒绝它。

第二个问题:

  

有没有办法获取有关变量的元数据,如果没有读取变量,该变量将允许执行后步骤发出警告?

提出这个问题没有多大意义,因为可能的答案不包括在可接受的答案列表中。但无论如何我会回答:

不,除非Bash被修改。

现在,即使你可能对我的意见不感兴趣,因为它不在可接受的答案列表之内,但无论如何我都会把它作为练习呈现给我,也许是对其他人有用的信息。

首先,在这种情况下发出警告通常是无用的,特别是在执行之后。无论在提供参数方面犯了什么错误,它们在那个时候已经生效,无论是数据损坏还是时间丢失。此外,如果他们认为脚本的工作结果没问题,大多数人都不会注意到警告。他们可能会在以后发现他们错了,但可能为时已晚。

如果您要验证参数,请在执行之前执行,如果错误则执行中止

确保环境变量名称中没有拼写错误的一种方法是通过要求它们的名称以固定字符串作为前缀,然后验证具有该前缀的所有变量名称是否已知,为它们创建命名空间。程序。但是,这不能防止前缀字符串中的拼写错误。尽管如此,我所知道的其他程序并没有这样做,这可能意味着几乎没有人期望这样的行为来自程序。这违反了“最少惊喜的规则”,而且我会说,这是不必要的。

我建议根本不验证环境变量名。如果您的程序具有复杂的配置(需要验证),请不要将其放入环境中。将其放入配置文件中,该文件不会与其他程序共享。

一种简单的方法是使配置文件成为源shell脚本 它设置了一堆变量。这将允许轻松“解析”(如Bash 会这样做)和验证。要验证它,请在子shell中获取它 (所以主shell不受影响),输出变量的名称, 过滤掉在采购之前设置的变量,然后将它们进行比较 已知配置变量名称列表。

这样的事情:

function list_vars() {
    declare -p | awk -F'[ =]' '/^declare/ {print $3}'
}

function unset_vars() {
    while read v; do
        unset "$v" 2>/dev/null;
    done < <(list_vars);
}

declare -a CONF_VAR_NAMES=(FOO BAR BAZ)

extra_vars=`
    (
        # Unset all variables that can be unset (and thus set)
        unset_vars
        # List variables set after sourcing configuration
        (. conf_file.sh; list_vars) |
            # Remove variables set before sourcing
            grep -v -F -f <(list_vars)
    ) |
        # Remove known variables
        grep -v -F -f <(IFS=$'\n'; echo "${CONF_VAR_NAMES[*]}")
`

if [ -n "$extra_vars" ]; then
    echo "Unknown variables set by configuration script: $extra_vars" >&2
    exit 1
fi

但是,您可能需要对PATH和其他重要变量进行特殊处理。 在采购之前简单地将所有变量设置为只读可能是个好主意, 在验证时。