为什么不能在 bash 4.1.2 中访问带有破折号的环境变量? [英] Why can't environment variables with dashes be accessed in bash 4.1.2?

查看:15
本文介绍了为什么不能在 bash 4.1.2 中访问带有破折号的环境变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 CentOS 5 主机(带有 bash 3.2.32)上,我们使用 Ruby (1.8.7) 来

On a CentOS 5 host (with bash 3.2.32), we use Ruby (1.8.7) to

ENV['AWS_foo-bar_ACCESS_KEY'] = xxxxx

然后,使用 bash,我们运行一个 shell 脚本:

Then, using bash, we run a shell script that does:

BUCKET_NAME=$1
AWS_ACCESS_KEY_ID_VAR="AWS_${BUCKET_NAME}_ACCESS_KEY_ID"
AWS_ACCESS_KEY_ID="${!AWS_ACCESS_KEY_ID_VAR}"
export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}

这在 CentOS 5 上运行良好.

This works fine on CentOS 5.

但是,在 CentOS 6(使用 bash 4.1.2)上,我们得到了错误

However, on CentOS 6 (with bash 4.1.2), we get the error

-bash: export: `AWS_foo-bar_ACCESS_KEY_ID=xxxxx': not a valid identifier

据我们了解,这会失败,因为变量名中不允许使用 -.但是为什么这适用于 bash 3.2 而不是 bash 4.1?

It is our understanding that this fails because - is not allowed in the variable name. But why does this work on bash 3.2 and not bash 4.1?

推荐答案

为什么"几乎无关紧要:POSIX 标准明确规定 export 只需要支持有效的参数名称,并且带有破折号的任何内容都不是有效名称.因此,不需要任何 POSIX shell 来支持通过间接扩展或其他方式使用破折号导出或扩展变量名.

The "why" is almost irrelevant: The POSIX standard makes it very clear that export is only required to support arguments which are valid names, and anything with a dash is not a valid name. Thus, no POSIX shell is required to support exporting or expanding variable names with dashes, via indirect expansion or otherwise.

值得注意的是,ShellShock - 一个由对环境内容的草率处理引起的主要安全漏洞 - 已在当前 CentOS 6 更新存储库中的 bash 4.1 中得到修复;在产生安全漏洞的领域增加严格性应该不足为奇.

It's worth noting that ShellShock -- a major security bug caused by sloppy handling of environment contents -- is fixed in the bash 4.1 present in the current CentOS 6 updates repo; increased rigor in an area which spawned security bugs should be no surprise.

本答案的其余部分将重点说明 bash 4.1 的新行为是 POSIX 明确允许甚至要求的——因此先前的行为是未定义的实现工件.

The remainder of this answer will focus on demonstrating that the new behavior of bash 4.1 is explicitly allowed, or even required, by POSIX -- and thus that the prior behavior was an undefined implementation artifact.

在环境变量上引用 POSIX:

这些字符串的形式为 name=value;名称不得包含字符=".对于在符合 IEEE Std 1003.1-2001 的系统中可移植的值,该值应由可移植字符集中的字符组成(NUL 除外,如下所示).环境中字符串的顺序没有任何意义.如果进程环境中有多个字符串具有相同的名称,则后果是不确定的.

These strings have the form name=value; names shall not contain the character '='. For values to be portable across systems conforming to IEEE Std 1003.1-2001, the value shall be composed of characters from the portable character set (except NUL and as indicated below). There is no meaning associated with the order of strings in the environment. If more than one string in a process' environment has the same name, the consequences are undefined.

IEEE Std 1003.1-2001 的 Shell 和 Utilities 卷中的实用程序使用的环境变量名称仅由 Portable Character Set 和不要以数字开头. 实现可能允许使用其他字符;应用程序应容忍此类名称的存在.大写和小写字母应保持其唯一身份,不得折叠在一起.包含小写字母的环境变量名称的名称空间是为应用程序保留的. 应用程序可以使用此名称空间中的名称定义任何环境变量,而无需修改标准实用程序的行为.

Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with a digit. Other characters may be permitted by an implementation; applications shall tolerate the presence of such names. Uppercase and lowercase letters shall retain their unique identities and shall not be folded together. The name space of environment variable names containing lowercase letters is reserved for applications. Applications can define any environment variables with names from this name space without modifying the behavior of the standard utilities.

注意:其他应用程序可能难以处理以数字开头的环境变量名称.因此,不建议在任何地方使用此类名称.

Note: Other applications may have difficulty dealing with environment variable names that start with a digit. For this reason, use of such names is not recommended anywhere.

因此:

  • 需要工具(包括 shell)才能完全支持包含大小写字母、数字(第一个位置除外)和下划线的环境变量名称.
  • 工具(包括外壳)可能会根据环境变量修改其行为,其名称符合上述规定且不包含小写字母.
  • 工具(包括外壳)应该容忍其他名称——这意味着它们不应该在它们面前崩溃或行为不端——但不需要支持它们.
  • Tools (including the shell) are required to fully support environment variable names with uppercase and lowercase letters, digits (except in the first position), and the underscore.
  • Tools (including the shell) may modify their behavior based on environment variables with names that comply with the above and additionally do not contain lowercase letters.
  • Tools (including the shell) should tolerate other names -- meaning they shouldn't crash or misbehave in their presence -- but are not required to support them.

最后,shell 被明确允许丢弃不是 shell 变量名的环境变量名.来自相关标准:

Finally, shells are explicitly allowed to discard environment variable names which are not also shell variable names. From the relevant standard:

未指定在调用时传递给 shell 的环境变量是否包含在传递给 execl() 和(如果 execl() 如上所述失败)到新的 shell.

It is unspecified whether environment variables that were passed to the shell when it was invoked, but were not used to initialize shell variables (see Shell Variables) because they had invalid names, are included in the environment passed to execl() and (if execl() fails as described above) to the new shell.

<小时>

此外,定义有效 shell 名称的内容定义明确:

名称 - 在 shell 命令语言中,仅由可移植字符集中的下划线、数字和字母组成的单词.名称的第一个字符不是数字.

Name - In the shell command language, a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit.

值得注意的是,在符合 POSIX 标准的 shell 中,只有下划线(不是破折号)被视为有效名称的一部分.

Notably, only underscores (not dashes) are considered part of a valid name in a POSIX-compliant shell.

...和 ​​export 的 POSIX 规范 明确使用名称"一词(它在上面引用的文本中定义),并将其描述为应用于变量"(shell 变量,对其名称的限制也受其他地方引用的限制)在本文档中):

...and the POSIX specification for export explicitly uses the word "name" (which it defined in the text quoted above), and describes it as applying to "variables" (shell variables, the restrictions on names for which are also subject to restrictions quoted elsewhere in this document):

shell 应将导出属性赋予与指定名称对应的变量,这将使它们处于随后执行的命令的环境中.如果变量名后跟=word,则该变量的值应设置为word.

The shell shall give the export attribute to the variables corresponding to the specified names, which shall cause them to be in the environment of subsequently executed commands. If the name of a variable is followed by = word, then the value of that variable shall be set to word.

<小时>

以上所说的——如果你的操作系统提供了一个 /proc/self/environ 代表你的环境变量在进程启动时的状态(在 shell 之前,因为它被允许做,可能会丢弃任何在 shell 中没有有效名称的变量),您可以提取具有无效名称的内容,如下所示:


All the above being said -- if your operating system provides a /proc/self/environ which represents the state of your enviroment variables at process startup (before a shell has, as it's allowed to do, potentially discarded any variables which don't have valid names in shell), you can extract content with invalid names like so:

# using a lower-case name where possible is in line with POSIX guidelines, see above
aws_access_key_id_var="AWS_${BUCKET_NAME}_ACCESS_KEY_ID"
while IFS= read -r -d '' var; do
  [[ $var = "$aws_access_key_id_var"=* ]] || continue
  val=${var#"${aws_access_key_id_var}="}
  break
done </proc/self/environ
echo "Extracted value: $val"

这篇关于为什么不能在 bash 4.1.2 中访问带有破折号的环境变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆